/[Apache-SVN]/httpd/httpd/trunk/modules/arch/unix/mod_privileges.c
ViewVC logotype

Contents of /httpd/httpd/trunk/modules/arch/unix/mod_privileges.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 771144 - (hide annotations)
Sun May 3 23:02:35 2009 UTC (6 months, 3 weeks ago) by niq
File MIME type: text/plain
File size: 21864 byte(s)
mod_privileges: introduce PrivilegesMode: fast mode as before vs secure
mode to fork an unprivileged child per-request in the manner of MPM-ITK
anwhere there's a risk of running malicious code.
Documentation to follow.
1 niq 713961 /* Licensed to the Apache Software Foundation (ASF) under one or more
2     * contributor license agreements. See the NOTICE file distributed with
3     * this work for additional information regarding copyright ownership.
4     * The ASF licenses this file to You under the Apache License, Version 2.0
5     * (the "License"); you may not use this file except in compliance with
6     * the License. You may obtain a copy of the License at
7     *
8     * http://www.apache.org/licenses/LICENSE-2.0
9     *
10     * Unless required by applicable law or agreed to in writing, software
11     * distributed under the License is distributed on an "AS IS" BASIS,
12     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     * See the License for the specific language governing permissions and
14     * limitations under the License.
15     */
16    
17     #include <priv.h>
18     #include <sys/types.h>
19     #include <unistd.h>
20    
21     #include "httpd.h"
22     #include "http_config.h"
23     #include "http_protocol.h"
24     #include "http_log.h"
25     #include "mpm_common.h"
26     #include "ap_mpm.h"
27     #include "apr_strings.h"
28    
29     /* TODO - get rid of unixd dependency */
30     #include "unixd.h"
31    
32     #define CFG_CHECK(x) if (x == -1) return strerror(errno);
33     #define CR_CHECK(x) if (x == -1) \
34     ap_log_error(APLOG_MARK, APLOG_CRIT,0,0, \
35     "Failed to initialise privileges: %s", strerror(errno))
36    
37     module AP_MODULE_DECLARE_DATA privileges_module;
38    
39     /* #define BIG_SECURITY_HOLE 1 */
40    
41 niq 771144 typedef enum { PRIV_UNSET, PRIV_FAST, PRIV_SECURE, PRIV_SELECTIVE } priv_mode;
42    
43 niq 713961 typedef struct {
44     priv_set_t *priv;
45     priv_set_t *child_priv;
46     uid_t uid;
47     gid_t gid;
48 niq 771144 priv_mode mode;
49 niq 713961 } priv_cfg;
50    
51 niq 771144 typedef struct {
52     priv_mode mode;
53     } priv_dir_cfg;
54    
55 niq 713961 static priv_set_t *priv_setid;
56     static priv_set_t *priv_default = NULL;
57     static int dtrace_enabled = 0;
58    
59     static apr_status_t priv_cfg_cleanup(void *CFG)
60     {
61     priv_cfg *cfg = CFG;
62     priv_freeset(cfg->priv);
63     priv_freeset(cfg->child_priv);
64     return APR_SUCCESS;
65     }
66 niq 771144 static void *privileges_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD)
67     {
68     /* inherit the mode if it's not set; the rest won't be inherited */
69     priv_cfg *base = BASE;
70     priv_cfg *add = ADD;
71     priv_cfg *ret = apr_pmemdup(pool, add, sizeof(priv_cfg));
72     ret->mode = (add->mode == PRIV_UNSET) ? base->mode : add->mode;
73     return ret;
74     }
75 niq 713961 static void *privileges_create_cfg(apr_pool_t *pool, server_rec *s)
76     {
77     priv_cfg *cfg = apr_palloc(pool, sizeof(priv_cfg));
78    
79     /* Start at basic privileges all round. */
80     cfg->priv = priv_str_to_set("basic", ",", NULL);
81     cfg->child_priv = priv_str_to_set("basic", ",", NULL);
82    
83     /* By default, run in secure mode.
84     * That means dropping basic privileges we don't usually need.
85     */
86     CR_CHECK(priv_delset(cfg->priv, PRIV_FILE_LINK_ANY));
87     CR_CHECK(priv_delset(cfg->priv, PRIV_PROC_INFO));
88     CR_CHECK(priv_delset(cfg->priv, PRIV_PROC_SESSION));
89    
90     /* Hmmm, should CGI default to secure too ? */
91     /*
92     CR_CHECK(priv_delset(cfg->child_priv, PRIV_FILE_LINK_ANY));
93     CR_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_INFO));
94     CR_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_SESSION));
95     CR_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_FORK));
96     CR_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_EXEC));
97     */
98    
99     /* we´ll use 0 for unset */
100     cfg->uid = 0;
101     cfg->gid = 0;
102 niq 771144 cfg->mode = PRIV_UNSET;
103 niq 713961 apr_pool_cleanup_register(pool, cfg, priv_cfg_cleanup,
104     apr_pool_cleanup_null);
105    
106     /* top-level default_priv wants the top-level cfg */
107     if (priv_default == NULL) {
108     priv_default = cfg->priv;
109     }
110     return cfg;
111     }
112 niq 771144 static void *privileges_create_dir_cfg(apr_pool_t *pool, char *dummy)
113     {
114     priv_dir_cfg *cfg = apr_palloc(pool, sizeof(priv_dir_cfg));
115     cfg->mode = PRIV_UNSET;
116     return cfg;
117     }
118     static void *privileges_merge_dir_cfg(apr_pool_t *pool, void *BASE, void *ADD)
119     {
120     priv_dir_cfg *base = BASE;
121     priv_dir_cfg *add = ADD;
122     priv_dir_cfg *ret = apr_palloc(pool, sizeof(priv_dir_cfg));
123     ret->mode = (add->mode == PRIV_UNSET) ? base->mode : add->mode;
124     return ret;
125     }
126 niq 713961
127     static apr_status_t privileges_end_req(void *data)
128     {
129     request_rec *r = data;
130     priv_cfg *cfg = ap_get_module_config(r->server->module_config,
131     &privileges_module);
132 niq 771144 priv_dir_cfg *dcfg = ap_get_module_config(r->per_dir_config,
133     &privileges_module);
134 niq 713961
135     /* ugly hack: grab default uid and gid from unixd */
136 covener 723078 extern unixd_config_rec ap_unixd_config;
137 niq 713961
138 niq 771144 /* If we forked a child, we dropped privilege to revert, so
139     * all we can do now is exit
140     */
141     if ((cfg->mode == PRIV_SECURE) ||
142     ((cfg->mode == PRIV_SELECTIVE) && (dcfg->mode == PRIV_SECURE))) {
143     // return APR_SUCCESS;
144     exit(0);
145     }
146    
147 niq 713961 /* if either user or group are not the default, restore them */
148     if (cfg->uid || cfg->gid) {
149     if (setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_setid) == -1) {
150     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
151     "PRIV_ON failed restoring default user/group");
152     }
153 covener 723078 if (cfg->uid && (setuid(ap_unixd_config.user_id) == -1)) {
154 niq 713961 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
155     "Error restoring default userid");
156     }
157 covener 723078 if (cfg->gid && (setgid(ap_unixd_config.group_id) == -1)) {
158 niq 713961 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
159     "Error restoring default group");
160     }
161     }
162    
163     /* restore default privileges */
164     if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_default) == -1) {
165     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
166 niq 738526 "Error restoring default privileges: %s", strerror(errno));
167 niq 713961 }
168     return APR_SUCCESS;
169     }
170 niq 771144 #if 0
171     static apr_status_t privileges_end_proc(void *data)
172     {
173     /* FIXME
174     * The process exists only for the request, and was created
175     * on the request pool which is now being destroyed.
176     * Need to figure out what needs doing here.
177     */
178     exit(0);
179     }
180     #endif
181 niq 713961 static int privileges_req(request_rec *r)
182     {
183 niq 771144 /* secure mode: fork a process to handle the request */
184     apr_proc_t proc;
185     apr_status_t rv;
186     int exitcode;
187     apr_exit_why_e exitwhy;
188     int fork_req;
189 niq 713961 priv_cfg *cfg = ap_get_module_config(r->server->module_config,
190     &privileges_module);
191    
192 niq 771144 void *breadcrumb = ap_get_module_config(r->request_config,
193     &privileges_module);
194    
195     if (!breadcrumb) {
196     /* first call: this is the vhost */
197     fork_req = (cfg->mode == PRIV_SECURE);
198    
199     /* set breadcrumb */
200     ap_set_module_config(r->request_config, &privileges_module, &cfg->mode);
201    
202     /* If we have per-dir config, defer doing anything */
203     if ((cfg->mode == PRIV_SELECTIVE)) {
204     /* Defer dropping privileges 'til we have a directory
205     * context that'll tell us whether to fork.
206     */
207     return DECLINED;
208     }
209     }
210     else {
211     /* second call is for per-directory. */
212     priv_dir_cfg *dcfg;
213     if ((cfg->mode != PRIV_SELECTIVE)) {
214     /* Our fate was already determined for the vhost -
215     * nothing to do per-directory
216     */
217     return DECLINED;
218     }
219     dcfg = ap_get_module_config(r->per_dir_config, &privileges_module);
220     fork_req = (dcfg->mode == PRIV_SECURE);
221     }
222    
223     if (fork_req) {
224     rv = apr_proc_fork(&proc, r->pool);
225     switch (rv) {
226     case APR_INPARENT:
227     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
228     "parent waiting for child");
229     /* FIXME - does the child need to run synchronously?
230     * esp. if we enable mod_privileges with threaded MPMs?
231     * We do need at least to ensure r outlives the child.
232     */
233     rv = apr_proc_wait(&proc, &exitcode, &exitwhy, APR_WAIT);
234     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "parent: child %s",
235     (rv == APR_CHILD_DONE) ? "done" : "notdone");
236    
237     /* The child has taken responsibility for reading all input
238     * and sending all output. So we need to bow right out,
239     * and even abandon "normal" housekeeping.
240     */
241     r->eos_sent = 1;
242     apr_table_unset(r->headers_in, "Content-Type");
243     apr_table_unset(r->headers_in, "Content-Length");
244     /* Testing with ab and 100k requests reveals no nasties
245     * so I infer we're not leaking anything like memory
246     * or file descriptors. That's nice!
247     */
248     return DONE;
249     case APR_INCHILD:
250     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "In child!");
251     // apr_pool_cleanup_register(r->pool, r, privileges_end_proc,
252     // apr_pool_cleanup_null);
253     break; /* now we'll drop privileges in the child */
254     default:
255     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
256     "Failed to fork secure child process!");
257     return HTTP_INTERNAL_SERVER_ERROR;
258     }
259     }
260    
261     /* OK, now drop privileges. */
262    
263 niq 713961 /* cleanup should happen even if something fails part-way through here */
264     apr_pool_cleanup_register(r->pool, r, privileges_end_req,
265     apr_pool_cleanup_null);
266     /* set user and group if configured */
267     if (cfg->uid || cfg->gid) {
268     if (setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_setid) == -1) {
269     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
270     "No privilege to set user/group");
271     }
272     /* if we should be able to set these but can't, it could be
273     * a serious security issue. Bail out rather than risk it!
274     */
275     if (cfg->uid && (setuid(cfg->uid) == -1)) {
276     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
277     "Error setting userid");
278     return HTTP_INTERNAL_SERVER_ERROR;
279     }
280     if (cfg->gid && (setgid(cfg->gid) == -1)) {
281     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
282     "Error setting group");
283     return HTTP_INTERNAL_SERVER_ERROR;
284     }
285     }
286     /* set vhost's privileges */
287     if (setppriv(PRIV_SET, PRIV_EFFECTIVE, cfg->priv) == -1) {
288     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
289 niq 738526 "Error setting effective privileges: %s", strerror(errno));
290 niq 713961 return HTTP_INTERNAL_SERVER_ERROR;
291     }
292    
293     /* ... including those of any subprocesses */
294     if (setppriv(PRIV_SET, PRIV_INHERITABLE, cfg->child_priv) == -1) {
295     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
296 niq 738526 "Error setting inheritable privileges: %s", strerror(errno));
297 niq 713961 return HTTP_INTERNAL_SERVER_ERROR;
298     }
299     if (setppriv(PRIV_SET, PRIV_LIMIT, cfg->child_priv) == -1) {
300     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
301 niq 738526 "Error setting limit privileges: %s", strerror(errno));
302 niq 713961 return HTTP_INTERNAL_SERVER_ERROR;
303     }
304    
305 niq 771144 /* If we're in a child process, drop down PPERM too */
306     if (fork_req) {
307     if (setppriv(PRIV_SET, PRIV_PERMITTED, cfg->priv) == -1) {
308     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
309     "Error setting permitted privileges: %s",
310     strerror(errno));
311     return HTTP_INTERNAL_SERVER_ERROR;
312     }
313     }
314    
315 niq 713961 return OK;
316     }
317     #define PDROP_CHECK(x) if (x == -1) { \
318     ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, \
319     "Error dropping privileges: %s", strerror(errno)); \
320     return !OK; \
321     }
322    
323     static int privileges_drop_first(apr_pool_t *pool, server_rec *s)
324     {
325     /* We need to set privileges before mod_unixd,
326     * 'cos otherwise setuid will wipe our privilege to do so
327     */
328     priv_cfg *spcfg;
329     server_rec *sp;
330     priv_set_t *ppriv = priv_allocset();
331    
332     /* compute ppriv from the union of all the vhosts plus setid */
333     priv_copyset(priv_setid, ppriv);
334     for (sp = s; sp != NULL; sp=sp->next) {
335     spcfg = ap_get_module_config(sp->module_config, &privileges_module);
336     priv_union(spcfg->priv, ppriv);
337     }
338     PDROP_CHECK(setppriv(PRIV_SET, PRIV_PERMITTED, ppriv))
339     PDROP_CHECK(setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv))
340     priv_freeset(ppriv);
341    
342     return OK;
343     }
344     static int privileges_drop_last(apr_pool_t *pool, server_rec *s)
345     {
346     /* Our config stuff has set the privileges we need, so now
347     * we just set them to those of the parent server_rec
348     *
349     * This has to happen after mod_unixd, 'cos mod_unixd needs
350     * privileges we drop here.
351     */
352     priv_cfg *cfg = ap_get_module_config(s->module_config, &privileges_module);
353    
354     /* defaults - the default vhost */
355     PDROP_CHECK(setppriv(PRIV_SET, PRIV_LIMIT, cfg->child_priv))
356     PDROP_CHECK(setppriv(PRIV_SET, PRIV_INHERITABLE, cfg->child_priv))
357     PDROP_CHECK(setppriv(PRIV_SET, PRIV_EFFECTIVE, cfg->priv))
358    
359     return OK;
360     }
361     static apr_status_t privileges_term(void *rec)
362     {
363     priv_freeset(priv_setid);
364     return APR_SUCCESS;
365     }
366     static int privileges_postconf(apr_pool_t *pconf, apr_pool_t *plog,
367     apr_pool_t *ptemp, server_rec *s)
368     {
369     priv_cfg *cfg;
370     server_rec *sp;
371    
372     /* if we have dtrace enabled, merge it into everything */
373     if (dtrace_enabled) {
374     for (sp = s; sp != NULL; sp = sp->next) {
375     cfg = ap_get_module_config(sp->module_config, &privileges_module);
376     CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_KERNEL));
377     CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_PROC));
378     CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_USER));
379     CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_KERNEL));
380     CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_PROC));
381     CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_USER));
382     }
383     CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_KERNEL));
384     CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_PROC));
385     CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_USER));
386     }
387    
388     /* set up priv_setid for per-request use */
389     priv_setid = priv_allocset();
390     apr_pool_cleanup_register(pconf, NULL, privileges_term,
391     apr_pool_cleanup_null);
392     priv_emptyset(priv_setid);
393     if (priv_addset(priv_setid, PRIV_PROC_SETID) == -1) {
394     ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, ptemp,
395 niq 738526 "priv_addset: %s", strerror(errno));
396 niq 713961 return !OK;
397     }
398     return OK;
399     }
400     static int privileges_init(apr_pool_t *pconf, apr_pool_t *plog,
401     apr_pool_t *ptemp)
402     {
403 niq 771144 #if 0
404 niq 713961 /* refuse to work if the MPM is threaded */
405     int threaded;
406     int rv = ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
407     if (rv != APR_SUCCESS) {
408     ap_log_perror(APLOG_MARK, APLOG_NOTICE, rv, ptemp,
409     "mod_privileges: unable to determine MPM characteristics."
410     " Please ensure you are using a non-threaded MPM "
411     "with this module.");
412     }
413     if (threaded) {
414     ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, ptemp,
415     "mod_privileges is not compatible with a threaded MPM.");
416     return !OK;
417     }
418 niq 771144 #endif
419 niq 713961 return OK;
420     }
421     static void privileges_hooks(apr_pool_t *pool)
422     {
423     ap_hook_post_read_request(privileges_req, NULL, NULL,
424     APR_HOOK_REALLY_FIRST);
425 niq 771144 ap_hook_header_parser(privileges_req, NULL, NULL, APR_HOOK_REALLY_FIRST);
426 niq 713961 ap_hook_drop_privileges(privileges_drop_first, NULL, NULL, APR_HOOK_FIRST);
427     ap_hook_drop_privileges(privileges_drop_last, NULL, NULL, APR_HOOK_LAST);
428     ap_hook_post_config(privileges_postconf, NULL, NULL, APR_HOOK_MIDDLE);
429     ap_hook_pre_config(privileges_init, NULL, NULL, APR_HOOK_FIRST);
430     }
431    
432     static const char *vhost_user(cmd_parms *cmd, void *dir, const char *arg)
433     {
434     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
435     &privileges_module);
436     cfg->uid = ap_uname2id(arg);
437     if (cfg->uid == 0) {
438     return apr_pstrcat(cmd->pool, "Invalid userid for VHostUser: ",
439     arg, NULL);
440     }
441     return NULL;
442     }
443     static const char *vhost_group(cmd_parms *cmd, void *dir, const char *arg)
444     {
445     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
446     &privileges_module);
447     cfg->gid = ap_gname2id(arg);
448     if (cfg->uid == 0) {
449     return apr_pstrcat(cmd->pool, "Invalid groupid for VHostGroup: ",
450     arg, NULL);
451     }
452     return NULL;
453     }
454     static const char *vhost_secure(cmd_parms *cmd, void *dir, int arg)
455     {
456     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
457     &privileges_module);
458     if (!arg) {
459     /* add basic privileges, excluding those covered by cgimode */
460     CFG_CHECK(priv_addset(cfg->priv, PRIV_FILE_LINK_ANY));
461     CFG_CHECK(priv_addset(cfg->priv, PRIV_PROC_INFO));
462     CFG_CHECK(priv_addset(cfg->priv, PRIV_PROC_SESSION));
463     }
464     return NULL;
465     }
466     static const char *vhost_cgimode(cmd_parms *cmd, void *dir, const char *arg)
467     {
468     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
469     &privileges_module);
470     if (!strcasecmp(arg, "on")) {
471     /* default - nothing to do */
472     }
473     else if (!strcasecmp(arg, "off")) {
474     /* drop fork+exec privs */
475     CFG_CHECK(priv_delset(cfg->priv, PRIV_PROC_FORK));
476     CFG_CHECK(priv_delset(cfg->priv, PRIV_PROC_EXEC));
477     }
478     else if (!strcasecmp(arg, "secure")) {
479     /* deny privileges to CGI procs */
480     CFG_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_FORK));
481     CFG_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_EXEC));
482     CFG_CHECK(priv_delset(cfg->child_priv, PRIV_FILE_LINK_ANY));
483     CFG_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_INFO));
484     CFG_CHECK(priv_delset(cfg->child_priv, PRIV_PROC_SESSION));
485     }
486     else {
487     return "VHostCGIMode must be On, Off or Secure";
488     }
489    
490     return NULL;
491     }
492     static const char *dtraceenable(cmd_parms *cmd, void *dir, int arg)
493     {
494     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
495     if (err != NULL) {
496     return err;
497     }
498     dtrace_enabled = arg;
499     return NULL;
500     }
501    
502 niq 771144 static const char *privs_mode(cmd_parms *cmd, void *dir, const char *arg)
503     {
504     priv_mode mode = PRIV_UNSET;
505     if (!strcasecmp(arg, "FAST")) {
506     mode = PRIV_FAST;
507     }
508     else if (!strcasecmp(arg, "SECURE")) {
509     mode = PRIV_SECURE;
510     }
511     else if (!strcasecmp(arg, "SELECTIVE")) {
512     mode = PRIV_SELECTIVE;
513     }
514    
515     if (cmd->path) {
516     /* In a directory context, set the per_dir_config */
517     priv_dir_cfg *cfg = dir;
518     cfg->mode = mode;
519     if ((mode == PRIV_UNSET) || (mode == PRIV_SELECTIVE)) {
520     return "PrivilegesMode in a Directory context must be FAST or SECURE";
521     }
522     }
523     else {
524     /* In a global or vhost context, set the server config */
525     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
526     &privileges_module);
527     cfg->mode = mode;
528     if (mode == PRIV_UNSET) {
529     return "PrivilegesMode must be FAST, SECURE or SELECTIVE";
530     }
531     }
532     return NULL;
533     }
534    
535 niq 713961 #ifdef BIG_SECURITY_HOLE
536     static const char *vhost_privs(cmd_parms *cmd, void *dir, const char *arg)
537     {
538     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
539     &privileges_module);
540     const char *priv = arg;
541    
542     if (*priv == '-') {
543     CFG_CHECK(priv_delset(cfg->priv, priv+1));
544     }
545     else if (*priv == '+') {
546     CFG_CHECK(priv_addset(cfg->priv, priv+1));
547     }
548     else {
549     priv_emptyset(cfg->priv);
550     CFG_CHECK(priv_addset(cfg->priv, priv));
551     }
552     return NULL;
553     }
554     static const char *vhost_cgiprivs(cmd_parms *cmd, void *dir, const char *arg)
555     {
556     priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
557     &privileges_module);
558     const char *priv = arg;
559     if (*priv == '-') {
560     CFG_CHECK(priv_delset(cfg->child_priv, priv+1));
561     }
562     else if (*priv == '+') {
563     CFG_CHECK(priv_addset(cfg->child_priv, priv+1));
564     }
565     else {
566     priv_emptyset(cfg->child_priv);
567     CFG_CHECK(priv_addset(cfg->child_priv, priv));
568     }
569     return NULL;
570     }
571     #endif
572     static const command_rec privileges_cmds[] = {
573     AP_INIT_TAKE1("VHostUser", vhost_user, NULL, RSRC_CONF,
574     "Userid under which the virtualhost will run"),
575     AP_INIT_TAKE1("VHostGroup", vhost_group, NULL, RSRC_CONF,
576     "Group under which the virtualhost will run"),
577     AP_INIT_FLAG("VHostSecure", vhost_secure, NULL, RSRC_CONF,
578 niq 771144 "Run in enhanced security mode (default ON)"),
579 niq 713961 AP_INIT_TAKE1("VHostCGIMode", vhost_cgimode, NULL, RSRC_CONF,
580     "Enable fork+exec for this virtualhost (Off|Secure|On)"),
581     AP_INIT_FLAG("DTracePrivileges", dtraceenable, NULL, RSRC_CONF,
582     "Enable DTrace"),
583 niq 771144 AP_INIT_TAKE1("PrivilegesMode", privs_mode, NULL, RSRC_CONF|ACCESS_CONF,
584     "tradeoff performance vs security (fast or secure)"),
585 niq 713961 #ifdef BIG_SECURITY_HOLE
586     AP_INIT_ITERATE("VHostPrivs", vhost_privs, NULL, RSRC_CONF,
587     "Privileges available in the (virtual) server"),
588     AP_INIT_ITERATE("VHostCGIPrivs", vhost_cgiprivs, NULL, RSRC_CONF,
589     "Privileges available to external programs"),
590     #endif
591     {NULL}
592     };
593     module AP_MODULE_DECLARE_DATA privileges_module = {
594     STANDARD20_MODULE_STUFF,
595 niq 771144 privileges_create_dir_cfg,
596     privileges_merge_dir_cfg,
597 niq 713961 privileges_create_cfg,
598 niq 771144 privileges_merge_cfg,
599 niq 713961 privileges_cmds,
600     privileges_hooks
601     };

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2