/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* ugly hack: grab default uid and gid from unixd */ extern unixd_config_rec ap_unixd_config;
/* If we forked a child, we dropped privilege to revert, so *allwecandonowisexit
*/ if ((cfg->mode == PRIV_SECURE) ||
((cfg->mode == PRIV_SELECTIVE) && (dcfg->mode == PRIV_SECURE))) { exit(0);
}
/* if either user or group are not the default, restore them */ if (cfg->uid || cfg->gid) { if (setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_setid) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02136) "PRIV_ON failed restoring default user/group");
} if (cfg->uid && (setuid(ap_unixd_config.user_id) == -1)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02137) "Error restoring default userid");
} if (cfg->gid && (setgid(ap_unixd_config.group_id) == -1)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02138) "Error restoring default group");
}
}
/* restore default privileges */ if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_default) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, APLOGNO(02139) "Error restoring default privileges");
} return APR_SUCCESS;
} staticint privileges_req(request_rec *r)
{ /* secure mode: fork a process to handle the request */
apr_proc_t proc;
apr_status_t rv; int exitcode;
apr_exit_why_e exitwhy; int fork_req;
priv_cfg *cfg = ap_get_module_config(r->server->module_config,
&privileges_module);
if (!breadcrumb) { /* first call: this is the vhost */
fork_req = (cfg->mode == PRIV_SECURE);
/* set breadcrumb */
ap_set_module_config(r->request_config, &privileges_module, &cfg->mode);
/* If we have per-dir config, defer doing anything */ if ((cfg->mode == PRIV_SELECTIVE)) { /* Defer dropping privileges 'til we have a directory *contextthat'lltelluswhethertofork.
*/ return DECLINED;
}
} else { /* second call is for per-directory. */
priv_dir_cfg *dcfg; if ((cfg->mode != PRIV_SELECTIVE)) { /* Our fate was already determined for the vhost - *nothingtodoper-directory
*/ return DECLINED;
}
dcfg = ap_get_module_config(r->per_dir_config, &privileges_module);
fork_req = (dcfg->mode == PRIV_SECURE);
}
if (fork_req) {
rv = apr_proc_fork(&proc, r->pool); switch (rv) { case APR_INPARENT:
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02140) "parent waiting for child"); /* FIXME - does the child need to run synchronously? *esp.ifweenablemod_privilegeswiththreadedMPMs? *Wedoneedatleasttoensureroutlivesthechild.
*/
rv = apr_proc_wait(&proc, &exitcode, &exitwhy, APR_WAIT);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02141) "parent: child %s",
(rv == APR_CHILD_DONE) ? "done" : "notdone");
/* The child has taken responsibility for reading all input *andsendingalloutput.Soweneedtobowrightout, *andevenabandon"normal"housekeeping.
*/
r->eos_sent = 1;
apr_table_unset(r->headers_in, "Content-Type");
apr_table_unset(r->headers_in, "Content-Length"); /* Testing with ab and 100k requests reveals no nasties *soIinferwe'renotleakinganythinglikememory *orfiledescriptors.That'snice!
*/ return DONE; case APR_INCHILD:
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02142) "In child!"); break; /* now we'll drop privileges in the child */ default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02143) "Failed to fork secure child process!"); return HTTP_INTERNAL_SERVER_ERROR;
}
}
/* OK, now drop privileges. */
/* cleanup should happen even if something fails part-way through here */
apr_pool_cleanup_register(r->pool, r, privileges_end_req,
apr_pool_cleanup_null); /* set user and group if configured */ if (cfg->uid || cfg->gid) { if (setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_setid) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02144) "No privilege to set user/group");
} /* if we should be able to set these but can't, it could be *aserioussecurityissue.Bailoutratherthanriskit!
*/ if (cfg->uid && (setuid(cfg->uid) == -1)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02145) "Error setting userid"); return HTTP_INTERNAL_SERVER_ERROR;
} if (cfg->gid && (setgid(cfg->gid) == -1)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02146) "Error setting group"); return HTTP_INTERNAL_SERVER_ERROR;
}
} /* set vhost's privileges */ if (setppriv(PRIV_SET, PRIV_EFFECTIVE, cfg->priv) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, APLOGNO(02147) "Error setting effective privileges"); return HTTP_INTERNAL_SERVER_ERROR;
}
/* ... including those of any subprocesses */ if (setppriv(PRIV_SET, PRIV_INHERITABLE, cfg->child_priv) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, APLOGNO(02148) "Error setting inheritable privileges"); return HTTP_INTERNAL_SERVER_ERROR;
} if (setppriv(PRIV_SET, PRIV_LIMIT, cfg->child_priv) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, APLOGNO(02149) "Error setting limit privileges"); return HTTP_INTERNAL_SERVER_ERROR;
}
/* If we're in a child process, drop down PPERM too */ if (fork_req) { if (setppriv(PRIV_SET, PRIV_PERMITTED, cfg->priv) == -1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, APLOGNO(02150) "Error setting permitted privileges"); return HTTP_INTERNAL_SERVER_ERROR;
}
}
staticint privileges_drop_first(apr_pool_t *pool, server_rec *s)
{ /* We need to set privileges before mod_unixd, *'cosotherwisesetuidwillwipeourprivilegetodoso
*/
priv_cfg *spcfg;
server_rec *sp;
priv_set_t *ppriv = priv_allocset();
/* compute ppriv from the union of all the vhosts plus setid */
priv_copyset(priv_setid, ppriv); for (sp = s; sp != NULL; sp=sp->next) {
spcfg = ap_get_module_config(sp->module_config, &privileges_module);
priv_union(spcfg->priv, ppriv);
}
PDROP_CHECK(setppriv(PRIV_SET, PRIV_PERMITTED, ppriv))
PDROP_CHECK(setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv))
priv_freeset(ppriv);
return OK;
} staticint privileges_drop_last(apr_pool_t *pool, server_rec *s)
{ /* Our config stuff has set the privileges we need, so now *wejustsetthemtothoseoftheparentserver_rec * *Thishastohappenaftermod_unixd,'cosmod_unixdneeds *privilegeswedrophere.
*/
priv_cfg *cfg = ap_get_module_config(s->module_config, &privileges_module);
if (cmd->path) { /* In a directory context, set the per_dir_config */
priv_dir_cfg *cfg = dir;
cfg->mode = mode; if ((mode == PRIV_UNSET) || (mode == PRIV_SELECTIVE)) { return"PrivilegesMode in a Directory context must be FAST or SECURE";
}
} else { /* In a global or vhost context, set the server config */
priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
&privileges_module);
cfg->mode = mode; if (mode == PRIV_UNSET) { return"PrivilegesMode must be FAST, SECURE or SELECTIVE";
}
} return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.