]> granicus.if.org Git - apache/commitdiff
Add back suexec support.
authorManoj Kasichainula <manoj@apache.org>
Mon, 23 Oct 2000 15:30:57 +0000 (15:30 +0000)
committerManoj Kasichainula <manoj@apache.org>
Mon, 23 Oct 2000 15:30:57 +0000 (15:30 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86712 13f79535-47bb-0310-9956-ffa450edef68

20 files changed:
STATUS
include/ap_mpm.h
include/httpd.h
modules/aaa/config.m4
modules/filters/mod_include.c
modules/generators/mod_cgi.c
modules/generators/mod_cgid.c
modules/generators/mod_suexec.c [new file with mode: 0644]
modules/mappers/mod_rewrite.c
modules/mappers/mod_userdir.c
modules/metadata/mod_mime_magic.c
os/beos/os.c
os/bs2000/os.c
os/os2/util_os2.c
os/tpf/os.c
os/unix/Makefile.in
os/unix/unixd.c
os/unix/unixd.h
server/config.c
support/suexec.c

diff --git a/STATUS b/STATUS
index 7d61b247234904cc33c864c52b11a2600e73aa60..f3a378a4108ee67561457dc8f485e78965bf27bb 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 Apache 2.0 STATUS:
-Last modified at [$Date: 2000/10/23 14:48:06 $]
+Last modified at [$Date: 2000/10/23 15:30:44 $]
 
 Release:
 
@@ -23,10 +23,6 @@ RELEASE SHOWSTOPPERS:
     * Some buff functionality is currently missing: translation of protocol 
       data for EBCDIC machines
 
-    * suEXEC doesn't work
-        Status: Manoj has posted an patch to fix this.
-        Message-ID: <20000825024943.A17578@manojk.users.mindspring.com>
-
     * Win32: Enable the Windows MPM to honor max_requests_per_child
         Status: Bill will fix this.
 
index 174fb0365cff713d4d751dbf166adba69ea60e61..945b647d7ce8c1cb9924b09cb83683d5a3e2b704 100644 (file)
@@ -141,4 +141,23 @@ AP_DECLARE(int) ap_graceful_stop_signalled(void);
 
 AP_DECLARE(void) ap_start_shutdown(void);
 
+/**
+ * Spawn a process with privileges that another module has requested
+ * @param r The request_rec of the current request
+ * @param newproc The resulting process handle.
+ * @param progname The program to run 
+ * @param const_args the arguments to pass to the new program.  The first 
+ *                   one should be the program name.
+ * @param env The new environment apr_table_t for the new process.  This 
+ *            should be a list of NULL-terminated strings.
+ * @param attr the procattr we should use to determine how to create the new
+ *         process
+ * @param p The pool to use. 
+ */
+extern apr_status_t ap_os_create_privileged_process(const request_rec *r,
+                              apr_proc_t *newproc, const char *progname,
+                              char *const *args, char **env,
+                              apr_procattr_t *attr, apr_pool_t *p);
+
+
 #endif
index 7e0f64f0f9e53e052bc0fbeab0b0969f6a8176e9..e65f59df3721a5435678758fc2e11b0d76759ec4 100644 (file)
@@ -990,11 +990,6 @@ struct server_rec {
     /** Wildcarded names for ServerAlias servers */
     apr_array_header_t *wild_names;
 
-    /** effective user id when calling exec wrapper */
-    uid_t server_uid;
-    /** effective group id when calling exec wrapper */
-    gid_t server_gid;
-
     /** limit on size of the HTTP request line    */
     int limit_req_line;
     /** limit on size of any request header field */
index 7f56053adbd82e67bc835fcfe4bd13e67f634e8a..ae09ad7f8dd0aafe9ff45c2be15c234fbeb0d383 100644 (file)
@@ -26,6 +26,7 @@ APACHE_CHECK_STANDARD_MODULE(imap, internal imagemaps, , yes)
 APACHE_CHECK_STANDARD_MODULE(actions, Action triggering on requests, action, yes)
 APACHE_CHECK_STANDARD_MODULE(speling, correct common URL misspellings, , no)
 APACHE_CHECK_STANDARD_MODULE(userdir, mapping of user requests, , yes)
+APACHE_CHECK_STANDARD_MODULE(suexec, set uid and gid for spawned processes, , yes)
 APACHE_CHECK_STANDARD_MODULE(alias, translation of requests, , yes)
 
 APACHE_CHECK_STANDARD_MODULE(rewrite, regex URL translation, , no, [
index 60b2dae02ff9013ff3151423be5cd01e65ce6cb2..c45fa2348a6ef5a38f1be5dbd274e8386b29595a 100644 (file)
@@ -946,7 +946,7 @@ static int include_cmd(char *s, request_rec *r, ap_filter_t *next)
         build_argv_list(&argv, r, r->pool);
         argv[0] = apr_pstrdup(r->pool, s);
         procnew = apr_pcalloc(r->pool, sizeof(*procnew));
-        rc = apr_create_process(procnew, s, argv, ap_create_environment(r->pool, env), procattr, r->pool);
+        rc = ap_os_create_privileged_process(r, procnew, s, argv, ap_create_environment(r->pool, env), procattr, r->pool);
 
         if (rc != APR_SUCCESS) {
             /* Bad things happened. Everyone should have cleaned up. */
index d1429d174781fb5f9e5957d5b9e0a1f838708714..8138d4e3d270a6eb6f056b8734ac0a8adf003b68 100644 (file)
@@ -83,6 +83,7 @@
 #include "http_main.h"
 #include "http_log.h"
 #include "util_script.h"
+#include "ap_mpm.h"
 #include "http_conf_globals.h"
 #ifdef HAVE_STRING_H
 #include <string.h>
@@ -368,7 +369,7 @@ static apr_status_t run_cgi_child(apr_file_t **script_out, apr_file_t **script_i
                      "couldn't set child process attributes: %s", r->filename);
     }
     else {
-        rc = apr_create_process(procnew, command, argv, env, procattr, p);
+        rc = ap_os_create_privileged_process(r, procnew, command, argv, env, procattr, p);
     
         if (rc != APR_SUCCESS) {
             /* Bad things happened. Everyone should have cleaned up. */
@@ -437,6 +438,14 @@ static apr_status_t build_argv_list(char ***argv, request_rec *r, apr_pool_t *p)
 
 static apr_status_t build_command_line(char **cmd, request_rec *r, apr_pool_t *p)
 {
+    char *argv0;
+
+    /* Allow suexec's "/" check to succeed */
+    if ((argv0 = strrchr(r->filename, '/')) != NULL)
+        argv0++;
+    else
+        argv0 = r->filename;
+
 #ifdef WIN32
     char *quoted_filename = NULL;
     char *interpreter = NULL;
@@ -455,9 +464,9 @@ static apr_status_t build_command_line(char **cmd, request_rec *r, apr_pool_t *p
     }
 
     /*
-     * Build the command string to pass to apr_create_process()
+     * Build the command string to pass to ap_os_create_privileged_process()
      */
-    quoted_filename = apr_pstrcat(p, "\"", r->filename, "\"", NULL);
+    quoted_filename = apr_pstrcat(p, "\"", argv0, "\"", NULL);
     if (interpreter && *interpreter) {
         if (arguments && *arguments)
             *cmd = apr_pstrcat(p, interpreter, " ", quoted_filename, " ", 
@@ -472,7 +481,7 @@ static apr_status_t build_command_line(char **cmd, request_rec *r, apr_pool_t *p
         *cmd = apr_pstrcat(p, quoted_filename, NULL);
     }
 #else
-    *cmd = apr_pstrcat(p, r->filename, NULL);
+    *cmd = argv0;
 #endif
     return APR_SUCCESS;
 }
index d388bbeb56c467a28feb9d6d81c3009bf0c55c33..4cf81744afeddee8239247612af4ddbde4ceb20a 100644 (file)
@@ -213,99 +213,19 @@ static int call_exec(request_rec *r, char *argv0, char **env, int shellcmd)
      * since that is better than allowing errors to go unnoticed. 
      */
     apr_put_os_file(&r->server->error_log, &errfileno, r->pool);
-    /* TODO: reimplement suexec */
-#if 0
-    if (ap_suexec_enabled
-        && ((r->server->server_uid != ap_user_id)
-            || (r->server->server_gid != ap_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 = apr_pstrdup(r->pool, r->uri + 2);
-            char *pos = strchr(username, '/');
-
-            if (pos) {
-                *pos = '\0';
-            }
-
-            if ((pw = getpwnam(username)) == NULL) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
-                             "getpwnam: invalid username %s", username);
-                return (pid);
-            }
-            execuser = apr_pstrcat(r->pool, "~", pw->pw_name, NULL);
-            user_gid = pw->pw_gid;
-
-            if ((gr = getgrgid(user_gid)) == NULL) {
-                if ((grpname = apr_palloc(r->pool, 16)) == NULL) {
-                    return (pid);
-                }
-                else {
-                    apr_snprintf(grpname, 16, "%ld", (long) user_gid);
-                }
-            }
-            else {
-                grpname = gr->gr_name;
-            }
-        }
-        else {
-            if ((pw = getpwuid(r->server->server_uid)) == NULL) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
-                             "getpwuid: invalid userid %ld",
-                             (long) r->server->server_uid);
-                return (pid);
-            }
-            execuser = apr_pstrdup(r->pool, pw->pw_name);
-
-            if ((gr = getgrgid(r->server->server_gid)) == NULL) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
-                             "getgrgid: invalid groupid %ld",
-                             (long) r->server->server_gid);
-                return (pid);
-            }
-            grpname = gr->gr_name;
-        }
-
-        if (shellcmd) {
-            execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0,
-                   NULL, env);
-        }
-
-        else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
-            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);
-        }
+    if (shellcmd) {
+        execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
     }
-    else {
-#endif
-        if (shellcmd) {
-            execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
-        }
 
-        else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
-            execle(r->filename, argv0, NULL, env);
-        }
+    else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
+        execle(r->filename, argv0, NULL, env);
+    }
 
-        else {
-            execve(r->filename,
-                   create_argv(r->pool, NULL, NULL, NULL, argv0, r->args),
-                   env);
-        }
-#if 0
+    else {
+        execve(r->filename,
+               create_argv(r->pool, NULL, NULL, NULL, argv0, r->args),
+               env);
     }
-#endif
     return (pid);
 }
 
@@ -358,9 +278,6 @@ static void get_req(int fd, request_rec *r, char **filename, char **argv0, char
     *env = environ; 
     r->args = ap_getword(r->pool, (const char **)&data, '\n'); 
   
-    read(fd, &r->server->server_uid, sizeof(uid_t)); 
-    read(fd, &r->server->server_gid, sizeof(gid_t)); 
-
     read(fd, &i, sizeof(int)); 
      
     /* add 1, so that if i == 0, we still malloc something. */ 
@@ -438,14 +355,6 @@ static void send_req(int fd, request_rec *r, char *argv0, char **env)
         ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                      "write to cgi daemon process"); 
         }     
-    if (write(fd, &r->server->server_uid, sizeof(uid_t)) < 0) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
-                     "write to cgi daemon process"); 
-        }     
-    if (write(fd, &r->server->server_gid, sizeof(gid_t)) < 0) { 
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
-                     "write to cgi daemon process"); 
-        }     
     if (write(fd, &core_module.module_index, sizeof(int)) < 0) { 
         ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                      "write to cgi daemon process"); 
diff --git a/modules/generators/mod_suexec.c b/modules/generators/mod_suexec.c
new file mode 100644 (file)
index 0000000..bf3a70f
--- /dev/null
@@ -0,0 +1,160 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "apr_strings.h"
+#include "suexec.h"
+#include "unixd.h"
+
+module MODULE_VAR_EXPORT suexec_module;
+
+typedef struct {
+    ap_unix_identity_t ugid;
+    int active;
+} suexec_config_t;
+
+/*
+ * Create a configuration specific to this module for a server or directory
+ * location, and fill it with the default settings.
+ */
+static void *mkconfig(apr_pool_t *p)
+{
+    suexec_config_t *cfg = apr_palloc(p, sizeof(suexec_config_t));
+
+    cfg->active = 0;
+    return cfg;
+}
+
+/*
+ * Respond to a callback to create configuration record for a server or
+ * vhost environment.
+ */
+static void *create_mconfig_for_server(apr_pool_t *p, server_rec *s)
+{
+    return mkconfig(p);
+}
+
+/*
+ * Respond to a callback to create a config record for a specific directory.
+ */
+static void *create_mconfig_for_directory(apr_pool_t *p, char *dir)
+{
+    return mkconfig(p);
+}
+
+static const char *set_suexec_ugid(cmd_parms *cmd, void *mconfig,
+                                   char *uid, char *gid)
+{
+    suexec_config_t *cfg = (suexec_config_t *) mconfig;
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+
+    if (err != NULL) {
+        return err;
+    }
+    if (unixd_config.suexec_enabled) {
+        cfg->ugid.uid = ap_uname2id(uid);
+        cfg->ugid.gid = ap_gname2id(gid);
+        cfg->active = 1;
+    }
+    else {
+        fprintf(stderr,
+                "Warning: SuexecUserGroup directive requires SUEXEC wrapper.\n");
+    }
+    return NULL;
+}
+
+static ap_unix_identity_t *get_suexec_id_doer(const request_rec *r)
+{
+    suexec_config_t *cfg =
+    (suexec_config_t *) ap_get_module_config(r->per_dir_config, &suexec_module);
+
+    return cfg->active ? &cfg->ugid : NULL;
+}
+
+/*
+ * Define the directives specific to this module.  This structure is referenced
+ * later by the 'module' structure.
+ */
+static const command_rec suexec_cmds[] =
+{
+    /* XXX - Another important reason not to allow this in .htaccess is that
+     * the ap_[ug]name2id() is not thread-safe */
+    AP_INIT_TAKE2("SuexecUserGroup", set_suexec_ugid, NULL, RSRC_CONF,
+      "User and group for spawned processes"),
+    { NULL }
+};
+
+static void suexec_hooks(void)
+{
+    ap_hook_get_suexec_identity(get_suexec_id_doer,NULL,NULL,AP_HOOK_MIDDLE);
+}
+
+module MODULE_VAR_EXPORT suexec_module =
+{
+    STANDARD20_MODULE_STUFF,
+    create_mconfig_for_directory,   /* create per-dir config */
+    NULL,                       /* merge per-dir config */
+    create_mconfig_for_server,  /* server config */
+    NULL,                       /* merge server config */
+    suexec_cmds,                /* command table */
+    NULL,                       /* handlers */
+    suexec_hooks               /* register hooks */
+};
index a3084afbbc22e7d85ef0b6b5d0c281b6d2c69abf..8f515a5b81f12f8056caaafdd50a73a747155026 100644 (file)
@@ -3383,7 +3383,7 @@ static apr_status_t rewritemap_program_child(apr_pool_t *p, const char *progname
     }
     else {
         procnew = apr_pcalloc(p, sizeof(*procnew));
-        rc = apr_create_process(procnew, progname, NULL, NULL, procattr, p);
+        rc = ap_os_create_privileged_process(r, procnew, progname, NULL, NULL, procattr, p);
     
         if (rc == APR_SUCCESS) {
             apr_note_subprocess(p, procnew, kill_after_timeout);
index 79efb2b7919f76965391cebf4ece8fb0d69e81ad..37bc6480e86a4abde2b5c468c6e47201a6ab00a4 100644 (file)
@@ -96,6 +96,7 @@
 #include "httpd.h"
 #include "http_config.h"
 #include "http_request.h"
+#include "suexec.h"
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
@@ -340,6 +341,10 @@ static int translate_userdir(request_rec *r)
             */
            if (*userdirs && dname[0] == 0)
                r->finfo = statbuf;
+
+            /* For use in the get_suexec_identity phase */
+            apr_table_setn(r->notes, "mod_userdir_user", w);
+
             return OK;
         }
     }
@@ -347,11 +352,38 @@ static int translate_userdir(request_rec *r)
     return DECLINED;
 }
 
+static ap_unix_identity_t *get_suexec_id_doer(const request_rec *r)
+{
+    const char *username = apr_table_get(r->notes, "mod_userdir_user");
+    struct passwd *pw = NULL;
+    ap_unix_identity_t *ugid = NULL;
+
+    if (username == NULL) {
+        return NULL;
+    }
+
+    /* XXX - NOT thread-safe! Need APR version of this function */
+    if ((pw = getpwnam(username)) == NULL) {
+        /* This should never happen. */
+        return NULL;
+    }
+    
+    if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t *))) == NULL) {
+        return NULL;
+    }
+
+    ugid->uid = pw->pw_uid;
+    ugid->gid = pw->pw_gid;
+    
+    return ugid;
+}
+
 static void register_hooks(void)
 {
     static const char * const aszSucc[]={ "mod_alias.c",NULL };
 
     ap_hook_translate_name(translate_userdir,NULL,aszSucc,AP_HOOK_MIDDLE);
+    ap_hook_get_suexec_identity(get_suexec_id_doer,NULL,NULL,AP_HOOK_MIDDLE);
 }
 
 module userdir_module = {
index 66bb811370a243a010bb0e7bae1b4c50fe2f9be3..2b1d02c4db76f46ba9f19bd7baab0f9b656cb22d 100644 (file)
@@ -2172,7 +2172,7 @@ static int uncompress_child(struct uncompress_parms *parm, apr_pool_t *cntxt,
         }
 
         procnew = apr_pcalloc(child_context, sizeof(*procnew));
-        rc = apr_create_process(procnew, compr[parm->method].argv[0],
+        rc = ap_os_create_privileged_rrocess(r, procnew, compr[parm->method].argv[0],
                                new_argv, env, procattr, child_context);
 
         if (rc != APR_SUCCESS) {
index 9b2f647dcfef291d08bb5214c3a99e12e1452525..b040432a1f90c33d64ca3902ae4e87812923e3e0 100644 (file)
 
 #include "ap_config.h"
 #include "os.h"
+#include "httpd.h"
 
 int ap_os_is_path_absolute(const char *file)
 {
   return file[0] == '/';
 }
+
+AP_DECLARE(apr_status_t) ap_os_create_privileged_process(const request_rec *r,
+                              apr_proc_t *newproc, const char *progname,
+                              char *const *args, char **env,
+                              apr_procattr_t *attr, apr_pool_t *p)
+{
+    return apr_create_process(newproc, progname, args, env, attr, p);
+}
index 2ad3a4966968423dce6ae86c2e42809b562be5ac..72f76640570cd8b1afe4a27638ee909a3bb971cd 100644 (file)
@@ -64,6 +64,7 @@
 #include "httpd.h"
 #include "http_core.h"
 #include "os.h"
+#include "httpd.h"
 
 /* Check the Content-Type to decide if conversion is needed */
 int ap_checkconv(struct request_rec *r)
@@ -102,3 +103,11 @@ int ap_checkconv(struct request_rec *r)
     return convert_to_ascii;
 }
 
+AP_DECLARE(apr_status_t) ap_os_create_privileged_process(const request_rec *r,
+                              apr_proc_t *newproc, const char *progname,
+                              char *const *args, char **env,
+                              apr_procattr_t *attr, apr_pool_t *p)
+{
+    return apr_create_process(newproc, progname, args, env, attr, p);
+}
+
index 8d0a5014b5bdbb65e1fae7d1ffae147dab8484e0..637eca4642eea038d8b8f01ddfdb060674044828 100644 (file)
@@ -170,3 +170,11 @@ char *ap_os_canonical_filename(apr_pool_t *pPool, const char *szFile)
     strlwr(szCanonicalFile);
     return szCanonicalFile;
 }
+
+AP_DECLARE(apr_status_t) ap_os_create_privileged_process(const request_rec *r,
+                              apr_proc_t *newproc, const char *progname,
+                              char *const *args, char **env,
+                              apr_procattr_t *attr, apr_pool_t *p)
+{
+    return apr_create_process(newproc, progname, args, env, attr, p);
+}
index 3833d9957b1b09335b3a692aa10edbf51e509e2a..a8af4bdaea5ac8077d78e273b146f8573f665ad3 100644 (file)
@@ -412,4 +412,10 @@ void os_tpf_child(APACHE_TPF_INPUT *input_parms) {
     ap_restart_time = input_parms->restart_time;
 }
 
-
+AP_DECLARE(apr_status_t) ap_os_create_privileged_process(const request_rec *r,
+                              apr_proc_t *newproc, const char *progname,
+                              char *const *args, char **env,
+                              apr_procattr_t *attr, apr_pool_t *p)
+{
+    return apr_create_process(newproc, progname, args, env, attr, p);
+}
index 63596967db125f6ceb5798cf56a04b7465f5309c..521f2984640f527dd0505c105341b3c54c27242e 100644 (file)
@@ -1,5 +1,5 @@
 
 LTLIBRARY_NAME    = libos.la
-LTLIBRARY_SOURCES = os-inline.c unixd.c
+LTLIBRARY_SOURCES = os-inline.c unixd.c suexec.c
 
 include $(top_srcdir)/build/ltlib.mk
index caa87fe45de6070ad50a3fe30337f8f2b6de09fa..d70b3fd5ccb826db455bbd38067d5e09f2a6bba8 100644 (file)
@@ -68,6 +68,8 @@
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif
+/* XXX */
+#include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -214,9 +216,22 @@ const char *unixd_set_group(cmd_parms *cmd, void *dummy, const char *arg)
 
 void unixd_pre_config(apr_pool_t *ptemp)
 {
+    apr_finfo_t wrapper;
+
     unixd_config.user_name = DEFAULT_USER;
     unixd_config.user_id = ap_uname2id(DEFAULT_USER);
     unixd_config.group_id = ap_gname2id(DEFAULT_GROUP);
+
+    /* Check for suexec */
+    unixd_config.suexec_enabled = 0;
+    if ((apr_stat(&wrapper, SUEXEC_BIN, ptemp)) != APR_SUCCESS) {
+        return;
+    }
+
+    /* XXX - apr_stat is incapable of checking suid bits (grumble) */
+    /* if ((wrapper.filetype & S_ISUID) && wrapper.user == 0) { */
+        unixd_config.suexec_enabled = 1;
+    /* } */
 }
 
 #ifdef NEED_AP_SYS_SIGLIST
index 0fdfcc271584ed1f19d7910b9f406fd045f9f369..d8ac46f87bae6e8a57f6136e41bcadff8f511ca3 100644 (file)
@@ -60,6 +60,7 @@
 #define UNIXD_H
 
 #include "httpd.h"
+#include "http_config.h"
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif
@@ -80,6 +81,7 @@ typedef struct {
     const char *user_name;
     uid_t user_id;
     gid_t group_id;
+    int suexec_enabled;
 } unixd_config_rec;
 extern unixd_config_rec unixd_config;
 
index cb6d8ef08132d33427faaccfbee6b0698c56c9cd..8f148cc49b4f7a2b2255f4965e108cf2503938a5 100644 (file)
@@ -1563,11 +1563,6 @@ AP_CORE_DECLARE(const char *) ap_init_virtual_host(apr_pool_t *p, const char *ho
     s->module_config = create_empty_config(p);
     s->lookup_defaults = ap_create_per_dir_config(p);
 
-#if 0
-    s->server_uid = ap_user_id;
-    s->server_gid = ap_group_id;
-#endif
-
     s->limit_req_line = main_server->limit_req_line;
     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
     s->limit_req_fields = main_server->limit_req_fields;
index 84c17d7b6191a51fbd3e0ded67de0eeab4d76c1d..b1d24e6d9b094c5982662da8e0bb9f8999185ba5 100644 (file)
 
 #include "suexec.h"
 
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#if HAVE_GRP_H
+#include <grp.h>
+#endif
+
 /*
  ***********************************************************************
  * There is no initgroups() in QNX, so I believe this is safe :-)
@@ -319,9 +327,17 @@ int main(int argc, char *argv[])
     /*
      * Error out if the target username is invalid.
      */
-    if ((pw = getpwnam(target_uname)) == NULL) {
-       log_err("invalid target user name: (%s)\n", target_uname);
-       exit(105);
+    if (strspn(target_uname, "1234567890") != strlen(target_uname)) {
+        if ((pw = getpwnam(target_uname)) == NULL) {
+           log_err("invalid target user name: (%s)\n", target_uname);
+           exit(105);
+        }
+    }
+    else {
+        if ((pw = getpwuid(atoi(target_uname))) == NULL) {
+            log_err("invalud target user id: (%s)\n", target_uname);
+            exit(121);
+        }
     }
 
     /*