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
}