1 /* $MirOS: src/usr.sbin/httpd/src/modules/standard/mod_rewrite.h,v 1.2 2013/10/31 20:07:25 tg Exp $ */
2 
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright © 2013
7  *	Thorsten “mirabilos” Glaser <tg@mirbsd.org>
8  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
9  * reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in
20  *    the documentation and/or other materials provided with the
21  *    distribution.
22  *
23  * 3. The end-user documentation included with the redistribution,
24  *    if any, must include the following acknowledgment:
25  *       "This product includes software developed by the
26  *        Apache Software Foundation (http://www.apache.org/)."
27  *    Alternately, this acknowledgment may appear in the software itself,
28  *    if and wherever such third-party acknowledgments normally appear.
29  *
30  * 4. The names "Apache" and "Apache Software Foundation" must
31  *    not be used to endorse or promote products derived from this
32  *    software without prior written permission. For written
33  *    permission, please contact apache@apache.org.
34  *
35  * 5. Products derived from this software may not be called "Apache",
36  *    nor may "Apache" appear in their name, without prior written
37  *    permission of the Apache Software Foundation.
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This software consists of voluntary contributions made by many
54  * individuals on behalf of the Apache Software Foundation.  For more
55  * information on the Apache Software Foundation, please see
56  * <http://www.apache.org/>.
57  *
58  * Portions of this software are based upon public domain software
59  * originally written at the National Center for Supercomputing Applications,
60  * University of Illinois, Urbana-Champaign.
61  */
62 
63 
64 #ifndef _MOD_REWRITE_H
65 #define _MOD_REWRITE_H 1
66 
67 /*
68 **                       _                            _ _
69 **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___
70 **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
71 **  | | | | | | (_) | (_| |   | | |  __/\ V  V /| |  | | ||  __/
72 **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
73 **                       |_____|
74 **
75 **  URL Rewriting Module
76 **
77 **  This module uses a rule-based rewriting engine (based on a
78 **  regular-expression parser) to rewrite requested URLs on the fly.
79 **
80 **  It supports an unlimited number of additional rule conditions (which can
81 **  operate on a lot of variables, even on HTTP headers) for granular
82 **  matching and even external database lookups (either via plain text
83 **  tables, DBM hash files or even external processes) for advanced URL
84 **  substitution.
85 **
86 **  It operates on the full URLs (including the PATH_INFO part) both in
87 **  per-server context (httpd.conf) and per-dir context (.htaccess) and even
88 **  can generate QUERY_STRING parts on result.   The rewriting result finally
89 **  can lead to internal subprocessing, external request redirection or even
90 **  to internal proxy throughput.
91 **
92 **  This module was originally written in April 1996 and
93 **  gifted exclusively to the The Apache Group in July 1997 by
94 **
95 **      Ralf S. Engelschall
96 **      rse@engelschall.com
97 **      www.engelschall.com
98 */
99 
100 
101     /* Include from the underlaying Unix system ... */
102 #include <string.h>
103 #include <stdarg.h>
104 #include <stdlib.h>
105 #include <time.h>
106 #include <signal.h>
107 #include <errno.h>
108 #include <ctype.h>
109 #include <sys/types.h>
110 #include <sys/stat.h>
111 
112     /* Include from the Apache server ... */
113 #define CORE_PRIVATE
114 #include "httpd.h"
115 #include "http_config.h"
116 #include "http_conf_globals.h"
117 #include "http_request.h"
118 #include "http_core.h"
119 #include "http_log.h"
120 #include "http_vhost.h"
121 
122     /*
123      * The key in the r->notes table wherein we store our accumulated
124      * Vary values, and the one used for per-condition checks in a chain.
125      */
126 #define VARY_KEY "rewrite-Vary"
127 #define VARY_KEY_THIS "rewrite-Vary-this"
128 
129     /* The NDBM support:
130      * We support only NDBM files.
131      * But we have to stat the file for the mtime,
132      * so we also need to know the file extension
133      */
134 #include <ndbm.h>
135 #if defined(DBM_SUFFIX)
136 #define NDBM_FILE_SUFFIX DBM_SUFFIX
137 #elif (defined(DB_LOCK) && defined(DB_SHMEM))
138 #define NDBM_FILE_SUFFIX ".db"
139 #else
140 #define NDBM_FILE_SUFFIX ".pag"
141 #endif
142 
143 
144     /* The locking support:
145      * Try to determine whether we should use fcntl() or flock().
146      * Would be better ap_config.h could provide this... :-(
147      * Small monkey business to ensure that fcntl is preferred,
148      * unless we specified USE_FLOCK_SERIALIZED_ACCEPT during compile.
149      */
150 #define USE_FLOCK 1
151 #include <sys/file.h>
152 #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
153 #define USE_FLOCK 1
154 #include <sys/file.h>
155 #ifndef LOCK_UN
156 #undef USE_FLOCK
157 #define USE_FCNTL 1
158 #include <fcntl.h>
159 #endif
160 #endif
161 
162 
163 /*
164 **
165 **  Some defines
166 **
167 */
168 
169 #define ENVVAR_SCRIPT_URL "SCRIPT_URL"
170 #define ENVVAR_SCRIPT_URI "SCRIPT_URI"
171 
172 #ifndef SUPPORT_DBM_REWRITEMAP
173 #define SUPPORT_DBM_REWRITEMAP 0
174 #endif
175 
176 #define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
177 
178 #define CONDFLAG_NONE               1<<0
179 #define CONDFLAG_NOCASE             1<<1
180 #define CONDFLAG_NOTMATCH           1<<2
181 #define CONDFLAG_ORNEXT             1<<3
182 
183 #define RULEFLAG_NONE               1<<0
184 #define RULEFLAG_FORCEREDIRECT      1<<1
185 #define RULEFLAG_LASTRULE           1<<2
186 #define RULEFLAG_NEWROUND           1<<3
187 #define RULEFLAG_CHAIN              1<<4
188 #define RULEFLAG_IGNOREONSUBREQ     1<<5
189 #define RULEFLAG_NOTMATCH           1<<6
190 #define RULEFLAG_PROXY              1<<7
191 #define RULEFLAG_PASSTHROUGH        1<<8
192 #define RULEFLAG_FORBIDDEN          1<<9
193 #define RULEFLAG_GONE               1<<10
194 #define RULEFLAG_QSAPPEND           1<<11
195 #define RULEFLAG_NOCASE             1<<12
196 #define RULEFLAG_NOESCAPE           1<<13
197 
198 #define ACTION_NORMAL               1<<0
199 #define ACTION_NOESCAPE             1<<1
200 
201 #define MAPTYPE_TXT                 1<<0
202 #define MAPTYPE_DBM                 1<<1
203 #define MAPTYPE_PRG                 1<<2
204 #define MAPTYPE_INT                 1<<3
205 #define MAPTYPE_RND                 1<<4
206 
207 #define ENGINE_DISABLED             1<<0
208 #define ENGINE_ENABLED              1<<1
209 
210 #define OPTION_NONE                 1<<0
211 #define OPTION_INHERIT              1<<1
212 
213 #define CACHEMODE_TS                1<<0
214 #define CACHEMODE_TTL               1<<1
215 
216 #define CACHE_TLB_ROWS 1024
217 #define CACHE_TLB_COLS 4
218 
219 #ifndef FALSE
220 #define FALSE 0
221 #define TRUE  !FALSE
222 #endif
223 
224 #ifndef NO
225 #define NO    FALSE
226 #define YES   TRUE
227 #endif
228 
229 #ifndef RAND_MAX
230 #define RAND_MAX 32767
231 #endif
232 
233 #ifndef LONG_STRING_LEN
234 #define LONG_STRING_LEN 2048
235 #endif
236 
237 #define MAX_ENV_FLAGS 15
238 
239 /* default maximum number of internal redirects */
240 #define REWRITE_REDIRECT_LIMIT 10
241 
242 /*
243 **
244 **  our private data structures we handle with
245 **
246 */
247 
248     /* the list structures for holding the mapfile information
249      * and the rewrite rules
250      */
251 typedef struct {
252     char *name;                    /* the name of the map */
253     char *datafile;                /* filename for map data files */
254     char *checkfile;               /* filename to check for map existence */
255     int   type;                    /* the type of the map */
256     int   fpin;                    /* in  file pointer for program maps */
257     int   fpout;                   /* out file pointer for program maps */
258     int   fperr;                   /* err file pointer for program maps */
259     char *(*func)(request_rec *,   /* function pointer for internal maps */
260                   char *);
261 } rewritemap_entry;
262 
263 typedef struct {
264     char    *input;                /* Input string of RewriteCond */
265     char    *pattern;              /* the RegExp pattern string */
266     regex_t *regexp;
267     int      flags;                /* Flags which control the match */
268 } rewritecond_entry;
269 
270 typedef struct {
271     array_header *rewriteconds;    /* the corresponding RewriteCond entries */
272     char    *pattern;              /* the RegExp pattern string */
273     regex_t *regexp;               /* the RegExp pattern compilation */
274     char    *output;               /* the Substitution string */
275     int      flags;                /* Flags which control the substitution */
276     char    *forced_mimetype;      /* forced MIME type of substitution */
277     int      forced_responsecode;  /* forced HTTP redirect response status */
278     char    *env[MAX_ENV_FLAGS+1]; /* added environment variables */
279     int      skip;                 /* number of next rules to skip */
280 } rewriterule_entry;
281 
282 
283     /* the per-server or per-virtual-server configuration
284      * statically generated once on startup for every server
285      */
286 typedef struct {
287     int           state;           /* the RewriteEngine state */
288     int           options;         /* the RewriteOption state */
289     char         *rewritelogfile;  /* the RewriteLog filename */
290     int           rewritelogfp;    /* the RewriteLog open filepointer */
291     int           rewriteloglevel; /* the RewriteLog level of verbosity */
292     array_header *rewritemaps;     /* the RewriteMap entries */
293     array_header *rewriteconds;    /* the RewriteCond entries (temporary) */
294     array_header *rewriterules;    /* the RewriteRule entries */
295     server_rec   *server;          /* the corresponding server indicator */
296     int          redirect_limit;   /* maximum number of internal redirects */
297 } rewrite_server_conf;
298 
299 
300     /* the per-directory configuration
301      * generated on-the-fly by Apache server for current request
302      */
303 typedef struct {
304     int           state;           /* the RewriteEngine state */
305     int           options;         /* the RewriteOption state */
306     array_header *rewriteconds;    /* the RewriteCond entries (temporary) */
307     array_header *rewriterules;    /* the RewriteRule entries */
308     char         *directory;       /* the directory where it applies */
309     char         *baseurl;         /* the base-URL  where it applies */
310     int          redirect_limit;   /* maximum number of internal redirects */
311 } rewrite_perdir_conf;
312 
313     /* the per-request configuration
314      */
315 typedef struct {
316     int           redirects;       /* current number of redirects */
317     int           redirect_limit;  /* maximum number of redirects */
318 } rewrite_request_conf;
319 
320 
321     /* the cache structures,
322      * a 4-way hash table with LRU functionality
323      */
324 typedef struct cacheentry {
325     time_t time;
326     char  *key;
327     char  *value;
328 } cacheentry;
329 
330 typedef struct tlbentry {
331     int t[CACHE_TLB_COLS];
332 } cachetlbentry;
333 
334 typedef struct cachelist {
335     char         *resource;
336     array_header *entries;
337     array_header *tlb;
338 } cachelist;
339 
340 typedef struct cache {
341     pool         *pool;
342     array_header *lists;
343 } cache;
344 
345 
346     /* the regex structure for the
347      * substitution of backreferences
348      */
349 typedef struct backrefinfo {
350     char *source;
351     int nsub;
352     regmatch_t regmatch[AP_MAX_REG_MATCH];
353 } backrefinfo;
354 
355 
356 /*
357 **
358 **  forward declarations
359 **
360 */
361 
362     /* config structure handling */
363 static void *config_server_create(pool *p, server_rec *s);
364 static void *config_server_merge (pool *p, void *basev, void *overridesv);
365 static void *config_perdir_create(pool *p, char *path);
366 static void *config_perdir_merge (pool *p, void *basev, void *overridesv);
367 
368     /* config directive handling */
369 static const char *cmd_rewriteengine(cmd_parms *cmd,
370                                      rewrite_perdir_conf *dconf, int flag);
371 static const char *cmd_rewriteoptions(cmd_parms *cmd,
372                                       void *in_dconf,
373                                       const char *option);
374 static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
375 static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
376 static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1,
377                                        char *a2);
378 static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1);
379 static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
380                                    char *a1);
381 static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
382                                    char *str);
383 static const char *cmd_rewritecond_parseflagfield(pool *p,
384                                                   rewritecond_entry *new,
385                                                   char *str);
386 static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg,
387                                            char *key, char *val);
388 static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
389                                    char *str);
390 static const char *cmd_rewriterule_parseflagfield(pool *p,
391                                                   rewriterule_entry *new,
392                                                   char *str);
393 static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg,
394                                            char *key, char *val);
395 
396     /* initialisation */
397 static void init_module(server_rec *s, pool *p);
398 static void init_child(server_rec *s, pool *p);
399 
400     /* runtime hooks */
401 static int hook_uri2file   (request_rec *r);
402 static int hook_mimetype   (request_rec *r);
403 static int hook_fixup      (request_rec *r);
404 static int handler_redirect(request_rec *r);
405 
406     /* rewriting engine */
407 static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
408                               char *perdir);
409 static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
410                               char *perdir);
411 static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
412                               char *perdir, backrefinfo *briRR,
413                               backrefinfo *briRC);
414 
415 static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
416 		       backrefinfo *briRR, backrefinfo *briRC);
417 static void do_expand_env(request_rec *r, char *env[],
418 			  backrefinfo *briRR, backrefinfo *briRC);
419 
420     /* URI transformation function */
421 static void  splitout_queryargs(request_rec *r, int qsappend);
422 static void  fully_qualify_uri(request_rec *r);
423 static void  reduce_uri(request_rec *r);
424 static unsigned is_absolute_uri(char *uri);
425 static char *escape_absolute_uri(ap_pool *p, char *uri, unsigned scheme);
426 static char *expand_tildepaths(request_rec *r, char *uri);
427 
428     /* rewrite map support functions */
429 static char *lookup_map(request_rec *r, char *name, char *key);
430 static char *lookup_map_txtfile(request_rec *r, char *file, char *key);
431 static char *lookup_map_dbmfile(request_rec *r, char *file, char *key);
432 static char *lookup_map_program(request_rec *r, int fpin,
433                                 int fpout, char *key);
434 static char *lookup_map_internal(request_rec *r,
435                                  char *(*func)(request_rec *r, char *key),
436                                  char *key);
437 static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
438 static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
439 static char *rewrite_mapfunc_escape(request_rec *r, char *key);
440 static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
441 static char *select_random_value_part(request_rec *r, char *value);
442 static void  rewrite_rand_init(void);
443 static int   rewrite_rand(int l, int h);
444 
445     /* rewriting logfile support */
446 static void  open_rewritelog(server_rec *s, pool *p);
447 static void  rewritelog(request_rec *r, int level, const char *text, ...)
448                         __attribute__((__format__(__printf__, 3, 4)));
449 static char *current_logtime(request_rec *r);
450 
451     /* rewriting lockfile support */
452 static void rewritelock_create(server_rec *s, pool *p);
453 static void rewritelock_open(server_rec *s, pool *p);
454 static void rewritelock_remove(void *data);
455 static void rewritelock_alloc(request_rec *r);
456 static void rewritelock_free(request_rec *r);
457 
458     /* program map support */
459 static void  run_rewritemap_programs(server_rec *s, pool *p);
460 static int   rewritemap_program_child(void *cmd, child_info *pinfo);
461 
462     /* env variable support */
463 static char *lookup_variable(request_rec *r, char *var);
464 static char *lookup_header(request_rec *r, const char *name);
465 
466     /* caching functions */
467 static cache *init_cache(pool *p);
468 static char  *get_cache_string(cache *c, char *res, int mode, time_t mtime,
469                                char *key);
470 static void   set_cache_string(cache *c, char *res, int mode, time_t mtime,
471                                char *key, char *value);
472 static cacheentry *retrieve_cache_string(cache *c, char *res, char *key);
473 static void   store_cache_string(cache *c, char *res, cacheentry *ce);
474 
475     /* misc functions */
476 static char  *subst_prefix_path(request_rec *r, char *input, char *match,
477                                 char *subst);
478 static int    parseargline(char *str, char **a1, char **a2, char **a3);
479 static int    prefix_stat(const char *path, ap_pool *pool);
480 static void   add_env_variable(request_rec *r, char *s);
481 static int    subreq_ok(request_rec *r);
482 static int    is_redirect_limit_exceeded(request_rec *r);
483 
484     /* File locking */
485 static void fd_lock(request_rec *r, int fd);
486 static void fd_unlock(request_rec *r, int fd);
487 
488     /* Lexicographic Comparison */
489 static int compare_lexicography(char *cpNum1, char *cpNum2);
490 
491     /* Bracketed expression handling */
492 static char *find_closing_bracket(char *s, int left, int right);
493 static char *find_char_in_brackets(char *s, int c, int left, int right);
494 
495     /* Find end of bracketed expression */
496 static char *find_closing_bracket(char *s, int left, int right);
497 
498 #endif /* _MOD_REWRITE_H */
499 
500 /*EOF*/
501