/[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 - (show 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 /* 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 typedef enum { PRIV_UNSET, PRIV_FAST, PRIV_SECURE, PRIV_SELECTIVE } priv_mode;
42
43 typedef struct {
44 priv_set_t *priv;
45 priv_set_t *child_priv;
46 uid_t uid;
47 gid_t gid;
48 priv_mode mode;
49 } priv_cfg;
50
51 typedef struct {
52 priv_mode mode;
53 } priv_dir_cfg;
54
55 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 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 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 cfg->mode = PRIV_UNSET;
103 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 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
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 priv_dir_cfg *dcfg = ap_get_module_config(r->per_dir_config,
133 &privileges_module);
134
135 /* ugly hack: grab default uid and gid from unixd */
136 extern unixd_config_rec ap_unixd_config;
137
138 /* 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 /* 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 if (cfg->uid && (setuid(ap_unixd_config.user_id) == -1)) {
154 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
155 "Error restoring default userid");
156 }
157 if (cfg->gid && (setgid(ap_unixd_config.group_id) == -1)) {
158 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 "Error restoring default privileges: %s", strerror(errno));
167 }
168 return APR_SUCCESS;
169 }
170 #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 static int privileges_req(request_rec *r)
182 {
183 /* 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 priv_cfg *cfg = ap_get_module_config(r->server->module_config,
190 &privileges_module);
191
192 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 /* 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 "Error setting effective privileges: %s", strerror(errno));
290 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 "Error setting inheritable privileges: %s", strerror(errno));
297 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 "Error setting limit privileges: %s", strerror(errno));
302 return HTTP_INTERNAL_SERVER_ERROR;
303 }
304
305 /* 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 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 "priv_addset: %s", strerror(errno));
396 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 #if 0
404 /* 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 #endif
419 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 ap_hook_header_parser(privileges_req, NULL, NULL, APR_HOOK_REALLY_FIRST);
426 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 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 #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 "Run in enhanced security mode (default ON)"),
579 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 AP_INIT_TAKE1("PrivilegesMode", privs_mode, NULL, RSRC_CONF|ACCESS_CONF,
584 "tradeoff performance vs security (fast or secure)"),
585 #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 privileges_create_dir_cfg,
596 privileges_merge_dir_cfg,
597 privileges_create_cfg,
598 privileges_merge_cfg,
599 privileges_cmds,
600 privileges_hooks
601 };

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2