httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <field...@kiwi.ICS.UCI.EDU>
Subject Re: [PATCH] Fix suexec goofing in util_script.c
Date Sat, 26 Apr 1997 01:23:56 GMT
Why is it that every time I try to fix one thing I end up finding
a bunch of other bugs that need fixing as well?  Anyway, the below
patch fixes PR#453 and PR#339 and some pre-bugdb reports of scripts
not getting the right arguments.

The fix that Jason described earlier today required a new create_argv
function, which I copied from the existing one and started tooling away
and then realized that the existing function is totally bogus (for both
suexec and non-suexec users).  So, rather than creating two bogus
functions, I just replaced the existing one (and made it static because
it is specific to util_script and of no use to other files).  Aside from
being faster and not including an always-false loop test, the new one
does not lose arguments after the first "+".

The rest of the change is as described earlier: if suexec is enabled,
avoid destroying r->url while obtaining the /~user and save the username
in a separate data area so that it won't be overwritten by the call
to getgrgid(), and do so in a way that uses the pool string allocation
functions correctly.

.....Roy

Index: util_script.h
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.h,v
retrieving revision 1.14
diff -c -r1.14 util_script.h
*** util_script.h	1997/03/18 09:46:27	1.14
--- util_script.h	1997/04/26 00:59:18
***************
*** 56,65 ****
  #define APACHE_ARG_MAX 512
  #endif
  
- char **create_argv(request_rec *r, char *av0, ...);
- #ifdef __EMX__
- char **create_argv_cmd(pool *p, char *av0, const char *args, char *path);
- #endif
  char **create_environment(pool *p, table *t);
  int find_path_info(char *uri, char *path_info);
  void add_cgi_vars(request_rec *r);
--- 56,61 ----
Index: util_script.c
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.c,v
retrieving revision 1.51
diff -c -r1.51 util_script.c
*** util_script.c	1997/04/25 13:39:33	1.51
--- util_script.c	1997/04/26 00:59:18
***************
*** 72,108 ****
  #define MALFORMED_MESSAGE "malformed header from script. Bad header="
  #define MALFORMED_HEADER_LENGTH_TO_SHOW 30
  
! char **create_argv(request_rec *r, char *av0, ...)
  {
-     int idx;
      char **av;
!     char *t, *arg;
!     va_list args;
  
!     av = (char **)palloc(r->pool, APACHE_ARG_MAX);
      
!     av[0] = av0;
!     idx = 1;
!     
!     va_start(args, av0);
!     while ((arg = va_arg(args, char *)) != NULL) {
! 	if ((t = strtok(arg, "+")) == NULL)
! 	    break;
! 	
  	unescape_url(t);
! 	av[idx] = escape_shell_cmd(r->pool, t);
! 	idx++;
! 	if (idx >= APACHE_ARG_MAX-1) break;
! 	
! 	while ((t = strtok(NULL, "+")) != NULL) {
! 	    unescape_url(t);
! 	    assert(idx < APACHE_ARG_MAX);
! 	    av[idx] = escape_shell_cmd(r->pool, t);
! 	    idx++;
! 	    if (idx >= APACHE_ARG_MAX-1) break;
! 	}
      }
-     va_end(args);
  
      av[idx] = NULL;
      return av;
--- 72,100 ----
  #define MALFORMED_MESSAGE "malformed header from script. Bad header="
  #define MALFORMED_HEADER_LENGTH_TO_SHOW 30
  
! static char **create_argv(pool *p, char *path, char *user, char *group,
!                           char *av0, const char *reqargs)
  {
      char **av;
!     char *t;
!     char *args = pstrdup(p, reqargs);
!     int idx = 0;
! 
!     av = (char **)palloc(p, APACHE_ARG_MAX * sizeof(char *));
!     
!     if (path)
!         av[idx++] = path;
!     if (user)
!         av[idx++] = user;
!     if (group)
!         av[idx++] = group;
  
!     av[idx++] = av0;
      
!     while ((idx < APACHE_ARG_MAX) && ((t = strtok(args, "+")) != NULL)) {
  	unescape_url(t);
! 	av[idx++] = escape_shell_cmd(p, t);
      }
  
      av[idx] = NULL;
      return av;
***************
*** 401,407 ****
  }
  
  #ifdef __EMX__
! char **create_argv_cmd(pool *p, char *av0, const char *args, char *path) {
      register int x,n;
      char **av;
      char *w;
--- 393,400 ----
  }
  
  #ifdef __EMX__
! static char **create_argv_cmd(pool *p, char *av0, const char *args, char *path)
! {
      register int x,n;
      char **av;
      char *w;
***************
*** 432,444 ****
  
  void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
  {
!     char *execuser;
!     core_dir_config *conf;
!     struct passwd *pw;
!     struct group *gr;
!     char *grpname;
!     
!     conf = (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
  
      /* the fd on r->server->error_log is closed, but we need somewhere to
       * put the error messages from the log_* functions. So, we use stderr,
--- 425,432 ----
  
  void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
  {
!     core_dir_config *conf =
!       (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
  
      /* the fd on r->server->error_log is closed, but we need somewhere to
       * put the error messages from the log_* functions. So, we use stderr,
***************
*** 525,531 ****
  	char *emxtemp;
              
  	/* For OS/2 place the variables in the current
! 	   enviornment then it will be inherited. This way
  	   the program will also get all of OS/2's other SETs. */
  	for (emxloop=0; ((emxtemp = env[emxloop]) != NULL); emxloop++)
  	    putenv(emxtemp);
--- 513,519 ----
  	char *emxtemp;
              
  	/* For OS/2 place the variables in the current
! 	   environment so that they will be inherited. This way
  	   the program will also get all of OS/2's other SETs. */
  	for (emxloop=0; ((emxtemp = env[emxloop]) != NULL); emxloop++)
  	    putenv(emxtemp);
***************
*** 536,580 ****
  	    execv("CMD.EXE", create_argv_cmd(r->pool, argv0, r->args, r->filename));
  	}
  	else
! 	    execv(r->filename, create_argv(r, argv0, r->args, (void *)NULL));
      }
      }
  #else
      if ( suexec_enabled &&
  	 ((r->server->server_uid != user_id) ||
  	  (r->server->server_gid != group_id) ||
! 	  (!strncmp("/~", r->uri, 2))) ) {
  
!         if (!strncmp("/~",r->uri,2)) {
!             r->uri += 2;
!             if ((pw = getpwnam (getword_nc (r->pool, &r->uri, '/'))) == NULL)
{
! 		log_unixerr("getpwnam", NULL, "invalid username", r->server);
! 		return;
  	    }
!             r->uri -= 2;
!             if ((gr = getgrgid (pw->pw_gid)) == NULL) {
! 		if ((grpname = palloc (r->pool, 16)) == NULL) 
! 		    return;
! 		else
! 		    ap_snprintf(grpname, sizeof(grpname), "%d\0", pw->pw_gid);
  	    }
!             else
! 		grpname = gr->gr_name;
! 	execuser = (char *) palloc (r->pool, (sizeof(pw->pw_name) + 1));
! 	execuser = pstrcat (r->pool, "~", pw->pw_name, NULL);
!         }
  	else {
  	    if ((pw = getpwuid (r->server->server_uid)) == NULL) {
  		log_unixerr("getpwuid", NULL, "invalid userid", r->server);
  		return;
  	    }
!             if ((gr = getgrgid (r->server->server_gid)) == NULL) {
  		log_unixerr("getgrgid", NULL, "invalid groupid", r->server);
  		return;
  	    }
! 	    execuser = (char *) palloc (r->pool, sizeof(pw->pw_name)); 
!             execuser = pw->pw_name;
!         }
    
    	if (shellcmd)
  	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env);
--- 524,579 ----
  	    execv("CMD.EXE", create_argv_cmd(r->pool, argv0, r->args, r->filename));
  	}
  	else
! 	    execv(r->filename,
! 	          create_argv(r->pool, NULL, NULL, NULL, argv0, r->args));
      }
      }
  #else
      if ( suexec_enabled &&
  	 ((r->server->server_uid != user_id) ||
  	  (r->server->server_gid != group_id) ||
! 	  (!strncmp("/~",r->uri,2))) ) {
  
! 	char *execuser, *grpname;
! 	struct passwd *pw;
! 	struct group *gr;
! 
! 	if (!strncmp("/~",r->uri,2)) {
! 	    gid_t user_gid;
! 	    char *username = pstrdup(r->pool, r->uri + 2);
! 	    int pos = ind(username, '/');
! 
! 	    if (pos >= 0) username[pos] = '\0';
! 
! 	    if ((pw = getpwnam(username)) == NULL) {
! 	        log_unixerr("getpwnam",username,"invalid username",r->server);
! 	        return;
  	    }
! 	    execuser = pstrcat(r->pool, "~", pw->pw_name, NULL);
! 	    user_gid = pw->pw_gid;
! 
! 	    if ((gr = getgrgid(user_gid)) == NULL) {
! 	        if ((grpname = palloc (r->pool, 16)) == NULL) 
! 	            return;
! 	        else
! 	            ap_snprintf(grpname, 16, "%d", user_gid);
  	    }
! 	    else
! 	        grpname = gr->gr_name;
! 	}
  	else {
  	    if ((pw = getpwuid (r->server->server_uid)) == NULL) {
  		log_unixerr("getpwuid", NULL, "invalid userid", r->server);
  		return;
  	    }
! 	    execuser = pstrdup(r->pool, pw->pw_name);
! 
! 	    if ((gr = getgrgid (r->server->server_gid)) == NULL) {
  		log_unixerr("getgrgid", NULL, "invalid groupid", r->server);
  		return;
  	    }
! 	    grpname = gr->gr_name;
! 	}
    
    	if (shellcmd)
  	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env);
***************
*** 583,591 ****
  	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env);
  
    	else {
! 	    execve(SUEXEC_BIN,
! 		   create_argv(r, SUEXEC_BIN, execuser, grpname, argv0, r->args, (void *)NULL),
! 		   env);
  	}
      }
      else {
--- 582,591 ----
  	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env);
  
    	else {
! 	    execve(SUEXEC_BIN, 
! 		   create_argv(r->pool, SUEXEC_BIN, execuser, grpname,
! 	                       argv0, r->args),
! 	           env);
  	}
      }
      else {
***************
*** 596,602 ****
  	    execle(r->filename, argv0, NULL, env);
  
  	else
! 	    execve(r->filename, create_argv(r, argv0, r->args, (void *)NULL), env);
      }
  #endif
  }
--- 596,604 ----
  	    execle(r->filename, argv0, NULL, env);
  
  	else
! 	    execve(r->filename,
! 	           create_argv(r->pool, NULL, NULL, NULL, argv0, r->args),
! 	           env);
      }
  #endif
  }

Mime
View raw message