1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58 
59 /*
60  * http_request.c: functions to get and process requests
61  *
62  * Rob McCool 3/21/93
63  *
64  * Thoroughly revamped by rst for Apache.  NB this file reads
65  * best from the bottom up.
66  *
67  */
68 
69 #define CORE_PRIVATE
70 #include "httpd.h"
71 #include "http_config.h"
72 #include "http_request.h"
73 #include "http_core.h"
74 #include "http_protocol.h"
75 #include "http_conf_globals.h"	/* for ap_extended_status */
76 #include "http_log.h"
77 #include "http_main.h"
78 #include "scoreboard.h"
79 #include "fnmatch.h"
80 
81 __RCSID("$MirOS: src/usr.sbin/httpd/src/main/http_request.c,v 1.2 2008/11/08 23:32:30 tg Exp $");
82 
83 /*****************************************************************
84  *
85  * Getting and checking directory configuration.  Also checks the
86  * FollowSymlinks and FollowSymOwner stuff, since this is really the
87  * only place that can happen (barring a new mid_dir_walk callout).
88  *
89  * We can't do it as an access_checker module function which gets
90  * called with the final per_dir_config, since we could have a directory
91  * with FollowSymLinks disabled, which contains a symlink to another
92  * with a .htaccess file which turns FollowSymLinks back on --- and
93  * access in such a case must be denied.  So, whatever it is that
94  * checks FollowSymLinks needs to know the state of the options as
95  * they change, all the way down.
96  */
97 
98 /*
99  * We don't want people able to serve up pipes, or unix sockets, or other
100  * scary things.  Note that symlink tests are performed later.
101  */
check_safe_file(request_rec * r)102 static int check_safe_file(request_rec *r)
103 {
104     if (r->finfo.st_mode == 0         /* doesn't exist */
105         || S_ISDIR(r->finfo.st_mode)
106         || S_ISREG(r->finfo.st_mode)
107         || S_ISLNK(r->finfo.st_mode)) {
108         return OK;
109     }
110     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
111                 "object is not a file, directory or symlink: %s",
112                 r->filename);
113     return HTTP_FORBIDDEN;
114 }
115 
116 
check_symlinks(char * d,int opts)117 static int check_symlinks(char *d, int opts)
118 {
119     struct stat lfi, fi;
120     char *lastp;
121     int res;
122 
123     if (opts & OPT_SYM_LINKS)
124         return OK;
125 
126     /*
127      * Strip trailing '/', if any, off what we're checking; trailing slashes
128      * make some systems follow symlinks to directories even in lstat().
129      * After we've done the lstat, put it back.  Also, don't bother checking
130      * '/' at all...
131      *
132      * Note that we don't have to worry about multiple slashes here because of
133      * no2slash() below...
134      */
135 
136     lastp = d + strlen(d) - 1;
137     if (lastp == d)
138         return OK;              /* Root directory, '/' */
139 
140     if (*lastp == '/')
141         *lastp = '\0';
142     else
143         lastp = NULL;
144 
145     res = lstat(d, &lfi);
146 
147     if (lastp)
148         *lastp = '/';
149 
150     /*
151      * Note that we don't reject accesses to nonexistent files (multiviews or
152      * the like may cons up a way to run the transaction anyway)...
153      */
154 
155     if (!(res >= 0) || !S_ISLNK(lfi.st_mode))
156         return OK;
157 
158     /* OK, it's a symlink.  May still be OK with OPT_SYM_OWNER */
159 
160     if (!(opts & OPT_SYM_OWNER))
161         return HTTP_FORBIDDEN;
162 
163     if (stat(d, &fi) < 0)
164         return HTTP_FORBIDDEN;
165 
166     return (fi.st_uid == lfi.st_uid) ? OK : HTTP_FORBIDDEN;
167 
168 }
169 
170 /* Dealing with the file system to get PATH_INFO
171  */
get_path_info(request_rec * r)172 static int get_path_info(request_rec *r)
173 {
174     char *cp;
175     char *path = r->filename;
176     char *end = &path[strlen(path)];
177     char *last_cp = NULL;
178     int rv;
179 
180     if (r->finfo.st_mode) {
181 	/* assume path_info already set */
182 	return OK;
183     }
184 
185 
186         /* Advance over trailing slashes ... NOT part of filename
187          * if file is not a UNC name (Win32 only).
188          */
189         for (cp = end; cp > path && cp[-1] == '/'; --cp)
190             continue;
191 
192     while (cp > path) {
193 
194         /* See if the pathname ending here exists... */
195 
196         *cp = '\0';
197 
198         /* We must not stat() filenames that may cause os-specific system
199          * problems, such as "/file/aux" on DOS-abused filesystems.
200          * So pretend that they do not exist by returning an ENOENT error.
201          * This will force us to drop that part of the path and keep
202          * looking back for a "real" file that exists, while still allowing
203          * the "invalid" path parts within the PATH_INFO.
204          */
205         if (!ap_os_is_filename_valid(path)) {
206             errno = ENOENT;
207             rv = -1;
208         }
209         else {
210             errno = 0;
211             rv = stat(path, &r->finfo);
212         }
213 
214         if (cp != end)
215             *cp = '/';
216 
217         if (!rv) {
218 
219             /*
220              * Aha!  Found something.  If it was a directory, we will search
221              * contents of that directory for a multi_match, so the PATH_INFO
222              * argument starts with the component after that.
223              */
224 
225             if (S_ISDIR(r->finfo.st_mode) && last_cp) {
226                 r->finfo.st_mode = 0;   /* No such file... */
227                 cp = last_cp;
228             }
229 
230             r->path_info = ap_pstrdup(r->pool, cp);
231             *cp = '\0';
232             return OK;
233         }
234 	/* must set this to zero, some stat()s may have corrupted it
235 	 * even if they returned an error.
236 	 */
237 	r->finfo.st_mode = 0;
238         if (errno == ENOENT || errno == ENOTDIR) {
239             last_cp = cp;
240 
241             while (--cp > path && *cp != '/')
242                 continue;
243 
244             while (cp > path && cp[-1] == '/')
245                 --cp;
246         }
247         else {
248             if (errno == EACCES)
249                 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
250                             "access to %s failed because search "
251                             "permissions are missing on a component "
252                             "of the path", r->uri);
253             else
254                 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
255                             "access to %s failed", r->uri);
256             return HTTP_FORBIDDEN;
257         }
258     }
259     return OK;
260 }
261 
directory_walk(request_rec * r)262 static int directory_walk(request_rec *r)
263 {
264     core_server_config *sconf = ap_get_module_config(r->server->module_config,
265                                                   &core_module);
266     void *per_dir_defaults = r->server->lookup_defaults;
267     void **sec = (void **) sconf->sec->elts;
268     int num_sec = sconf->sec->nelts;
269     char *test_filename;
270     char *test_dirname;
271     int res;
272     unsigned i, num_dirs;
273     int j, test_filename_len;
274 
275     /*
276      * Are we dealing with a file? If not, we can (hopefuly) safely assume we
277      * have a handler that doesn't require one, but for safety's sake, and so
278      * we have something find_types() can get something out of, fake one. But
279      * don't run through the directory entries.
280      */
281 
282     if (r->filename == NULL) {
283         r->filename = ap_pstrdup(r->pool, r->uri);
284         r->finfo.st_mode = 0;   /* Not really a file... */
285         r->per_dir_config = per_dir_defaults;
286 
287         return OK;
288     }
289 
290     /*
291      * Go down the directory hierarchy.  Where we have to check for symlinks,
292      * do so.  Where a .htaccess file has permission to override anything,
293      * try to find one.  If either of these things fails, we could poke
294      * around, see why, and adjust the lookup_rec accordingly --- this might
295      * save us a call to get_path_info (with the attendant stat()s); however,
296      * for the moment, that's not worth the trouble.
297      *
298      * Fake filenames (i.e. proxy:) only match Directory sections.
299      */
300 
301     if (!ap_os_is_path_absolute(r->filename))
302     {
303         void *this_conf, *entry_config;
304         core_dir_config *entry_core;
305         char *entry_dir;
306 
307         for (j = 0; j < num_sec; ++j) {
308 
309             entry_config = sec[j];
310 
311             entry_core = (core_dir_config *)
312                 ap_get_module_config(entry_config, &core_module);
313             entry_dir = entry_core->d;
314 
315             this_conf = NULL;
316             if (entry_core->r) {
317                 if (!ap_regexec(entry_core->r, r->filename, 0, NULL, 0))
318                     this_conf = entry_config;
319             }
320             else if (entry_core->d_is_fnmatch) {
321                 if (!ap_fnmatch(entry_dir, r->filename, 0))
322                     this_conf = entry_config;
323             }
324             else if (!strncmp(r->filename, entry_dir, strlen(entry_dir)))
325                 this_conf = entry_config;
326 
327             if (this_conf)
328                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
329                                                          per_dir_defaults,
330                                                          this_conf);
331         }
332 
333         r->per_dir_config = per_dir_defaults;
334 
335         return OK;
336     }
337 
338     r->filename   = ap_os_case_canonical_filename(r->pool, r->filename);
339 
340     res = get_path_info(r);
341     if (res != OK) {
342         return res;
343     }
344 
345     r->case_preserved_filename = r->filename;
346 
347     r->filename   = ap_os_canonical_filename(r->pool, r->filename);
348 
349     test_filename = ap_pstrdup(r->pool, r->filename);
350 
351     ap_no2slash(test_filename);
352     num_dirs = ap_count_dirs(test_filename);
353 
354     if (!ap_os_is_filename_valid(r->filename) &&
355         !(r->method_number == M_OPTIONS && !strcmp(r->uri, "*"))) {
356         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
357                       "Filename is not valid: %s", r->filename);
358         return HTTP_FORBIDDEN;
359     }
360 
361     if ((res = check_safe_file(r))) {
362         return res;
363     }
364 
365     test_filename_len = strlen(test_filename);
366     if (test_filename[test_filename_len - 1] == '/')
367         --num_dirs;
368 
369     if (S_ISDIR(r->finfo.st_mode))
370         ++num_dirs;
371 
372     /*
373      * We will use test_dirname as scratch space while we build directory
374      * names during the walk.  Profiling shows directory_walk to be a busy
375      * function so we try to avoid allocating lots of extra memory here.
376      * We need 2 extra bytes, one for trailing \0 and one because
377      * make_dirstr_prefix will add potentially one extra /.
378      */
379     test_dirname = ap_palloc(r->pool, test_filename_len + 2);
380 
381 
382     /* Normal File Systems are rooted at / */
383     i = 1;
384 
385     /* j keeps track of which section we're on, see core_reorder_directories */
386     j = 0;
387     for (; i <= num_dirs; ++i) {
388         int overrides_here;
389         core_dir_config *core_dir = (core_dir_config *)
390             ap_get_module_config(per_dir_defaults, &core_module);
391 
392         /*
393          * XXX: this could be made faster by only copying the next component
394          * rather than copying the entire thing all over.
395          */
396         ap_make_dirstr_prefix(test_dirname, test_filename, i);
397 
398         /*
399          * Do symlink checks first, because they are done with the
400          * permissions appropriate to the *parent* directory...
401          */
402 
403         if ((res = check_symlinks(test_dirname, core_dir->opts))) {
404             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
405                         "Symbolic link not allowed: %s", test_dirname);
406             return res;
407         }
408 
409         /*
410          * Begin *this* level by looking for matching <Directory> sections
411          * from access.conf.
412          */
413 
414         for (; j < num_sec; ++j) {
415             void *entry_config = sec[j];
416             core_dir_config *entry_core;
417             char *entry_dir;
418             void *this_conf;
419 
420             entry_core = (core_dir_config *)
421                          ap_get_module_config(entry_config, &core_module);
422             entry_dir = entry_core->d;
423 
424             if (entry_core->r
425 		|| !ap_os_is_path_absolute(entry_dir)
426                 || entry_core->d_components > i)
427                 break;
428 
429             this_conf = NULL;
430             if (entry_core->d_is_fnmatch) {
431                 if (!ap_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) {
432                     this_conf = entry_config;
433                 }
434             }
435             else if (!strcmp(test_dirname, entry_dir))
436                 this_conf = entry_config;
437 
438             if (this_conf) {
439                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
440                                                          per_dir_defaults,
441                                                          this_conf);
442                 core_dir = (core_dir_config *)
443                            ap_get_module_config(per_dir_defaults, &core_module);
444             }
445         }
446         overrides_here = core_dir->override;
447 
448         /* If .htaccess files are enabled, check for one. */
449 
450         if (overrides_here) {
451             void *htaccess_conf = NULL;
452 
453             res = ap_parse_htaccess(&htaccess_conf, r, overrides_here,
454                                  ap_pstrdup(r->pool, test_dirname),
455                                  sconf->access_name);
456             if (res)
457                 return res;
458 
459             if (htaccess_conf) {
460                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
461 							    per_dir_defaults,
462 							    htaccess_conf);
463 		r->per_dir_config = per_dir_defaults;
464 	    }
465         }
466     }
467 
468     /*
469      * There's two types of IS_SPECIAL sections (see http_core.c), and we've
470      * already handled the proxy:-style stuff.  Now we'll deal with the
471      * regexes.
472      */
473     for (; j < num_sec; ++j) {
474         void *entry_config = sec[j];
475         core_dir_config *entry_core;
476 
477         entry_core = (core_dir_config *)
478                      ap_get_module_config(entry_config, &core_module);
479 
480         if (entry_core->r) {
481             if (!ap_regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
482                 per_dir_defaults =
483                     ap_merge_per_dir_configs(r->pool, per_dir_defaults,
484                                           entry_config);
485             }
486         }
487     }
488     r->per_dir_config = per_dir_defaults;
489 
490     /*
491      * Symlink permissions are determined by the parent.  If the request is
492      * for a directory then applying the symlink test here would use the
493      * permissions of the directory as opposed to its parent.  Consider a
494      * symlink pointing to a dir with a .htaccess disallowing symlinks.  If
495      * you access /symlink (or /symlink/) you would get a 403 without this
496      * S_ISDIR test.  But if you accessed /symlink/index.html, for example,
497      * you would *not* get the 403.
498      */
499     if (!S_ISDIR(r->finfo.st_mode)
500         && (res = check_symlinks(r->filename, ap_allow_options(r)))) {
501         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
502                     "Symbolic link not allowed: %s", r->filename);
503         return res;
504     }
505     return OK;                  /* Can only "fail" if access denied by the
506                                  * symlink goop. */
507 }
508 
location_walk(request_rec * r)509 static int location_walk(request_rec *r)
510 {
511     core_server_config *sconf = ap_get_module_config(r->server->module_config,
512                                                   &core_module);
513     void *per_dir_defaults = r->per_dir_config;
514     void **url = (void **) sconf->sec_url->elts;
515     int len, num_url = sconf->sec_url->nelts;
516     char *test_location;
517     void *this_conf, *entry_config;
518     core_dir_config *entry_core;
519     char *entry_url;
520     int j;
521 
522     if (!num_url) {
523 	return OK;
524     }
525 
526     /* Location and LocationMatch differ on their behaviour w.r.t. multiple
527      * slashes.  Location matches multiple slashes with a single slash,
528      * LocationMatch doesn't.  An exception, for backwards brokenness is
529      * absoluteURIs... in which case neither match multiple slashes.
530      */
531     if (r->uri[0] != '/') {
532 	test_location = r->uri;
533     }
534     else {
535 	test_location = ap_pstrdup(r->pool, r->uri);
536 	ap_no2slash(test_location);
537     }
538 
539     /* Go through the location entries, and check for matches. */
540 
541     /* we apply the directive sections in some order;
542      * should really try them with the most general first.
543      */
544     for (j = 0; j < num_url; ++j) {
545 
546 	entry_config = url[j];
547 
548 	entry_core = (core_dir_config *)
549 	    ap_get_module_config(entry_config, &core_module);
550 	entry_url = entry_core->d;
551 
552 	len = strlen(entry_url);
553 
554 	this_conf = NULL;
555 
556 	if (entry_core->r) {
557 	    if (!ap_regexec(entry_core->r, r->uri, 0, NULL, 0))
558 		this_conf = entry_config;
559 	}
560 	else if (entry_core->d_is_fnmatch) {
561 	    if (!ap_fnmatch(entry_url, test_location, FNM_PATHNAME)) {
562 		this_conf = entry_config;
563 	    }
564 	}
565 	else if (!strncmp(test_location, entry_url, len) &&
566 		    (entry_url[len - 1] == '/' ||
567 		test_location[len] == '/' || test_location[len] == '\0'))
568 	    this_conf = entry_config;
569 
570 	if (this_conf)
571 	    per_dir_defaults = ap_merge_per_dir_configs(r->pool,
572 					    per_dir_defaults, this_conf);
573     }
574     r->per_dir_config = per_dir_defaults;
575 
576     return OK;
577 }
578 
file_walk(request_rec * r)579 static int file_walk(request_rec *r)
580 {
581     core_dir_config *conf = ap_get_module_config(r->per_dir_config, &core_module);
582     void *per_dir_defaults = r->per_dir_config;
583     void **file = (void **) conf->sec->elts;
584     int num_files = conf->sec->nelts;
585     char *test_file;
586 
587     /* get the basename */
588     test_file = strrchr(r->filename, '/');
589     if (test_file == NULL) {
590 	test_file = r->filename;
591     }
592     else {
593 	++test_file;
594     }
595 
596     /* Go through the file entries, and check for matches. */
597 
598     if (num_files) {
599         void *this_conf, *entry_config;
600         core_dir_config *entry_core;
601         char *entry_file;
602         int j;
603 
604         /* we apply the directive sections in some order;
605          * should really try them with the most general first.
606          */
607         for (j = 0; j < num_files; ++j) {
608 
609             entry_config = file[j];
610 
611             entry_core = (core_dir_config *)
612                          ap_get_module_config(entry_config, &core_module);
613             entry_file = entry_core->d;
614 
615             this_conf = NULL;
616 
617             if (entry_core->r) {
618                 if (!ap_regexec(entry_core->r, test_file, 0, NULL, 0))
619                     this_conf = entry_config;
620             }
621             else if (entry_core->d_is_fnmatch) {
622                 if (!ap_fnmatch(entry_file, test_file, FNM_PATHNAME)) {
623                     this_conf = entry_config;
624                 }
625             }
626             else if (!strcmp(test_file, entry_file)) {
627                 this_conf = entry_config;
628 	    }
629 
630             if (this_conf)
631                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
632                                                          per_dir_defaults,
633                                                          this_conf);
634         }
635         r->per_dir_config = per_dir_defaults;
636     }
637     return OK;
638 }
639 
640 /*****************************************************************
641  *
642  * The sub_request mechanism.
643  *
644  * Fns to look up a relative URI from, e.g., a map file or SSI document.
645  * These do all access checks, etc., but don't actually run the transaction
646  * ... use run_sub_req below for that.  Also, be sure to use destroy_sub_req
647  * as appropriate if you're likely to be creating more than a few of these.
648  * (An early Apache version didn't destroy the sub_reqs used in directory
649  * indexing.  The result, when indexing a directory with 800-odd files in
650  * it, was massively excessive storage allocation).
651  *
652  * Note more manipulation of protocol-specific vars in the request
653  * structure...
654  */
655 
make_sub_request(const request_rec * r)656 static request_rec *make_sub_request(const request_rec *r)
657 {
658     pool *rrp = ap_make_sub_pool(r->pool);
659     request_rec *rr = ap_pcalloc(rrp, sizeof(request_rec));
660 
661     rr->pool = rrp;
662     return rr;
663 }
664 
ap_sub_req_method_uri(const char * method,const char * new_file,const request_rec * r)665 API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method,
666                                                 const char *new_file,
667                                                 const request_rec *r)
668 {
669     request_rec *rnew;
670     int res;
671     char *udir;
672 
673     rnew = make_sub_request(r);
674     rnew->hostname       = r->hostname;
675     rnew->request_time   = r->request_time;
676     rnew->connection     = r->connection;
677     rnew->server         = r->server;
678     rnew->request_config = ap_create_request_config(rnew->pool);
679     rnew->htaccess       = r->htaccess;
680     rnew->per_dir_config = r->server->lookup_defaults;
681 
682     ap_set_sub_req_protocol(rnew, r);
683 
684     /* would be nicer to pass "method" to ap_set_sub_req_protocol */
685     rnew->method = method;
686     rnew->method_number = ap_method_number_of(method);
687 
688     if (new_file[0] == '/')
689         ap_parse_uri(rnew, new_file);
690     else {
691         udir = ap_make_dirstr_parent(rnew->pool, r->uri);
692         udir = ap_escape_uri(rnew->pool, udir);    /* re-escape it */
693         ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
694     }
695 
696     /* We cannot return NULL without violating the API. So just turn this
697      * subrequest into a 500 to indicate the failure. */
698     if (ap_is_recursion_limit_exceeded(r)) {
699         rnew->status = HTTP_INTERNAL_SERVER_ERROR;
700         return rnew;
701     }
702 
703     res = ap_unescape_url(rnew->uri);
704     if (res) {
705         rnew->status = res;
706         return rnew;
707     }
708 
709     ap_getparents(rnew->uri);
710 
711     if ((res = location_walk(rnew))) {
712         rnew->status = res;
713         return rnew;
714     }
715 
716     res = ap_translate_name(rnew);
717     if (res) {
718         rnew->status = res;
719         return rnew;
720     }
721 
722     /*
723      * We could be clever at this point, and avoid calling directory_walk,
724      * etc. However, we'd need to test that the old and new filenames contain
725      * the same directory components, so it would require duplicating the
726      * start of translate_name. Instead we rely on the cache of .htaccess
727      * results.
728      *
729      * NB: directory_walk() clears the per_dir_config, so we don't inherit
730      * from location_walk() above
731      */
732 
733     if ((res = directory_walk(rnew))
734         || (res = file_walk(rnew))
735         || (res = location_walk(rnew))
736         || ((ap_satisfies(rnew) == SATISFY_ALL
737              || ap_satisfies(rnew) == SATISFY_NOSPEC)
738             ? ((res = ap_check_access(rnew))
739                || (ap_some_auth_required(rnew)
740                    && ((res = ap_check_user_id(rnew))
741                        || (res = ap_check_auth(rnew)))))
742             : ((res = ap_check_access(rnew))
743                && (!ap_some_auth_required(rnew)
744                    || ((res = ap_check_user_id(rnew))
745                        || (res = ap_check_auth(rnew)))))
746            )
747         || (res = ap_find_types(rnew))
748         || (res = ap_run_fixups(rnew))
749        ) {
750         rnew->status = res;
751     }
752     return rnew;
753 }
754 
ap_sub_req_lookup_uri(const char * new_file,const request_rec * r)755 API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
756                                                 const request_rec *r)
757 {
758     return ap_sub_req_method_uri("GET", new_file, r);
759 }
760 
ap_sub_req_lookup_file(const char * new_file,const request_rec * r)761 API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
762                                               const request_rec *r)
763 {
764     request_rec *rnew;
765     int res;
766     char *fdir;
767 
768     rnew = make_sub_request(r);
769     rnew->hostname       = r->hostname;
770     rnew->request_time   = r->request_time;
771     rnew->connection     = r->connection;
772     rnew->server         = r->server;
773     rnew->request_config = ap_create_request_config(rnew->pool);
774     rnew->htaccess       = r->htaccess;
775 
776     ap_set_sub_req_protocol(rnew, r);
777     fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
778 
779     /* We cannot return NULL without violating the API. So just turn this
780      * subrequest into a 500. */
781     if (ap_is_recursion_limit_exceeded(r)) {
782         rnew->status = HTTP_INTERNAL_SERVER_ERROR;
783         return rnew;
784     }
785 
786     /*
787      * Check for a special case... if there are no '/' characters in new_file
788      * at all, then we are looking at a relative lookup in the same
789      * directory. That means we won't have to redo directory_walk, and we may
790      * not even have to redo access checks.
791      */
792 
793     if (strchr(new_file, '/') == NULL) {
794         char *udir = ap_make_dirstr_parent(rnew->pool, r->uri);
795 
796         rnew->uri = ap_make_full_path(rnew->pool, udir, new_file);
797         rnew->filename = ap_make_full_path(rnew->pool, fdir, new_file);
798         ap_parse_uri(rnew, rnew->uri);    /* fill in parsed_uri values */
799         if (stat(rnew->filename, &rnew->finfo) < 0) {
800             rnew->finfo.st_mode = 0;
801             /* Special case for filenames which exceed the maximum limit
802 	     * imposed by the operating system (~1024). These should
803 	     * NOT be treated like "file not found", because there is
804 	     * a difference between "the file is not there" and
805 	     * "the file exists, but you tried to access it using a
806 	     * path which exceeds the path length limit".
807 	     * The idea here is to handle DoS attacks with long
808 	     * runs of //////'s in a graceful and secure manner.
809 	     */
810             if (errno == ENAMETOOLONG) {
811                 ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
812                               "Possible DoS attempt? Path=%s", r->filename);
813                 rnew->status = HTTP_FORBIDDEN;
814                 return rnew;
815             }
816         }
817 
818         if ((res = check_safe_file(rnew))) {
819             rnew->status = res;
820             return rnew;
821         }
822 
823         rnew->per_dir_config = r->per_dir_config;
824 
825         /*
826          * no matter what, if it's a subdirectory, we need to re-run
827          * directory_walk
828          */
829         if (S_ISDIR(rnew->finfo.st_mode)) {
830             res = directory_walk(rnew);
831             if (!res) {
832                 res = file_walk(rnew);
833             }
834         }
835         else {
836             if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew)))) {
837                 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, rnew,
838                             "Symbolic link not allowed: %s", rnew->filename);
839                 rnew->status = res;
840                 return rnew;
841             }
842             /*
843              * do a file_walk, if it doesn't change the per_dir_config then
844              * we know that we don't have to redo all the access checks
845              */
846             if ((res = file_walk(rnew))) {
847                 rnew->status = res;
848                 return rnew;
849             }
850             if (rnew->per_dir_config == r->per_dir_config) {
851                 if ((res = ap_find_types(rnew)) || (res = ap_run_fixups(rnew))) {
852                     rnew->status = res;
853                 }
854                 return rnew;
855             }
856         }
857     }
858     else {
859 	/* XXX: @@@: What should be done with the parsed_uri values? */
860 	ap_parse_uri(rnew, new_file);	/* fill in parsed_uri values */
861         /*
862          * XXX: this should be set properly like it is in the same-dir case
863          * but it's actually sometimes to impossible to do it... because the
864          * file may not have a uri associated with it -djg
865          */
866         rnew->uri = "INTERNALLY GENERATED file-relative req";
867         rnew->filename = ((ap_os_is_path_absolute(new_file)) ?
868                           ap_pstrdup(rnew->pool, new_file) :
869                           ap_make_full_path(rnew->pool, fdir, new_file));
870         rnew->per_dir_config = r->server->lookup_defaults;
871         res = directory_walk(rnew);
872         if (!res) {
873             res = file_walk(rnew);
874         }
875     }
876 
877     if (res
878         || ((ap_satisfies(rnew) == SATISFY_ALL
879              || ap_satisfies(rnew) == SATISFY_NOSPEC)
880             ? ((res = ap_check_access(rnew))
881                || (ap_some_auth_required(rnew)
882                    && ((res = ap_check_user_id(rnew))
883                        || (res = ap_check_auth(rnew)))))
884             : ((res = ap_check_access(rnew))
885                && (!ap_some_auth_required(rnew)
886                    || ((res = ap_check_user_id(rnew))
887                        || (res = ap_check_auth(rnew)))))
888            )
889         || (res = ap_find_types(rnew))
890         || (res = ap_run_fixups(rnew))
891        ) {
892         rnew->status = res;
893     }
894     return rnew;
895 }
896 
ap_run_sub_req(request_rec * r)897 API_EXPORT(int) ap_run_sub_req(request_rec *r)
898 {
899     int retval = ap_invoke_handler(r);
900     ap_finalize_sub_req_protocol(r);
901     return retval;
902 }
903 
ap_destroy_sub_req(request_rec * r)904 API_EXPORT(void) ap_destroy_sub_req(request_rec *r)
905 {
906     /* Reclaim the space */
907     ap_destroy_pool(r->pool);
908 }
909 
910 /*****************************************************************
911  *
912  * Mainline request processing...
913  */
914 
ap_die(int type,request_rec * r)915 API_EXPORT(void) ap_die(int type, request_rec *r)
916 {
917     int error_index = ap_index_of_response(type);
918     char *custom_response = ap_response_code_string(r, error_index);
919     int recursive_error = 0;
920 
921     if (type == DONE) {
922         ap_finalize_request_protocol(r);
923         return;
924     }
925 
926     /*
927      * The following takes care of Apache redirects to custom response URLs
928      * Note that if we are already dealing with the response to some other
929      * error condition, we just report on the original error, and give up on
930      * any attempt to handle the other thing "intelligently"...
931      */
932 
933     if (r->status != HTTP_OK) {
934         recursive_error = type;
935 
936         while (r->prev && (r->prev->status != HTTP_OK))
937             r = r->prev;        /* Get back to original error */
938 
939         type = r->status;
940         custom_response = NULL; /* Do NOT retry the custom thing! */
941     }
942 
943     r->status = type;
944 
945     /*
946      * This test is done here so that none of the auth modules needs to know
947      * about proxy authentication.  They treat it like normal auth, and then
948      * we tweak the status.
949      */
950     if (r->status == AUTH_REQUIRED && r->proxyreq == STD_PROXY) {
951         r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
952     }
953 
954     /*
955      * If we want to keep the connection, be sure that the request body
956      * (if any) has been read.
957      */
958     if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
959         && !ap_status_drops_connection(r->status)
960         && r->connection && (r->connection->keepalive != -1)) {
961 
962         (void) ap_discard_request_body(r);
963     }
964 
965     /*
966      * Two types of custom redirects --- plain text, and URLs. Plain text has
967      * a leading '"', so the URL code, here, is triggered on its absence
968      */
969 
970     if (custom_response && custom_response[0] != '"') {
971 
972         if (ap_is_url(custom_response)) {
973             /*
974              * The URL isn't local, so lets drop through the rest of this
975              * apache code, and continue with the usual REDIRECT handler.
976              * But note that the client will ultimately see the wrong
977              * status...
978              *
979              * Also, before updating r->status, we may need to ensure that
980              * the connection is dropped.  For example, there may be
981              * unread request body that would confuse us if we try
982              * to read another request.
983              */
984             if (ap_status_drops_connection(r->status)) {
985                 r->connection->keepalive = -1;
986             }
987             r->status = REDIRECT;
988             ap_table_setn(r->headers_out, "Location", custom_response);
989         }
990         else if (custom_response[0] == '/') {
991             const char *error_notes;
992             r->no_local_copy = 1;       /* Do NOT send USE_LOCAL_COPY for
993                                          * error documents! */
994             /*
995              * This redirect needs to be a GET no matter what the original
996              * method was.
997              */
998             ap_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
999 
1000 	    /*
1001 	     * Provide a special method for modules to communicate
1002 	     * more informative (than the plain canned) messages to us.
1003 	     * Propagate them to ErrorDocuments via the ERROR_NOTES variable:
1004 	     */
1005             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
1006 		ap_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
1007 	    }
1008 	    /*
1009 	     * If it is already a GET or a HEAD, don't change it
1010 	     * (method_number for GET and HEAD is the same)
1011 	     */
1012 	    if(r->method_number!=M_GET) {
1013             	r->method = ap_pstrdup(r->pool, "GET");
1014             	r->method_number = M_GET;
1015 	    }
1016             ap_internal_redirect(custom_response, r);
1017             return;
1018         }
1019         else {
1020             /*
1021              * Dumb user has given us a bad url to redirect to --- fake up
1022              * dying with a recursive server error...
1023              */
1024             recursive_error = SERVER_ERROR;
1025             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
1026                         "Invalid error redirection directive: %s",
1027                         custom_response);
1028         }
1029     }
1030     ap_send_error_response(r, recursive_error);
1031 }
1032 
decl_die(int status,char * phase,request_rec * r)1033 static void decl_die(int status, char *phase, request_rec *r)
1034 {
1035     if (status == DECLINED) {
1036         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r,
1037                     "configuration error:  couldn't %s: %s", phase, r->uri);
1038         ap_die(SERVER_ERROR, r);
1039     }
1040     else
1041         ap_die(status, r);
1042 }
1043 
ap_some_auth_required(request_rec * r)1044 API_EXPORT(int) ap_some_auth_required(request_rec *r)
1045 {
1046     /* Is there a require line configured for the type of *this* req? */
1047 
1048     const array_header *reqs_arr = ap_requires(r);
1049     require_line *reqs;
1050     int i;
1051 
1052     if (!reqs_arr)
1053         return 0;
1054 
1055     reqs = (require_line *) reqs_arr->elts;
1056 
1057     for (i = 0; i < reqs_arr->nelts; ++i)
1058         if (reqs[i].method_mask & (1 << r->method_number))
1059             return 1;
1060 
1061     return 0;
1062 }
1063 
process_request_internal(request_rec * r)1064 static void process_request_internal(request_rec *r)
1065 {
1066     int access_status;
1067 
1068     /* Ignore embedded %2F's in path for proxy requests */
1069     if (r->proxyreq == NOT_PROXY && r->parsed_uri.path) {
1070 	access_status = ap_unescape_url(r->parsed_uri.path);
1071 	if (access_status) {
1072 	    ap_die(access_status, r);
1073 	    return;
1074 	}
1075     }
1076 
1077     ap_getparents(r->uri);     /* OK --- shrinking transformations... */
1078 
1079     if ((access_status = location_walk(r))) {
1080         ap_die(access_status, r);
1081         return;
1082     }
1083 
1084     if ((access_status = ap_translate_name(r))) {
1085         decl_die(access_status, "translate", r);
1086         return;
1087     }
1088 
1089     if (r->proxyreq == NOT_PROXY) {
1090 	/*
1091 	 * We don't want TRACE to run through the normal handler set, we
1092 	 * handle it specially.
1093 	 */
1094 	if (r->method_number == M_TRACE) {
1095 	    if ((access_status = ap_send_http_trace(r)))
1096 		ap_die(access_status, r);
1097 	    else
1098 		ap_finalize_request_protocol(r);
1099 	    return;
1100 	}
1101     }
1102 
1103     if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) {
1104         r->proto_num = HTTP_VERSION(1,0);
1105     }
1106 
1107     /*
1108      * NB: directory_walk() clears the per_dir_config, so we don't inherit
1109      * from location_walk() above
1110      */
1111 
1112     if ((access_status = directory_walk(r))) {
1113         ap_die(access_status, r);
1114         return;
1115     }
1116 
1117     if ((access_status = file_walk(r))) {
1118         ap_die(access_status, r);
1119         return;
1120     }
1121 
1122     if ((access_status = location_walk(r))) {
1123         ap_die(access_status, r);
1124         return;
1125     }
1126 
1127     if ((access_status = ap_header_parse(r))) {
1128         ap_die(access_status, r);
1129         return;
1130     }
1131 
1132     switch (ap_satisfies(r)) {
1133     case SATISFY_ALL:
1134     case SATISFY_NOSPEC:
1135         if ((access_status = ap_check_access(r)) != 0) {
1136             decl_die(access_status, "check access", r);
1137             return;
1138         }
1139         if (ap_some_auth_required(r)) {
1140             if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
1141                 decl_die(access_status, ap_auth_type(r)
1142 		    ? "check user.  No user file?"
1143 		    : "perform authentication. AuthType not set!", r);
1144                 return;
1145             }
1146             if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
1147                 decl_die(access_status, ap_auth_type(r)
1148 		    ? "check access.  No groups file?"
1149 		    : "perform authentication. AuthType not set!", r);
1150                 return;
1151             }
1152         }
1153         break;
1154     case SATISFY_ANY:
1155         if (((access_status = ap_check_access(r)) != 0)) {
1156             if (!ap_some_auth_required(r)) {
1157                 decl_die(access_status, "check access", r);
1158                 return;
1159             }
1160             if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
1161                 decl_die(access_status, ap_auth_type(r)
1162 		    ? "check user.  No user file?"
1163 		    : "perform authentication. AuthType not set!", r);
1164                 return;
1165             }
1166             if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
1167                 decl_die(access_status, ap_auth_type(r)
1168 		    ? "check access.  No groups file?"
1169 		    : "perform authentication. AuthType not set!", r);
1170                 return;
1171             }
1172         }
1173         break;
1174     }
1175 
1176     if (! (r->proxyreq != NOT_PROXY
1177 	   && r->parsed_uri.scheme != NULL
1178 	   && strcmp(r->parsed_uri.scheme, "http") == 0) ) {
1179 	if ((access_status = ap_find_types(r)) != 0) {
1180 	    decl_die(access_status, "find types", r);
1181 	    return;
1182 	}
1183     }
1184 
1185     if ((access_status = ap_run_fixups(r)) != 0) {
1186         ap_die(access_status, r);
1187         return;
1188     }
1189 
1190     if ((access_status = ap_invoke_handler(r)) != 0) {
1191         ap_die(access_status, r);
1192         return;
1193     }
1194 
1195     /* Take care of little things that need to happen when we're done */
1196     ap_finalize_request_protocol(r);
1197 }
1198 
ap_process_request(request_rec * r)1199 API_EXPORT(void) ap_process_request(request_rec *r)
1200 {
1201     int old_stat;
1202 
1203     if (ap_extended_status)
1204 	ap_time_process_request(r->connection->child_num, START_PREQUEST);
1205 
1206     process_request_internal(r);
1207 
1208     old_stat = ap_update_child_status(r->connection->child_num,
1209                                    SERVER_BUSY_LOG, r);
1210 
1211     /*
1212      * We want to flush the last packet if this isn't a pipelining connection
1213      * *before* we start into logging.  Suppose that the logging causes a DNS
1214      * lookup to occur, which may have a high latency.  If we hold off on
1215      * this packet, then it'll appear like the link is stalled when really
1216      * it's the application that's stalled.
1217      */
1218     ap_bhalfduplex(r->connection->client);
1219     ap_log_transaction(r);
1220 
1221     (void) ap_update_child_status(r->connection->child_num, old_stat, r);
1222     if (ap_extended_status)
1223 	ap_time_process_request(r->connection->child_num, STOP_PREQUEST);
1224 }
1225 
rename_original_env(pool * p,table * t)1226 static table *rename_original_env(pool *p, table *t)
1227 {
1228     array_header *env_arr = ap_table_elts(t);
1229     table_entry *elts = (table_entry *) env_arr->elts;
1230     table *new = ap_make_table(p, env_arr->nalloc);
1231     int i;
1232 
1233     for (i = 0; i < env_arr->nelts; ++i) {
1234         if (!elts[i].key)
1235             continue;
1236         ap_table_setn(new, ap_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
1237                   elts[i].val);
1238     }
1239 
1240     return new;
1241 }
1242 
internal_internal_redirect(const char * new_uri,request_rec * r)1243 static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r)
1244 {
1245     int access_status;
1246     request_rec *new;
1247     const char *ccp;
1248 
1249     if (ap_is_recursion_limit_exceeded(r)) {
1250         ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
1251         return NULL;
1252     }
1253 
1254     new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec));
1255 
1256     new->connection = r->connection;
1257     new->server     = r->server;
1258     new->pool       = r->pool;
1259 
1260     /*
1261      * A whole lot of this really ought to be shared with http_protocol.c...
1262      * another missing cleanup.  It's particularly inappropriate to be
1263      * setting header_only, etc., here.
1264      */
1265 
1266     new->method          = r->method;
1267     new->method_number   = r->method_number;
1268     /* initialize context _BEFORE_ ap_parse_uri() call */
1269     new->ctx             = r->ctx;
1270     ap_parse_uri(new, new_uri);
1271     new->request_config = ap_create_request_config(r->pool);
1272     new->per_dir_config = r->server->lookup_defaults;
1273 
1274     new->prev = r;
1275     r->next   = new;
1276 
1277     /* Inherit the rest of the protocol info... */
1278 
1279     new->the_request = r->the_request;
1280 
1281     new->allowed         = r->allowed;
1282 
1283     new->status          = r->status;
1284     new->assbackwards    = r->assbackwards;
1285     new->header_only     = r->header_only;
1286     new->protocol        = r->protocol;
1287     new->proto_num       = r->proto_num;
1288     new->hostname        = r->hostname;
1289     new->request_time    = r->request_time;
1290     new->main            = r->main;
1291 
1292     new->headers_in      = r->headers_in;
1293     new->headers_out     = ap_make_table(r->pool, 12);
1294     new->err_headers_out = r->err_headers_out;
1295     new->subprocess_env  = rename_original_env(r->pool, r->subprocess_env);
1296     new->notes           = ap_make_table(r->pool, 5);
1297 
1298     new->htaccess        = r->htaccess;
1299     new->no_cache        = r->no_cache;
1300     new->expecting_100	 = r->expecting_100;
1301     new->no_local_copy   = r->no_local_copy;
1302     new->read_length     = r->read_length;     /* We can only read it once */
1303     new->vlist_validator = r->vlist_validator;
1304 
1305     if ((ccp = ap_table_get(r->notes, "address-family")) != NULL)
1306 	ap_table_setn(new->notes, "address-family", ccp);
1307 
1308     ap_table_setn(new->subprocess_env, "REDIRECT_STATUS",
1309 	ap_psprintf(r->pool, "%d", r->status));
1310 
1311     /*
1312      * XXX: hmm.  This is because mod_setenvif and mod_unique_id really need
1313      * to do their thing on internal redirects as well.  Perhaps this is a
1314      * misnamed function.
1315      */
1316     if ((access_status = ap_run_post_read_request(new))) {
1317         ap_die(access_status, new);
1318         return NULL;
1319     }
1320 
1321     return new;
1322 }
1323 
ap_internal_redirect(const char * new_uri,request_rec * r)1324 API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *r)
1325 {
1326     request_rec *new = internal_internal_redirect(new_uri, r);
1327 
1328     if (new) {
1329         process_request_internal(new);
1330     }
1331 }
1332 
1333 /* This function is designed for things like actions or CGI scripts, when
1334  * using AddHandler, and you want to preserve the content type across
1335  * an internal redirect.
1336  */
ap_internal_redirect_handler(const char * new_uri,request_rec * r)1337 API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
1338 {
1339     request_rec *new = internal_internal_redirect(new_uri, r);
1340 
1341     if (new) {
1342         if (r->handler)
1343             new->content_type = r->content_type;
1344         process_request_internal(new);
1345     }
1346 }
1347 
1348 /*
1349  * Is it the initial main request, which we only get *once* per HTTP request?
1350  */
ap_is_initial_req(request_rec * r)1351 API_EXPORT(int) ap_is_initial_req(request_rec *r)
1352 {
1353     return
1354         (r->main == NULL)       /* otherwise, this is a sub-request */
1355         &&
1356         (r->prev == NULL);      /* otherwise, this is an internal redirect */
1357 }
1358 
1359 /*
1360  * Function to set the r->mtime field to the specified value if it's later
1361  * than what's already there.
1362  */
ap_update_mtime(request_rec * r,time_t dependency_mtime)1363 API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime)
1364 {
1365     if (r->mtime < dependency_mtime) {
1366         r->mtime = dependency_mtime;
1367     }
1368     return r->mtime;
1369 }
1370