>Number: 1905 >Category: suexec >Synopsis: Allow modules to set user:group for execution. >Confidential: no >Severity: non-critical >Priority: medium >Responsible: apache >State: open >Class: change-request >Submitter-Id: apache >Arrival-Date: Mon Mar 2 15:40:00 PST 1998 >Last-Modified: >Originator: [EMAIL PROTECTED] >Organization: apache >Release: 1.3b5 >Environment: SunOS cave 5.6 Generic sun4u sparc SUNW,Ultra-2 >Description: Rather than patch the core to provide finer control over suid execution (PR 1769), why not allow modules to control by whom programs are run?
The included patch should do just that, looking for information in suexec_module request_config data. This could have gone in the notes table, but I wanted to pass the uid/gid. Packing and unpacking numbers into notes would have felt like more of a kludge than having an empty suexec_module (well, ok, I didn't think about it until after I wrote it), but it might be a good idea. Also, the default behavior is unchanged. I've tested this with a (not included) module that sends the username/groupname of the cgi script (or including file for exec cmds) to suexec. It seems to work with my modified suexec (which logs to syslog & uses slightly weaker restrictions). BTW, dealing with XBitHack and ScriptAlias is a pain. My module acts as a handler for CGI & shtml types to avoid being called on every access. I had to snarf the code from mod_cgi and mod_include. Not pretty. Some modules may want to export a few functions, perhaps with the modulename prepended. In case the patch doesn't come through, it'll be at http://www.cise.ufl.edu/~ejr/suexec_module.patch . It's just a cvs diff -u, so it won't apply perfectly from the top level. Jason >How-To-Repeat: >Fix: Index: apache-1.3-code/include/suexec_module.h diff -u /dev/null apache-1.3-code/include/suexec_module.h:1.1 --- /dev/null Mon Mar 2 17:26:27 1998 +++ apache-1.3-code/include/suexec_module.h Mon Mar 2 13:51:41 1998 @@ -0,0 +1,9 @@ +typedef struct { + char *username; + uid_t uid; + char *groupname; + gid_t gid; + int paranoia; /* if not 1, a notice will be issued */ +} suexec_req_data; + +extern module suexec_module; Index: apache-1.3-code/main/Makefile.tmpl diff -u apache-1.3-code/main/Makefile.tmpl:1.1.1.1 apache-1.3-code/main/Makefile.tmpl:1.2 --- apache-1.3-code/main/Makefile.tmpl:1.1.1.1 Mon Mar 2 10:42:41 1998 +++ apache-1.3-code/main/Makefile.tmpl Mon Mar 2 13:52:50 1998 @@ -12,7 +12,7 @@ OBJS= alloc.o http_main.o http_core.o http_config.o http_request.o \ http_log.o http_protocol.o rfc1413.o util.o util_script.o buff.o \ md5c.o util_md5.o explain.o http_bprintf.o util_date.o \ - fnmatch.o http_vhost.o + fnmatch.o http_vhost.o suexec_module.o .c.o: $(CC) -c $(INCLUDES) $(CFLAGS) $(SPACER) $< Index: apache-1.3-code/main/suexec_module.c diff -u /dev/null apache-1.3-code/main/suexec_module.c:1.1 --- /dev/null Mon Mar 2 17:26:28 1998 +++ apache-1.3-code/main/suexec_module.c Mon Mar 2 13:51:54 1998 @@ -0,0 +1,30 @@ +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_conf_globals.h" +#include "suexec_module.h" + +module suexec_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command table */ + NULL, /* handlers */ + NULL, /* translate_handler */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* pre-run fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post_read_request */ +}; Index: apache-1.3-code/main/util_script.c diff -u apache-1.3-code/main/util_script.c:1.1.1.1 apache-1.3-code/main/util_script.c:1.2 --- apache-1.3-code/main/util_script.c:1.1.1.1 Mon Mar 2 10:42:43 1998 +++ apache-1.3-code/main/util_script.c Mon Mar 2 13:52:02 1998 @@ -62,6 +62,7 @@ #include "http_request.h" /* for sub_req_lookup_uri() */ #include "util_script.h" #include "util_date.h" /* For parseHTTPdate() */ +#include "suexec_module.h" /* * Various utility functions which are common to a whole lot of @@ -794,10 +795,40 @@ return (pid); } #else - if (suexec_enabled && - ((r->server->server_uid != user_id) || - (r->server->server_gid != group_id) || - (!strncmp("/~", r->uri, 2)))) { + if (suexec_enabled) { + suexec_req_data *req_data = + (suexec_req_data *) get_module_config(r->request_config, + &suexec_module); + + if (NULL != req_data) { + if (1 != req_data->paranoia) { + aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r->server, + "call_exec: %s:%s (set non-standard) executing " + "%s", req_data->username, req_data->groupname, + argv0); + } + + if ((user_id != req_data->uid) || (group_id != req_data->gid)) { + if (shellcmd) { + execle(SUEXEC_BIN, SUEXEC_BIN, req_data->username, + req_data->groupname, argv0, NULL, env); + } + else if ((!r->args) || (!r->args[0]) || (ind(r->args, '=') >= 0)) { + execle(SUEXEC_BIN, SUEXEC_BIN, req_data->username, + req_data->groupname, argv0, NULL, env); + } + else { + execve(SUEXEC_BIN, + create_argv(r->pool, SUEXEC_BIN, req_data->username, + req_data->groupname, + argv0, r->args), + env); + } + } + } + else if ((r->server->server_uid != user_id) || + (r->server->server_gid != group_id) || + (!strncmp("/~", r->uri, 2))) { char *execuser, *grpname; struct passwd *pw; @@ -858,6 +889,7 @@ argv0, r->args), env); } + } } else { if (shellcmd) %0 >Audit-Trail: >Unformatted: [In order for any reply to be added to the PR database, ] [you need to include <[EMAIL PROTECTED]> in the Cc line ] [and leave the subject line UNCHANGED. This is not done] [automatically because of the potential for mail loops. ]
