diff --git a/CHANGES b/CHANGES
index 81d6db7ebe..4d780b102b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@ Changes with Apache 2.3.9
Fix a denial of service attack against mod_reqtimeout.
[Stefan Fritsch]
+ *) suEXEC: Add Suexec directive to disable suEXEC without renaming the
+ binary (Suexec Off), or force startup failure if suEXEC is required
+ but not supported (Suexec On). Change SuexecUserGroup to fail
+ startup instead of just printing a warning if suEXEC is disabled.
+ [Jeff Trawick]
+
*) core: Add Error directive for aborting startup or htaccess processing
with a specified error message. [Jeff Trawick]
diff --git a/docs/manual/mod/mod_suexec.xml b/docs/manual/mod/mod_suexec.xml
index 1bdbb4c2d0..17f05a3267 100644
--- a/docs/manual/mod/mod_suexec.xml
+++ b/docs/manual/mod/mod_suexec.xml
@@ -62,8 +62,11 @@ later.
SuexecUserGroup nobody nogroup
+
In Apache httpd 2.3.9 and later, startup will fail if this
+ directive is specified but the suEXEC feature is disabled.
-
+Suexec
+
diff --git a/docs/manual/mod/mod_unixd.xml b/docs/manual/mod/mod_unixd.xml
index 257e3edc71..9c8fe0636a 100644
--- a/docs/manual/mod/mod_unixd.xml
+++ b/docs/manual/mod/mod_unixd.xml
@@ -26,6 +26,8 @@
Basic (required) security for Unix-family platforms.
Base
+suEXEC support
+
Group
Group under which the server will answer
@@ -139,4 +141,21 @@ requests
+
+Suexec
+Enable or disable the suEXEC feature
+Suexec On|Off
+On if suexec binary exists with proper owner and mode,
+Off otherwise
+server config
+Available in Apache httpd 2.3.9 and later
+
+
+ When On, startup will fail if the suexec binary doesn't exist
+ or has an invalid owner or file mode.
+ When Off, suEXEC will be disabled even if the suexec binary exists
+ and has a valid owner and file mode.
+
+
+
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 2922e41a58..3c9250a850 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -282,6 +282,7 @@
* mod_ssl's parser. Clean up ap_expr's public
* interface.
* 20101106.1 (2.3.9-dev) Add ap_pool_cleanup_set_null() generic cleanup
+ * 20101106.2 (2.3.9-dev) Add suexec_disabled_reason field to ap_unixd_config
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
diff --git a/modules/arch/unix/mod_unixd.c b/modules/arch/unix/mod_unixd.c
index 50395ee19c..af30720662 100644
--- a/modules/arch/unix/mod_unixd.c
+++ b/modules/arch/unix/mod_unixd.c
@@ -260,6 +260,28 @@ unixd_set_chroot_dir(cmd_parms *cmd, void *dummy,
return NULL;
}
+static const char *
+unixd_set_suexec(cmd_parms *cmd, void *dummy, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (err != NULL) {
+ return err;
+ }
+
+ if (!ap_unixd_config.suexec_enabled && arg) {
+ return apr_pstrcat(cmd->pool, "suEXEC isn't supported: ",
+ ap_unixd_config.suexec_disabled_reason, NULL);
+ }
+
+ if (!arg) {
+ ap_unixd_config.suexec_disabled_reason = "Suexec directive is Off";
+ }
+
+ ap_unixd_config.suexec_enabled = arg;
+ return NULL;
+}
+
static int
unixd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp)
@@ -278,7 +300,16 @@ unixd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
if ((wrapper.protection & APR_USETID) && wrapper.user == 0
&& (access(SUEXEC_BIN, R_OK|X_OK) == 0)) {
ap_unixd_config.suexec_enabled = 1;
+ ap_unixd_config.suexec_disabled_reason = "";
}
+ else {
+ ap_unixd_config.suexec_disabled_reason =
+ "Invalid owner or file mode for " SUEXEC_BIN;
+ }
+ }
+ else {
+ ap_unixd_config.suexec_disabled_reason =
+ "Missing suexec binary " SUEXEC_BIN;
}
ap_sys_privileges_handlers(1);
@@ -354,6 +385,8 @@ static const command_rec unixd_cmds[] = {
"Effective group id for this server"),
AP_INIT_TAKE1("ChrootDir", unixd_set_chroot_dir, NULL, RSRC_CONF,
"The directory to chroot(2) into"),
+ AP_INIT_FLAG("Suexec", unixd_set_suexec, NULL, RSRC_CONF,
+ "Enable or disable suEXEC support"),
{NULL}
};
diff --git a/modules/generators/mod_suexec.c b/modules/generators/mod_suexec.c
index e548d71cdc..9a7d2cfe4f 100644
--- a/modules/generators/mod_suexec.c
+++ b/modules/generators/mod_suexec.c
@@ -64,16 +64,18 @@ static const char *set_suexec_ugid(cmd_parms *cmd, void *mconfig,
if (err != NULL) {
return err;
}
- if (ap_unixd_config.suexec_enabled) {
- cfg->ugid.uid = ap_uname2id(uid);
- cfg->ugid.gid = ap_gname2id(gid);
- cfg->ugid.userdir = 0;
- cfg->active = 1;
- }
- else {
- fprintf(stderr,
- "Warning: SuexecUserGroup directive requires SUEXEC wrapper.\n");
+
+ if (!ap_unixd_config.suexec_enabled) {
+ return apr_pstrcat(cmd->pool, "SuexecUserGroup configured, but "
+ "suEXEC is disabled: ",
+ ap_unixd_config.suexec_disabled_reason, NULL);
}
+
+ cfg->ugid.uid = ap_uname2id(uid);
+ cfg->ugid.gid = ap_gname2id(gid);
+ cfg->ugid.userdir = 0;
+ cfg->active = 1;
+
return NULL;
}
diff --git a/os/unix/unixd.h b/os/unix/unixd.h
index c9d6ea96a2..6b8a79ae32 100644
--- a/os/unix/unixd.h
+++ b/os/unix/unixd.h
@@ -77,6 +77,7 @@ typedef struct {
gid_t group_id;
int suexec_enabled;
const char *chroot_dir;
+ const char *suexec_disabled_reason; /* suitable msg if !suexec_enabled */
} unixd_config_rec;
AP_DECLARE_DATA extern unixd_config_rec ap_unixd_config;