You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Henning P. Schmiedehausen" <ma...@hometree.net> on 2001/06/19 11:29:46 UTC

[PATCH] Apache-1.3 - factoring out suexec handling

[ 3rd try. Hope this one goes through. :-( ]

Hi,

the attached patch scratches an itch I have for quite a while. I have
a box which has two Apache installations running from the same
binaries. One should use the suexec wrapper, the other shouldn't. This
was at the moment only possible with major hussle, because the suexec
handling is not controlled by a config option but by the existence (or
non-existence) of the suexec binary.

This patch moves the suexec-detection into a separate source file; I
also changed the check in all available modules from directly asking
the ap_suexec_enable variable to a call to ap_get_suexec(). 3rd party
modules can still use the ap_suexec_enabled variable to track the
state.

If you add this patch you will notice also a new module which is
always present in the server, http_suexec.c, this contains a new
control switch and is for factoring out from http_core (I considered
keeping it in there but I didn't want to clutter the file more).

There is now a new global config option (this is server global for all
running virtual hosts. I was thinking about moving it into the virtual
hosts but I didn't want to change the behaviour of the suexec related 
modules. 

If you put nothing or

suexec	on

into the config file, then the behaviour is "as is", this is, if a
wrapper is present, then it is used, if no wrapper is present, then
the normal exec()'ing is used.

If you put 

suexec    off

into the config file, then no matter, whether a wrapper is present or not,
the wrapper is ignored and normal exec()'ing is used.

Here is the patch, it is against 1.3.20 but it also applies (with some
offsets) to 1.3_20010617101200, which seems to be the latest CVS
snapshot.

Comments and criticsism welcome, I use it on my box (RH Linux 6.2,
Kernel 2.2) with success.

	Regards
		Henning

diff -Nurb --exclude=*~ apache_1.3.20/src/Configure apache_1.3.20.p/src/Configure
--- apache_1.3.20/src/Configure	Thu May 10 16:04:16 2001
+++ apache_1.3.20.p/src/Configure	Sat Jun 16 19:47:50 2001
@@ -1953,7 +1953,9 @@
 $CAT > $awkfile <<'EOFM'
     BEGIN {
 	modules[n++] = "core"
+	modules[n++] = "suexec"
 	pmodules[pn++] = "core"
+	pmodules[pn++] = "suexec"
     } 
     /^Module/ { modules[n++] = $2 ; pmodules[pn++] = $2 } 
     /^%Module/ { pmodules[pn++] = $2 } 
diff -Nurb --exclude=*~ apache_1.3.20/src/main/Makefile.tmpl apache_1.3.20.p/src/main/Makefile.tmpl
--- apache_1.3.20/src/main/Makefile.tmpl	Fri Jun 23 01:22:27 2000
+++ apache_1.3.20.p/src/main/Makefile.tmpl	Sat Jun 16 19:22:33 2001
@@ -8,7 +8,7 @@
 HEADERS= test_char.h uri_delims.h 
 
 OBJS= alloc.o buff.o \
-      http_config.o http_core.o http_log.o \
+      http_config.o http_core.o http_log.o http_suexec.o \
       http_main.o http_protocol.o http_request.o http_vhost.o \
       util.o util_date.o util_script.o util_uri.o util_md5.o \
       rfc1413.o
@@ -124,6 +124,7 @@
  $(INCDIR)/http_protocol.h $(INCDIR)/http_conf_globals.h \
  $(INCDIR)/http_log.h $(INCDIR)/http_main.h $(INCDIR)/scoreboard.h \
  $(INCDIR)/fnmatch.h
+http_suexec.o: http_suexec.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h
 http_vhost.o: http_vhost.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
  $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
  $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_alloc.h \
diff -Nurb --exclude=*~ apache_1.3.20/src/main/http_config.c apache_1.3.20.p/src/main/http_config.c
--- apache_1.3.20/src/main/http_config.c	Wed Jan 24 03:11:09 2001
+++ apache_1.3.20.p/src/main/http_config.c	Sat Jun 16 19:50:16 2001
@@ -781,6 +781,9 @@
 
     /* This is required; so we add it always.  */
     ap_add_named_module("http_core.c");
+	/* So I could factor out most of the suexec stuff
+	 * into its own module -- hps */
+    ap_add_named_module("http_suexec.c");
 }
 
 /*****************************************************************
@@ -1745,10 +1748,5 @@
     for (n = 0; ap_loaded_modules[n]; ++n) {
 	printf("  %s\n", ap_loaded_modules[n]->name);
     }
-#if !defined(WIN32) && !defined(NETWARE)
-    printf("suexec: %s\n",
-	   ap_suexec_enabled
-	       ? "enabled; valid wrapper " SUEXEC_BIN
-	       : "disabled; invalid wrapper " SUEXEC_BIN);
-#endif
+    display_suexec_status();
 }
diff -Nurb --exclude=*~ apache_1.3.20/src/main/http_core.c apache_1.3.20.p/src/main/http_core.c
--- apache_1.3.20/src/main/http_core.c	Fri Mar  9 11:10:25 2001
+++ apache_1.3.20.p/src/main/http_core.c	Sat Jun 16 18:47:21 2001
@@ -2038,14 +2038,14 @@
 	cmd->server->server_uid = ap_user_id = ap_uname2id(arg);
     }
     else {
-        if (ap_suexec_enabled) {
+        if (ap_get_suexec()) {
 	    cmd->server->server_uid = ap_uname2id(arg);
 	}
 	else {
 	    cmd->server->server_uid = ap_user_id;
 	    fprintf(stderr,
 		    "Warning: User directive in <VirtualHost> "
-		    "requires SUEXEC wrapper.\n");
+		    "requires SUEXEC wrapper present and enabled.\n");
 	}
     }
 #if !defined (BIG_SECURITY_HOLE) && !defined (OS2)
@@ -2079,14 +2079,14 @@
 	cmd->server->server_gid = ap_group_id = ap_gname2id(arg);
     }
     else {
-        if (ap_suexec_enabled) {
+        if (ap_get_suexec()) {
 	    cmd->server->server_gid = ap_gname2id(arg);
 	}
 	else {
 	    cmd->server->server_gid = ap_group_id;
 	    fprintf(stderr,
-		    "Warning: Group directive in <VirtualHost> requires "
-		    "SUEXEC wrapper.\n");
+		    "Warning: Group directive in <VirtualHost> "
+		    "requires SUEXEC wrapper present and enabled.\n");
 	}
     }
 
diff -Nurb --exclude=*~ apache_1.3.20/src/main/http_main.c apache_1.3.20.p/src/main/http_main.c
--- apache_1.3.20/src/main/http_main.c	Thu Apr 12 19:49:26 2001
+++ apache_1.3.20.p/src/main/http_main.c	Sat Jun 16 19:20:10 2001
@@ -256,7 +256,6 @@
 API_VAR_EXPORT int ap_daemons_max_free=0;
 API_VAR_EXPORT int ap_daemons_limit=0;
 time_t ap_restart_time=0;
-API_VAR_EXPORT int ap_suexec_enabled = 0;
 int ap_listenbacklog;
 int ap_dump_settings = 0;
 API_VAR_EXPORT int ap_extended_status = 0;
@@ -3178,24 +3177,6 @@
 #endif /* !defined(WIN32) && !defined(NETWARE) && !defined(BEOS) */
 }
 
-/* check to see if we have the 'suexec' setuid wrapper installed */
-static int init_suexec(void)
-{
-    int result = 0;
-
-#if !defined(WIN32) && !defined(NETWARE)
-    struct stat wrapper;
-
-    if ((stat(SUEXEC_BIN, &wrapper)) != 0) {
-	result = 0;
-    }
-    else if ((wrapper.st_mode & S_ISUID) && (wrapper.st_uid == 0)) {
-	result = 1;
-    }
-#endif /* ndef WIN32 */
-    return result;
-}
-
 /*****************************************************************
  * Connection structures and accounting...
  */
@@ -4692,10 +4673,9 @@
 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
 		    "%s configured -- resuming normal operations",
 		    ap_get_server_version());
-	if (ap_suexec_enabled) {
-	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
-		         "suEXEC mechanism enabled (wrapper: %s)", SUEXEC_BIN);
-	}
+
+	display_suexec_bootstatus(server_conf);
+
 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
 		    "Server built: %s", ap_get_server_built());
 	restart_pending = shutdown_pending = 0;
@@ -4936,7 +4916,7 @@
 	    show_compile_settings();
 	    exit(0);
 	case 'l':
-	    ap_suexec_enabled = init_suexec();
+	    init_suexec();
 	    ap_show_modules();
 	    exit(0);
 	case 'L':
@@ -4983,7 +4963,7 @@
 	}
     }
 
-    ap_suexec_enabled = init_suexec();
+    init_suexec();
     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
 
     if (ap_configtestonly) {
@@ -6627,7 +6607,7 @@
 {
     ap_set_version();
     ap_init_modules(pconf, server_conf);
-    ap_suexec_enabled = init_suexec();
+    init_suexec();
     version_locked++;
     ap_open_logs(server_conf, plog);
     set_group_privs();
diff -Nurb --exclude=*~ apache_1.3.20/src/main/http_suexec.c apache_1.3.20.p/src/main/http_suexec.c
--- apache_1.3.20/src/main/http_suexec.c	Thu Jan  1 01:00:00 1970
+++ apache_1.3.20.p/src/main/http_suexec.c	Sat Jun 16 20:10:59 2001
@@ -0,0 +1,208 @@
+/* ====================================================================
+ * 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.
+ */
+
+/*
+ * factored out the whole suexec handling as it got too complicated
+ * (for me) and I wanted it to be configureable because I have boxes
+ * that run both, suexec'd and non-suexec'd servers with the same binaries
+ *
+ * Tested it on Linux 2.2, should work on other platforms ok.
+ *
+ *  Henning P. Schmiedehausen <hp...@intermeta.de>  -- 2001-06-16
+ *
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+
+#include <sys/stat.h>
+
+/*
+ * ap_suexec_enabled contains the current state of globally enabling and
+ * disabling the suexec wrappers. It should be treated "read-only"
+ *
+ */
+
+API_VAR_EXPORT int ap_suexec_enabled = 0;
+
+static int found_suexec_wrapper = 0;
+
+/*
+ * The default behaviour (that is: No suexec directive and wrapper found)
+ * is to enable the suexec wrapper. So this defaults to "on"
+ */
+static int enabled_suexec       = 1;
+
+int ap_get_suexec()
+{
+    return found_suexec_wrapper && enabled_suexec;
+}
+
+static void update_suexec_enabled()
+{
+    ap_suexec_enabled = found_suexec_wrapper && enabled_suexec;
+}
+
+
+/* check to see if we have the 'suexec' setuid wrapper installed */
+
+void init_suexec(void)
+{
+#if !defined(WIN32) && !defined(NETWARE)
+    struct stat wrapper;
+
+    found_suexec_wrapper = 0;
+
+    if ((stat(SUEXEC_BIN, &wrapper)) != 0) {
+	found_suexec_wrapper = 0;
+	update_suexec_enabled();
+    }
+    else if ((wrapper.st_mode & S_ISUID) && (wrapper.st_uid == 0)) {
+	found_suexec_wrapper = 1;
+	update_suexec_enabled();
+    }
+#else
+
+    found_suexec_wrapper = 0;
+    update_suexec_enabled();
+
+#endif /* ndef WIN32 */
+}
+
+void display_suexec_status()
+{
+#if !defined(WIN32) && !defined(NETWARE)
+    printf("suexec: %s\n",
+	   found_suexec_wrapper
+	       ? "valid wrapper " SUEXEC_BIN
+	       : "invalid wrapper " SUEXEC_BIN);
+#else
+    printf("suexec: is not supported by this platform\n");
+#endif
+}
+
+void display_suexec_bootstatus(server_rec *c)
+{
+    if (!found_suexec_wrapper) {
+	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, c,
+		     "no suexec wrapper found");
+    }
+    else {
+	if (enabled_suexec) {
+	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, c,
+			 "suexec mechanism enabled (wrapper: %s)", SUEXEC_BIN);
+	}
+	else {
+	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, c,
+			 "suexec mechanism disabled (wrapper: %s)", SUEXEC_BIN);
+	}
+    }
+}
+
+static const char *cmd_suexec(cmd_parms *cmd, void *d, int arg)
+{
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+    if (err != NULL) {
+        return err;
+    }
+
+#if !defined(WIN32) && !defined(NETWARE)
+    enabled_suexec = (arg != 0);
+    update_suexec_enabled();
+#else
+    enabled_suexec = 0;
+    update_suexec_enabled();
+#endif
+    return NULL;
+}
+
+static const command_rec suexec_cmds[] = {
+
+/* enable or disable the suexec wrapper */
+
+{ "SuExec", cmd_suexec, NULL, RSRC_CONF, FLAG,
+  "Enables or disables the use of the suexec wrapper (it still must be "
+  "present in the file system)." },
+{ NULL }
+};
+
+API_VAR_EXPORT 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 */
+    suexec_cmds,                /* 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 */
+};
+
diff -Nurb --exclude=*~ apache_1.3.20/src/main/util_script.c apache_1.3.20.p/src/main/util_script.c
--- apache_1.3.20/src/main/util_script.c	Wed May  9 07:17:11 2001
+++ apache_1.3.20.p/src/main/util_script.c	Sat Jun 16 18:51:06 2001
@@ -1181,7 +1181,7 @@
     }
 #elif defined(NETWARE)
 #else
-    if (ap_suexec_enabled
+    if (ap_get_suexec()
 	&& ((r->server->server_uid != ap_user_id)
 	    || (r->server->server_gid != ap_group_id)
 	    || (!strncmp("/~", r->uri, 2)))) {
diff -Nurb --exclude=*~ apache_1.3.20/src/modules/standard/mod_cgi.c apache_1.3.20.p/src/modules/standard/mod_cgi.c
--- apache_1.3.20/src/modules/standard/mod_cgi.c	Fri Mar  9 11:10:33 2001
+++ apache_1.3.20.p/src/modules/standard/mod_cgi.c	Sat Jun 16 18:50:34 2001
@@ -424,7 +424,7 @@
     if (S_ISDIR(r->finfo.st_mode))
 	return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
 			       "attempt to invoke directory as script");
-    if (!ap_suexec_enabled) {
+    if (!ap_get_suexec()) {
 	if (!ap_can_exec(&r->finfo))
 	    return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
 				   "file permissions deny server execution");





-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20