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;