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 /*
18  * http_config.c: once was auxiliary functions for reading httpd's config
19  * file and converting filenames into a namespace
20  *
21  * Rob McCool
22  *
23  * Wall-to-wall rewrite for Apache... commands which are part of the
24  * server core can now be found next door in "http_core.c".  Now contains
25  * general command loop, and functions which do bookkeeping for the new
26  * Apache config stuff (modules and configuration vectors).
27  *
28  * rst
29  *
30  */
31 
32 #include "apr.h"
33 #include "apr_strings.h"
34 #include "apr_portable.h"
35 #include "apr_file_io.h"
36 #include "apr_fnmatch.h"
37 
38 #define APR_WANT_STDIO
39 #define APR_WANT_STRFUNC
40 #include "apr_want.h"
41 
42 #include "ap_config.h"
43 #include "httpd.h"
44 #include "http_config.h"
45 #include "http_protocol.h"
46 #include "http_core.h"
47 #include "http_log.h"      /* for errors in parse_htaccess */
48 #include "http_request.h"  /* for default_handler (see invoke_handler) */
49 #include "http_main.h"
50 #include "http_vhost.h"
51 #include "util_cfgtree.h"
52 #include "util_varbuf.h"
53 #include "mpm_common.h"
54 
55 #define APLOG_UNSET   (APLOG_NO_MODULE - 1)
56 /* we know core's module_index is 0 */
57 #undef APLOG_MODULE_INDEX
58 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
59 
60 AP_DECLARE_DATA const char *ap_server_argv0 = NULL;
61 AP_DECLARE_DATA const char *ap_server_root = NULL;
62 AP_DECLARE_DATA server_rec *ap_server_conf = NULL;
63 AP_DECLARE_DATA apr_pool_t *ap_pglobal = NULL;
64 
65 AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config = NULL;
66 AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config = NULL;
67 AP_DECLARE_DATA apr_array_header_t *ap_server_config_defines = NULL;
68 
69 AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL;
70 
71 APR_HOOK_STRUCT(
72            APR_HOOK_LINK(header_parser)
73            APR_HOOK_LINK(pre_config)
74            APR_HOOK_LINK(check_config)
75            APR_HOOK_LINK(post_config)
76            APR_HOOK_LINK(open_logs)
77            APR_HOOK_LINK(child_init)
78            APR_HOOK_LINK(handler)
79            APR_HOOK_LINK(quick_handler)
80            APR_HOOK_LINK(optional_fn_retrieve)
81            APR_HOOK_LINK(test_config)
82            APR_HOOK_LINK(open_htaccess)
83 )
84 
85 AP_IMPLEMENT_HOOK_RUN_ALL(int, header_parser,
86                           (request_rec *r), (r), OK, DECLINED)
87 
88 AP_IMPLEMENT_HOOK_RUN_ALL(int, pre_config,
89                           (apr_pool_t *pconf, apr_pool_t *plog,
90                            apr_pool_t *ptemp),
91                           (pconf, plog, ptemp), OK, DECLINED)
92 
93 AP_IMPLEMENT_HOOK_RUN_ALL(int, check_config,
94                           (apr_pool_t *pconf, apr_pool_t *plog,
95                            apr_pool_t *ptemp, server_rec *s),
96                           (pconf, plog, ptemp, s), OK, DECLINED)
97 
98 AP_IMPLEMENT_HOOK_VOID(test_config,
99                        (apr_pool_t *pconf, server_rec *s),
100                        (pconf, s))
101 
102 AP_IMPLEMENT_HOOK_RUN_ALL(int, post_config,
103                           (apr_pool_t *pconf, apr_pool_t *plog,
104                            apr_pool_t *ptemp, server_rec *s),
105                           (pconf, plog, ptemp, s), OK, DECLINED)
106 
107 /* During the course of debugging I expanded this macro out, so
108  * rather than remove all the useful information there is in the
109  * following lines, I'm going to leave it here in case anyone
110  * else finds it useful.
111  *
112  * Ben has looked at it and thinks it correct :)
113  *
114 AP_DECLARE(int) ap_hook_post_config(ap_HOOK_post_config_t *pf,
115                                     const char * const *aszPre,
116                                     const char * const *aszSucc,
117                                     int nOrder)
118 {
119     ap_LINK_post_config_t *pHook;
120 
121     if (!_hooks.link_post_config) {
122         _hooks.link_post_config = apr_array_make(apr_hook_global_pool, 1,
123                                                  sizeof(ap_LINK_post_config_t));
124         apr_hook_sort_register("post_config", &_hooks.link_post_config);
125     }
126 
127     pHook = apr_array_push(_hooks.link_post_config);
128     pHook->pFunc = pf;
129     pHook->aszPredecessors = aszPre;
130     pHook->aszSuccessors = aszSucc;
131     pHook->nOrder = nOrder;
132     pHook->szName = apr_hook_debug_current;
133 
134     if (apr_hook_debug_enabled)
135         apr_hook_debug_show("post_config", aszPre, aszSucc);
136 }
137 
138 AP_DECLARE(apr_array_header_t *) ap_hook_get_post_config(void)
139 {
140     return _hooks.link_post_config;
141 }
142 
143 AP_DECLARE(int) ap_run_post_config(apr_pool_t *pconf,
144                                    apr_pool_t *plog,
145                                    apr_pool_t *ptemp,
146                                    server_rec *s)
147 {
148     ap_LINK_post_config_t *pHook;
149     int n;
150 
151     if (!_hooks.link_post_config)
152         return;
153 
154     pHook = (ap_LINK_post_config_t *)_hooks.link_post_config->elts;
155     for (n = 0; n < _hooks.link_post_config->nelts; ++n)
156         pHook[n].pFunc (pconf, plog, ptemp, s);
157 }
158  */
159 
160 AP_IMPLEMENT_HOOK_RUN_ALL(int, open_logs,
161                           (apr_pool_t *pconf, apr_pool_t *plog,
162                            apr_pool_t *ptemp, server_rec *s),
163                           (pconf, plog, ptemp, s), OK, DECLINED)
164 
165 AP_IMPLEMENT_HOOK_VOID(child_init,
166                        (apr_pool_t *pchild, server_rec *s),
167                        (pchild, s))
168 
169 AP_IMPLEMENT_HOOK_RUN_FIRST(int, handler, (request_rec *r),
170                             (r), DECLINED)
171 
172 AP_IMPLEMENT_HOOK_RUN_FIRST(int, quick_handler, (request_rec *r, int lookup),
173                             (r, lookup), DECLINED)
174 
175 AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, open_htaccess,
176                             (request_rec *r, const char *dir_name, const char *access_name,
177                              ap_configfile_t **conffile, const char **full_name),
178                             (r, dir_name, access_name, conffile, full_name),
179                             AP_DECLINED)
180 
181 /* hooks with no args are implemented last, after disabling APR hook probes */
182 #if defined(APR_HOOK_PROBES_ENABLED)
183 #undef APR_HOOK_PROBES_ENABLED
184 #undef APR_HOOK_PROBE_ENTRY
185 #define APR_HOOK_PROBE_ENTRY(ud,ns,name,args)
186 #undef APR_HOOK_PROBE_RETURN
187 #define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args)
188 #undef APR_HOOK_PROBE_INVOKE
189 #define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args)
190 #undef APR_HOOK_PROBE_COMPLETE
191 #define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args)
192 #undef APR_HOOK_INT_DCL_UD
193 #define APR_HOOK_INT_DCL_UD
194 #endif
195 AP_IMPLEMENT_HOOK_VOID(optional_fn_retrieve, (void), ())
196 
197 /****************************************************************
198  *
199  * We begin with the functions which deal with the linked list
200  * of modules which control just about all of the server operation.
201  */
202 
203 /* total_modules is the number of modules that have been linked
204  * into the server.
205  */
206 static int total_modules = 0;
207 
208 /* dynamic_modules is the number of modules that have been added
209  * after the pre-loaded ones have been set up. It shouldn't be larger
210  * than DYNAMIC_MODULE_LIMIT.
211  */
212 static int dynamic_modules = 0;
213 
214 /* The maximum possible value for total_modules, i.e. number of static
215  * modules plus DYNAMIC_MODULE_LIMIT.
216  */
217 static int max_modules = 0;
218 
219 /* The number of elements we need to alloc for config vectors. Before loading
220  * of dynamic modules, we must be liberal and set this to max_modules. After
221  * loading of dynamic modules, we can trim it down to total_modules. On
222  * restart, reset to max_modules.
223  */
224 static int conf_vector_length = 0;
225 
226 static int reserved_module_slots = 0;
227 
228 AP_DECLARE_DATA module *ap_top_module = NULL;
229 AP_DECLARE_DATA module **ap_loaded_modules=NULL;
230 
231 static apr_hash_t *ap_config_hash = NULL;
232 
233 /* a list of the module symbol names with the trailing "_module"removed */
234 static char **ap_module_short_names = NULL;
235 
236 typedef int (*handler_func)(request_rec *);
237 typedef void *(*dir_maker_func)(apr_pool_t *, char *);
238 typedef void *(*merger_func)(apr_pool_t *, void *, void *);
239 
240 /* A list of the merge_dir_config functions of all loaded modules, sorted
241  * by module_index.
242  * Using this list in ap_merge_per_dir_configs() is faster than following
243  * the module->next linked list because of better memory locality (resulting
244  * in better cache usage).
245  */
246 static merger_func *merger_func_cache;
247 
248 /* maximum nesting level for config directories */
249 #ifndef AP_MAX_INCLUDE_DIR_DEPTH
250 #define AP_MAX_INCLUDE_DIR_DEPTH (128)
251 #endif
252 
253 /* Dealing with config vectors.  These are associated with per-directory,
254  * per-server, and per-request configuration, and have a void* pointer for
255  * each modules.  The nature of the structure pointed to is private to the
256  * module in question... the core doesn't (and can't) know.  However, there
257  * are defined interfaces which allow it to create instances of its private
258  * per-directory and per-server structures, and to merge the per-directory
259  * structures of a directory and its subdirectory (producing a new one in
260  * which the defaults applying to the base directory have been properly
261  * overridden).
262  */
263 
create_empty_config(apr_pool_t * p)264 static ap_conf_vector_t *create_empty_config(apr_pool_t *p)
265 {
266     void *conf_vector = apr_pcalloc(p, sizeof(void *) * conf_vector_length);
267     return conf_vector;
268 }
269 
create_default_per_dir_config(apr_pool_t * p)270 static ap_conf_vector_t *create_default_per_dir_config(apr_pool_t *p)
271 {
272     void **conf_vector = apr_pcalloc(p, sizeof(void *) * conf_vector_length);
273     module *modp;
274 
275     for (modp = ap_top_module; modp; modp = modp->next) {
276         dir_maker_func df = modp->create_dir_config;
277 
278         if (df)
279             conf_vector[modp->module_index] = (*df)(p, NULL);
280     }
281 
282     return (ap_conf_vector_t *)conf_vector;
283 }
284 
ap_merge_per_dir_configs(apr_pool_t * p,ap_conf_vector_t * base,ap_conf_vector_t * new_conf)285 AP_CORE_DECLARE(ap_conf_vector_t *) ap_merge_per_dir_configs(apr_pool_t *p,
286                                            ap_conf_vector_t *base,
287                                            ap_conf_vector_t *new_conf)
288 {
289     void **conf_vector = apr_palloc(p, sizeof(void *) * conf_vector_length);
290     void **base_vector = (void **)base;
291     void **new_vector = (void **)new_conf;
292     int i;
293 
294     for (i = 0; i < total_modules; i++) {
295         if (!new_vector[i]) {
296             conf_vector[i] = base_vector[i];
297         }
298         else {
299             const merger_func df = merger_func_cache[i];
300             if (df && base_vector[i]) {
301                 conf_vector[i] = (*df)(p, base_vector[i], new_vector[i]);
302             }
303             else
304                 conf_vector[i] = new_vector[i];
305         }
306     }
307 
308     return (ap_conf_vector_t *)conf_vector;
309 }
310 
create_server_config(apr_pool_t * p,server_rec * s)311 static ap_conf_vector_t *create_server_config(apr_pool_t *p, server_rec *s)
312 {
313     void **conf_vector = apr_pcalloc(p, sizeof(void *) * conf_vector_length);
314     module *modp;
315 
316     for (modp = ap_top_module; modp; modp = modp->next) {
317         if (modp->create_server_config)
318             conf_vector[modp->module_index] = (*modp->create_server_config)(p, s);
319     }
320 
321     return (ap_conf_vector_t *)conf_vector;
322 }
323 
merge_server_configs(apr_pool_t * p,ap_conf_vector_t * base,server_rec * virt)324 static void merge_server_configs(apr_pool_t *p, ap_conf_vector_t *base,
325                                  server_rec *virt)
326 {
327     /* Can reuse the 'virt' vector for the spine of it, since we don't
328      * have to deal with the moral equivalent of .htaccess files here...
329      */
330 
331     void **base_vector = (void **)base;
332     void **virt_vector = (void **)virt->module_config;
333     module *modp;
334 
335     for (modp = ap_top_module; modp; modp = modp->next) {
336         merger_func df = modp->merge_server_config;
337         int i = modp->module_index;
338 
339         if (!virt_vector[i]) {
340             if (df && modp->create_server_config
341                    && (ap_get_module_flags(modp) &
342                        AP_MODULE_FLAG_ALWAYS_MERGE)) {
343                 virt_vector[i] = (*modp->create_server_config)(p, virt);
344             }
345             else {
346                 virt_vector[i] = base_vector[i];
347                 df = NULL;
348             }
349         }
350         if (df) {
351             virt_vector[i] = (*df)(p, base_vector[i], virt_vector[i]);
352         }
353     }
354 }
355 
ap_create_request_config(apr_pool_t * p)356 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_request_config(apr_pool_t *p)
357 {
358     return create_empty_config(p);
359 }
360 
ap_create_conn_config(apr_pool_t * p)361 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_conn_config(apr_pool_t *p)
362 {
363     return create_empty_config(p);
364 }
365 
ap_create_per_dir_config(apr_pool_t * p)366 AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_per_dir_config(apr_pool_t *p)
367 {
368     return create_empty_config(p);
369 }
370 
371 /* Invoke the filter_init_func for all filters with FILTERS where f->r
372  * matches R.  Restricting to a matching R avoids re-running init
373  * functions for filters configured for r->main where r is a
374  * subrequest.  */
invoke_filter_init(request_rec * r,ap_filter_t * filters)375 static int invoke_filter_init(request_rec *r, ap_filter_t *filters)
376 {
377     while (filters) {
378         if (filters->frec->filter_init_func && filters->r == r) {
379             int result = filters->frec->filter_init_func(filters);
380             if (result != OK) {
381                 return result;
382             }
383         }
384         filters = filters->next;
385     }
386     return OK;
387 }
388 
ap_invoke_handler(request_rec * r)389 AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
390 {
391     const char *handler;
392     const char *p;
393     int result;
394     const char *old_handler = r->handler;
395     const char *ignore;
396 
397     /*
398      * The new insert_filter stage makes the most sense here.  We only use
399      * it when we are going to run the request, so we must insert filters
400      * if any are available.  Since the goal of this phase is to allow all
401      * modules to insert a filter if they want to, this filter returns
402      * void.  I just can't see any way that this filter can reasonably
403      * fail, either your modules inserts something or it doesn't.  rbb
404      */
405     ap_run_insert_filter(r);
406 
407     /* Before continuing, allow each filter that is in the two chains to
408      * run their init function to let them do any magic before we could
409      * start generating data.
410      */
411     result = invoke_filter_init(r, r->input_filters);
412     if (result != OK) {
413         return result;
414     }
415     result = invoke_filter_init(r, r->output_filters);
416     if (result != OK) {
417         return result;
418     }
419 
420     if (!r->handler) {
421         if (r->content_type) {
422             handler = r->content_type;
423             if ((p=ap_strchr_c(handler, ';')) != NULL) {
424                 char *new_handler = (char *)apr_pmemdup(r->pool, handler,
425                                                         p - handler + 1);
426                 char *p2 = new_handler + (p - handler);
427                 handler = new_handler;
428 
429                 /* exclude media type arguments */
430                 while (p2 > handler && p2[-1] == ' ')
431                     --p2; /* strip trailing spaces */
432 
433                 *p2='\0';
434             }
435         }
436         else {
437             handler = AP_DEFAULT_HANDLER_NAME;
438         }
439 
440         r->handler = handler;
441     }
442 
443     result = ap_run_handler(r);
444 
445     r->handler = old_handler;
446 
447     if (result == DECLINED && r->handler && r->filename) {
448         ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00523)
449             "handler \"%s\" not found for: %s", r->handler, r->filename);
450     }
451     if ((result != OK) && (result != DONE) && (result != DECLINED) && (result != SUSPENDED)
452         && (result != AP_FILTER_ERROR) /* ap_die() knows about this specifically */
453         && !ap_is_HTTP_VALID_RESPONSE(result)) {
454         /* If a module is deliberately returning something else
455          * (request_rec in non-HTTP or proprietary extension?)
456          * let it set a note to allow it explicitly.
457          * Otherwise, a return code that is neither reserved nor HTTP
458          * is a bug, as in PR#31759.
459          */
460         ignore = apr_table_get(r->notes, "HTTP_IGNORE_RANGE");
461         if (!ignore) {
462             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00524)
463                           "Handler for %s returned invalid result code %d",
464                           r->handler, result);
465             result = HTTP_INTERNAL_SERVER_ERROR;
466         }
467     }
468 
469     return result == DECLINED ? HTTP_INTERNAL_SERVER_ERROR : result;
470 }
471 
ap_method_is_limited(cmd_parms * cmd,const char * method)472 AP_DECLARE(int) ap_method_is_limited(cmd_parms *cmd, const char *method)
473 {
474     int methnum;
475 
476     methnum = ap_method_number_of(method);
477 
478     /*
479      * A method number either hardcoded into apache or
480      * added by a module and registered.
481      */
482     if (methnum != M_INVALID) {
483         return (cmd->limited & (AP_METHOD_BIT << methnum)) ? 1 : 0;
484     }
485 
486     return 0; /* not found */
487 }
488 
ap_register_hooks(module * m,apr_pool_t * p)489 AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
490 {
491     if (m->register_hooks) {
492         if (getenv("SHOW_HOOKS")) {
493             printf("Registering hooks for %s\n", m->name);
494             apr_hook_debug_enabled = 1;
495         }
496 
497         apr_hook_debug_current = m->name;
498         m->register_hooks(p);
499     }
500 }
501 
502 static void ap_add_module_commands(module *m, apr_pool_t *p);
503 
504 typedef struct ap_mod_list_struct ap_mod_list;
505 struct ap_mod_list_struct {
506     struct ap_mod_list_struct *next;
507     module *m;
508     const command_rec *cmd;
509 };
510 
rebuild_conf_hash(apr_pool_t * p,int add_prelinked)511 static void rebuild_conf_hash(apr_pool_t *p, int add_prelinked)
512 {
513     module **m;
514 
515     ap_config_hash = apr_hash_make(p);
516 
517     apr_pool_cleanup_register(p, &ap_config_hash, ap_pool_cleanup_set_null,
518                               apr_pool_cleanup_null);
519     if (add_prelinked) {
520         for (m = ap_prelinked_modules; *m != NULL; m++) {
521             ap_add_module_commands(*m, p);
522         }
523     }
524 }
525 
ap_add_module_commands(module * m,apr_pool_t * p)526 static void ap_add_module_commands(module *m, apr_pool_t *p)
527 {
528     apr_pool_t *tpool;
529     ap_mod_list *mln;
530     const command_rec *cmd;
531     char *dir;
532 
533     cmd = m->cmds;
534 
535     if (ap_config_hash == NULL) {
536         rebuild_conf_hash(p, 0);
537     }
538 
539     tpool = apr_hash_pool_get(ap_config_hash);
540 
541     while (cmd && cmd->name) {
542         mln = apr_palloc(tpool, sizeof(ap_mod_list));
543         mln->cmd = cmd;
544         mln->m = m;
545         dir = apr_pstrdup(tpool, cmd->name);
546 
547         ap_str_tolower(dir);
548 
549         mln->next = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
550         apr_hash_set(ap_config_hash, dir, APR_HASH_KEY_STRING, mln);
551         ++cmd;
552     }
553 }
554 
555 
556 /* One-time setup for precompiled modules --- NOT to be done on restart */
557 
ap_add_module(module * m,apr_pool_t * p,const char * sym_name)558 AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p,
559                                        const char *sym_name)
560 {
561     ap_module_symbol_t *sym = ap_prelinked_module_symbols;
562 
563     /* This could be called from a LoadModule httpd.conf command,
564      * after the file has been linked and the module structure within it
565      * teased out...
566      */
567 
568     if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
569         return apr_psprintf(p, "Module \"%s\" is not compatible with this "
570                             "version of Apache (found %d, need %d). Please "
571                             "contact the vendor for the correct version.",
572                             m->name, m->version, MODULE_MAGIC_NUMBER_MAJOR);
573     }
574 
575     if (m->module_index == -1) {
576         if (dynamic_modules >= DYNAMIC_MODULE_LIMIT) {
577             return apr_psprintf(p, "Module \"%s\" could not be loaded, "
578                                 "because the dynamic module limit was "
579                                 "reached. Please increase "
580                                 "DYNAMIC_MODULE_LIMIT and recompile.", m->name);
581         }
582         /*
583          * If this fails some module forgot to call ap_reserve_module_slots*.
584          */
585         ap_assert(total_modules < conf_vector_length);
586 
587         m->module_index = total_modules++;
588         dynamic_modules++;
589 
590     }
591     else if (!sym_name) {
592         while (sym->modp != NULL) {
593             if (sym->modp == m) {
594                 sym_name = sym->name;
595                 break;
596             }
597             sym++;
598         }
599     }
600 
601     if (m->next == NULL) {
602         m->next = ap_top_module;
603         ap_top_module = m;
604     }
605 
606     if (sym_name) {
607         int len = strlen(sym_name);
608         int slen = strlen("_module");
609         if (len > slen && !strcmp(sym_name + len - slen, "_module")) {
610             len -= slen;
611         }
612 
613         ap_module_short_names[m->module_index] = ap_malloc(len + 1);
614         memcpy(ap_module_short_names[m->module_index], sym_name, len);
615         ap_module_short_names[m->module_index][len] = '\0';
616         merger_func_cache[m->module_index] = m->merge_dir_config;
617     }
618 
619 
620     /* Some C compilers put a complete path into __FILE__, but we want
621      * only the filename (e.g. mod_includes.c). So check for path
622      * components (Unix and DOS), and remove them.
623      */
624 
625     if (ap_strrchr_c(m->name, '/'))
626         m->name = 1 + ap_strrchr_c(m->name, '/');
627 
628     if (ap_strrchr_c(m->name, '\\'))
629         m->name = 1 + ap_strrchr_c(m->name, '\\');
630 
631 #ifdef _OSD_POSIX
632     /* __FILE__ =
633      * "*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)"
634      */
635 
636     /* We cannot fix the string in-place, because it's const */
637     if (m->name[strlen(m->name)-1] == ')') {
638         char *tmp = ap_malloc(strlen(m->name)); /* FIXME: memory leak, albeit a small one */
639         memcpy(tmp, m->name, strlen(m->name)-1);
640         tmp[strlen(m->name)-1] = '\0';
641         m->name = tmp;
642     }
643 #endif /*_OSD_POSIX*/
644 
645     ap_add_module_commands(m, p);
646     /*  FIXME: is this the right place to call this?
647      *  It doesn't appear to be
648      */
649     ap_register_hooks(m, p);
650 
651     return NULL;
652 }
653 
654 /*
655  * remove_module undoes what add_module did. There are some caveats:
656  * when the module is removed, its slot is lost so all the current
657  * per-dir and per-server configurations are invalid. So we should
658  * only ever call this function when you are invalidating almost
659  * all our current data. I.e. when doing a restart.
660  */
661 
ap_remove_module(module * m)662 AP_DECLARE(void) ap_remove_module(module *m)
663 {
664     module *modp;
665 
666     modp = ap_top_module;
667     if (modp == m) {
668         /* We are the top module, special case */
669         ap_top_module = modp->next;
670         m->next = NULL;
671     }
672     else {
673         /* Not the top module, find use. When found modp will
674          * point to the module _before_ us in the list
675          */
676 
677         while (modp && modp->next != m) {
678             modp = modp->next;
679         }
680 
681         if (!modp) {
682             /* Uh-oh, this module doesn't exist */
683             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00525)
684                          "Cannot remove module %s: not found in module list",
685                          m->name);
686             return;
687         }
688 
689         /* Eliminate us from the module list */
690         modp->next = modp->next->next;
691     }
692 
693     free(ap_module_short_names[m->module_index]);
694     ap_module_short_names[m->module_index] = NULL;
695     merger_func_cache[m->module_index] = NULL;
696 
697     m->module_index = -1; /* simulate being unloaded, should
698                            * be unnecessary */
699     dynamic_modules--;
700     total_modules--;
701 }
702 
ap_add_loaded_module(module * mod,apr_pool_t * p,const char * short_name)703 AP_DECLARE(const char *) ap_add_loaded_module(module *mod, apr_pool_t *p,
704                                               const char *short_name)
705 {
706     module **m;
707     const char *error;
708 
709     /*
710      *  Add module pointer to top of chained module list
711      */
712     error = ap_add_module(mod, p, short_name);
713     if (error) {
714         return error;
715     }
716 
717     /*
718      *  And module pointer to list of loaded modules
719      *
720      *  Notes: 1. ap_add_module() would already complain if no more space
721      *            exists for adding a dynamically loaded module
722      *         2. ap_add_module() accepts double inclusion, so we have
723      *            to accept this, too.
724      */
725     for (m = ap_loaded_modules; *m != NULL; m++)
726         ;
727     *m++ = mod;
728     *m = NULL;
729 
730     return NULL;
731 }
732 
ap_remove_loaded_module(module * mod)733 AP_DECLARE(void) ap_remove_loaded_module(module *mod)
734 {
735     module **m;
736     module **m2;
737     int done;
738 
739     /*
740      *  Remove module pointer from chained module list
741      */
742     ap_remove_module(mod);
743 
744     /*
745      *  Remove module pointer from list of loaded modules
746      *
747      *  Note: 1. We cannot determine if the module was successfully
748      *           removed by ap_remove_module().
749      *        2. We have not to complain explicitly when the module
750      *           is not found because ap_remove_module() did it
751      *           for us already.
752      */
753     for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
754         if (*m2 == mod && done == 0)
755             done = 1;
756         else
757             *m++ = *m2;
758     }
759 
760     *m = NULL;
761 }
762 
ap_setup_prelinked_modules(process_rec * process)763 AP_DECLARE(const char *) ap_setup_prelinked_modules(process_rec *process)
764 {
765     module **m;
766     module **m2;
767     const char *error;
768 
769     apr_hook_global_pool=process->pconf;
770 
771     rebuild_conf_hash(process->pconf, 0);
772 
773     /*
774      *  Initialise total_modules variable and module indices
775      */
776     total_modules = 0;
777     for (m = ap_preloaded_modules; *m != NULL; m++)
778         (*m)->module_index = total_modules++;
779 
780     max_modules = total_modules + DYNAMIC_MODULE_LIMIT + 1;
781     conf_vector_length = max_modules;
782 
783     /*
784      *  Initialise list of loaded modules and short names
785      */
786     ap_loaded_modules = (module **)apr_palloc(process->pool,
787         sizeof(module *) * conf_vector_length);
788     if (!ap_module_short_names)
789         ap_module_short_names = ap_calloc(sizeof(char *), conf_vector_length);
790 
791     if (!merger_func_cache)
792         merger_func_cache = ap_calloc(sizeof(merger_func), conf_vector_length);
793 
794     if (ap_loaded_modules == NULL || ap_module_short_names == NULL
795         || merger_func_cache == NULL)
796         return "Ouch! Out of memory in ap_setup_prelinked_modules()!";
797 
798     for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
799         *m2++ = *m++;
800 
801     *m2 = NULL;
802 
803     /*
804      *   Initialize chain of linked (=activate) modules
805      */
806     for (m = ap_prelinked_modules; *m != NULL; m++) {
807         error = ap_add_module(*m, process->pconf, NULL);
808         if (error) {
809             return error;
810         }
811     }
812 
813     apr_hook_sort_all();
814 
815     return NULL;
816 }
817 
ap_find_module_name(module * m)818 AP_DECLARE(const char *) ap_find_module_name(module *m)
819 {
820     return m->name;
821 }
822 
ap_find_module_short_name(int module_index)823 AP_DECLARE(const char *) ap_find_module_short_name(int module_index)
824 {
825         if (module_index < 0 || module_index >= conf_vector_length)
826                 return NULL;
827         return ap_module_short_names[module_index];
828 }
829 
ap_find_linked_module(const char * name)830 AP_DECLARE(module *) ap_find_linked_module(const char *name)
831 {
832     module *modp;
833 
834     for (modp = ap_top_module; modp; modp = modp->next) {
835         if (strcmp(modp->name, name) == 0)
836             return modp;
837     }
838 
839     return NULL;
840 }
841 
842 /*****************************************************************
843  *
844  * Resource, access, and .htaccess config files now parsed by a common
845  * command loop.
846  *
847  * Let's begin with the basics; parsing the line and
848  * invoking the function...
849  */
850 
851 #define AP_MAX_ARGC 64
852 
invoke_cmd(const command_rec * cmd,cmd_parms * parms,void * mconfig,const char * args)853 static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
854                               void *mconfig, const char *args)
855 {
856     int override_list_ok = 0;
857     char *w, *w2, *w3;
858     const char *errmsg = NULL;
859 
860     /* Have we been provided a list of acceptable directives? */
861     if (parms->override_list != NULL) {
862          if (apr_table_get(parms->override_list, cmd->name) != NULL) {
863               override_list_ok = 1;
864          }
865     }
866 
867     if ((parms->override & cmd->req_override) == 0 && !override_list_ok) {
868         if (parms->override & NONFATAL_OVERRIDE) {
869             ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, parms->temp_pool,
870                           APLOGNO(02295)
871                           "%s in .htaccess forbidden by AllowOverride",
872                           cmd->name);
873             return NULL;
874         }
875         else if (parms->directive && parms->directive->parent) {
876             return apr_pstrcat(parms->pool, cmd->name, " not allowed in ",
877                                parms->directive->parent->directive, ">",
878                                " context", NULL);
879         }
880         else {
881             return apr_pstrcat(parms->pool, cmd->name,
882                                " not allowed here", NULL);
883         }
884     }
885 
886     parms->info = cmd->cmd_data;
887     parms->cmd = cmd;
888 
889     switch (cmd->args_how) {
890     case RAW_ARGS:
891 #ifdef RESOLVE_ENV_PER_TOKEN
892         args = ap_resolve_env(parms->pool,args);
893 #endif
894         return cmd->AP_RAW_ARGS(parms, mconfig, args);
895 
896     case TAKE_ARGV:
897         {
898             char *argv[AP_MAX_ARGC];
899             int argc = 0;
900 
901             do {
902                 w = ap_getword_conf(parms->pool, &args);
903                 if (*w == '\0' && *args == '\0') {
904                     break;
905                 }
906                 argv[argc] = w;
907                 argc++;
908             } while (argc < AP_MAX_ARGC && *args != '\0');
909 
910             return cmd->AP_TAKE_ARGV(parms, mconfig, argc, argv);
911         }
912 
913     case NO_ARGS:
914         if (*args != 0)
915             return apr_pstrcat(parms->pool, cmd->name, " takes no arguments",
916                                NULL);
917 
918         return cmd->AP_NO_ARGS(parms, mconfig);
919 
920     case TAKE1:
921         w = ap_getword_conf(parms->pool, &args);
922 
923         if (*w == '\0' || *args != 0)
924             return apr_pstrcat(parms->pool, cmd->name, " takes one argument",
925                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
926 
927         return cmd->AP_TAKE1(parms, mconfig, w);
928 
929     case TAKE2:
930         w = ap_getword_conf(parms->pool, &args);
931         w2 = ap_getword_conf(parms->pool, &args);
932 
933         if (*w == '\0' || *w2 == '\0' || *args != 0)
934             return apr_pstrcat(parms->pool, cmd->name, " takes two arguments",
935                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
936 
937         return cmd->AP_TAKE2(parms, mconfig, w, w2);
938 
939     case TAKE12:
940         w = ap_getword_conf(parms->pool, &args);
941         w2 = ap_getword_conf(parms->pool, &args);
942 
943         if (*w == '\0' || *args != 0)
944             return apr_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
945                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
946 
947         return cmd->AP_TAKE2(parms, mconfig, w, *w2 ? w2 : NULL);
948 
949     case TAKE3:
950         w = ap_getword_conf(parms->pool, &args);
951         w2 = ap_getword_conf(parms->pool, &args);
952         w3 = ap_getword_conf(parms->pool, &args);
953 
954         if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
955             return apr_pstrcat(parms->pool, cmd->name, " takes three arguments",
956                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
957 
958         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
959 
960     case TAKE23:
961         w = ap_getword_conf(parms->pool, &args);
962         w2 = ap_getword_conf(parms->pool, &args);
963         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
964 
965         if (*w == '\0' || *w2 == '\0' || *args != 0)
966             return apr_pstrcat(parms->pool, cmd->name,
967                                " takes two or three arguments",
968                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
969 
970         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
971 
972     case TAKE123:
973         w = ap_getword_conf(parms->pool, &args);
974         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
975         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
976 
977         if (*w == '\0' || *args != 0)
978             return apr_pstrcat(parms->pool, cmd->name,
979                                " takes one, two or three arguments",
980                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
981 
982         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
983 
984     case TAKE13:
985         w = ap_getword_conf(parms->pool, &args);
986         w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
987         w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
988 
989         if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
990             return apr_pstrcat(parms->pool, cmd->name,
991                                " takes one or three arguments",
992                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
993 
994         return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
995 
996     case ITERATE:
997         w = ap_getword_conf(parms->pool, &args);
998 
999         if (*w == '\0')
1000             return apr_pstrcat(parms->pool, cmd->name,
1001                                " requires at least one argument",
1002                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
1003 
1004         while (*w != '\0') {
1005             errmsg = cmd->AP_TAKE1(parms, mconfig, w);
1006 
1007             if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
1008                 return errmsg;
1009 
1010             w = ap_getword_conf(parms->pool, &args);
1011         }
1012 
1013         return errmsg;
1014 
1015     case ITERATE2:
1016         w = ap_getword_conf(parms->pool, &args);
1017 
1018         if (*w == '\0' || *args == 0)
1019             return apr_pstrcat(parms->pool, cmd->name,
1020                                " requires at least two arguments",
1021                                cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
1022 
1023         while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0') {
1024 
1025             errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2);
1026 
1027             if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
1028                 return errmsg;
1029         }
1030 
1031         return errmsg;
1032 
1033     case FLAG:
1034         /*
1035          * This is safe to use temp_pool here, because the 'flag' itself is not
1036          * forwarded as-is
1037          */
1038         w = ap_getword_conf(parms->temp_pool, &args);
1039 
1040         if (*w == '\0' || (ap_cstr_casecmp(w, "on") && ap_cstr_casecmp(w, "off")))
1041             return apr_pstrcat(parms->pool, cmd->name, " must be On or Off",
1042                                NULL);
1043 
1044         return cmd->AP_FLAG(parms, mconfig, ap_cstr_casecmp(w, "off") != 0);
1045 
1046     default:
1047         return apr_pstrcat(parms->pool, cmd->name,
1048                            " is improperly configured internally (server bug)",
1049                            NULL);
1050     }
1051 }
1052 
ap_find_command(const char * name,const command_rec * cmds)1053 AP_CORE_DECLARE(const command_rec *) ap_find_command(const char *name,
1054                                                      const command_rec *cmds)
1055 {
1056     while (cmds->name) {
1057         if (!ap_cstr_casecmp(name, cmds->name))
1058             return cmds;
1059 
1060         ++cmds;
1061     }
1062 
1063     return NULL;
1064 }
1065 
ap_find_command_in_modules(const char * cmd_name,module ** mod)1066 AP_CORE_DECLARE(const command_rec *) ap_find_command_in_modules(
1067                                           const char *cmd_name, module **mod)
1068 {
1069     const command_rec *cmdp;
1070     module *modp;
1071 
1072     for (modp = *mod; modp; modp = modp->next) {
1073         if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
1074             *mod = modp;
1075             return cmdp;
1076         }
1077     }
1078 
1079     return NULL;
1080 }
1081 
ap_set_config_vectors(server_rec * server,ap_conf_vector_t * section_vector,const char * section,module * mod,apr_pool_t * pconf)1082 AP_CORE_DECLARE(void *) ap_set_config_vectors(server_rec *server,
1083                                               ap_conf_vector_t *section_vector,
1084                                               const char *section,
1085                                               module *mod, apr_pool_t *pconf)
1086 {
1087     void *section_config = ap_get_module_config(section_vector, mod);
1088     void *server_config = ap_get_module_config(server->module_config, mod);
1089 
1090     if (!section_config && mod->create_dir_config) {
1091         /* ### need to fix the create_dir_config functions' prototype... */
1092         section_config = (*mod->create_dir_config)(pconf, (char *)section);
1093         ap_set_module_config(section_vector, mod, section_config);
1094     }
1095 
1096     if (!server_config && mod->create_server_config) {
1097         server_config = (*mod->create_server_config)(pconf, server);
1098         ap_set_module_config(server->module_config, mod, server_config);
1099     }
1100 
1101     return section_config;
1102 }
1103 
1104 static const char *execute_now(char *cmd_line, const char *args,
1105                                cmd_parms *parms,
1106                                apr_pool_t *p, apr_pool_t *ptemp,
1107                                ap_directive_t **sub_tree,
1108                                ap_directive_t *parent);
1109 
ap_build_config_sub(apr_pool_t * p,apr_pool_t * temp_pool,const char * l,cmd_parms * parms,ap_directive_t ** current,ap_directive_t ** curr_parent,ap_directive_t ** conftree)1110 static const char *ap_build_config_sub(apr_pool_t *p, apr_pool_t *temp_pool,
1111                                        const char *l, cmd_parms *parms,
1112                                        ap_directive_t **current,
1113                                        ap_directive_t **curr_parent,
1114                                        ap_directive_t **conftree)
1115 {
1116     const char *retval = NULL;
1117     const char *args;
1118     char *cmd_name;
1119     ap_directive_t *newdir;
1120     const command_rec *cmd;
1121     ap_mod_list *ml;
1122     char *lname;
1123 
1124     if (*l == '#' || *l == '\0')
1125         return NULL;
1126 
1127 #if RESOLVE_ENV_PER_TOKEN
1128     args = l;
1129 #else
1130     args = ap_resolve_env(temp_pool, l);
1131 #endif
1132 
1133     /* The first word is the name of a directive.  We can safely use the
1134      * 'temp_pool' for it.  If it matches the name of a known directive, we
1135      * can reference the string within the module if needed.  Otherwise, we
1136      * can still make a copy in the 'p' pool. */
1137     cmd_name = ap_getword_conf(temp_pool, &args);
1138     if (*cmd_name == '\0') {
1139         /* Note: this branch should not occur. An empty line should have
1140          * triggered the exit further above.
1141          */
1142         return NULL;
1143     }
1144 
1145     if (cmd_name[1] != '/') {
1146         char *lastc = cmd_name + strlen(cmd_name) - 1;
1147         if (*lastc == '>') {
1148             *lastc = '\0' ;
1149         }
1150         if (cmd_name[0] == '<' && *args == '\0') {
1151             args = ">";
1152         }
1153     }
1154 
1155     newdir = apr_pcalloc(p, sizeof(ap_directive_t));
1156     newdir->filename = parms->config_file->name;
1157     newdir->line_num = parms->config_file->line_number;
1158     newdir->args = apr_pstrdup(p, args);
1159 
1160     lname = apr_pstrdup(temp_pool, cmd_name);
1161     ap_str_tolower(lname);
1162     ml = apr_hash_get(ap_config_hash, lname, APR_HASH_KEY_STRING);
1163 
1164     if (ml && (cmd = ml->cmd) != NULL) {
1165         newdir->directive = cmd->name;
1166         if (cmd->req_override & EXEC_ON_READ) {
1167             ap_directive_t *sub_tree = NULL;
1168 
1169             parms->err_directive = newdir;
1170             retval = execute_now(cmd_name, args, parms, p, temp_pool,
1171                                  &sub_tree, *curr_parent);
1172             if (*current) {
1173                 (*current)->next = sub_tree;
1174             }
1175             else {
1176                 *current = sub_tree;
1177                 if (*curr_parent) {
1178                     (*curr_parent)->first_child = (*current);
1179                 }
1180                 if (*current) {
1181                     (*current)->parent = (*curr_parent);
1182                 }
1183             }
1184             if (*current) {
1185                 if (!*conftree) {
1186                     /* Before walking *current to the end of the list,
1187                      * set the head to *current.
1188                      */
1189                     *conftree = *current;
1190                 }
1191                 while ((*current)->next != NULL) {
1192                     (*current) = (*current)->next;
1193                     (*current)->parent = (*curr_parent);
1194                 }
1195             }
1196             return retval;
1197         }
1198     }
1199     else {
1200         /* No known directive found?  Make a copy of what we have parsed. */
1201         newdir->directive = apr_pstrdup(p, cmd_name);
1202     }
1203 
1204 
1205     if (cmd_name[0] == '<') {
1206         if (cmd_name[1] != '/') {
1207             (*current) = ap_add_node(curr_parent, *current, newdir, 1);
1208         }
1209         else if (*curr_parent == NULL) {
1210             parms->err_directive = newdir;
1211             return apr_pstrcat(p, cmd_name,
1212                                " without matching <", cmd_name + 2,
1213                                " section", NULL);
1214         }
1215         else {
1216             char *bracket = cmd_name + strlen(cmd_name) - 1;
1217 
1218             if (*bracket != '>') {
1219                 parms->err_directive = newdir;
1220                 return apr_pstrcat(p, cmd_name,
1221                                    "> directive missing closing '>'", NULL);
1222             }
1223 
1224             *bracket = '\0';
1225 
1226             if (ap_cstr_casecmp(cmd_name + 2,
1227                            (*curr_parent)->directive + 1) != 0) {
1228                 parms->err_directive = newdir;
1229                 return apr_pstrcat(p, "Expected </",
1230                                    (*curr_parent)->directive + 1, "> but saw ",
1231                                    cmd_name, ">", NULL);
1232             }
1233 
1234             *bracket = '>';
1235 
1236             /* done with this section; move up a level */
1237             *current = *curr_parent;
1238             *curr_parent = (*current)->parent;
1239         }
1240     }
1241     else {
1242         *current = ap_add_node(curr_parent, *current, newdir, 0);
1243     }
1244 
1245     return retval;
1246 }
1247 
1248 #define VARBUF_INIT_LEN 200
1249 #define VARBUF_MAX_LEN  (16*1024*1024)
1250 
ap_build_cont_config(apr_pool_t * p,apr_pool_t * temp_pool,cmd_parms * parms,ap_directive_t ** current,ap_directive_t ** curr_parent,char * orig_directive)1251 AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
1252                                               apr_pool_t *temp_pool,
1253                                               cmd_parms *parms,
1254                                               ap_directive_t **current,
1255                                               ap_directive_t **curr_parent,
1256                                               char *orig_directive)
1257 {
1258     char *bracket;
1259     const char *retval;
1260     ap_directive_t *sub_tree = NULL;
1261     apr_status_t rc;
1262     struct ap_varbuf vb;
1263     apr_size_t max_len = VARBUF_MAX_LEN;
1264     if (p == temp_pool)
1265         max_len = HUGE_STRING_LEN; /* lower limit for .htaccess */
1266 
1267     bracket = apr_pstrcat(temp_pool, orig_directive + 1, ">", NULL);
1268     ap_varbuf_init(temp_pool, &vb, VARBUF_INIT_LEN);
1269 
1270     while ((rc = ap_varbuf_cfg_getline(&vb, parms->config_file, max_len))
1271            == APR_SUCCESS) {
1272         if (!memcmp(vb.buf, "</", 2)
1273             && (ap_cstr_casecmp(vb.buf + 2, bracket) == 0)
1274             && (*curr_parent == NULL)) {
1275             break;
1276         }
1277         retval = ap_build_config_sub(p, temp_pool, vb.buf, parms, current,
1278                                      curr_parent, &sub_tree);
1279         if (retval != NULL)
1280             return retval;
1281 
1282         if (sub_tree == NULL) {
1283             sub_tree = *curr_parent;
1284         }
1285 
1286         if (sub_tree == NULL) {
1287             sub_tree = *current;
1288         }
1289     }
1290     ap_varbuf_free(&vb);
1291     if (rc != APR_EOF && rc != APR_SUCCESS)
1292         return ap_pcfg_strerror(temp_pool, parms->config_file, rc);
1293 
1294     *current = sub_tree;
1295     return NULL;
1296 }
1297 
ap_walk_config_sub(const ap_directive_t * current,cmd_parms * parms,ap_conf_vector_t * section_vector)1298 static const char *ap_walk_config_sub(const ap_directive_t *current,
1299                                       cmd_parms *parms,
1300                                       ap_conf_vector_t *section_vector)
1301 {
1302     const command_rec *cmd;
1303     ap_mod_list *ml;
1304     char *dir = apr_pstrdup(parms->temp_pool, current->directive);
1305 
1306     ap_str_tolower(dir);
1307 
1308     ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
1309 
1310     if (ml == NULL) {
1311         parms->err_directive = current;
1312         if (parms->override & NONFATAL_UNKNOWN) {
1313             ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, parms->temp_pool,
1314                           APLOGNO(02296) "Unknown directive %s "
1315                           "perhaps misspelled or defined by a module "
1316                           "not included in the server configuration", dir);
1317             return NULL;
1318         }
1319         else {
1320             return apr_pstrcat(parms->pool, "Invalid command '",
1321                                current->directive,
1322                                "', perhaps misspelled or defined by a module "
1323                                "not included in the server configuration",
1324                                NULL);
1325         }
1326     }
1327 
1328     for ( ; ml != NULL; ml = ml->next) {
1329         void *dir_config = ap_set_config_vectors(parms->server,
1330                                                  section_vector,
1331                                                  parms->path,
1332                                                  ml->m,
1333                                                  parms->pool);
1334         const char *retval;
1335         cmd = ml->cmd;
1336 
1337         /* Once was enough? */
1338         if (cmd->req_override & EXEC_ON_READ) {
1339             continue;
1340         }
1341 
1342         retval = invoke_cmd(cmd, parms, dir_config, current->args);
1343 
1344         if (retval != NULL && strcmp(retval, DECLINE_CMD) != 0) {
1345             /* If the directive in error has already been set, don't
1346              * replace it.  Otherwise, an error inside a container
1347              * will be reported as occurring on the first line of the
1348              * container.
1349              */
1350             if (!parms->err_directive) {
1351                 parms->err_directive = current;
1352             }
1353             return retval;
1354         }
1355     }
1356 
1357     return NULL;
1358 }
1359 
ap_walk_config(ap_directive_t * current,cmd_parms * parms,ap_conf_vector_t * section_vector)1360 AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current,
1361                                         cmd_parms *parms,
1362                                         ap_conf_vector_t *section_vector)
1363 {
1364     ap_conf_vector_t *oldconfig = parms->context;
1365 
1366     parms->context = section_vector;
1367 
1368     /* scan through all directives, executing each one */
1369     for (; current != NULL; current = current->next) {
1370         const char *errmsg;
1371 
1372         parms->directive = current;
1373 
1374         /* actually parse the command and execute the correct function */
1375         errmsg = ap_walk_config_sub(current, parms, section_vector);
1376         if (errmsg != NULL) {
1377             /* restore the context (just in case) */
1378             parms->context = oldconfig;
1379             return errmsg;
1380         }
1381     }
1382 
1383     parms->context = oldconfig;
1384     return NULL;
1385 }
1386 
ap_build_config(cmd_parms * parms,apr_pool_t * p,apr_pool_t * temp_pool,ap_directive_t ** conftree)1387 AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
1388                                          apr_pool_t *p, apr_pool_t *temp_pool,
1389                                          ap_directive_t **conftree)
1390 {
1391     ap_directive_t *current = *conftree;
1392     ap_directive_t *curr_parent = NULL;
1393     const char *errmsg;
1394     ap_directive_t **last_ptr = NULL;
1395     apr_status_t rc;
1396     struct ap_varbuf vb;
1397     apr_size_t max_len = VARBUF_MAX_LEN;
1398     if (p == temp_pool)
1399         max_len = HUGE_STRING_LEN; /* lower limit for .htaccess */
1400 
1401     ap_varbuf_init(temp_pool, &vb, VARBUF_INIT_LEN);
1402 
1403     if (current != NULL) {
1404         /* If we have to traverse the whole tree again for every included
1405          * config file, the required time grows as O(n^2) with the number of
1406          * files. This can be a significant delay for large configurations.
1407          * Therefore we cache a pointer to the last node.
1408          */
1409         last_ptr = &(current->last);
1410 
1411         if (last_ptr && *last_ptr) {
1412             current = *last_ptr;
1413         }
1414 
1415         while (current->next) {
1416             current = current->next;
1417         }
1418 
1419         if (last_ptr) {
1420             /* update cached pointer to last node */
1421             *last_ptr = current;
1422         }
1423     }
1424 
1425     while ((rc = ap_varbuf_cfg_getline(&vb, parms->config_file, max_len))
1426            == APR_SUCCESS) {
1427         errmsg = ap_build_config_sub(p, temp_pool, vb.buf, parms,
1428                                      &current, &curr_parent, conftree);
1429         if (errmsg != NULL)
1430             return errmsg;
1431 
1432         if (*conftree == NULL && curr_parent != NULL) {
1433             *conftree = curr_parent;
1434         }
1435 
1436         if (*conftree == NULL && current != NULL) {
1437             *conftree = current;
1438         }
1439     }
1440     ap_varbuf_free(&vb);
1441     if (rc != APR_EOF && rc != APR_SUCCESS)
1442         return ap_pcfg_strerror(temp_pool, parms->config_file, rc);
1443 
1444     if (curr_parent != NULL) {
1445         errmsg = "";
1446 
1447         while (curr_parent != NULL) {
1448             errmsg = apr_psprintf(p, "%s%s%s:%u: %s> was not closed.",
1449                                   errmsg,
1450                                   *errmsg == '\0' ? "" : APR_EOL_STR,
1451                                   curr_parent->filename,
1452                                   curr_parent->line_num,
1453                                   curr_parent->directive);
1454 
1455             parms->err_directive = curr_parent;
1456             curr_parent = curr_parent->parent;
1457         }
1458 
1459         return errmsg;
1460     }
1461 
1462     return NULL;
1463 }
1464 
1465 /*
1466  * Generic command functions...
1467  */
1468 
ap_set_string_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)1469 AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
1470                                                    void *struct_ptr,
1471                                                    const char *arg)
1472 {
1473     int offset = (int)(long)cmd->info;
1474 
1475     *(const char **)((char *)struct_ptr + offset) = arg;
1476 
1477     return NULL;
1478 }
1479 
ap_set_int_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)1480 AP_DECLARE_NONSTD(const char *) ap_set_int_slot(cmd_parms *cmd,
1481                                                 void *struct_ptr,
1482                                                 const char *arg)
1483 {
1484     char *endptr;
1485     char *error_str = NULL;
1486     int offset = (int)(long)cmd->info;
1487 
1488     *(int *)((char*)struct_ptr + offset) = strtol(arg, &endptr, 10);
1489 
1490     if ((*arg == '\0') || (*endptr != '\0')) {
1491         error_str = apr_psprintf(cmd->pool,
1492                      "Invalid value for directive %s, expected integer",
1493                      cmd->directive->directive);
1494     }
1495 
1496     return error_str;
1497 }
1498 
ap_set_string_slot_lower(cmd_parms * cmd,void * struct_ptr,const char * arg_)1499 AP_DECLARE_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
1500                                                          void *struct_ptr,
1501                                                          const char *arg_)
1502 {
1503     char *arg = apr_pstrdup(cmd->pool,arg_);
1504     int offset = (int)(long)cmd->info;
1505 
1506     ap_str_tolower(arg);
1507     *(char **)((char *)struct_ptr + offset) = arg;
1508 
1509     return NULL;
1510 }
1511 
ap_set_flag_slot(cmd_parms * cmd,void * struct_ptr_v,int arg)1512 AP_DECLARE_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
1513                                                  void *struct_ptr_v, int arg)
1514 {
1515     int offset = (int)(long)cmd->info;
1516     char *struct_ptr = (char *)struct_ptr_v;
1517 
1518     *(int *)(struct_ptr + offset) = arg ? 1 : 0;
1519 
1520     return NULL;
1521 }
1522 
ap_set_flag_slot_char(cmd_parms * cmd,void * struct_ptr_v,int arg)1523 AP_DECLARE_NONSTD(const char *) ap_set_flag_slot_char(cmd_parms *cmd,
1524                                                       void *struct_ptr_v, int arg)
1525 {
1526     int offset = (int)(long)cmd->info;
1527     char *struct_ptr = (char *)struct_ptr_v;
1528 
1529     *(struct_ptr + offset) = arg ? 1 : 0;
1530 
1531     return NULL;
1532 }
1533 
1534 
ap_set_file_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)1535 AP_DECLARE_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, void *struct_ptr,
1536                                                  const char *arg)
1537 {
1538     /* Prepend server_root to relative arg.
1539      * This allows most args to be independent of server_root,
1540      * so the server can be moved or mirrored with less pain.
1541      */
1542     const char *path;
1543     int offset = (int)(long)cmd->info;
1544 
1545     path = ap_server_root_relative(cmd->pool, arg);
1546 
1547     if (!path) {
1548         return apr_pstrcat(cmd->pool, cmd->cmd->name, ": Invalid file path '",
1549                            arg, "'", NULL);
1550     }
1551 
1552     *(const char **) ((char*)struct_ptr + offset) = path;
1553 
1554     return NULL;
1555 }
1556 
ap_set_deprecated(cmd_parms * cmd,void * struct_ptr,const char * arg)1557 AP_DECLARE_NONSTD(const char *) ap_set_deprecated(cmd_parms *cmd,
1558                                                   void *struct_ptr,
1559                                                   const char *arg)
1560 {
1561     return cmd->cmd->errmsg;
1562 }
1563 
ap_reset_module_loglevels(struct ap_logconf * l,int val)1564 AP_DECLARE(void) ap_reset_module_loglevels(struct ap_logconf *l, int val)
1565 {
1566     if (l->module_levels)
1567         memset(l->module_levels, val, conf_vector_length);
1568 }
1569 
ap_set_module_loglevel(apr_pool_t * pool,struct ap_logconf * l,int index,int level)1570 AP_DECLARE(void) ap_set_module_loglevel(apr_pool_t *pool, struct ap_logconf *l,
1571                                         int index, int level)
1572 {
1573     if (!l->module_levels) {
1574         l->module_levels = apr_palloc(pool, conf_vector_length);
1575         if (l->level == APLOG_UNSET) {
1576                 ap_reset_module_loglevels(l, APLOG_UNSET);
1577         }
1578         else {
1579                 ap_reset_module_loglevels(l, APLOG_NO_MODULE);
1580         }
1581     }
1582 
1583     l->module_levels[index] = level;
1584 }
1585 
1586 /*****************************************************************
1587  *
1588  * Reading whole config files...
1589  */
1590 
1591 static cmd_parms default_parms =
1592 {NULL, 0, 0, NULL, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1593 
ap_server_root_relative(apr_pool_t * p,const char * file)1594 AP_DECLARE(char *) ap_server_root_relative(apr_pool_t *p, const char *file)
1595 {
1596     char *newpath = NULL;
1597     apr_status_t rv;
1598     rv = apr_filepath_merge(&newpath, ap_server_root, file,
1599                             APR_FILEPATH_TRUENAME, p);
1600     if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv)
1601                                       || APR_STATUS_IS_ENOENT(rv)
1602                                       || APR_STATUS_IS_ENOTDIR(rv))) {
1603         return newpath;
1604     }
1605     else {
1606         return NULL;
1607     }
1608 }
1609 
ap_runtime_dir_relative(apr_pool_t * p,const char * file)1610 AP_DECLARE(char *) ap_runtime_dir_relative(apr_pool_t *p, const char *file)
1611 {
1612     char *newpath = NULL;
1613     apr_status_t rv;
1614     const char *runtime_dir = ap_runtime_dir ? ap_runtime_dir : ap_server_root_relative(p, DEFAULT_REL_RUNTIMEDIR);
1615 
1616     rv = apr_filepath_merge(&newpath, runtime_dir, file,
1617                             APR_FILEPATH_TRUENAME, p);
1618     if (newpath && (rv == APR_SUCCESS || APR_STATUS_IS_EPATHWILD(rv)
1619                                       || APR_STATUS_IS_ENOENT(rv)
1620                                       || APR_STATUS_IS_ENOTDIR(rv))) {
1621         return newpath;
1622     }
1623     else {
1624         return NULL;
1625     }
1626 }
1627 
1628 
ap_soak_end_container(cmd_parms * cmd,char * directive)1629 AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
1630 {
1631     struct ap_varbuf vb;
1632     const char *args;
1633     char *cmd_name;
1634     apr_status_t rc;
1635     apr_size_t max_len = VARBUF_MAX_LEN;
1636     if (cmd->pool == cmd->temp_pool)
1637         max_len = HUGE_STRING_LEN; /* lower limit for .htaccess */
1638 
1639     ap_varbuf_init(cmd->temp_pool, &vb, VARBUF_INIT_LEN);
1640 
1641     while ((rc = ap_varbuf_cfg_getline(&vb, cmd->config_file, max_len))
1642            == APR_SUCCESS) {
1643         args = vb.buf;
1644 
1645         cmd_name = ap_getword_conf(cmd->temp_pool, &args);
1646         if (cmd_name[0] == '<') {
1647             if (cmd_name[1] == '/') {
1648                 cmd_name[strlen(cmd_name) - 1] = '\0';
1649 
1650                 if (ap_cstr_casecmp(cmd_name + 2, directive + 1) != 0) {
1651                     return apr_pstrcat(cmd->pool, "Expected </",
1652                                        directive + 1, "> but saw ",
1653                                        cmd_name, ">", NULL);
1654                 }
1655 
1656                 ap_varbuf_free(&vb);
1657                 return NULL; /* found end of container */
1658             }
1659             else {
1660                 const char *msg;
1661 
1662                 if (*args == '\0' && cmd_name[strlen(cmd_name) - 1] == '>') {
1663                     cmd_name[strlen(cmd_name) - 1] = '\0';
1664                 }
1665 
1666                 if ((msg = ap_soak_end_container(cmd, cmd_name)) != NULL) {
1667                     return msg;
1668                 }
1669             }
1670         }
1671     }
1672     if (rc != APR_EOF && rc != APR_SUCCESS)
1673         return ap_pcfg_strerror(cmd->temp_pool, cmd->config_file, rc);
1674 
1675     return apr_pstrcat(cmd->pool, "Expected </",
1676                        directive + 1, "> before end of configuration",
1677                        NULL);
1678 }
1679 
execute_now(char * cmd_line,const char * args,cmd_parms * parms,apr_pool_t * p,apr_pool_t * ptemp,ap_directive_t ** sub_tree,ap_directive_t * parent)1680 static const char *execute_now(char *cmd_line, const char *args,
1681                                cmd_parms *parms,
1682                                apr_pool_t *p, apr_pool_t *ptemp,
1683                                ap_directive_t **sub_tree,
1684                                ap_directive_t *parent)
1685 {
1686     const command_rec *cmd;
1687     ap_mod_list *ml;
1688     char *dir = apr_pstrdup(parms->temp_pool, cmd_line);
1689 
1690     ap_str_tolower(dir);
1691 
1692     ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
1693 
1694     if (ml == NULL) {
1695         return apr_pstrcat(parms->pool, "Invalid command '",
1696                            cmd_line,
1697                            "', perhaps misspelled or defined by a module "
1698                            "not included in the server configuration",
1699                            NULL);
1700     }
1701 
1702     for ( ; ml != NULL; ml = ml->next) {
1703         const char *retval;
1704         cmd = ml->cmd;
1705 
1706         retval = invoke_cmd(cmd, parms, sub_tree, args);
1707 
1708         if (retval != NULL) {
1709             return retval;
1710         }
1711     }
1712 
1713     return NULL;
1714 }
1715 
1716 /* This structure and the following functions are needed for the
1717  * table-based config file reading. They are passed to the
1718  * cfg_open_custom() routine.
1719  */
1720 
1721 /* Structure to be passed to cfg_open_custom(): it contains an
1722  * index which is incremented from 0 to nelts on each call to
1723  * cfg_getline() (which in turn calls arr_elts_getstr())
1724  * and an apr_array_header_t pointer for the string array.
1725  */
1726 typedef struct {
1727     apr_array_header_t *array;
1728     int curr_idx;
1729 } arr_elts_param_t;
1730 
1731 
1732 /* arr_elts_getstr() returns the next line from the string array. */
arr_elts_getstr(void * buf,apr_size_t bufsiz,void * param)1733 static apr_status_t arr_elts_getstr(void *buf, apr_size_t bufsiz, void *param)
1734 {
1735     arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
1736     const char *elt;
1737 
1738     /* End of array reached? */
1739     if (++arr_param->curr_idx > arr_param->array->nelts)
1740         return APR_EOF;
1741 
1742     /* return the line */
1743     elt = ((const char **)arr_param->array->elts)[arr_param->curr_idx - 1];
1744     if (apr_cpystrn(buf, elt, bufsiz) - (char *)buf >= bufsiz - 1)
1745         return APR_ENOSPC;
1746     return APR_SUCCESS;
1747 }
1748 
1749 
1750 /* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
arr_elts_close(void * param)1751 static apr_status_t arr_elts_close(void *param)
1752 {
1753     arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
1754 
1755     arr_param->curr_idx = arr_param->array->nelts;
1756 
1757     return APR_SUCCESS;
1758 }
1759 
process_command_config(server_rec * s,apr_array_header_t * arr,ap_directive_t ** conftree,apr_pool_t * p,apr_pool_t * ptemp)1760 static const char *process_command_config(server_rec *s,
1761                                           apr_array_header_t *arr,
1762                                           ap_directive_t **conftree,
1763                                           apr_pool_t *p,
1764                                           apr_pool_t *ptemp)
1765 {
1766     const char *errmsg;
1767     cmd_parms parms;
1768     arr_elts_param_t arr_parms;
1769 
1770     arr_parms.curr_idx = 0;
1771     arr_parms.array = arr;
1772 
1773     if (ap_config_hash == NULL) {
1774         rebuild_conf_hash(s->process->pconf, 1);
1775     }
1776 
1777     parms = default_parms;
1778     parms.pool = p;
1779     parms.temp_pool = ptemp;
1780     parms.server = s;
1781     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1782     parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
1783 
1784     parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
1785                                             &arr_parms, NULL,
1786                                             arr_elts_getstr, arr_elts_close);
1787 
1788     errmsg = ap_build_config(&parms, p, ptemp, conftree);
1789     ap_cfg_closefile(parms.config_file);
1790 
1791     if (errmsg) {
1792         return apr_pstrcat(p, "Syntax error in -C/-c directive: ", errmsg,
1793                            NULL);
1794     }
1795 
1796     return NULL;
1797 }
1798 
1799 /**
1800  * Used by -D DUMP_INCLUDES to output the config file "tree".
1801  */
dump_config_name(const char * fname,apr_pool_t * p)1802 static void dump_config_name(const char *fname, apr_pool_t *p)
1803 {
1804     unsigned i, recursion, line_number;
1805     void *data;
1806     apr_file_t *out = NULL;
1807 
1808     apr_file_open_stdout(&out, p);
1809 
1810     /* ap_include_sentinel is defined by the core Include directive; use it to
1811      * figure out how deep in the stack we are.
1812      */
1813     apr_pool_userdata_get(&data, "ap_include_sentinel", p);
1814 
1815     if (data) {
1816         recursion = *(unsigned *)data;
1817     } else {
1818         recursion = 0;
1819     }
1820 
1821     /* Indent once for each level. */
1822     for (i = 0; i < (recursion + 1); ++i) {
1823         apr_file_printf(out, "  ");
1824     }
1825 
1826     /* ap_include_lineno is similarly defined to tell us where in the last
1827      * config file we were.
1828      */
1829     apr_pool_userdata_get(&data, "ap_include_lineno", p);
1830 
1831     if (data) {
1832         line_number = *(unsigned *)data;
1833     } else {
1834         line_number = 0;
1835     }
1836 
1837     /* Print the line number and the name of the parsed file. */
1838     if (line_number > 0) {
1839         apr_file_printf(out, "(%u)", line_number);
1840     } else {
1841         apr_file_printf(out, "(*)");
1842     }
1843 
1844     apr_file_printf(out, " %s\n", fname);
1845 }
1846 
ap_process_resource_config(server_rec * s,const char * fname,ap_directive_t ** conftree,apr_pool_t * p,apr_pool_t * ptemp)1847 AP_DECLARE(const char *) ap_process_resource_config(server_rec *s,
1848                                                     const char *fname,
1849                                                     ap_directive_t **conftree,
1850                                                     apr_pool_t *p,
1851                                                     apr_pool_t *ptemp)
1852 {
1853     ap_configfile_t *cfp;
1854     cmd_parms parms;
1855     apr_status_t rv;
1856     const char *error;
1857 
1858     parms = default_parms;
1859     parms.pool = p;
1860     parms.temp_pool = ptemp;
1861     parms.server = s;
1862     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1863     parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
1864 
1865     rv = ap_pcfg_openfile(&cfp, p, fname);
1866     if (rv != APR_SUCCESS) {
1867         return apr_psprintf(p, "Could not open configuration file %s: %pm",
1868                             fname, &rv);
1869     }
1870 
1871     if (ap_exists_config_define("DUMP_INCLUDES")) {
1872         dump_config_name(fname, p);
1873     }
1874 
1875     parms.config_file = cfp;
1876     error = ap_build_config(&parms, p, ptemp, conftree);
1877     ap_cfg_closefile(cfp);
1878 
1879     if (error) {
1880         if (parms.err_directive)
1881             return apr_psprintf(p, "Syntax error on line %d of %s: %s",
1882                                 parms.err_directive->line_num,
1883                                 parms.err_directive->filename, error);
1884         else
1885             return error;
1886     }
1887 
1888     return NULL;
1889 }
1890 
1891 typedef struct {
1892     server_rec *s;
1893     ap_directive_t **conftree;
1894 } configs;
1895 
process_resource_config_cb(ap_dir_match_t * w,const char * fname)1896 static const char *process_resource_config_cb(ap_dir_match_t *w, const char *fname)
1897 {
1898     configs *cfgs = w->ctx;
1899     return ap_process_resource_config(cfgs->s, fname, cfgs->conftree, w->p, w->ptemp);
1900 }
1901 
ap_process_fnmatch_configs(server_rec * s,const char * fname,ap_directive_t ** conftree,apr_pool_t * p,apr_pool_t * ptemp,int optional)1902 AP_DECLARE(const char *) ap_process_fnmatch_configs(server_rec *s,
1903                                                     const char *fname,
1904                                                     ap_directive_t **conftree,
1905                                                     apr_pool_t *p,
1906                                                     apr_pool_t *ptemp,
1907                                                     int optional)
1908 {
1909     configs cfgs;
1910     ap_dir_match_t w;
1911 
1912     cfgs.s = s;
1913     cfgs.conftree = conftree;
1914 
1915     w.prefix = "Include/IncludeOptional: ";
1916     w.p = p;
1917     w.ptemp = ptemp;
1918     w.flags = (optional ? AP_DIR_FLAG_OPTIONAL : AP_DIR_FLAG_NONE) | AP_DIR_FLAG_RECURSIVE;
1919     w.cb = process_resource_config_cb;
1920     w.ctx = &cfgs;
1921     w.depth = 0;
1922 
1923     /* don't require conf/httpd.conf if we have a -C or -c switch */
1924     if ((ap_server_pre_read_config->nelts
1925         || ap_server_post_read_config->nelts)
1926         && !(strcmp(fname, ap_server_root_relative(ptemp, SERVER_CONFIG_FILE)))) {
1927         apr_finfo_t finfo;
1928 
1929         if (apr_stat(&finfo, fname, APR_FINFO_LINK | APR_FINFO_TYPE, ptemp) != APR_SUCCESS)
1930             return NULL;
1931     }
1932 
1933     if (!apr_fnmatch_test(fname)) {
1934         return ap_dir_nofnmatch(&w, fname);
1935     }
1936     else {
1937         apr_status_t status;
1938         const char *rootpath, *filepath = fname;
1939 
1940         /* locate the start of the directories proper */
1941         status = apr_filepath_root(&rootpath, &filepath, APR_FILEPATH_TRUENAME, ptemp);
1942 
1943         /* we allow APR_SUCCESS and APR_EINCOMPLETE */
1944         if (APR_ERELATIVE == status) {
1945             return apr_pstrcat(p, "Include must have an absolute path, ", fname, NULL);
1946         }
1947         else if (APR_EBADPATH == status) {
1948             return apr_pstrcat(p, "Include has a bad path, ", fname, NULL);
1949         }
1950 
1951         /* walk the filepath */
1952         return ap_dir_fnmatch(&w, rootpath, filepath);
1953     }
1954 }
1955 
ap_process_config_tree(server_rec * s,ap_directive_t * conftree,apr_pool_t * p,apr_pool_t * ptemp)1956 AP_DECLARE(int) ap_process_config_tree(server_rec *s,
1957                                        ap_directive_t *conftree,
1958                                        apr_pool_t *p,
1959                                        apr_pool_t *ptemp)
1960 {
1961     const char *errmsg;
1962     cmd_parms parms;
1963 
1964     parms = default_parms;
1965     parms.pool = p;
1966     parms.temp_pool = ptemp;
1967     parms.server = s;
1968     parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
1969     parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
1970     parms.limited = -1;
1971 
1972     errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
1973     if (errmsg) {
1974         if (parms.err_directive)
1975             ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p, APLOGNO(00526)
1976                           "Syntax error on line %d of %s:",
1977                           parms.err_directive->line_num,
1978                           parms.err_directive->filename);
1979         ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p, "%s", errmsg);
1980         return HTTP_INTERNAL_SERVER_ERROR;
1981     }
1982 
1983     return OK;
1984 }
1985 
ap_open_htaccess(request_rec * r,const char * dir_name,const char * access_name,ap_configfile_t ** conffile,const char ** full_name)1986 apr_status_t ap_open_htaccess(request_rec *r, const char *dir_name,
1987                               const char *access_name,
1988                               ap_configfile_t **conffile,
1989                               const char **full_name)
1990 {
1991     *full_name = ap_make_full_path(r->pool, dir_name, access_name);
1992     return ap_pcfg_openfile(conffile, r->pool, *full_name);
1993 }
1994 
ap_parse_htaccess(ap_conf_vector_t ** result,request_rec * r,int override,int override_opts,apr_table_t * override_list,const char * d,const char * access_names)1995 AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
1996                                        request_rec *r, int override,
1997                                        int override_opts, apr_table_t *override_list,
1998                                        const char *d, const char *access_names)
1999 {
2000     ap_configfile_t *f = NULL;
2001     cmd_parms parms;
2002     const char *filename;
2003     const struct htaccess_result *cache;
2004     struct htaccess_result *new;
2005     ap_conf_vector_t *dc = NULL;
2006     apr_status_t status;
2007 
2008     /* firstly, search cache */
2009     for (cache = r->htaccess; cache != NULL; cache = cache->next) {
2010         if (cache->override == override && strcmp(cache->dir, d) == 0) {
2011             *result = cache->htaccess;
2012             return OK;
2013         }
2014     }
2015 
2016     parms = default_parms;
2017     parms.override = override;
2018     parms.override_opts = override_opts;
2019     parms.override_list = override_list;
2020     parms.pool = r->pool;
2021     parms.temp_pool = r->pool;
2022     parms.server = r->server;
2023     parms.path = apr_pstrdup(r->pool, d);
2024 
2025     /* loop through the access names and find the first one */
2026     while (access_names[0]) {
2027         const char *access_name = ap_getword_conf(r->pool, &access_names);
2028 
2029         filename = NULL;
2030         status = ap_run_open_htaccess(r, d, access_name, &f, &filename);
2031         if (status == APR_SUCCESS) {
2032             const char *errmsg;
2033             ap_directive_t *temptree = NULL;
2034 
2035             dc = ap_create_per_dir_config(r->pool);
2036 
2037             parms.config_file = f;
2038             errmsg = ap_build_config(&parms, r->pool, r->pool, &temptree);
2039             if (errmsg == NULL)
2040                 errmsg = ap_walk_config(temptree, &parms, dc);
2041 
2042             ap_cfg_closefile(f);
2043 
2044             if (errmsg) {
2045                 ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r,
2046                               "%s: %s", filename, errmsg);
2047                 return HTTP_INTERNAL_SERVER_ERROR;
2048             }
2049 
2050             *result = dc;
2051             break;
2052         }
2053         else {
2054             if (!APR_STATUS_IS_ENOENT(status)
2055                 && !APR_STATUS_IS_ENOTDIR(status)) {
2056                 ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r, APLOGNO(00529)
2057                               "%s pcfg_openfile: unable to check htaccess file, "
2058                               "ensure it is readable and that '%s' "
2059                               "is executable",
2060                               filename, d);
2061                 apr_table_setn(r->notes, "error-notes",
2062                                "Server unable to read htaccess file, denying "
2063                                "access to be safe");
2064                 return HTTP_FORBIDDEN;
2065             }
2066         }
2067     }
2068 
2069     /* cache it */
2070     new = apr_palloc(r->pool, sizeof(struct htaccess_result));
2071     new->dir = parms.path;
2072     new->override = override;
2073     new->override_opts = override_opts;
2074     new->htaccess = dc;
2075 
2076     /* add to head of list */
2077     new->next = r->htaccess;
2078     r->htaccess = new;
2079 
2080     return OK;
2081 }
2082 
ap_init_virtual_host(apr_pool_t * p,const char * hostname,server_rec * main_server,server_rec ** ps)2083 AP_CORE_DECLARE(const char *) ap_init_virtual_host(apr_pool_t *p,
2084                                                    const char *hostname,
2085                                                    server_rec *main_server,
2086                                                    server_rec **ps)
2087 {
2088     server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
2089 
2090     /* TODO: this crap belongs in http_core */
2091     s->process = main_server->process;
2092     s->server_admin = NULL;
2093     s->server_hostname = NULL;
2094     s->server_scheme = NULL;
2095     s->error_fname = NULL;
2096     s->timeout = 0;
2097     s->keep_alive_timeout = 0;
2098     s->keep_alive = -1;
2099     s->keep_alive_max = -1;
2100     s->error_log = main_server->error_log;
2101     s->log.level = APLOG_UNSET;
2102     s->log.module_levels = NULL;
2103     /* useful default, otherwise we get a port of 0 on redirects */
2104     s->port = main_server->port;
2105     s->next = NULL;
2106 
2107     s->is_virtual = 1;
2108     s->names = apr_array_make(p, 4, sizeof(char **));
2109     s->wild_names = apr_array_make(p, 4, sizeof(char **));
2110 
2111     s->module_config = create_empty_config(p);
2112     s->lookup_defaults = ap_create_per_dir_config(p);
2113 
2114     s->limit_req_line = main_server->limit_req_line;
2115     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
2116     s->limit_req_fields = main_server->limit_req_fields;
2117 
2118     *ps = s;
2119 
2120     return ap_parse_vhost_addrs(p, hostname, s);
2121 }
2122 
ap_new_log_config(apr_pool_t * p,const struct ap_logconf * old)2123 AP_DECLARE(struct ap_logconf *) ap_new_log_config(apr_pool_t *p,
2124                                                   const struct ap_logconf *old)
2125 {
2126     struct ap_logconf *l = apr_pcalloc(p, sizeof(struct ap_logconf));
2127     if (old) {
2128         l->level = old->level;
2129         if (old->module_levels) {
2130             l->module_levels =
2131                 apr_pmemdup(p, old->module_levels, conf_vector_length);
2132         }
2133     }
2134     else {
2135         l->level = APLOG_UNSET;
2136     }
2137     return l;
2138 }
2139 
ap_merge_log_config(const struct ap_logconf * old_conf,struct ap_logconf * new_conf)2140 AP_DECLARE(void) ap_merge_log_config(const struct ap_logconf *old_conf,
2141                                      struct ap_logconf *new_conf)
2142 {
2143     if (new_conf->level != APLOG_UNSET) {
2144         /* Setting the main loglevel resets all per-module log levels.
2145          * I.e. if new->level has been set, we must ignore old->module_levels.
2146          */
2147         return;
2148     }
2149 
2150     new_conf->level = old_conf->level;
2151     if (new_conf->module_levels == NULL) {
2152         new_conf->module_levels = old_conf->module_levels;
2153     }
2154     else if (old_conf->module_levels != NULL) {
2155         int i;
2156         for (i = 0; i < conf_vector_length; i++) {
2157             if (new_conf->module_levels[i] == APLOG_UNSET)
2158                 new_conf->module_levels[i] = old_conf->module_levels[i];
2159         }
2160     }
2161 }
2162 
ap_fixup_virtual_hosts(apr_pool_t * p,server_rec * main_server)2163 AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, server_rec *main_server)
2164 {
2165     server_rec *virt;
2166     core_dir_config *dconf =
2167         ap_get_core_module_config(main_server->lookup_defaults);
2168     dconf->log = &main_server->log;
2169 
2170     for (virt = main_server->next; virt; virt = virt->next) {
2171         merge_server_configs(p, main_server->module_config, virt);
2172 
2173         virt->lookup_defaults =
2174             ap_merge_per_dir_configs(p, main_server->lookup_defaults,
2175                                      virt->lookup_defaults);
2176 
2177         if (virt->server_admin == NULL)
2178             virt->server_admin = main_server->server_admin;
2179 
2180         if (virt->timeout == 0)
2181             virt->timeout = main_server->timeout;
2182 
2183         if (virt->keep_alive_timeout == 0)
2184             virt->keep_alive_timeout = main_server->keep_alive_timeout;
2185 
2186         if (virt->keep_alive == -1)
2187             virt->keep_alive = main_server->keep_alive;
2188 
2189         if (virt->keep_alive_max == -1)
2190             virt->keep_alive_max = main_server->keep_alive_max;
2191 
2192         ap_merge_log_config(&main_server->log, &virt->log);
2193 
2194         dconf = ap_get_core_module_config(virt->lookup_defaults);
2195         dconf->log = &virt->log;
2196 
2197         /* XXX: this is really something that should be dealt with by a
2198          * post-config api phase
2199          */
2200         ap_core_reorder_directories(p, virt);
2201     }
2202 
2203     ap_core_reorder_directories(p, main_server);
2204 }
2205 
2206 /*****************************************************************
2207  *
2208  * Getting *everything* configured...
2209  */
2210 
init_config_globals(apr_pool_t * p)2211 static void init_config_globals(apr_pool_t *p)
2212 {
2213     /* Global virtual host hash bucket pointers.  Init to null. */
2214     ap_init_vhost_config(p);
2215 }
2216 
init_server_config(process_rec * process,apr_pool_t * p)2217 static server_rec *init_server_config(process_rec *process, apr_pool_t *p)
2218 {
2219     apr_status_t rv;
2220     server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
2221 
2222     apr_file_open_stderr(&s->error_log, p);
2223     s->process = process;
2224     s->port = 0;
2225     s->server_admin = DEFAULT_ADMIN;
2226     s->server_hostname = NULL;
2227     s->server_scheme = NULL;
2228     s->error_fname = DEFAULT_ERRORLOG;
2229     s->log.level = DEFAULT_LOGLEVEL;
2230     s->log.module_levels = NULL;
2231     s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
2232     s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
2233     s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
2234     s->timeout = apr_time_from_sec(DEFAULT_TIMEOUT);
2235     s->keep_alive_timeout = apr_time_from_sec(DEFAULT_KEEPALIVE_TIMEOUT);
2236     s->keep_alive_max = DEFAULT_KEEPALIVE;
2237     s->keep_alive = 1;
2238     s->next = NULL;
2239     s->addrs = apr_pcalloc(p, sizeof(server_addr_rec));
2240 
2241     /* NOT virtual host; don't match any real network interface */
2242     rv = apr_sockaddr_info_get(&s->addrs->host_addr,
2243                                NULL, APR_UNSPEC, 0, 0, p);
2244     if (rv != APR_SUCCESS) {
2245         /* should we test here for rv being an EAIERR? */
2246         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, rv, NULL, APLOGNO(00530)
2247                      "initialisation: bug or getaddrinfo fail");
2248         return NULL;
2249     }
2250 
2251     s->addrs->host_port = 0; /* matches any port */
2252     s->addrs->virthost = ""; /* must be non-NULL */
2253     s->names = s->wild_names = NULL;
2254 
2255     s->module_config = create_server_config(p, s);
2256     s->lookup_defaults = create_default_per_dir_config(p);
2257 
2258     return s;
2259 }
2260 
2261 
reset_conf_vector_length(void * dummy)2262 static apr_status_t reset_conf_vector_length(void *dummy)
2263 {
2264     reserved_module_slots = 0;
2265     conf_vector_length = max_modules;
2266     return APR_SUCCESS;
2267 }
2268 
conf_vector_length_pre_config(apr_pool_t * pconf,apr_pool_t * plog,apr_pool_t * ptemp)2269 static int conf_vector_length_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
2270                                          apr_pool_t *ptemp)
2271 {
2272     /*
2273      * We have loaded all modules that are loaded by EXEC_ON_READ directives.
2274      * From now on we reduce the size of the config vectors to what we need,
2275      * plus what has been reserved (e.g. by mod_perl) for additional modules
2276      * loaded later on.
2277      * If max_modules is too small, ap_add_module() will abort.
2278      */
2279     if (total_modules + reserved_module_slots < max_modules) {
2280         conf_vector_length = total_modules + reserved_module_slots;
2281     }
2282     apr_pool_cleanup_register(pconf, NULL, reset_conf_vector_length,
2283                               apr_pool_cleanup_null);
2284     return OK;
2285 }
2286 
2287 
ap_register_config_hooks(apr_pool_t * p)2288 AP_CORE_DECLARE(void) ap_register_config_hooks(apr_pool_t *p)
2289 {
2290     ap_hook_pre_config(conf_vector_length_pre_config, NULL, NULL,
2291                        APR_HOOK_REALLY_LAST);
2292 }
2293 
ap_read_config(process_rec * process,apr_pool_t * ptemp,const char * filename,ap_directive_t ** conftree)2294 AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp,
2295                                        const char *filename,
2296                                        ap_directive_t **conftree)
2297 {
2298     const char *confname, *error;
2299     apr_pool_t *p = process->pconf;
2300     server_rec *s = init_server_config(process, p);
2301     if (s == NULL) {
2302         return s;
2303     }
2304 
2305     init_config_globals(p);
2306 
2307     if (ap_exists_config_define("DUMP_INCLUDES")) {
2308         apr_file_t *out = NULL;
2309         apr_file_open_stdout(&out, p);
2310 
2311         /* Included files will be dumped as the config is walked; print a
2312          * header.
2313          */
2314         apr_file_printf(out, "Included configuration files:\n");
2315     }
2316 
2317     /* All server-wide config files now have the SAME syntax... */
2318     error = process_command_config(s, ap_server_pre_read_config, conftree,
2319                                    p, ptemp);
2320     if (error) {
2321         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, 0, NULL, "%s: %s",
2322                      ap_server_argv0, error);
2323         return NULL;
2324     }
2325 
2326     /* process_command_config may change the ServerRoot so
2327      * compute this config file name afterwards.
2328      */
2329     confname = ap_server_root_relative(p, filename);
2330 
2331     if (!confname) {
2332         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT,
2333                      APR_EBADPATH, NULL, APLOGNO(00532) "Invalid config file path %s",
2334                      filename);
2335         return NULL;
2336     }
2337 
2338     error = ap_process_resource_config(s, confname, conftree, p, ptemp);
2339     if (error) {
2340         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, 0, NULL,
2341                      "%s: %s", ap_server_argv0, error);
2342         return NULL;
2343     }
2344 
2345     error = ap_check_mpm();
2346     if (error) {
2347         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, 0, NULL, APLOGNO(00534)
2348                      "%s: Configuration error: %s", ap_server_argv0, error);
2349         return NULL;
2350     }
2351 
2352     error = process_command_config(s, ap_server_post_read_config, conftree,
2353                                    p, ptemp);
2354 
2355     if (error) {
2356         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, 0, NULL, "%s: %s",
2357                      ap_server_argv0, error);
2358         return NULL;
2359     }
2360 
2361     return s;
2362 }
2363 
ap_single_module_configure(apr_pool_t * p,server_rec * s,module * m)2364 AP_DECLARE(void) ap_single_module_configure(apr_pool_t *p, server_rec *s,
2365                                             module *m)
2366 {
2367     if (m->create_server_config)
2368         ap_set_module_config(s->module_config, m,
2369                              (*m->create_server_config)(p, s));
2370 
2371     if (m->create_dir_config)
2372         ap_set_module_config(s->lookup_defaults, m,
2373                              (*m->create_dir_config)(p, NULL));
2374 }
2375 
ap_run_rewrite_args(process_rec * process)2376 AP_DECLARE(void) ap_run_rewrite_args(process_rec *process)
2377 {
2378     module *m;
2379 
2380     for (m = ap_top_module; m; m = m->next) {
2381         if (m->rewrite_args) {
2382             (*m->rewrite_args)(process);
2383         }
2384     }
2385 }
2386 
2387 /********************************************************************
2388  * Configuration directives are restricted in terms of where they may
2389  * appear in the main configuration files and/or .htaccess files according
2390  * to the bitmask req_override in the command_rec structure.
2391  * If any of the overrides set in req_override are also allowed in the
2392  * context in which the command is read, then the command is allowed.
2393  * The context is determined as follows:
2394  *
2395  *    inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
2396  *    within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
2397  *    within .htaccess --> override = AllowOverride for current directory;
2398  *
2399  * the result is, well, a rather confusing set of possibilities for when
2400  * a particular directive is allowed to be used.  This procedure prints
2401  * in English where the given (pc) directive can be used.
2402  */
show_overrides(const command_rec * pc,module * pm)2403 static void show_overrides(const command_rec *pc, module *pm)
2404 {
2405     int n = 0;
2406 
2407     printf("\tAllowed in *.conf ");
2408     if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES))
2409         || ((pc->req_override & RSRC_CONF)
2410         && ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT))))) {
2411         printf("anywhere");
2412     }
2413     else if (pc->req_override & RSRC_CONF) {
2414         printf("only outside <Directory>, <Files>, <Location>, or <If>");
2415     }
2416     else {
2417         printf("only inside <Directory>, <Files>, <Location>, or <If>");
2418     }
2419 
2420     /* Warn if the directive is allowed inside <Directory> or .htaccess
2421      * but module doesn't support per-dir configuration
2422      */
2423     if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
2424         printf(" [no per-dir config]");
2425 
2426     if (pc->req_override & OR_ALL) {
2427         printf(" and in .htaccess\n\twhen AllowOverride");
2428 
2429         if ((pc->req_override & OR_ALL) == OR_ALL) {
2430             printf(" isn't None");
2431         }
2432         else {
2433             printf(" includes ");
2434 
2435             if (pc->req_override & OR_AUTHCFG) {
2436                 if (n++)
2437                     printf(" or ");
2438 
2439                 printf("AuthConfig");
2440             }
2441 
2442             if (pc->req_override & OR_LIMIT) {
2443                 if (n++)
2444                     printf(" or ");
2445 
2446                 printf("Limit");
2447             }
2448 
2449             if (pc->req_override & OR_OPTIONS) {
2450                 if (n++)
2451                     printf(" or ");
2452 
2453                 printf("Options");
2454             }
2455 
2456             if (pc->req_override & OR_FILEINFO) {
2457                 if (n++)
2458                     printf(" or ");
2459 
2460                 printf("FileInfo");
2461             }
2462 
2463             if (pc->req_override & OR_INDEXES) {
2464                 if (n++)
2465                     printf(" or ");
2466 
2467                 printf("Indexes");
2468             }
2469         }
2470     }
2471 
2472     printf("\n");
2473 }
2474 
2475 /* Show the preloaded configuration directives, the help string explaining
2476  * the directive arguments, in what module they are handled, and in
2477  * what parts of the configuration they are allowed.  Used for httpd -L.
2478  */
ap_show_directives(void)2479 AP_DECLARE(void) ap_show_directives(void)
2480 {
2481     const command_rec *pc;
2482     int n;
2483 
2484     for (n = 0; ap_loaded_modules[n]; ++n) {
2485         for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
2486             printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
2487 
2488             if (pc->errmsg)
2489                 printf("\t%s\n", pc->errmsg);
2490 
2491             show_overrides(pc, ap_loaded_modules[n]);
2492         }
2493     }
2494 }
2495 
2496 /* Show the preloaded module names.  Used for httpd -l. */
ap_show_modules(void)2497 AP_DECLARE(void) ap_show_modules(void)
2498 {
2499     int n;
2500 
2501     printf("Compiled in modules:\n");
2502     for (n = 0; ap_loaded_modules[n]; ++n)
2503         printf("  %s\n", ap_loaded_modules[n]->name);
2504 }
2505 
ap_exists_directive(apr_pool_t * p,const char * name)2506 AP_DECLARE(int) ap_exists_directive(apr_pool_t *p, const char *name)
2507 {
2508     char *lname = apr_pstrdup(p, name);
2509 
2510     ap_str_tolower(lname);
2511 
2512     return ap_config_hash &&
2513         apr_hash_get(ap_config_hash, lname, APR_HASH_KEY_STRING) != NULL;
2514 }
2515 
ap_retained_data_get(const char * key)2516 AP_DECLARE(void *) ap_retained_data_get(const char *key)
2517 {
2518     void *retained;
2519 
2520     apr_pool_userdata_get((void *)&retained, key, ap_pglobal);
2521     return retained;
2522 }
2523 
ap_retained_data_create(const char * key,apr_size_t size)2524 AP_DECLARE(void *) ap_retained_data_create(const char *key, apr_size_t size)
2525 {
2526     void *retained;
2527 
2528     retained = apr_pcalloc(ap_pglobal, size);
2529     apr_pool_userdata_set((const void *)retained, key, apr_pool_cleanup_null, ap_pglobal);
2530     return retained;
2531 }
2532 
count_directives_sub(const char * directive,ap_directive_t * current)2533 static int count_directives_sub(const char *directive, ap_directive_t *current)
2534 {
2535     int count = 0;
2536     while (current != NULL) {
2537         if (current->first_child != NULL)
2538             count += count_directives_sub(directive, current->first_child);
2539         if (ap_cstr_casecmp(current->directive, directive) == 0)
2540             count++;
2541         current = current->next;
2542     }
2543     return count;
2544 }
2545 
ap_reserve_module_slots(int count)2546 AP_DECLARE(void) ap_reserve_module_slots(int count)
2547 {
2548     reserved_module_slots += count;
2549 }
2550 
ap_reserve_module_slots_directive(const char * directive)2551 AP_DECLARE(void) ap_reserve_module_slots_directive(const char *directive)
2552 {
2553     ap_reserve_module_slots(count_directives_sub(directive, ap_conftree));
2554 }
2555