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