httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Randy Terbush <ra...@zyzzyva.com>
Subject Re: suEXEC, son of suCGI.
Date Mon, 29 Jul 1996 13:30:01 GMT

> Well, Randy and I are at a mid-point in the development of suEXEC.  So, we
> thought we'd submit it for your perusal.  I've attached suexec.c and
> suexec.patch to this letter.  That patch should apply cleanly to the
> current dev version.  If it doesn't you'll have to speak with Randy about
> that.  8)

Actually, this patch was made prior to several other patches this weekend.
I'll include a copy made against this mornings tree. If anyone would like
a non-MIME version of suEXEC.c, let me know.

> I'll finish up by giving you a quick tour of how suEXEC works...
> 
> 1.  At startup (and at SIGHUP?), the server checks for the suexec binary,
> as DEFINEd at compilation.  If it exists, is owned by root, and is
> setuid'd, it enables suexec.  It any of these checks fail, it disables
> suexec. 

Actually, I purposely placed the call to init_suexec() before child_main()
which if I understand correctly will prevent the server from being SIGHUP'd
to detect a newly installed setuid wrapper.

> To close, here is what I see on the TODO list to finish this up.  Any
> additions, deletions, code patches, et cetera are greatly appreciated.
> 8)
> 	* paranoia() routine within server

Regarding additional checks in the server, I'm not sure that execution
with the wrapper would benefit much from additional checks. I do think
though that other checks for non-setuid behavior could be justified.
RST convinced me to take these out of the "centralized exec" changes,
and I have seen the benefits.

Index: src/http_conf_globals.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_conf_globals.h,v
retrieving revision 1.2
diff -c -r1.2 http_conf_globals.h
*** http_conf_globals.h	1996/02/22 11:46:43	1.2
--- http_conf_globals.h	1996/07/29 13:27:06
***************
*** 67,72 ****
--- 67,73 ----
  extern int daemons_min_free;
  extern int daemons_max_free;
  extern int daemons_limit;
+ extern int suexec_enabled;
  
  extern char *pid_fname;
  extern char *scoreboard_fname;
Index: src/http_core.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_core.c,v
retrieving revision 1.26
diff -c -r1.26 http_core.c
*** http_core.c	1996/07/28 19:35:49	1.26
--- http_core.c	1996/07/29 13:27:18
***************
*** 708,714 ****
  
  char *end_virthost_magic = "</Virtualhost> out of place";
  
! char *end_virtualhost_section (cmd_parms *cmd, void *dummy) {
      return end_virthost_magic;
  }
  
--- 708,721 ----
  
  char *end_virthost_magic = "</Virtualhost> out of place";
  
! char *end_virtualhost_section (cmd_parms *cmd, void *dummy)
! {
!     if (!cmd->server->server_uid)
! 	cmd->server->server_uid = user_id;
! 
!     if (!cmd->server->server_gid)
! 	cmd->server->server_gid = group_id;
!     
      return end_virthost_magic;
  }
  
***************
*** 766,779 ****
      return NULL;
  }
  
! char *set_user (cmd_parms *cmd, void *dummy, char *arg) {
!     user_name = pstrdup (cmd->pool, arg);
!     user_id = uname2id (user_name);
      return NULL;
  }
  
! char *set_group (cmd_parms *cmd, void *dummy, char *arg) {
!     group_id = gname2id(arg);
      return NULL;
  }
  
--- 773,805 ----
      return NULL;
  }
  
! char *set_user (cmd_parms *cmd, void *dummy, char *arg)
! {
!     uid_t uid;
!     
!     uid = uname2id (arg);
!     
!     if (!cmd->server->is_virtual) {
! 	user_name = pstrdup (cmd->pool, arg);
! 	user_id = uid;
!     }
!     
!     cmd->server->server_uid = uid;
! 
      return NULL;
  }
  
! char *set_group (cmd_parms *cmd, void *dummy, char *arg)
! {
!     gid_t gid;
!     
!     gid = gname2id(arg);
! 
!     if (!cmd->server->is_virtual)
! 	group_id = gid;
!     
!     cmd->server->server_gid = gid;
! 
      return NULL;
  }
  
***************
*** 1017,1024 ****
  { "ServerType", server_type, NULL, RSRC_CONF, TAKE1,"'inetd' or 'standalone'"},
  { "Port", server_port, NULL, RSRC_CONF, TAKE1, "a TCP port number"},
  { "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, FLAG, NULL },
! { "User", set_user, NULL, RSRC_CONF, TAKE1, "a username"},
! { "Group", set_group, NULL, RSRC_CONF, TAKE1, "a group name"},
  { "ServerAdmin", set_server_string_slot,
    (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
    "The email address of the server administrator" },
--- 1043,1050 ----
  { "ServerType", server_type, NULL, RSRC_CONF, TAKE1,"'inetd' or 'standalone'"},
  { "Port", server_port, NULL, RSRC_CONF, TAKE1, "a TCP port number"},
  { "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, FLAG, NULL },
! { "User", set_user, NULL, RSRC_CONF, TAKE1, "effective user id for this server"},
! { "Group", set_group, NULL, RSRC_CONF, TAKE1, "effective group id for this server"},
  { "ServerAdmin", set_server_string_slot,
    (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
    "The email address of the server administrator" },
Index: src/http_main.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.c,v
retrieving revision 1.56
diff -c -r1.56 http_main.c
*** http_main.c	1996/07/28 00:03:15	1.56
--- http_main.c	1996/07/29 13:27:34
***************
*** 89,94 ****
--- 89,95 ----
  #include "scoreboard.h"
  #include <setjmp.h>
  #include <assert.h>
+ #include <sys/stat.h>
  #ifdef HAVE_SHMGET
  #include <sys/types.h>
  #include <sys/ipc.h>
***************
*** 132,137 ****
--- 133,139 ----
  int daemons_max_free;
  int daemons_limit;
  time_t restart_time;
+ int suexec_enabled = 0;
  
  char server_root[MAX_STRING_LEN];
  char server_confname[MAX_STRING_LEN];
***************
*** 1122,1127 ****
--- 1124,1145 ----
    }
  }
  
+ /* check to see if we have the 'suexec' setuid wrapper installed */
+ int init_suexec ()
+ {
+     struct stat wrapper;
+     
+     if ((stat(SUEXEC_BIN, &wrapper)) != 0)
+       return (suexec_enabled);
+     
+     if ((wrapper.st_mode & S_ISUID) && wrapper.st_uid == 0) {
+       suexec_enabled = 1;
+       fprintf(stderr, "Configuring Apache for use with suexec wrapper.\n");
+     }
+ 
+     return (suexec_enabled);
+ }
+ 
  static int is_graceful;
  static int generation;
  
***************
*** 1821,1826 ****
--- 1839,1845 ----
      setup_prelinked_modules();
      
      server_conf = read_config (pconf, ptrans, server_confname);
+     suexec_enabled = init_suexec();
      
      if(standalone) {
          clear_pool (pconf);	/* standalone_main rereads... */
Index: src/httpd.h
===================================================================
RCS file: /export/home/cvs/apache/src/httpd.h,v
retrieving revision 1.41
diff -c -r1.41 httpd.h
*** httpd.h	1996/07/29 02:32:33	1.41
--- httpd.h	1996/07/29 13:27:41
***************
*** 169,174 ****
--- 169,177 ----
  #define SHELL_PATH "/bin/sh"
  #endif
  
+ /* The path to the suExec wrapper */
+ #define SUEXEC_BIN "/www/sbin/suexec"
+ 
  /* The default string lengths */
  #define MAX_STRING_LEN HUGE_STRING_LEN
  #define HUGE_STRING_LEN 8192
***************
*** 470,515 ****
  
  struct server_rec {
  
!   server_rec *next;
    
!   /* Full locations of server config info */
    
!   char *srm_confname;
!   char *access_confname;
    
!   /* Contact information */
    
!   char *server_admin;
!   char *server_hostname;
!   short port;                    /* for redirects, etc. */
    
!   /* Log files --- note that transfer log is now in the modules... */
    
!   char *error_fname;
!   FILE *error_log;
    
!   /* Module-specific configuration for server, and defaults... */
  
!   int is_virtual;               /* true if this is the virtual server */
!   void *module_config;		/* Config vector containing pointers to
  				 * modules' per-server config structures.
  				 */
!   void *lookup_defaults;	/* MIME type info, etc., before we start
  				 * checking per-directory info.
  				 */
!   /* Transaction handling */
  
!   struct in_addr host_addr;	/* The bound address, for this server */
!   short host_port;              /* The bound port, for this server */
!   int timeout;			/* Timeout, in seconds, before we give up */
!   int keep_alive_timeout;	/* Seconds we'll wait for another request */
!   int keep_alive;		/* Maximum requests per connection */
  
!   char *path;			/* Pathname for ServerPath */
!   int pathlen;			/* Length of path */
  
!   char *names;			/* Wildcarded names for HostAlias servers */
!   char *virthost;		/* The name given in <VirtualHost> */
  };
  
  /* These are more like real hosts than virtual hosts */
--- 473,521 ----
  
  struct server_rec {
  
!     server_rec *next;
    
!     /* Full locations of server config info */
    
!     char *srm_confname;
!     char *access_confname;
    
!     /* Contact information */
    
!     char *server_admin;
!     char *server_hostname;
!     short port;                    /* for redirects, etc. */
    
!     /* Log files --- note that transfer log is now in the modules... */
    
!     char *error_fname;
!     FILE *error_log;
    
!     /* Module-specific configuration for server, and defaults... */
  
!     int is_virtual;             /* true if this is the virtual server */
!     void *module_config;	/* Config vector containing pointers to
  				 * modules' per-server config structures.
  				 */
!     void *lookup_defaults;	/* MIME type info, etc., before we start
  				 * checking per-directory info.
  				 */
!     /* Transaction handling */
! 
!     struct in_addr host_addr;	/* The bound address, for this server */
!     short host_port;            /* The bound port, for this server */
!     int timeout;		/* Timeout, in seconds, before we give up */
!     int keep_alive_timeout;	/* Seconds we'll wait for another request */
!     int keep_alive;		/* Maximum requests per connection */
  
!     char *path;			/* Pathname for ServerPath */
!     int pathlen;		/* Length of path */
  
!     char *names;		/* Wildcarded names for HostAlias servers */
!     char *virthost;		/* The name given in <VirtualHost> */
  
!     uid_t server_uid;		/* effective user id when calling exec wrapper */
!     gid_t server_gid;		/* effective group id when calling exec wrapper */
  };
  
  /* These are more like real hosts than virtual hosts */
Index: src/util_script.c
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.c,v
retrieving revision 1.15
diff -c -r1.15 util_script.c
*** util_script.c	1996/07/27 04:24:43	1.15
--- util_script.c	1996/07/29 13:27:47
***************
*** 369,375 ****
--- 369,379 ----
  
  void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
  {
+     char *execuser;
      core_dir_config *conf;
+     struct passwd *pw;
+     struct group *gr;
+     
  
      conf = (core_dir_config *)pcalloc(r->pool, sizeof(core_dir_config));
      
***************
*** 439,453 ****
  	    execv(r->filename, create_argv(r->pool, argv0, r->args));
      }
  #else
!     
!     if (shellcmd) 
! 	execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
  
!     else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
! 	execle(r->filename, argv0, NULL, env);
  
!     else
! 	execve(r->filename, create_argv(r->pool, argv0, r->args), env);
!     
  #endif
  }
--- 443,496 ----
  	    execv(r->filename, create_argv(r->pool, argv0, r->args));
      }
  #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 (r->pool, &r->uri, '/'))) == NULL) {
! 		log_unixerr("getpwnam", NULL, "invalid username", r->server);
! 		return;
! 	    }
!             r->uri -= 2;
!             gr = getgrgid (pw->pw_gid);
!             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, gr->gr_name, argv0, NULL, env);
  
!   	else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
! 	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, gr->gr_name, argv0, NULL, env);
!   
!   	else
! 	    execle(SUEXEC_BIN, SUEXEC_BIN, execuser, gr->gr_name,
!   		   create_argv(r->pool, argv0, r->args), NULL, env);
!     }
!     else {
! 	if (shellcmd) 
! 	    execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
! 	
! 	else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
! 	    execle(r->filename, argv0, NULL, env);
! 
! 	else
! 	    execve(r->filename, create_argv(r->pool, argv0, r->args), env);
!     }
  #endif
  }




Mime
View raw message