Apache HTTPD
request.c
Go to the documentation of this file.
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 * @file request.c
19 * @brief functions to get and process requests
20 *
21 * @author Rob McCool 3/21/93
22 *
23 * Thoroughly revamped by rst for Apache. NB this file reads
24 * best from the bottom up.
25 *
26 */
27
28#include "apr_strings.h"
29#include "apr_file_io.h"
30#include "apr_fnmatch.h"
31
32#define APR_WANT_STRFUNC
33#include "apr_want.h"
34
35#include "ap_config.h"
36#include "ap_provider.h"
37#include "httpd.h"
38#include "http_config.h"
39#include "http_request.h"
40#include "http_core.h"
41#include "http_protocol.h"
42#include "http_log.h"
43#include "http_main.h"
44#include "util_filter.h"
45#include "util_charset.h"
46#include "util_script.h"
47#include "ap_expr.h"
48#include "mod_request.h"
49
50#include "mod_core.h"
51#include "mod_auth.h"
52
53#if APR_HAVE_STDARG_H
54#include <stdarg.h>
55#endif
56
57/* we know core's module_index is 0 */
58#undef APLOG_MODULE_INDEX
59#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
60
77
103 (finfo, r, wanted), AP_DECLINED)
106
110
111
113{
114 if (status == DECLINED) {
116 "configuration error: couldn't %s: %s", phase, r->uri);
118 }
119 else {
121 "auth phase '%s' gave status %d: %s", phase,
122 status, r->uri);
123 return status;
124 }
125}
126
128{
129 int access_status;
130 char *olduser = r->user;
131 int rv = FALSE;
132
133 switch (ap_satisfies(r)) {
134 case SATISFY_ALL:
135 case SATISFY_NOSPEC:
137 break;
138 }
139
141 if (access_status == DECLINED) {
142 rv = TRUE;
143 }
144
145 break;
146 case SATISFY_ANY:
148 break;
149 }
150
152 if (access_status == DECLINED) {
153 rv = TRUE;
154 }
155
156 break;
157 }
158
159 r->user = olduser;
160 return rv;
161}
162
164{
165 int access_status;
167
169 return access_status;
170 }
171 if ((access_status = ap_if_walk(r))) {
172 return access_status;
173 }
174
176 if (d->log)
177 r->log = d->log;
178
179 return OK;
180}
181
182/* This is the master logic for processing requests. Do NOT duplicate
183 * this logic elsewhere, or the security model will be broken by future
184 * API changes. Each phase must be individually optimized to pick up
185 * redundant/duplicate calls by subrequests, and redirects.
186 */
188{
190 int file_req = (r->main && r->filename);
193 unsigned int normalize_flags;
194
196 if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
198 }
199 if (file_req) {
200 /* File subrequests can have a relative path. */
202 }
203
204 if (r->parsed_uri.path) {
205 /* Normalize: remove /./ and shrink /../ segments, plus
206 * decode unreserved chars (first time only to avoid
207 * double decoding after ap_unescape_url() below).
208 */
213 "invalid URI path (%s)", r->unparsed_uri);
214 return HTTP_BAD_REQUEST;
215 }
216 }
217
218 /* All file subrequests are a huge pain... they cannot bubble through the
219 * next several steps. Only file subrequests are allowed an empty uri,
220 * otherwise let (pre_)translate_name kill the request.
221 */
222 if (!file_req) {
223 ap_conf_vector_t *per_dir_config = r->per_dir_config;
224
226 return access_status;
227 }
228
229 /* Let pre_translate_name hooks work with non-decoded URIs, and
230 * eventually prevent further URI transformations (return DONE).
231 */
234 return access_status;
235 }
236
237 /* Throw away pre_trans only merging */
238 r->per_dir_config = per_dir_config;
239 }
240
241 /* Ignore URL unescaping for translated URIs already */
242 if (access_status != DONE && r->parsed_uri.path) {
244 /* Unreserved chars were already decoded by ap_normalize_path() */
246 if (!d->allow_encoded_slashes) {
248 }
249 else if (!d->decode_encoded_slashes) {
251 }
253 if (access_status) {
255 if (! d->allow_encoded_slashes) {
257 "found %%2f (encoded '/') in URI path (%s), "
258 "returning 404", r->unparsed_uri);
259 }
260 }
261 return access_status;
262 }
263
264 if (d->allow_encoded_slashes && d->decode_encoded_slashes) {
265 /* Decoding slashes might have created new // or /./ or /../
266 * segments (e.g. "/.%2F/"), so re-normalize.
267 */
269 }
270 }
271
272 /* Same, translate_name is not suited for file subrequests */
273 if (!file_req) {
275 return access_status;
276 }
277
279 return decl_die(access_status, "translate", r);
280 }
281 }
282
283 /* Reset to the server default config prior to running map_to_storage
284 */
286
288 /* This request wasn't in storage (e.g. TRACE) */
289 return access_status;
290 }
291
292 /* Rerun the location walk, which overrides any map_to_storage config.
293 */
295 return access_status;
296 }
297
299 return access_status;
300 }
301
302 /* Only on the main request! */
303 if (r->main == NULL) {
305 return access_status;
306 }
307 }
308
309 /* Skip authn/authz if the parent or prior request passed the authn/authz,
310 * and that configuration didn't change (this requires optimized _walk()
311 * functions in map_to_storage that use the same merge results given
312 * identical input.) If the config changes, we must re-auth.
313 */
314 if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
315 r->user = r->prev->user;
317 }
318 else if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
319 r->user = r->main->user;
321 }
322 else {
323 /* A module using a confusing API (ap_get_basic_auth_pw) caused
324 ** r->user to be filled out prior to check_authn hook. We treat
325 ** it is inadvertent.
326 */
328 r->user = NULL;
329 }
330
331 switch (ap_satisfies(r)) {
332 case SATISFY_ALL:
333 case SATISFY_NOSPEC:
335 return decl_die(access_status,
336 "check access (with Satisfy All)", r);
337 }
338
341 || (access_status == OK && ap_run_force_authn(r) == OK)) {
343 return decl_die(access_status, "check user", r);
344 }
345 if (r->user == NULL) {
346 /* don't let buggy authn module crash us in authz */
348 "No authentication done but request not "
349 "allowed without authentication for %s. "
350 "Authentication not configured?",
351 r->uri);
353 return decl_die(access_status, "check user", r);
354 }
356 return decl_die(access_status, "check authorization", r);
357 }
358 }
359 else if (access_status == OK) {
361 "request authorized without authentication by "
362 "access_checker_ex hook: %s", r->uri);
363 }
364 else {
365 return decl_die(access_status, "check access", r);
366 }
367 break;
368 case SATISFY_ANY:
371 "request authorized without authentication by "
372 "access_checker hook and 'Satisfy any': %s",
373 r->uri);
374 break;
375 }
376
379 || (access_status == OK && ap_run_force_authn(r) == OK)) {
381 return decl_die(access_status, "check user", r);
382 }
383 if (r->user == NULL) {
384 /* don't let buggy authn module crash us in authz */
386 "No authentication done but request not "
387 "allowed without authentication for %s. "
388 "Authentication not configured?",
389 r->uri);
391 return decl_die(access_status, "check user", r);
392 }
394 return decl_die(access_status, "check authorization", r);
395 }
396 }
397 else if (access_status == OK) {
399 "request authorized without authentication by "
400 "access_checker_ex hook: %s", r->uri);
401 }
402 else {
403 return decl_die(access_status, "check access", r);
404 }
405 break;
406 }
407 }
408 /* XXX Must make certain the ap_run_type_checker short circuits mime
409 * in mod-proxy for r->proxyreq && r->parsed_uri.scheme
410 * && !strcmp(r->parsed_uri.scheme, "http")
411 */
413 return decl_die(access_status, "find types", r);
414 }
415
416 if ((access_status = ap_run_fixups(r)) != OK) {
417 ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "fixups hook gave %d: %s",
419 return access_status;
420 }
421
422 return OK;
423}
424
425
426/* Useful caching structures to repeat _walk/merge sequences as required
427 * when a subrequest or redirect reuses substantially the same config.
428 *
429 * Directive order in the httpd.conf file and its Includes significantly
430 * impact this optimization. Grouping common blocks at the front of the
431 * config that are less likely to change between a request and
432 * its subrequests, or between a request and its redirects reduced
433 * the work of these functions significantly.
434 */
435
436typedef struct walk_walked_t {
437 ap_conf_vector_t *matched; /* A dir_conf sections we matched */
438 ap_conf_vector_t *merged; /* The dir_conf merged result */
440
441typedef struct walk_cache_t {
442 const char *cached; /* The identifier we matched */
443 ap_conf_vector_t **dir_conf_tested; /* The sections we matched against */
444 ap_conf_vector_t *dir_conf_merged; /* Base per_dir_config */
445 ap_conf_vector_t *per_dir_result; /* per_dir_config += walked result */
446 apr_array_header_t *walked; /* The list of walk_walked_t results */
447 struct walk_cache_t *prev; /* Prev cache of same call in this (sub)req */
448 int count; /* Number of prev invocations of same call in this (sub)req */
450
452{
453 void **note, **inherit_note;
455 int count;
456
457 /* Find the most relevant, recent walk cache to work from and provide
458 * a copy the caller is allowed to munge. In the case of a sub-request
459 * or internal redirect, this is the cache corresponding to the equivalent
460 * invocation of the same function call in the "parent" request, if such
461 * a cache exists. Otherwise it is the walk cache of the previous
462 * invocation of the same function call in the current request, if
463 * that exists; if not, then create a new walk cache.
464 */
467
469 count = prev_cache ? (prev_cache->count + 1) : 0;
470
471 if ((r->prev
473 && *inherit_note)
474 || (r->main
476 && *inherit_note)) {
478
479 while (inherit_cache->count > count) {
481 }
482 if (inherit_cache->count == count) {
484 }
485 }
486
487 if (copy_cache) {
488 cache = apr_pmemdup(r->pool, copy_cache, sizeof(*cache));
489 cache->walked = apr_array_copy(r->pool, cache->walked);
490 cache->prev = prev_cache;
491 cache->count = count;
492 }
493 else {
494 cache = apr_pcalloc(r->pool, sizeof(*cache));
495 cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t));
496 }
497
498 *note = cache;
499
500 return cache;
501}
502
503/*****************************************************************
504 *
505 * Getting and checking directory configuration. Also checks the
506 * FollowSymlinks and FollowSymOwner stuff, since this is really the
507 * only place that can happen (barring a new mid_dir_walk callout).
508 *
509 * We can't do it as an access_checker module function which gets
510 * called with the final per_dir_config, since we could have a directory
511 * with FollowSymLinks disabled, which contains a symlink to another
512 * with a .htaccess file which turns FollowSymLinks back on --- and
513 * access in such a case must be denied. So, whatever it is that
514 * checks FollowSymLinks needs to know the state of the options as
515 * they change, all the way down.
516 */
517
518
519/*
520 * resolve_symlink must _always_ be called on an APR_LNK file type!
521 * It will resolve the actual target file type, modification date, etc,
522 * and provide any processing required for symlink evaluation.
523 * Path must already be cleaned, no trailing slash, no multi-slashes,
524 * and don't call this on the root!
525 *
526 * Simply, the number of times we deref a symlink are minimal compared
527 * to the number of times we had an extra lstat() since we 'weren't sure'.
528 *
529 * To optimize, we stat() anything when given (opts & OPT_SYM_LINKS), otherwise
530 * we start off with an lstat(). Every lstat() must be dereferenced in case
531 * it points at a 'nasty' - we must always rerun check_safe_file (or similar.)
532 */
533static int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
534{
536 const char *savename;
537
538 if (!(opts & (OPT_SYM_OWNER | OPT_SYM_LINKS))) {
539 return HTTP_FORBIDDEN;
540 }
541
542 /* Save the name from the valid bits. */
543 savename = (lfi->valid & APR_FINFO_NAME) ? lfi->name : NULL;
544
545 /* if OPT_SYM_OWNER is unset, we only need to check target accessible */
546 if (!(opts & OPT_SYM_OWNER)) {
547 if (apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME | APR_FINFO_LINK), p)
548 != APR_SUCCESS)
549 {
550 return HTTP_FORBIDDEN;
551 }
552
553 /* Give back the target */
554 memcpy(lfi, &fi, sizeof(fi));
555 if (savename) {
556 lfi->name = savename;
557 lfi->valid |= APR_FINFO_NAME;
558 }
559
560 return OK;
561 }
562
563 /* OPT_SYM_OWNER only works if we can get the owner of
564 * both the file and symlink. First fill in a missing
565 * owner of the symlink, then get the info of the target.
566 */
567 if (!(lfi->valid & APR_FINFO_OWNER)) {
568 if (apr_stat(lfi, d, lfi->valid | APR_FINFO_LINK | APR_FINFO_OWNER, p)
569 != APR_SUCCESS)
570 {
571 return HTTP_FORBIDDEN;
572 }
573 }
574
575 if (apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME), p) != APR_SUCCESS) {
576 return HTTP_FORBIDDEN;
577 }
578
579 if (apr_uid_compare(fi.user, lfi->user) != APR_SUCCESS) {
580 return HTTP_FORBIDDEN;
581 }
582
583 /* Give back the target */
584 memcpy(lfi, &fi, sizeof(fi));
585 if (savename) {
586 lfi->name = savename;
587 lfi->valid |= APR_FINFO_NAME;
588 }
589
590 return OK;
591}
592
593
594/*
595 * As we walk the directory configuration, the merged config won't
596 * be 'rooted' to a specific vhost until the very end of the merge.
597 *
598 * We need a very fast mini-merge to a real, vhost-rooted merge
599 * of core.opts and core.override, the only options tested within
600 * directory_walk itself.
601 *
602 * See core.c::merge_core_dir_configs() for explanation.
603 */
604
613
615{
617
618 if (!this_dir) {
619 return;
620 }
621
622 if (this_dir->opts & OPT_UNSET) {
623 opts->add = (opts->add & ~this_dir->opts_remove)
624 | this_dir->opts_add;
625 opts->remove = (opts->remove & ~this_dir->opts_add)
626 | this_dir->opts_remove;
627 opts->opts = (opts->opts & ~opts->remove) | opts->add;
628 }
629 else {
630 opts->opts = this_dir->opts;
631 opts->add = this_dir->opts_add;
632 opts->remove = this_dir->opts_remove;
633 }
634
635 if (!(this_dir->override & OR_UNSET)) {
636 opts->override = this_dir->override;
637 opts->override_opts = this_dir->override_opts;
638 }
639
640 if (this_dir->override_list != NULL) {
641 opts->override_list = this_dir->override_list;
642 }
643}
644
645
646/*****************************************************************
647 *
648 * Getting and checking directory configuration. Also checks the
649 * FollowSymlinks and FollowSymOwner stuff, since this is really the
650 * only place that can happen (barring a new mid_dir_walk callout).
651 *
652 * We can't do it as an access_checker module function which gets
653 * called with the final per_dir_config, since we could have a directory
654 * with FollowSymLinks disabled, which contains a symlink to another
655 * with a .htaccess file which turns FollowSymLinks back on --- and
656 * access in such a case must be denied. So, whatever it is that
657 * checks FollowSymLinks needs to know the state of the options as
658 * they change, all the way down.
659 */
660
662{
666 ap_conf_vector_t **sec_ent = (ap_conf_vector_t **) sconf->sec_dir->elts;
667 int num_sec = sconf->sec_dir->nelts;
669 char *entry_dir;
670 apr_status_t rv;
671 int cached;
672
673 /* XXX: Better (faster) tests needed!!!
674 *
675 * "OK" as a response to a real problem is not _OK_, but to allow broken
676 * modules to proceed, we will permit the not-a-path filename to pass the
677 * following two tests. This behavior may be revoked in future versions
678 * of Apache. We still must catch it later if it's heading for the core
679 * handler. Leave INFO notes here for module debugging.
680 */
681 if (r->filename == NULL) {
683 "Module bug? Request filename is missing for URI %s",
684 r->uri);
685 return OK;
686 }
687
688 /* Canonicalize the file path without resolving filename case or aliases
689 * so we can begin by checking the cache for a recent directory walk.
690 * This call will ensure we have an absolute path in the same pass.
691 */
694 != APR_SUCCESS) {
696 "Module bug? Request filename path %s is invalid or "
697 "or not absolute for uri %s",
698 r->filename, r->uri);
699 return OK;
700 }
701
702 /* XXX Notice that this forces path_info to be canonical. That might
703 * not be desired by all apps. However, some of those same apps likely
704 * have significant security holes.
705 */
707
709 cached = (cache->cached != NULL);
710
711 /* If this is not a dirent subrequest with a preconstructed
712 * r->finfo value, then we can simply stat the filename to
713 * save burning mega-cycles with unneeded stats - if this is
714 * an exact file match. We don't care about failure... we
715 * will stat by component failing this meager attempt.
716 *
717 * It would be nice to distinguish APR_ENOENT from other
718 * types of failure, such as APR_ENOTDIR. We can do something
719 * with APR_ENOENT, knowing that the path is good.
720 */
721 if (r->finfo.filetype == APR_NOFILE || r->finfo.filetype == APR_LNK) {
723
724 /* some OSs will return APR_SUCCESS/APR_REG if we stat
725 * a regular file but we have '/' at the end of the name;
726 *
727 * other OSs will return APR_ENOTDIR for that situation;
728 *
729 * handle it the same everywhere by simulating a failure
730 * if it looks like a directory but really isn't
731 *
732 * Also reset if the stat failed, just for safety.
733 */
734 if ((rv != APR_SUCCESS) ||
735 (r->finfo.filetype != APR_NOFILE &&
736 (r->finfo.filetype != APR_DIR) &&
737 (r->filename[strlen(r->filename) - 1] == '/'))) {
738 r->finfo.filetype = APR_NOFILE; /* forget what we learned */
739 }
740 }
741
742 if (r->finfo.filetype == APR_REG) {
744 }
745 else if (r->filename[strlen(r->filename) - 1] != '/') {
747 }
748
749 /* If we have a file already matches the path of r->filename,
750 * and the vhost's list of directory sections hasn't changed,
751 * we can skip rewalking the directory_walk entries.
752 */
753 if (cached
754 && ((r->finfo.filetype == APR_REG)
755 || ((r->finfo.filetype == APR_DIR)
756 && (!r->path_info || !*r->path_info)))
757 && (cache->dir_conf_tested == sec_ent)
758 && (strcmp(entry_dir, cache->cached) == 0)) {
759 int familiar = 0;
760
761 /* Well this looks really familiar! If our end-result (per_dir_result)
762 * didn't change, we have absolutely nothing to do :)
763 * Otherwise (as is the case with most dir_merged/file_merged requests)
764 * we must merge our dir_conf_merged onto this new r->per_dir_config.
765 */
766 if (r->per_dir_config == cache->per_dir_result) {
767 familiar = 1;
768 }
769
770 if (r->per_dir_config == cache->dir_conf_merged) {
771 r->per_dir_config = cache->per_dir_result;
772 familiar = 1;
773 }
774
775 if (familiar) {
777 int res;
780
782 opts = this_dir->opts;
783 /*
784 * If Symlinks are allowed in general we do not need the following
785 * check.
786 */
787 if (!(opts & OPT_SYM_LINKS)) {
790 /*
791 * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
792 * have added APR_FINFO_NAME to the wanted parameter of
793 * apr_stat above. On Unix platforms this means that apr_stat
794 * is always going to return APR_INCOMPLETE in the case that
795 * the call to the native stat / lstat did not fail.
796 */
797 if ((rv != APR_INCOMPLETE) && (rv != APR_SUCCESS)) {
798 /*
799 * This should never happen, because we did a stat on the
800 * same file, resolving a possible symlink several lines
801 * above. Therefore do not make a detailed analysis of rv
802 * in this case for the reason of the failure, just bail out
803 * with a HTTP_FORBIDDEN in case we hit a race condition
804 * here.
805 */
807 "access to %s failed; stat of '%s' failed.",
808 r->uri, r->filename);
809 return r->status = HTTP_FORBIDDEN;
810 }
811 if (thisinfo.filetype == APR_LNK) {
812 /* Is this a possibly acceptable symlink? */
814 opts, r->pool)) != OK) {
816 "Symbolic link not allowed "
817 "or link target not accessible: %s",
818 r->filename);
819 return r->status = res;
820 }
821 }
822 }
823 return OK;
824 }
825
826 if (cache->walked->nelts) {
827 now_merged = ((walk_walked_t*)cache->walked->elts)
828 [cache->walked->nelts - 1].merged;
829 }
830 }
831 else {
832 /* We start now_merged from NULL since we want to build
833 * a locations list that can be merged to any vhost.
834 */
835 int sec_idx;
836 int matches = cache->walked->nelts;
838 walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
842 char *save_path_info;
844 char *buf;
845 unsigned int seg, startseg;
847
848 /* Invariant: from the first time filename_len is set until
849 * it goes out of scope, filename_len==strlen(r->filename)
850 */
851 apr_size_t filename_len;
852#ifdef CASE_BLIND_FILESYSTEM
854#endif
855
856 cached &= auth_internal_per_conf;
857
858 /*
859 * We must play our own mini-merge game here, for the few
860 * running dir_config values we care about within dir_walk.
861 * We didn't start the merge from r->per_dir_config, so we
862 * accumulate opts and override as we merge, from the globals.
863 */
865 opts.opts = this_dir->opts;
866 opts.add = this_dir->opts_add;
867 opts.remove = this_dir->opts_remove;
868 opts.override = this_dir->override;
869 opts.override_opts = this_dir->override_opts;
870 opts.override_list = this_dir->override_list;
871
872 /* Set aside path_info to merge back onto path_info later.
873 * If r->filename is a directory, we must remerge the path_info,
874 * before we continue! [Directories cannot, by definition, have
875 * path info. Either the next segment is not-found, or a file.]
876 *
877 * r->path_info tracks the unconsumed source path.
878 * r->filename tracks the path as we process it
879 */
880 if ((r->finfo.filetype == APR_DIR) && r->path_info && *r->path_info)
881 {
883 r->path_info,
885 != APR_SUCCESS) {
887 "dir_walk error, path_info %s is not relative "
888 "to the filename path %s for uri %s",
889 r->path_info, r->filename, r->uri);
891 }
892
894 }
895 else {
897 r->path_info = r->filename;
898 }
899
900#ifdef CASE_BLIND_FILESYSTEM
901
902 canonical_len = 0;
905 == r->path_info[canonical_len])) {
907 }
908
909 while (canonical_len
910 && ((r->canonical_filename[canonical_len - 1] != '/'
912 || (r->path_info[canonical_len - 1] != '/'
913 && r->path_info[canonical_len - 1]))) {
915 }
916
917 /*
918 * Now build r->filename component by component, starting
919 * with the root (on Unix, simply "/"). We will make a huge
920 * assumption here for efficiency, that any canonical path
921 * already given included a canonical root.
922 */
923 rv = apr_filepath_root((const char **)&r->filename,
924 (const char **)&r->path_info,
926 r->pool);
927 filename_len = strlen(r->filename);
928
929 /*
930 * Bad assumption above? If the root's length is longer
931 * than the canonical length, then it cannot be trusted as
932 * a truename. So try again, this time more seriously.
933 */
934 if ((rv == APR_SUCCESS) && canonical_len
935 && (filename_len > canonical_len)) {
936 rv = apr_filepath_root((const char **)&r->filename,
937 (const char **)&r->path_info,
939 filename_len = strlen(r->filename);
940 canonical_len = 0;
941 }
942
943#else /* ndef CASE_BLIND_FILESYSTEM, really this simple for Unix today; */
944
945 rv = apr_filepath_root((const char **)&r->filename,
946 (const char **)&r->path_info,
947 0, r->pool);
948 filename_len = strlen(r->filename);
949
950#endif
951
952 if (rv != APR_SUCCESS) {
954 "dir_walk error, could not determine the root "
955 "path of filename %s%s for uri %s",
956 r->filename, r->path_info, r->uri);
958 }
959
960 /* Working space for terminating null and an extra / is required.
961 */
962 buflen = filename_len + strlen(r->path_info) + 2;
964 memcpy(buf, r->filename, filename_len + 1);
965 r->filename = buf;
966 thisinfo.valid = APR_FINFO_TYPE;
967 thisinfo.filetype = APR_DIR; /* It's the root, of course it's a dir */
968
969 /*
970 * seg keeps track of which segment we've copied.
971 * sec_idx keeps track of which section we're on, since sections are
972 * ordered by number of segments. See core_reorder_directories
973 * startseg tells us how many segments describe the root path
974 * e.g. the complete path "//host/foo/" to a UNC share (4)
975 */
977 sec_idx = 0;
978
979 /*
980 * Go down the directory hierarchy. Where we have to check for
981 * symlinks, do so. Where a .htaccess file has permission to
982 * override anything, try to find one.
983 */
984 do {
985 int res;
986 char *seg_name;
987 char *delim;
988 int temp_slash=0;
989
990 /* We have no trailing slash, but we sure would appreciate one.
991 * However, we don't want to append a / our first time through.
992 */
993 if ((seg > startseg) && r->filename[filename_len-1] != '/') {
994 r->filename[filename_len++] = '/';
995 r->filename[filename_len] = 0;
996 temp_slash=1;
997 }
998
999 /* Begin *this* level by looking for matching <Directory> sections
1000 * from the server config.
1001 */
1002 for (; sec_idx < num_sec; ++sec_idx) {
1003
1007
1008 /* No more possible matches for this many segments?
1009 * We are done when we find relative/regex/longer components.
1010 */
1011 if (entry_core->r || entry_core->d_components > seg) {
1012 break;
1013 }
1014
1015 /* We will never skip '0' element components, e.g. plain old
1016 * <Directory >, and <Directory "/"> are classified as zero
1017 * so that Win32/Netware/OS2 etc all pick them up.
1018 * Otherwise, skip over the mismatches.
1019 */
1020 if (entry_core->d_components
1021 && ((entry_core->d_components < seg)
1022 || (entry_core->d_is_fnmatch
1023 ? (apr_fnmatch(entry_core->d, r->filename,
1025 : (strcmp(r->filename, entry_core->d) != 0)))) {
1026 continue;
1027 }
1028
1029 /* If we haven't continue'd above, we have a match.
1030 *
1031 * Calculate our full-context core opts & override.
1032 */
1034
1035 /* If we merged this same section last time, reuse it
1036 */
1037 if (matches) {
1038 if (last_walk->matched == sec_ent[sec_idx]) {
1039 now_merged = last_walk->merged;
1040 ++last_walk;
1041 --matches;
1042 continue;
1043 }
1044
1045 /* We fell out of sync. This is our own copy of walked,
1046 * so truncate the remaining matches and reset remaining.
1047 */
1048 cache->walked->nelts -= matches;
1049 matches = 0;
1050 cached = 0;
1051 }
1052
1053 if (now_merged) {
1055 now_merged,
1056 sec_ent[sec_idx]);
1057 }
1058 else {
1060 }
1061
1063 last_walk->matched = sec_ent[sec_idx];
1064 last_walk->merged = now_merged;
1065 }
1066
1067 /* If .htaccess files are enabled, check for one, provided we
1068 * have reached a real path.
1069 */
1070 do { /* Not really a loop, just a break'able code block */
1071
1073
1074 /* No htaccess in an incomplete root path,
1075 * nor if it's disabled
1076 */
1077 if (seg < startseg || (!opts.override
1078 && apr_is_empty_table(opts.override_list)
1079 )) {
1080 break;
1081 }
1082
1083
1085 opts.override_opts, opts.override_list,
1086 r->filename, sconf->access_name);
1087 if (res) {
1088 return res;
1089 }
1090
1091 if (!htaccess_conf) {
1092 break;
1093 }
1094
1095 /* If we are still here, we found our htaccess.
1096 *
1097 * Calculate our full-context core opts & override.
1098 */
1100
1101 /* If we merged this same htaccess last time, reuse it...
1102 * this wouldn't work except that we cache the htaccess
1103 * sections for the lifetime of the request, so we match
1104 * the same conf. Good planning (no, pure luck ;)
1105 */
1106 if (matches) {
1107 if (last_walk->matched == htaccess_conf) {
1108 now_merged = last_walk->merged;
1109 ++last_walk;
1110 --matches;
1111 break;
1112 }
1113
1114 /* We fell out of sync. This is our own copy of walked,
1115 * so truncate the remaining matches and reset
1116 * remaining.
1117 */
1118 cache->walked->nelts -= matches;
1119 matches = 0;
1120 cached = 0;
1121 }
1122
1123 if (now_merged) {
1125 now_merged,
1127 }
1128 else {
1130 }
1131
1133 last_walk->matched = htaccess_conf;
1134 last_walk->merged = now_merged;
1135
1136 } while (0); /* Only one htaccess, not a real loop */
1137
1138 /* That temporary trailing slash was useful, now drop it.
1139 */
1140 if (temp_slash) {
1141 r->filename[--filename_len] = '\0';
1142 }
1143
1144 /* Time for all good things to come to an end?
1145 */
1146 if (!r->path_info || !*r->path_info) {
1147 break;
1148 }
1149
1150 /* Now it's time for the next segment...
1151 * We will assume the next element is an end node, and fix it up
1152 * below as necessary...
1153 */
1154
1155 seg_name = r->filename + filename_len;
1156 delim = strchr(r->path_info + (*r->path_info == '/' ? 1 : 0), '/');
1157 if (delim) {
1159 *delim = '\0';
1161 filename_len += path_info_len;
1162 r->path_info = delim;
1163 *delim = '/';
1164 }
1165 else {
1168 filename_len += path_info_len;
1170 }
1171 if (*seg_name == '/')
1172 ++seg_name;
1173
1174 /* If nothing remained but a '/' string, we are finished
1175 * XXX: NO WE ARE NOT!!! Now process this puppy!!! */
1176 if (!*seg_name) {
1177 break;
1178 }
1179
1180 /* First optimization;
1181 * If...we knew r->filename was a file, and
1182 * if...we have strict (case-sensitive) filenames, or
1183 * we know the canonical_filename matches to _this_ name, and
1184 * if...we have allowed symlinks
1185 * skip the lstat and dummy up an APR_DIR value for thisinfo.
1186 */
1187 if (r->finfo.filetype != APR_NOFILE
1189 && (filename_len <= canonical_len)
1190#endif
1191 && ((opts.opts & (OPT_SYM_OWNER | OPT_SYM_LINKS)) == OPT_SYM_LINKS))
1192 {
1193
1194 thisinfo.filetype = APR_DIR;
1195 ++seg;
1196 continue;
1197 }
1198
1199 /* We choose apr_stat with flag APR_FINFO_LINK here, rather that
1200 * plain apr_stat, so that we capture this path object rather than
1201 * its target. We will replace the info with our target's info
1202 * below. We especially want the name of this 'link' object, not
1203 * the name of its target, if we are fixing the filename
1204 * case/resolving aliases.
1205 */
1208
1209 if (APR_STATUS_IS_ENOENT(rv)) {
1210 /* Nothing? That could be nice. But our directory
1211 * walk is done.
1212 */
1213 thisinfo.filetype = APR_NOFILE;
1214 break;
1215 }
1216 else if (APR_STATUS_IS_EACCES(rv)) {
1218 "access to %s denied (filesystem path '%s') "
1219 "because search permissions are missing on a "
1220 "component of the path", r->uri, r->filename);
1221 return r->status = HTTP_FORBIDDEN;
1222 }
1223 else if ((rv != APR_SUCCESS && rv != APR_INCOMPLETE)
1224 || !(thisinfo.valid & APR_FINFO_TYPE)) {
1225 /* If we hit ENOTDIR, we must have over-optimized, deny
1226 * rather than assume not found.
1227 */
1229 "access to %s failed (filesystem path '%s')",
1230 r->uri, r->filename);
1231 return r->status = HTTP_FORBIDDEN;
1232 }
1233
1234 /* Fix up the path now if we have a name, and they don't agree
1235 */
1236 if ((thisinfo.valid & APR_FINFO_NAME)
1237 && strcmp(seg_name, thisinfo.name)) {
1238 /* TODO: provide users an option that an internal/external
1239 * redirect is required here? We need to walk the URI and
1240 * filename in tandem to properly correlate these.
1241 */
1242 strcpy(seg_name, thisinfo.name);
1243 filename_len = strlen(r->filename);
1244 }
1245
1246 if (thisinfo.filetype == APR_LNK) {
1247 /* Is this a possibly acceptable symlink?
1248 */
1250 opts.opts, r->pool)) != OK) {
1252 "Symbolic link not allowed "
1253 "or link target not accessible: %s",
1254 r->filename);
1255 return r->status = res;
1256 }
1257 }
1258
1259 /* Ok, we are done with the link's info, test the real target
1260 */
1261 if (thisinfo.filetype == APR_REG ||
1262 thisinfo.filetype == APR_NOFILE) {
1263 /* That was fun, nothing left for us here
1264 */
1265 break;
1266 }
1267 else if (thisinfo.filetype != APR_DIR) {
1269 "Forbidden: %s doesn't point to "
1270 "a file or directory",
1271 r->filename);
1272 return r->status = HTTP_FORBIDDEN;
1273 }
1274
1275 ++seg;
1276 } while (thisinfo.filetype == APR_DIR);
1277
1278 /* If we have _not_ optimized, this is the time to recover
1279 * the final stat result.
1280 */
1281 if (r->finfo.filetype == APR_NOFILE || r->finfo.filetype == APR_LNK) {
1282 r->finfo = thisinfo;
1283 }
1284
1285 /* Now splice the saved path_info back onto any new path_info
1286 */
1287 if (save_path_info) {
1288 if (r->path_info && *r->path_info) {
1291 }
1292 else {
1294 }
1295 }
1296
1297 /*
1298 * Now we'll deal with the regexes, note we pick up sec_idx
1299 * where we left off (we gave up after we hit entry_core->r)
1300 */
1301 for (; sec_idx < num_sec; ++sec_idx) {
1302
1303 int nmatch = 0;
1304 int i;
1306
1309
1310 if (!entry_core->r) {
1311 continue;
1312 }
1313
1314 if (entry_core->refs && entry_core->refs->nelts) {
1315 if (!rxpool) {
1317 apr_pool_tag(rxpool, "directory_walk_rxpool");
1318 }
1319 nmatch = entry_core->refs->nelts;
1321 }
1322
1323 if (ap_regexec(entry_core->r, r->filename, nmatch, pmatch, 0)) {
1324 continue;
1325 }
1326
1327 for (i = 0; i < nmatch; i++) {
1328 if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
1329 ((const char **)entry_core->refs->elts)[i]) {
1331 ((const char **)entry_core->refs->elts)[i],
1333 r->filename + pmatch[i].rm_so,
1334 pmatch[i].rm_eo - pmatch[i].rm_so));
1335 }
1336 }
1337
1338 /* If we haven't already continue'd above, we have a match.
1339 *
1340 * Calculate our full-context core opts & override.
1341 */
1343
1344 /* If we merged this same section last time, reuse it
1345 */
1346 if (matches) {
1347 if (last_walk->matched == sec_ent[sec_idx]) {
1348 now_merged = last_walk->merged;
1349 ++last_walk;
1350 --matches;
1351 continue;
1352 }
1353
1354 /* We fell out of sync. This is our own copy of walked,
1355 * so truncate the remaining matches and reset remaining.
1356 */
1357 cache->walked->nelts -= matches;
1358 matches = 0;
1359 cached = 0;
1360 }
1361
1362 if (now_merged) {
1364 now_merged,
1365 sec_ent[sec_idx]);
1366 }
1367 else {
1369 }
1370
1372 last_walk->matched = sec_ent[sec_idx];
1373 last_walk->merged = now_merged;
1374 }
1375
1376 if (rxpool) {
1378 }
1379
1380 /* Whoops - everything matched in sequence, but either the original
1381 * walk found some additional matches (which we need to truncate), or
1382 * this walk found some additional matches.
1383 */
1384 if (matches) {
1385 cache->walked->nelts -= matches;
1386 cached = 0;
1387 }
1388 else if (cache->walked->nelts > cached_matches) {
1389 cached = 0;
1390 }
1391 }
1392
1393/* It seems this shouldn't be needed anymore. We translated the
1394 x symlink above into a real resource, and should have died up there.
1395 x Even if we keep this, it needs more thought (maybe an r->file_is_symlink)
1396 x perhaps it should actually happen in file_walk, so we catch more
1397 x obscure cases in autoindex subrequests, etc.
1398 x
1399 x * Symlink permissions are determined by the parent. If the request is
1400 x * for a directory then applying the symlink test here would use the
1401 x * permissions of the directory as opposed to its parent. Consider a
1402 x * symlink pointing to a dir with a .htaccess disallowing symlinks. If
1403 x * you access /symlink (or /symlink/) you would get a 403 without this
1404 x * APR_DIR test. But if you accessed /symlink/index.html, for example,
1405 x * you would *not* get the 403.
1406 x
1407 x if (r->finfo.filetype != APR_DIR
1408 x && (res = resolve_symlink(r->filename, r->info, ap_allow_options(r),
1409 x r->pool))) {
1410 x ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1411 x "Symbolic link not allowed: %s", r->filename);
1412 x return res;
1413 x }
1414 */
1415
1416 /* Save future sub-requestors much angst in processing
1417 * this subrequest. If dir_walk couldn't canonicalize
1418 * the file path, nothing can.
1419 */
1421
1422 if (r->finfo.filetype == APR_DIR) {
1423 cache->cached = apr_pstrdup(r->pool, r->filename);
1424 }
1425 else {
1427 }
1428
1429 if (cached
1430 && r->per_dir_config == cache->dir_conf_merged) {
1431 r->per_dir_config = cache->per_dir_result;
1432 return OK;
1433 }
1434
1435 cache->dir_conf_tested = sec_ent;
1436 cache->dir_conf_merged = r->per_dir_config;
1437
1438 /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
1439 * and note the end result to (potentially) skip this step next time.
1440 */
1441 if (now_merged) {
1444 now_merged);
1445 }
1446 cache->per_dir_result = r->per_dir_config;
1447
1448 return OK;
1449}
1450
1451
1453{
1457 ap_conf_vector_t **sec_ent = (ap_conf_vector_t **)sconf->sec_url->elts;
1458 int num_sec = sconf->sec_url->nelts;
1460 const char *entry_uri;
1461 int cached;
1462
1463 /* No tricks here, there are no <Locations > to parse in this vhost.
1464 * We won't destroy the cache, just in case _this_ redirect is later
1465 * redirected again to a vhost with <Location > blocks to optimize.
1466 */
1467 if (!num_sec) {
1468 return OK;
1469 }
1470
1472 cached = (cache->cached != NULL);
1473
1474 /*
1475 * When merge_slashes is set to AP_CORE_CONFIG_OFF the slashes in r->uri
1476 * have not been merged. But for Location walks we always go with merged
1477 * slashes no matter what merge_slashes is set to.
1478 */
1479 if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
1480 entry_uri = r->uri;
1481 }
1482 else {
1483 char *uri = apr_pstrdup(r->pool, r->uri);
1485 entry_uri = uri;
1486 }
1487
1488 /* If we have an cache->cached location that matches r->uri,
1489 * and the vhost's list of locations hasn't changed, we can skip
1490 * rewalking the location_walk entries.
1491 */
1492 if (cached
1493 && (cache->dir_conf_tested == sec_ent)
1494 && (strcmp(entry_uri, cache->cached) == 0)) {
1495 /* Well this looks really familiar! If our end-result (per_dir_result)
1496 * didn't change, we have absolutely nothing to do :)
1497 * Otherwise (as is the case with most dir_merged/file_merged requests)
1498 * we must merge our dir_conf_merged onto this new r->per_dir_config.
1499 */
1500 if (r->per_dir_config == cache->per_dir_result) {
1501 return OK;
1502 }
1503
1504 if (cache->walked->nelts) {
1505 now_merged = ((walk_walked_t*)cache->walked->elts)
1506 [cache->walked->nelts - 1].merged;
1507 }
1508 }
1509 else {
1510 /* We start now_merged from NULL since we want to build
1511 * a locations list that can be merged to any vhost.
1512 */
1513 int len, sec_idx;
1514 int matches = cache->walked->nelts;
1515 int cached_matches = matches;
1516 walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
1518
1519 cached &= auth_internal_per_conf;
1520 cache->cached = apr_pstrdup(r->pool, entry_uri);
1521
1522 /* Go through the location entries, and check for matches.
1523 * We apply the directive sections in given order, we should
1524 * really try them with the most general first.
1525 */
1526 for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
1527
1530
1531 /* ### const strlen can be optimized in location config parsing */
1532 len = strlen(entry_core->d);
1533
1534 /* Test the regex, fnmatch or string as appropriate.
1535 * If it's a strcmp, and the <Location > pattern was
1536 * not slash terminated, then this uri must be slash
1537 * terminated (or at the end of the string) to match.
1538 */
1539 if (entry_core->r) {
1540
1541 int nmatch = 0;
1542 int i;
1544
1545 if (entry_core->refs && entry_core->refs->nelts) {
1546 if (!rxpool) {
1548 apr_pool_tag(rxpool, "location_walk_rxpool");
1549 }
1550 nmatch = entry_core->refs->nelts;
1552 }
1553
1554 if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
1555 continue;
1556 }
1557
1558 for (i = 0; i < nmatch; i++) {
1559 if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
1560 ((const char **)entry_core->refs->elts)[i]) {
1562 ((const char **)entry_core->refs->elts)[i],
1564 r->uri + pmatch[i].rm_so,
1565 pmatch[i].rm_eo - pmatch[i].rm_so));
1566 }
1567 }
1568
1569 }
1570 else {
1571
1572 if ((entry_core->d_is_fnmatch
1573 ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
1574 : (strncmp(entry_core->d, cache->cached, len)
1575 || (len > 0
1576 && entry_core->d[len - 1] != '/'
1577 && cache->cached[len] != '/'
1578 && cache->cached[len] != '\0')))) {
1579 continue;
1580 }
1581
1582 }
1583
1584 /* If we merged this same section last time, reuse it
1585 */
1586 if (matches) {
1587 if (last_walk->matched == sec_ent[sec_idx]) {
1588 now_merged = last_walk->merged;
1589 ++last_walk;
1590 --matches;
1591 continue;
1592 }
1593
1594 /* We fell out of sync. This is our own copy of walked,
1595 * so truncate the remaining matches and reset remaining.
1596 */
1597 cache->walked->nelts -= matches;
1598 matches = 0;
1599 cached = 0;
1600 }
1601
1602 if (now_merged) {
1604 now_merged,
1605 sec_ent[sec_idx]);
1606 }
1607 else {
1609 }
1610
1612 last_walk->matched = sec_ent[sec_idx];
1613 last_walk->merged = now_merged;
1614 }
1615
1616 if (rxpool) {
1618 }
1619
1620 /* Whoops - everything matched in sequence, but either the original
1621 * walk found some additional matches (which we need to truncate), or
1622 * this walk found some additional matches.
1623 */
1624 if (matches) {
1625 cache->walked->nelts -= matches;
1626 cached = 0;
1627 }
1628 else if (cache->walked->nelts > cached_matches) {
1629 cached = 0;
1630 }
1631 }
1632
1633 if (cached
1634 && r->per_dir_config == cache->dir_conf_merged) {
1635 r->per_dir_config = cache->per_dir_result;
1636 return OK;
1637 }
1638
1639 cache->dir_conf_tested = sec_ent;
1640 cache->dir_conf_merged = r->per_dir_config;
1641
1642 /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
1643 * and note the end result to (potentially) skip this step next time.
1644 */
1645 if (now_merged) {
1648 now_merged);
1649 }
1650 cache->per_dir_result = r->per_dir_config;
1651
1652 return OK;
1653}
1654
1656{
1660 int num_sec = 0;
1662 const char *test_file;
1663 int cached;
1664
1665 if (dconf->sec_file) {
1666 sec_ent = (ap_conf_vector_t **)dconf->sec_file->elts;
1667 num_sec = dconf->sec_file->nelts;
1668 }
1669
1670 /* To allow broken modules to proceed, we allow missing filenames to pass.
1671 * We will catch it later if it's heading for the core handler.
1672 * directory_walk already posted an INFO note for module debugging.
1673 */
1674 if (r->filename == NULL) {
1675 return OK;
1676 }
1677
1678 /* No tricks here, there are just no <Files > to parse in this context.
1679 * We won't destroy the cache, just in case _this_ redirect is later
1680 * redirected again to a context containing the same or similar <Files >.
1681 */
1682 if (!num_sec) {
1683 return OK;
1684 }
1685
1687 cached = (cache->cached != NULL);
1688
1689 /* Get the basename .. and copy for the cache just
1690 * in case r->filename is munged by another module
1691 */
1692 test_file = strrchr(r->filename, '/');
1693 if (test_file == NULL) {
1695 }
1696 else {
1698 }
1699
1700 /* If we have an cache->cached file name that matches test_file,
1701 * and the directory's list of file sections hasn't changed, we
1702 * can skip rewalking the file_walk entries.
1703 */
1704 if (cached
1705 && (cache->dir_conf_tested == sec_ent)
1706 && (strcmp(test_file, cache->cached) == 0)) {
1707 /* Well this looks really familiar! If our end-result (per_dir_result)
1708 * didn't change, we have absolutely nothing to do :)
1709 * Otherwise (as is the case with most dir_merged requests)
1710 * we must merge our dir_conf_merged onto this new r->per_dir_config.
1711 */
1712 if (r->per_dir_config == cache->per_dir_result) {
1713 return OK;
1714 }
1715
1716 if (cache->walked->nelts) {
1717 now_merged = ((walk_walked_t*)cache->walked->elts)
1718 [cache->walked->nelts - 1].merged;
1719 }
1720 }
1721 else {
1722 /* We start now_merged from NULL since we want to build
1723 * a file section list that can be merged to any dir_walk.
1724 */
1725 int sec_idx;
1726 int matches = cache->walked->nelts;
1727 int cached_matches = matches;
1728 walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
1730
1731 cached &= auth_internal_per_conf;
1732 cache->cached = test_file;
1733
1734 /* Go through the location entries, and check for matches.
1735 * We apply the directive sections in given order, we should
1736 * really try them with the most general first.
1737 */
1738 for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
1741
1742 if (entry_core->r) {
1743
1744 int nmatch = 0;
1745 int i;
1747
1748 if (entry_core->refs && entry_core->refs->nelts) {
1749 if (!rxpool) {
1751 apr_pool_tag(rxpool, "file_walk_rxpool");
1752 }
1753 nmatch = entry_core->refs->nelts;
1755 }
1756
1757 if (ap_regexec(entry_core->r, cache->cached, nmatch, pmatch, 0)) {
1758 continue;
1759 }
1760
1761 for (i = 0; i < nmatch; i++) {
1762 if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
1763 ((const char **)entry_core->refs->elts)[i]) {
1765 ((const char **)entry_core->refs->elts)[i],
1767 cache->cached + pmatch[i].rm_so,
1768 pmatch[i].rm_eo - pmatch[i].rm_so));
1769 }
1770 }
1771
1772 }
1773 else {
1774 if ((entry_core->d_is_fnmatch
1775 ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
1776 : strcmp(entry_core->d, cache->cached))) {
1777 continue;
1778 }
1779 }
1780
1781 /* If we merged this same section last time, reuse it
1782 */
1783 if (matches) {
1784 if (last_walk->matched == sec_ent[sec_idx]) {
1785 now_merged = last_walk->merged;
1786 ++last_walk;
1787 --matches;
1788 continue;
1789 }
1790
1791 /* We fell out of sync. This is our own copy of walked,
1792 * so truncate the remaining matches and reset remaining.
1793 */
1794 cache->walked->nelts -= matches;
1795 matches = 0;
1796 cached = 0;
1797 }
1798
1799 if (now_merged) {
1801 now_merged,
1802 sec_ent[sec_idx]);
1803 }
1804 else {
1806 }
1807
1809 last_walk->matched = sec_ent[sec_idx];
1810 last_walk->merged = now_merged;
1811 }
1812
1813 if (rxpool) {
1815 }
1816
1817 /* Whoops - everything matched in sequence, but either the original
1818 * walk found some additional matches (which we need to truncate), or
1819 * this walk found some additional matches.
1820 */
1821 if (matches) {
1822 cache->walked->nelts -= matches;
1823 cached = 0;
1824 }
1825 else if (cache->walked->nelts > cached_matches) {
1826 cached = 0;
1827 }
1828 }
1829
1830 if (cached
1831 && r->per_dir_config == cache->dir_conf_merged) {
1832 r->per_dir_config = cache->per_dir_result;
1833 return OK;
1834 }
1835
1836 cache->dir_conf_tested = sec_ent;
1837 cache->dir_conf_merged = r->per_dir_config;
1838
1839 /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
1840 * and note the end result to (potentially) skip this step next time.
1841 */
1842 if (now_merged) {
1845 now_merged);
1846 }
1847 cache->per_dir_result = r->per_dir_config;
1848
1849 return OK;
1850}
1851
1853{
1856 int num_sec = 0;
1858 int cached;
1859 int sec_idx;
1860 int matches;
1861 int cached_matches;
1862 int prev_result = -1;
1864
1865 if (dconf && dconf->sec_if) {
1866 sec_ent = (ap_conf_vector_t **)dconf->sec_if->elts;
1867 num_sec = dconf->sec_if->nelts;
1868 }
1869
1870 /* No tricks here, there are just no <If > to parse in this context.
1871 * We won't destroy the cache, just in case _this_ redirect is later
1872 * redirected again to a context containing the same or similar <If >.
1873 */
1874 if (!num_sec) {
1875 return OK;
1876 }
1877
1879 cached = (cache->cached != NULL);
1880 cache->cached = (void *)1;
1881 matches = cache->walked->nelts;
1883 last_walk = (walk_walked_t*)cache->walked->elts;
1884
1885 cached &= auth_internal_per_conf;
1886
1887 /* Go through the if entries, and check for matches */
1888 for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
1889 const char *err = NULL;
1891 int rc;
1893
1894 AP_DEBUG_ASSERT(entry_core->condition_ifelse != 0);
1895 if (entry_core->condition_ifelse & AP_CONDITION_ELSE) {
1897 if (prev_result == 1)
1898 continue;
1899 }
1900
1901 if (entry_core->condition_ifelse & AP_CONDITION_IF) {
1902 rc = ap_expr_exec(r, entry_core->condition, &err);
1903 if (rc <= 0) {
1904 if (rc < 0)
1906 "Failed to evaluate <If > condition: %s",
1907 err);
1908 prev_result = 0;
1909 continue;
1910 }
1911 prev_result = 1;
1912 }
1913 else {
1914 prev_result = -1;
1915 }
1916
1917 /* If we merged this same section last time, reuse it
1918 */
1919 if (matches) {
1920 if (last_walk->matched == sec_ent[sec_idx]) {
1921 now_merged = last_walk->merged;
1922 ++last_walk;
1923 --matches;
1924 continue;
1925 }
1926
1927 /* We fell out of sync. This is our own copy of walked,
1928 * so truncate the remaining matches and reset remaining.
1929 */
1930 cache->walked->nelts -= matches;
1931 matches = 0;
1932 cached = 0;
1933 }
1934
1935 if (now_merged) {
1937 now_merged,
1938 sec_ent[sec_idx]);
1939 }
1940 else {
1942 }
1943
1945 last_walk->matched = sec_ent[sec_idx];
1946 last_walk->merged = now_merged;
1947 }
1948
1949 /* Everything matched in sequence, but it may be that the original
1950 * walk found some additional matches (which we need to truncate), or
1951 * this walk found some additional matches.
1952 */
1953 if (matches) {
1954 cache->walked->nelts -= matches;
1955 cached = 0;
1956 }
1957 else if (cache->walked->nelts > cached_matches) {
1958 cached = 0;
1959 }
1960
1961 if (cached
1962 && r->per_dir_config == cache->dir_conf_merged) {
1963 r->per_dir_config = cache->per_dir_result;
1964 return OK;
1965 }
1966
1967 cache->dir_conf_tested = sec_ent;
1968 cache->dir_conf_merged = r->per_dir_config;
1969
1970 /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
1971 * and note the end result to (potentially) skip this step next time.
1972 */
1973 if (now_merged) {
1976 now_merged);
1977 }
1978 cache->per_dir_result = r->per_dir_config;
1979
1980 if (now_merged) {
1982
1983 /* Allow nested <If>s and their configs to get merged
1984 * with the current one.
1985 */
1986 return ap_if_walk_sub(r, dconf_merged);
1987 }
1988
1989 return OK;
1990}
1991
1993{
1995 int status = ap_if_walk_sub(r, dconf);
1996 return status;
1997}
1998
1999/*****************************************************************
2000 *
2001 * The sub_request mechanism.
2002 *
2003 * Fns to look up a relative URI from, e.g., a map file or SSI document.
2004 * These do all access checks, etc., but don't actually run the transaction
2005 * ... use run_sub_req below for that. Also, be sure to use destroy_sub_req
2006 * as appropriate if you're likely to be creating more than a few of these.
2007 * (An early Apache version didn't destroy the sub_reqs used in directory
2008 * indexing. The result, when indexing a directory with 800-odd files in
2009 * it, was massively excessive storage allocation).
2010 *
2011 * Note more manipulation of protocol-specific vars in the request
2012 * structure...
2013 */
2014
2017{
2018 apr_pool_t *rrp;
2019 request_rec *rnew;
2020
2022 apr_pool_tag(rrp, "subrequest");
2023 rnew = apr_pcalloc(rrp, sizeof(request_rec));
2024 rnew->pool = rrp;
2025
2026 rnew->hostname = r->hostname;
2027 rnew->request_time = r->request_time;
2028 rnew->connection = r->connection;
2029 rnew->server = r->server;
2030 rnew->log = r->log;
2031
2033
2034 /* Start a clean config from this subrequest's vhost. Optimization in
2035 * Location/File/Dir walks from the parent request assure that if the
2036 * config blocks of the subrequest match the parent request, no merges
2037 * will actually occur (and generally a minimal number of merges are
2038 * required, even if the parent and subrequest aren't quite identical.)
2039 */
2041
2042 rnew->htaccess = r->htaccess;
2043 rnew->allowed_methods = ap_make_method_list(rnew->pool, 2);
2044
2045 /* make a copy of the allowed-methods list */
2047
2048 /* start with the same set of output filters */
2049 if (next_filter) {
2051
2052 /* while there are no input filters for a subrequest, we will
2053 * try to insert some, so if we don't have valid data, the code
2054 * will seg fault.
2055 */
2056 rnew->input_filters = r->input_filters;
2060 while (scan && (scan != r->proto_output_filters)) {
2061 if (scan->frec == ap_subreq_core_filter_handle) {
2062 break;
2063 }
2064 scan = scan->next;
2065 }
2066 if (!scan || scan == r->proto_output_filters) {
2068 NULL, rnew, rnew->connection);
2069 }
2070 }
2071 else {
2072 /* If NULL - we are expecting to be internal_fast_redirect'ed
2073 * to this subrequest - or this request will never be invoked.
2074 * Ignore the original request filter stack entirely, and
2075 * drill the input and output stacks back to the connection.
2076 */
2079
2082 }
2083
2085 rnew->useragent_ip = r->useragent_ip;
2086
2087 /* no input filters for a subrequest */
2088
2090
2091 /* We have to run this after we fill in sub req vars,
2092 * or the r->main pointer won't be setup
2093 */
2095
2096 /* Begin by presuming any module can make its own path_info assumptions,
2097 * until some module interjects and changes the value.
2098 */
2100
2101 /* Pass on the kept body (if any) into the new request. */
2102 rnew->kept_body = r->kept_body;
2103
2104 return rnew;
2105}
2106
2109{
2111
2112 if (APR_BUCKET_IS_EOS(e)) {
2114 }
2115
2116 if (!APR_BRIGADE_EMPTY(bb)) {
2117 return ap_pass_brigade(f->next, bb);
2118 }
2119
2120 return APR_SUCCESS;
2121}
2122
2124
2126{
2127 /* Is there a require line configured for the type of *this* req? */
2130 }
2131 else
2132 return 0;
2133}
2134
2140
2142{
2143 int total_auth_hooks = 0;
2144 int total_auth_providers = 0;
2145
2147
2148 if (_hooks.link_access_checker) {
2149 total_auth_hooks += _hooks.link_access_checker->nelts;
2150 }
2151 if (_hooks.link_access_checker_ex) {
2152 total_auth_hooks += _hooks.link_access_checker_ex->nelts;
2153 }
2154 if (_hooks.link_check_user_id) {
2155 total_auth_hooks += _hooks.link_check_user_id->nelts;
2156 }
2157 if (_hooks.link_auth_checker) {
2158 total_auth_hooks += _hooks.link_auth_checker->nelts;
2159 }
2160
2162 return;
2163 }
2164
2171
2173 return;
2174 }
2175
2177}
2178
2180 const char *provider_group,
2181 const char *provider_name,
2182 const char *provider_version,
2183 const void *provider,
2184 int type)
2185{
2188 }
2189
2190 return ap_register_provider(pool, provider_group, provider_name,
2191 provider_version, provider);
2192}
2193
2195 const char * const *aszPre,
2196 const char * const *aszSucc,
2197 int nOrder, int type)
2198{
2201 }
2202
2204}
2205
2207 const char * const *aszPre,
2208 const char * const *aszSucc,
2209 int nOrder, int type)
2210{
2213 }
2214
2216}
2217
2219 const char * const *aszPre,
2220 const char * const *aszSucc,
2221 int nOrder, int type)
2222{
2225 }
2226
2228}
2229
2231 const char * const *aszPre,
2232 const char * const *aszSucc,
2233 int nOrder, int type)
2234{
2237 }
2238
2240}
2241
2243 const char *new_uri,
2244 const request_rec *r,
2246{
2247 request_rec *rnew;
2248 /* Initialise res, to avoid a gcc warning */
2250 char *udir;
2251
2253
2254 /* would be nicer to pass "method" to ap_set_sub_req_protocol */
2255 rnew->method = method;
2257
2258 if (new_uri[0] == '/') {
2259 ap_parse_uri(rnew, new_uri);
2260 }
2261 else {
2262 udir = ap_make_dirstr_parent(rnew->pool, r->uri);
2263 udir = ap_escape_uri(rnew->pool, udir); /* re-escape it */
2265 }
2266
2267 /* We cannot return NULL without violating the API. So just turn this
2268 * subrequest into a 500 to indicate the failure. */
2271 return rnew;
2272 }
2273
2274 /* lookup_uri
2275 * If the content can be served by the quick_handler, we can
2276 * safely bypass request_internal processing.
2277 *
2278 * If next_filter is NULL we are expecting to be
2279 * internal_fast_redirect'ed to the subrequest, or the subrequest will
2280 * never be invoked. We need to make sure that the quickhandler is not
2281 * invoked by any lookups. Since an internal_fast_redirect will always
2282 * occur too late for the quickhandler to handle the request.
2283 */
2284 if (next_filter) {
2285 res = ap_run_quick_handler(rnew, 1);
2286 }
2287
2288 if (next_filter == NULL || res != OK) {
2289 if ((res = ap_process_request_internal(rnew))) {
2290 rnew->status = res;
2291 }
2292 }
2293
2294 return rnew;
2295}
2296
2303
2305 const request_rec *r,
2306 int subtype,
2308{
2309 request_rec *rnew;
2310 int res;
2311 char *fdir;
2312 char *udir;
2313
2315
2316 /* Special case: we are looking at a relative lookup in the same directory.
2317 * This is 100% safe, since dirent->name just came from the filesystem.
2318 */
2319 if (r->path_info && *r->path_info) {
2320 /* strip path_info off the end of the uri to keep it in sync
2321 * with r->filename, which has already been stripped by directory_walk,
2322 * merge the dirent->name, and then, if the caller wants us to remerge
2323 * the original path info, do so. Note we never fix the path_info back
2324 * to r->filename, since dir_walk would do so (but we don't expect it
2325 * to happen in the usual cases)
2326 */
2327 udir = apr_pstrdup(rnew->pool, r->uri);
2330
2331 rnew->uri = ap_make_full_path(rnew->pool, udir, dirent->name);
2332 if (subtype == AP_SUBREQ_MERGE_ARGS) {
2333 rnew->uri = ap_make_full_path(rnew->pool, rnew->uri, r->path_info + 1);
2334 rnew->path_info = apr_pstrdup(rnew->pool, r->path_info);
2335 }
2336 rnew->uri = ap_escape_uri(rnew->pool, rnew->uri);
2337 }
2338 else {
2339 udir = ap_make_dirstr_parent(rnew->pool, r->uri);
2340 rnew->uri = ap_escape_uri(rnew->pool, ap_make_full_path(rnew->pool,
2341 udir,
2342 dirent->name));
2343 }
2344
2346 rnew->filename = ap_make_full_path(rnew->pool, fdir, dirent->name);
2347 if (r->canonical_filename == r->filename) {
2348 rnew->canonical_filename = rnew->filename;
2349 }
2350
2351 /* XXX This is now less relevant; we will do a full location walk
2352 * these days for this case. Preserve the apr_stat results, and
2353 * perhaps we also tag that symlinks were tested and/or found for
2354 * r->filename.
2355 */
2357
2358 if ((dirent->valid & APR_FINFO_MIN) != APR_FINFO_MIN) {
2359 /*
2360 * apr_dir_read isn't very complete on this platform, so
2361 * we need another apr_stat (with or without APR_FINFO_LINK
2362 * depending on whether we allow all symlinks here.) If this
2363 * is an APR_LNK that resolves to an APR_DIR, then we will rerun
2364 * everything anyways... this should be safe.
2365 */
2366 apr_status_t rv;
2367 if (ap_allow_options(rnew) & OPT_SYM_LINKS) {
2368 if (((rv = apr_stat(&rnew->finfo, rnew->filename,
2369 APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
2370 && (rv != APR_INCOMPLETE)) {
2371 rnew->finfo.filetype = APR_NOFILE;
2372 }
2373 }
2374 else {
2375 if (((rv = apr_stat(&rnew->finfo, rnew->filename,
2377 rnew->pool)) != APR_SUCCESS)
2378 && (rv != APR_INCOMPLETE)) {
2379 rnew->finfo.filetype = APR_NOFILE;
2380 }
2381 }
2382 }
2383 else {
2384 memcpy(&rnew->finfo, dirent, sizeof(apr_finfo_t));
2385 }
2386
2387 if (rnew->finfo.filetype == APR_LNK) {
2388 /*
2389 * Resolve this symlink. We should tie this back to dir_walk's cache
2390 */
2391 if ((res = resolve_symlink(rnew->filename, &rnew->finfo,
2392 ap_allow_options(rnew), rnew->pool))
2393 != OK) {
2394 rnew->status = res;
2395 return rnew;
2396 }
2397 }
2398
2399 if (rnew->finfo.filetype == APR_DIR) {
2400 /* ap_make_full_path overallocated the buffers
2401 * by one character to help us out here.
2402 */
2403 strcat(rnew->filename, "/");
2404 if (!rnew->path_info || !*rnew->path_info) {
2405 strcat(rnew->uri, "/");
2406 }
2407 }
2408
2409 /* fill in parsed_uri values
2410 */
2411 if (r->args && *r->args && (subtype == AP_SUBREQ_MERGE_ARGS)) {
2412 ap_parse_uri(rnew, apr_pstrcat(r->pool, rnew->uri, "?",
2413 r->args, NULL));
2414 }
2415 else {
2416 ap_parse_uri(rnew, rnew->uri);
2417 }
2418
2419 /* We cannot return NULL without violating the API. So just turn this
2420 * subrequest into a 500. */
2423 return rnew;
2424 }
2425
2426 if ((res = ap_process_request_internal(rnew))) {
2427 rnew->status = res;
2428 }
2429
2430 return rnew;
2431}
2432
2434 const request_rec *r,
2436{
2437 request_rec *rnew;
2438 int res;
2439 char *fdir;
2441
2443
2445 fdirlen = strlen(fdir);
2446
2447 /* Translate r->filename, if it was canonical, it stays canonical
2448 */
2449 if (r->canonical_filename == r->filename) {
2450 rnew->canonical_filename = (char*)(1);
2451 }
2452
2455 rnew->status = HTTP_FORBIDDEN;
2456 return rnew;
2457 }
2458
2459 if (rnew->canonical_filename) {
2460 rnew->canonical_filename = rnew->filename;
2461 }
2462
2463 /*
2464 * Check for a special case... if there are no '/' characters in new_file
2465 * at all, and the path was the same, then we are looking at a relative
2466 * lookup in the same directory. Fixup the URI to match.
2467 */
2468
2469 if (strncmp(rnew->filename, fdir, fdirlen) == 0
2470 && rnew->filename[fdirlen]
2471 && ap_strchr_c(rnew->filename + fdirlen, '/') == NULL) {
2472 apr_status_t rv;
2473 if (ap_allow_options(rnew) & OPT_SYM_LINKS) {
2474 if (((rv = apr_stat(&rnew->finfo, rnew->filename,
2475 APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
2476 && (rv != APR_INCOMPLETE)) {
2477 rnew->finfo.filetype = APR_NOFILE;
2478 }
2479 }
2480 else {
2481 if (((rv = apr_stat(&rnew->finfo, rnew->filename,
2483 rnew->pool)) != APR_SUCCESS)
2484 && (rv != APR_INCOMPLETE)) {
2485 rnew->finfo.filetype = APR_NOFILE;
2486 }
2487 }
2488
2489 if (r->uri && *r->uri) {
2490 char *udir = ap_make_dirstr_parent(rnew->pool, r->uri);
2491 rnew->uri = ap_make_full_path(rnew->pool, udir,
2492 rnew->filename + fdirlen);
2493 ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */
2494 }
2495 else {
2496 ap_parse_uri(rnew, new_file); /* fill in parsed_uri values */
2497 rnew->uri = apr_pstrdup(rnew->pool, "");
2498 }
2499 }
2500 else {
2501 /* XXX: @@@: What should be done with the parsed_uri values?
2502 * We would be better off stripping down to the 'common' elements
2503 * of the path, then reassembling the URI as best as we can.
2504 */
2505 ap_parse_uri(rnew, new_file); /* fill in parsed_uri values */
2506 /*
2507 * XXX: this should be set properly like it is in the same-dir case
2508 * but it's actually sometimes to impossible to do it... because the
2509 * file may not have a uri associated with it -djg
2510 */
2511 rnew->uri = apr_pstrdup(rnew->pool, "");
2512 }
2513
2514 /* We cannot return NULL without violating the API. So just turn this
2515 * subrequest into a 500. */
2518 return rnew;
2519 }
2520
2521 if ((res = ap_process_request_internal(rnew))) {
2522 rnew->status = res;
2523 }
2524
2525 return rnew;
2526}
2527
2529{
2530 int retval = DECLINED;
2531 /* Run the quick handler if the subrequest is not a dirent or file
2532 * subrequest
2533 */
2534 if (!(r->filename && r->finfo.filetype != APR_NOFILE)) {
2536 }
2537 if (retval != OK) {
2539 if (retval == DONE) {
2540 retval = OK;
2541 }
2542 }
2544 return retval;
2545}
2546
2548{
2549 /* Reclaim the space */
2551}
2552
2553/*
2554 * Function to set the r->mtime field to the specified value if it's later
2555 * than what's already there.
2556 */
2563
2564/*
2565 * Is it the initial main request, which we only get *once* per HTTP request?
2566 */
2568{
2569 return (r->main == NULL) /* otherwise, this is a sub-request */
2570 && (r->prev == NULL); /* otherwise, this is an internal redirect */
2571}
2572
Symbol export macros and hook functions.
#define AP_DECLARE(type)
Definition ap_config.h:67
Expression parser.
#define AP_IMPLEMENT_HOOK_VOID(name, args_decl, args_use)
Definition ap_hooks.h:94
#define AP_IMPLEMENT_HOOK_RUN_ALL(ret, name, args_decl, args_use, ok, decline)
Definition ap_hooks.h:117
#define AP_IMPLEMENT_HOOK_RUN_FIRST(ret, name, args_decl, args_use, decline)
Definition ap_hooks.h:137
Apache Provider API.
const char apr_size_t ap_regmatch_t * pmatch
Definition ap_regex.h:172
const char apr_size_t len
Definition ap_regex.h:187
const char apr_size_t nmatch
Definition ap_regex.h:172
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
APR File I/O Handling.
APR FNMatch Functions.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
ap_conf_vector_t * ap_merge_per_dir_configs(apr_pool_t *p, ap_conf_vector_t *base, ap_conf_vector_t *new_conf)
Definition config.c:285
int 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)
Definition config.c:1995
int ap_invoke_handler(request_rec *r)
Definition config.c:389
#define AP_DECLINED
Definition httpd.h:401
int ap_run_quick_handler(request_rec *r, int lookup_uri)
Definition config.c:173
int ap_run_header_parser(request_rec *r)
Definition config.c:86
ap_conf_vector_t * ap_create_request_config(apr_pool_t *p)
Definition config.c:356
struct ap_conf_vector_t ap_conf_vector_t
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
#define AP_CORE_DECLARE_NONSTD
Definition httpd.h:390
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
ap_filter_t * ap_add_output_filter_handle(ap_filter_rec_t *f, void *ctx, request_rec *r, conn_rec *c)
#define OPT_SYM_OWNER
Definition http_core.h:84
#define OPT_SYM_LINKS
Definition http_core.h:76
#define OPT_UNSET
Definition http_core.h:80
#define AP_NOTE_IF_WALK
Definition http_core.h:453
ap_filter_rec_t * ap_subreq_core_filter_handle
Definition core.c:131
#define SATISFY_ANY
Definition http_core.h:125
unsigned int overrides_t
Definition http_core.h:483
#define ap_get_core_module_config(v)
Definition http_core.h:383
unsigned char allow_options_t
Definition http_core.h:482
#define AP_NOTE_FILE_WALK
Definition http_core.h:452
int ap_satisfies(request_rec *r)
Definition core.c:821
int ap_is_recursion_limit_exceeded(const request_rec *r)
Definition core.c:3992
#define SATISFY_NOSPEC
Definition http_core.h:127
#define AP_CORE_CONFIG_OFF
Definition http_core.h:504
#define AP_NOTE_DIRECTORY_WALK
Definition http_core.h:450
#define SATISFY_ALL
Definition http_core.h:123
void ** ap_get_request_note(request_rec *r, apr_size_t note_num)
Definition core.c:5184
#define AP_NOTE_LOCATION_WALK
Definition http_core.h:451
int ap_allow_options(request_rec *r)
Definition core.c:771
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_INFO
Definition http_log.h:70
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_TRACE3
Definition http_log.h:74
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_CRIT
Definition http_log.h:66
const unsigned char * buf
Definition util_md5.h:50
int ap_method_number_of(const char *method)
void ap_finalize_sub_req_protocol(request_rec *sub_r)
Definition protocol.c:1710
#define AP_GET_BASIC_AUTH_PW_NOTE
ap_method_list_t * ap_make_method_list(apr_pool_t *p, int nelts)
void ap_parse_uri(request_rec *r, const char *uri)
Definition protocol.c:580
void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
Definition protocol.c:1655
void ap_copy_method_list(ap_method_list_t *dest, ap_method_list_t *src)
apr_array_header_t * ap_list_provider_names(apr_pool_t *pool, const char *provider_group, const char *provider_version)
Definition provider.c:127
apr_status_t ap_register_provider(apr_pool_t *pool, const char *provider_group, const char *provider_name, const char *provider_version, const void *provider)
Definition provider.c:35
apr_status_t ap_register_auth_provider(apr_pool_t *pool, const char *provider_group, const char *provider_name, const char *provider_version, const void *provider, int type)
Definition request.c:2179
#define AP_AUTH_INTERNAL_PER_CONF
void ap_setup_auth_internal(apr_pool_t *ptemp)
Definition request.c:2141
#define AP_AUTH_INTERNAL_MASK
void ap_clear_auth_internal(void)
Definition request.c:2135
apr_status_t ap_sub_req_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
Definition request.c:2107
int ap_run_fixups(request_rec *r)
Definition request.c:87
int ap_run_type_checker(request_rec *r)
Definition request.c:89
int ap_directory_walk(request_rec *r)
Definition request.c:661
void ap_hook_access_checker_ex(ap_HOOK_access_checker_ex_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:93
int ap_some_auth_required(request_rec *r)
Definition request.c:2125
void ap_hook_auth_checker(ap_HOOK_auth_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:95
void ap_hook_check_access_ex(ap_HOOK_access_checker_ex_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder, int type)
Definition request.c:2206
int ap_file_walk(request_rec *r)
Definition request.c:1655
void ap_hook_check_access(ap_HOOK_access_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder, int type)
Definition request.c:2194
request_rec * ap_sub_req_lookup_dirent(const apr_finfo_t *dirent, const request_rec *r, int subtype, ap_filter_t *next_filter)
Definition request.c:2304
#define AP_SUBREQ_MERGE_ARGS
int ap_run_auth_checker(request_rec *r)
Definition request.c:95
void ap_hook_check_user_id(ap_HOOK_check_user_id_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:85
int ap_run_access_checker_ex(request_rec *r)
Definition request.c:93
int ap_if_walk(request_rec *r)
Definition request.c:1992
int ap_run_access_checker(request_rec *r)
Definition request.c:91
int ap_run_force_authn(request_rec *r)
Definition request.c:105
request_rec * ap_sub_req_lookup_uri(const char *new_uri, const request_rec *r, ap_filter_t *next_filter)
Definition request.c:2297
int ap_run_sub_req(request_rec *r)
Definition request.c:2528
int ap_is_initial_req(request_rec *r)
Definition request.c:2567
request_rec * ap_sub_req_lookup_file(const char *new_file, const request_rec *r, ap_filter_t *next_filter)
Definition request.c:2433
int ap_process_request_internal(request_rec *r)
Definition request.c:187
int ap_run_create_request(request_rec *r)
Definition request.c:98
int ap_run_post_perdir_config(request_rec *r)
Definition request.c:100
void ap_hook_access_checker(ap_HOOK_access_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:91
int ap_run_pre_translate_name(request_rec *r)
Definition request.c:79
void ap_destroy_sub_req(request_rec *r)
Definition request.c:2547
request_rec * ap_sub_req_method_uri(const char *method, const char *new_uri, const request_rec *r, ap_filter_t *next_filter)
Definition request.c:2242
int ap_run_translate_name(request_rec *r)
Definition request.c:81
int ap_run_map_to_storage(request_rec *r)
Definition request.c:83
void ap_hook_check_authn(ap_HOOK_check_user_id_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder, int type)
Definition request.c:2218
apr_status_t ap_run_dirwalk_stat(apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted)
Definition request.c:103
int ap_some_authn_required(request_rec *r)
Definition request.c:127
int ap_run_check_user_id(request_rec *r)
Definition request.c:85
int ap_location_walk(request_rec *r)
Definition request.c:1452
void ap_hook_check_authz(ap_HOOK_auth_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder, int type)
Definition request.c:2230
void ap_update_mtime(request_rec *r, apr_time_t dependency_mtime)
Definition request.c:2557
int ap_find_path_info(const char *uri, const char *path_info)
#define APR_INCOMPLETE
Definition apr_errno.h:452
unsigned int count
Definition apr_md5.h:152
#define APR_STATUS_IS_EACCES(s)
Definition apr_errno.h:1231
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_file_t * f
#define APR_BRIGADE_LAST(b)
apr_bucket * e
#define APR_BRIGADE_EMPTY(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
const char *const const char *const * aszSucc
Definition apr_hooks.h:346
#define APR_HOOK_LINK(name)
Definition apr_hooks.h:139
const char *const * aszPre
Definition apr_hooks.h:345
#define APR_HOOK_STRUCT(members)
Definition apr_hooks.h:135
void(*) const char *const const char *const in nOrder)
#define APR_OPTIONAL_FN_TYPE(name)
apr_redis_t * rc
Definition apr_redis.h:173
const char * uri
Definition apr_uri.h:159
int ap_expr_exec(request_rec *r, const ap_expr_info_t *expr, const char **err)
#define OR_UNSET
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define ap_is_HTTP_ERROR(x)
Definition httpd.h:554
#define HTTP_FORBIDDEN
Definition httpd.h:511
#define HTTP_NOT_FOUND
Definition httpd.h:512
#define AP_NORMALIZE_DECODE_UNRESERVED
Definition httpd.h:1789
#define AP_NORMALIZE_ALLOW_RELATIVE
Definition httpd.h:1787
char * ap_make_full_path(apr_pool_t *a, const char *dir, const char *f)
Definition util.c:2346
int ap_count_dirs(const char *path)
Definition util.c:708
#define AP_UNESCAPE_URL_KEEP_SLASHES
Definition httpd.h:1754
int ap_unescape_url_ex(char *url, unsigned int flags)
Definition util.c:1955
#define ap_escape_uri(ppool, path)
Definition httpd.h:1836
int ap_normalize_path(char *path, unsigned int flags)
Definition util.c:489
#define AP_UNESCAPE_URL_KEEP_UNRESERVED
Definition httpd.h:1752
#define ap_strchr_c(s, c)
Definition httpd.h:2353
#define AP_NORMALIZE_MERGE_SLASHES
Definition httpd.h:1790
void ap_no2slash(char *name)
Definition util.c:640
char * ap_make_dirstr_parent(apr_pool_t *p, const char *s)
Definition util.c:692
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
#define AP_UNESCAPE_URL_FORBID_SLASHES
Definition httpd.h:1753
#define AP_NORMALIZE_NOT_ABOVE_ROOT
Definition httpd.h:1788
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
@ APR_LNK
@ APR_REG
@ APR_DIR
@ APR_NOFILE
int type
#define APR_FINFO_OWNER
#define APR_FINFO_MIN
const char apr_int32_t wanted
#define APR_FINFO_NAME
#define APR_FINFO_LINK
#define APR_FINFO_TYPE
#define APR_FILEPATH_NOTRELATIVE
#define APR_FILEPATH_NOTABOVEROOT
#define APR_FILEPATH_TRUENAME
#define APR_FNM_PATHNAME
Definition apr_fnmatch.h:61
const char * opts
Definition apr_getopt.h:122
apr_interval_time_t t
apr_size_t buflen
apr_uint32_t apr_pool_t apr_uint32_t apr_pollset_method_e method
Definition apr_poll.h:195
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_int32_t apr_int32_t apr_int32_t err
int int status
apr_int64_t apr_time_t
Definition apr_time.h:45
int ap_HOOK_access_checker_ex_t(request_rec *r)
int ap_HOOK_check_user_id_t(request_rec *r)
int ap_HOOK_access_checker_t(request_rec *r)
int ap_HOOK_auth_checker_t(request_rec *r)
#define AP_REQ_DEFAULT_PATH_INFO
Definition httpd.h:765
Apache Configuration.
CORE HTTP Daemon.
#define AP_CONDITION_IF
Definition http_core.h:637
#define AP_CONDITION_ELSE
Definition http_core.h:638
Apache Logging library.
Command line options.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
Authentication and Authorization Extension for Apache.
#define AUTHN_PROVIDER_VERSION
Definition mod_auth.h:41
#define AUTHN_PROVIDER_GROUP
Definition mod_auth.h:39
#define AUTHZ_PROVIDER_VERSION
Definition mod_auth.h:42
#define AUTHZ_PROVIDER_GROUP
Definition mod_auth.h:40
static int authz_some_auth_required(request_rec *r)
mod_core private header file
mod_request private header file
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
sconf
Definition mod_so.c:349
static int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
Definition request.c:533
static walk_cache_t * prep_walk_cache(apr_size_t t, request_rec *r)
Definition request.c:451
static int auth_internal_per_conf_hooks
Definition request.c:108
static int decl_die(int status, const char *phase, request_rec *r)
Definition request.c:112
static int walk_location_and_if(request_rec *r)
Definition request.c:163
static int auth_internal_per_conf_providers
Definition request.c:109
static void core_opts_merge(const ap_conf_vector_t *sec, core_opts_t *opts)
Definition request.c:614
apr_OFN_authz_some_auth_required_t * ap__authz_ap_some_auth_required
Definition core.c:5056
static int auth_internal_per_conf
Definition request.c:107
static int ap_if_walk_sub(request_rec *r, core_dir_config *dconf)
Definition request.c:1852
static struct @50 _hooks
static request_rec * make_sub_request(const request_rec *r, ap_filter_t *next_filter)
Definition request.c:2015
static OCSP_REQUEST * create_request(X509_STORE_CTX *ctx, X509 *cert, OCSP_CERTID **certid, server_rec *s, apr_pool_t *p, SSLSrvConfigRec *sc)
The representation of a filter chain.
ap_filter_t * next
apr_filetype_e filetype
const char * name
char * path
Definition apr_uri.h:99
Per-directory configuration.
Definition http_core.h:527
apr_array_header_t * sec_file
Definition http_core.h:598
apr_array_header_t * sec_if
Definition http_core.h:599
apr_table_t * override_list
Definition request.c:611
allow_options_t remove
Definition request.c:608
allow_options_t add
Definition request.c:607
overrides_t override_opts
Definition request.c:610
allow_options_t opts
Definition request.c:606
A structure that represents the current request.
Definition httpd.h:845
char * user
Definition httpd.h:1005
int status
Definition httpd.h:891
char * uri
Definition httpd.h:1016
struct ap_filter_t * output_filters
Definition httpd.h:1070
char * useragent_ip
Definition httpd.h:1101
request_rec * prev
Definition httpd.h:856
apr_time_t mtime
Definition httpd.h:933
struct ap_filter_t * proto_input_filters
Definition httpd.h:1079
apr_table_t * notes
Definition httpd.h:985
const char * hostname
Definition httpd.h:883
const struct htaccess_result * htaccess
Definition httpd.h:1067
int used_path_info
Definition httpd.h:1036
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
apr_sockaddr_t * useragent_addr
Definition httpd.h:1100
char * filename
Definition httpd.h:1018
apr_time_t request_time
Definition httpd.h:886
apr_uri_t parsed_uri
Definition httpd.h:1092
char * unparsed_uri
Definition httpd.h:1014
conn_rec * connection
Definition httpd.h:849
apr_bucket_brigade * kept_body
Definition httpd.h:953
ap_method_list_t * allowed_methods
Definition httpd.h:926
struct ap_filter_t * proto_output_filters
Definition httpd.h:1076
apr_finfo_t finfo
Definition httpd.h:1094
char * canonical_filename
Definition httpd.h:1022
const struct ap_logconf * log
Definition httpd.h:1054
struct ap_filter_t * input_filters
Definition httpd.h:1072
struct ap_conf_vector_t * request_config
Definition httpd.h:1049
request_rec * main
Definition httpd.h:860
apr_table_t * subprocess_env
Definition httpd.h:983
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
const char * method
Definition httpd.h:900
char * path_info
Definition httpd.h:1024
char * args
Definition httpd.h:1026
char * ap_auth_type
Definition httpd.h:1007
struct ap_conf_vector_t * lookup_defaults
Definition httpd.h:1343
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
ap_conf_vector_t ** dir_conf_tested
Definition request.c:443
struct walk_cache_t * prev
Definition request.c:447
apr_array_header_t * walked
Definition request.c:446
const char * cached
Definition request.c:442
ap_conf_vector_t * per_dir_result
Definition request.c:445
ap_conf_vector_t * dir_conf_merged
Definition request.c:444
ap_conf_vector_t * merged
Definition request.c:438
ap_conf_vector_t * matched
Definition request.c:437
charset conversion
Apache filter library.
Apache script tools.