randy 96/08/02 13:39:20
Modified: src CHANGES http_conf_globals.h http_core.c http_main.c httpd.h util_script.c Log: Set Userid/Groupid execution of CGI based on User/Group directives or UserDir owner via ~user mapping. Reviewed by: Robert Thau, Jason Dour Revision Changes Path 1.47 +7 -1 apache/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache/src/CHANGES,v retrieving revision 1.46 retrieving revision 1.47 diff -C3 -r1.46 -r1.47 *** CHANGES 1996/07/29 22:51:59 1.46 --- CHANGES 1996/08/02 20:39:09 1.47 *************** *** 1,5 **** --- 1,11 ---- Changes with Apache 1.2b1: + *) Add setuid/gid execution via setuid wrapper + Apache can now execute CGI scripts as the User/Group of the + virtualhost, or as the owner of the UserDir through ~user. + The wrapper program (suexec) is detected and configured at + startup. [Randy Terbush, Jason Dour] + *) Supplemental POSIX regex package included in source for those platforms that require/want it. We start needing POSIX/regex... *************** *** 16,22 **** changed #tmpXXXX to tmpXXXX in temp file template, for broken link/unlink changed Expire to Expires in cache_update() added appropriate #defines for Next compile ! added $Id: CHANGES,v 1.46 1996/07/29 22:51:59 jim Exp $ for RCS/CVS [Chuck Murcko] *) Fix ErrorDocument handling. When ErrorDocument failed it used to display filename instead of error message. [Paul Sutton] --- 22,28 ---- changed #tmpXXXX to tmpXXXX in temp file template, for broken link/unlink changed Expire to Expires in cache_update() added appropriate #defines for Next compile ! added $Id: CHANGES,v 1.47 1996/08/02 20:39:09 randy Exp $ for RCS/CVS [Chuck Murcko] *) Fix ErrorDocument handling. When ErrorDocument failed it used to display filename instead of error message. [Paul Sutton] 1.3 +1 -0 apache/src/http_conf_globals.h Index: http_conf_globals.h =================================================================== RCS file: /export/home/cvs/apache/src/http_conf_globals.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C3 -r1.2 -r1.3 *** http_conf_globals.h 1996/02/22 11:46:43 1.2 --- http_conf_globals.h 1996/08/02 20:39:11 1.3 *************** *** 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; 1.28 +31 -8 apache/src/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache/src/http_core.c,v retrieving revision 1.27 retrieving revision 1.28 diff -C3 -r1.27 -r1.28 *** http_core.c 1996/07/29 18:09:13 1.27 --- http_core.c 1996/08/02 20:39:13 1.28 *************** *** 709,715 **** char *end_virthost_magic = "</Virtualhost> out of place"; ! char *end_virtualhost_section (cmd_parms *cmd, void *dummy) { return end_virthost_magic; } --- 709,716 ---- char *end_virthost_magic = "</Virtualhost> out of place"; ! char *end_virtualhost_section (cmd_parms *cmd, void *dummy) ! { return end_virthost_magic; } *************** *** 738,743 **** --- 739,747 ---- if (s->access_confname) process_resource_config (s, s->access_confname, p, ptemp); + s->server_uid = user_id; + s->server_gid = group_id; + if (errmsg == end_virthost_magic) return NULL; return errmsg; } *************** *** 767,780 **** 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; } --- 771,803 ---- 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; } *************** *** 1018,1025 **** { "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" }, --- 1041,1048 ---- { "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" }, 1.57 +19 -0 apache/src/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apache/src/http_main.c,v retrieving revision 1.56 retrieving revision 1.57 diff -C3 -r1.56 -r1.57 *** http_main.c 1996/07/28 00:03:15 1.56 --- http_main.c 1996/08/02 20:39:14 1.57 *************** *** 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... */ 1.42 +31 -25 apache/src/httpd.h Index: httpd.h =================================================================== RCS file: /export/home/cvs/apache/src/httpd.h,v retrieving revision 1.41 retrieving revision 1.42 diff -C3 -r1.41 -r1.42 *** httpd.h 1996/07/29 02:32:33 1.41 --- httpd.h 1996/08/02 20:39:15 1.42 *************** *** 169,174 **** --- 169,177 ---- #define SHELL_PATH "/bin/sh" #endif + /* The path to the suExec wrapper */ + #define SUEXEC_BIN "/usr/local/etc/httpd/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 */ 1.16 +51 -8 apache/src/util_script.c Index: util_script.c =================================================================== RCS file: /export/home/cvs/apache/src/util_script.c,v retrieving revision 1.15 retrieving revision 1.16 diff -C3 -r1.15 -r1.16 *** util_script.c 1996/07/27 04:24:43 1.15 --- util_script.c 1996/08/02 20:39:16 1.16 *************** *** 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 }