akosut 96/07/25 12:32:33
Modified: src alloc.c alloc.h buff.c conf.h http_bprintf.c http_core.c http_core.h http_request.c Log: Add <Files> directive, and allow <Directory> and <Location> (and <Files>) to use regex. Also fix <Location> "bug" and add regcomp() function. Reviewed by: Randy Terbush, Brian Behlendorf Revision Changes Path 1.8 +21 -0 apache/src/alloc.c Index: alloc.c =================================================================== RCS file: /export/home/cvs/apache/src/alloc.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C3 -r1.7 -r1.8 *** alloc.c 1996/07/21 14:49:01 1.7 --- alloc.c 1996/07/25 19:32:25 1.8 *************** *** 803,808 **** --- 803,829 ---- return res; } + /* + * Here's a pool-based interface to POSIX regex's regcomp(). + * Note that we return regex_t instead of being passed one. + * The reason is that if you use an already-used regex_t structure, + * the memory that you've already allocated gets forgotten, and + * regfree() doesn't clear it. So we don't allow it. + */ + + static void regex_cleanup (void *preg) { regfree ((regex_t *)preg); } + + regex_t *pregcomp(pool *p, const char *pattern, int cflags) { + regex_t *preg = palloc(p, sizeof(regex_t)); + + if (regcomp(preg, pattern, cflags)) + return NULL; + + register_cleanup (p, (void *)preg, regex_cleanup, regex_cleanup); + + return preg; + } + /***************************************************************** * * More grotty system stuff... subprocesses. Frump. These don't use 1.7 +2 -0 apache/src/alloc.h Index: alloc.h =================================================================== RCS file: /export/home/cvs/apache/src/alloc.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C3 -r1.6 -r1.7 *** alloc.h 1996/07/21 14:49:01 1.6 --- alloc.h 1996/07/25 19:32:26 1.7 *************** *** 207,212 **** --- 207,214 ---- void note_cleanups_for_fd (pool *, int); void kill_cleanups_for_fd (pool *p, int fd); + regex_t *pregcomp(pool *p, const char *pattern, int cflags); + /* routines to note closes... file descriptors are constrained enough * on some systems that we want to support this. */ 1.4 +1 -0 apache/src/buff.c Index: buff.c =================================================================== RCS file: /export/home/cvs/apache/src/buff.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C3 -r1.3 -r1.4 *** buff.c 1996/05/08 15:28:19 1.3 --- buff.c 1996/07/25 19:32:26 1.4 *************** *** 56,61 **** --- 56,62 ---- #include <string.h> #include <unistd.h> + #include "conf.h" #include "alloc.h" #include "buff.h" 1.24 +1 -0 apache/src/conf.h Index: conf.h =================================================================== RCS file: /export/home/cvs/apache/src/conf.h,v retrieving revision 1.23 retrieving revision 1.24 diff -C3 -r1.23 -r1.24 *** conf.h 1996/07/18 18:44:44 1.23 --- conf.h 1996/07/25 19:32:27 1.24 *************** *** 388,393 **** --- 388,394 ---- #ifndef QNX #include <memory.h> #endif + #include "regex/regex.h" #ifdef HAVE_RESOURCE #include <sys/resource.h> 1.5 +1 -7 apache/src/http_bprintf.c Index: http_bprintf.c =================================================================== RCS file: /export/home/cvs/apache/src/http_bprintf.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C3 -r1.4 -r1.5 *** http_bprintf.c 1996/07/16 19:57:25 1.4 --- http_bprintf.c 1996/07/25 19:32:27 1.5 *************** *** 13,27 **** * 18 May 1996 Initial revision [Ben Laurie] */ - #include <stdio.h> - #include <stdlib.h> - #include <stdarg.h> - #include <string.h> - #ifndef QNX - #include <memory.h> - #endif #include <assert.h> #include <math.h> #include "alloc.h" #include "buff.h" --- 13,21 ---- * 18 May 1996 Initial revision [Ben Laurie] */ #include <assert.h> #include <math.h> + #include "conf.h" #include "alloc.h" #include "buff.h" 1.19 +78 -2 apache/src/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache/src/http_core.c,v retrieving revision 1.18 retrieving revision 1.19 diff -C3 -r1.18 -r1.19 *** http_core.c 1996/06/12 18:14:31 1.18 --- http_core.c 1996/07/25 19:32:28 1.19 *************** *** 93,98 **** --- 93,101 ---- conf->hostname_lookups = 2;/* binary, but will use 2 as an "unset = on" */ conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */ + + conf->sec = make_array (a, 2, sizeof(void *)); + return (void *)conf; } *************** *** 107,112 **** --- 110,116 ---- memcpy ((char *)conf, (const char *)base, sizeof(core_dir_config)); conf->d = new->d; + conf->r = new->r; if (new->opts != OPT_UNSET) conf->opts = new->opts; if (new->override != OR_UNSET) conf->override = new->override; *************** *** 124,129 **** --- 128,135 ---- if ((new->do_rfc1413 & 2) == 0) conf->do_rfc1413 = new->do_rfc1413; if ((new->content_md5 & 2) == 0) conf->content_md5 = new->content_md5; + conf->sec = append_arrays (a, base->sec, new->sec); + return (void*)conf; } *************** *** 179,184 **** --- 185,197 ---- *new_space = url_config; } + void add_file_conf (core_dir_config *conf, void *url_config) + { + void **new_space = (void **) push_array (conf->sec); + + *new_space = url_config; + } + /***************************************************************** * * There are some elements of the core config structures in which *************** *** 518,536 **** char *errmsg, *endp = strrchr (arg, '>'); int old_overrides = cmd->override; char *old_path = cmd->path; void *new_dir_conf = create_per_dir_config (cmd->pool); if (endp) *endp = '\0'; if (cmd->path) return "<Directory> sections don't nest"; if (cmd->limited != -1) return "Can't have <Directory> within <Limit>"; ! cmd->path = getword_conf (cmd->pool, &arg); cmd->override = OR_ALL|ACCESS_CONF; errmsg = srm_command_loop (cmd, new_dir_conf); add_per_dir_conf (cmd->server, new_dir_conf); ! cmd->path = old_path; cmd->override = old_overrides; --- 531,559 ---- char *errmsg, *endp = strrchr (arg, '>'); int old_overrides = cmd->override; char *old_path = cmd->path; + core_dir_config *conf; void *new_dir_conf = create_per_dir_config (cmd->pool); + regex_t *r = NULL; if (endp) *endp = '\0'; if (cmd->path) return "<Directory> sections don't nest"; if (cmd->limited != -1) return "Can't have <Directory> within <Limit>"; ! cmd->path = getword_conf (cmd->pool, &arg); cmd->override = OR_ALL|ACCESS_CONF; + if (!strcmp(cmd->path, "~")) { + cmd->path = getword_conf (cmd->pool, &arg); + r = pregcomp(cmd->pool, cmd->path, REG_EXTENDED); + } + errmsg = srm_command_loop (cmd, new_dir_conf); add_per_dir_conf (cmd->server, new_dir_conf); ! ! conf = (core_dir_config *)get_module_config(new_dir_conf, &core_module); ! conf->r = r; ! cmd->path = old_path; cmd->override = old_overrides; *************** *** 550,555 **** --- 573,579 ---- int old_overrides = cmd->override; char *old_path = cmd->path; core_dir_config *conf; + regex_t *r = NULL; void *new_url_conf = create_per_dir_config (cmd->pool); *************** *** 561,571 **** --- 585,601 ---- cmd->path = getword_conf (cmd->pool, &arg); cmd->override = OR_ALL|ACCESS_CONF; + if (!strcmp(cmd->path, "~")) { + cmd->path = getword_conf (cmd->pool, &arg); + r = pregcomp(cmd->pool, cmd->path, REG_EXTENDED); + } + errmsg = srm_command_loop (cmd, new_url_conf); if (errmsg != end_url_magic) return errmsg; conf = (core_dir_config *)get_module_config(new_url_conf, &core_module); conf->d = pstrdup(cmd->pool, cmd->path); /* No mangling, please */ + conf->r = r; add_per_url_conf (cmd->server, new_url_conf); *************** *** 575,580 **** --- 605,654 ---- return NULL; } + static char *end_file_magic = "</Files> outside of any <Files> section"; + + char *end_filesection (cmd_parms *cmd, void *dummy) { + return end_file_magic; + } + + char *filesection (cmd_parms *cmd, core_dir_config *c, char *arg) + { + char *errmsg, *endp = strrchr (arg, '>'); + char *old_path = cmd->path; + core_dir_config *conf; + regex_t *r = NULL; + + void *new_file_conf = create_per_dir_config (cmd->pool); + + if (endp) *endp = '\0'; + + if (cmd->limited != -1) return "Can't have <Files> within <Limit>"; + + cmd->path = getword_conf (cmd->pool, &arg); + + if (!strcmp(cmd->path, "~")) { + cmd->path = getword_conf (cmd->pool, &arg); + if (old_path && cmd->path[0] != '/' && cmd->path[0] != '^') + cmd->path = pstrcat(cmd->pool, "^", old_path, cmd->path, NULL); + r = pregcomp(cmd->pool, cmd->path, REG_EXTENDED); + } + else if (old_path && cmd->path[0] != '/') + cmd->path = pstrcat(cmd->pool, old_path, cmd->path, NULL); + + errmsg = srm_command_loop (cmd, new_file_conf); + if (errmsg != end_file_magic) return errmsg; + + conf = (core_dir_config *)get_module_config(new_file_conf, &core_module); + conf->d = pstrdup(cmd->pool, cmd->path); + conf->r = r; + + add_file_conf (c, new_file_conf); + + cmd->path = old_path; + + return NULL; + } + /* httpd.conf commands... beginning with the <VirtualHost> business */ char *end_virthost_magic = "</Virtualhost> out of place"; *************** *** 779,784 **** --- 853,860 ---- { "</Directory>", end_dirsection, NULL, ACCESS_CONF, NO_ARGS, NULL }, { "<Location", urlsection, NULL, RSRC_CONF, RAW_ARGS, NULL }, { "</Location>", end_urlsection, NULL, ACCESS_CONF, NO_ARGS, NULL }, + { "<Files", filesection, NULL, OR_ALL, RAW_ARGS, NULL }, + { "</Files>", end_filesection, NULL, OR_ALL, NO_ARGS, NULL }, { "<Limit", limit, NULL, OR_ALL, RAW_ARGS, NULL }, { "</Limit>", endlimit, NULL, OR_ALL, RAW_ARGS, NULL }, { "AuthType", set_string_slot, (void*)XtOffsetOf(core_dir_config, auth_type), 1.7 +5 -1 apache/src/http_core.h Index: http_core.h =================================================================== RCS file: /export/home/cvs/apache/src/http_core.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C3 -r1.6 -r1.7 *** http_core.h 1996/04/06 23:38:25 1.6 --- http_core.h 1996/07/25 19:32:28 1.7 *************** *** 152,157 **** --- 152,161 ---- int hostname_lookups; int do_rfc1413; /* See if client is advertising a username? */ + /* Access control */ + array_header *sec; + regex_t *r; + } core_dir_config; /* Per-server core configuration */ *************** *** 165,171 **** char *document_root; /* Access control */ ! char *access_name; array_header *sec; array_header *sec_url; --- 169,175 ---- char *document_root; /* Access control */ ! char *access_name; array_header *sec; array_header *sec_url; 1.12 +97 -10 apache/src/http_request.c Index: http_request.c =================================================================== RCS file: /export/home/cvs/apache/src/http_request.c,v retrieving revision 1.11 retrieving revision 1.12 diff -C3 -r1.11 -r1.12 *** http_request.c 1996/07/01 18:10:29 1.11 --- http_request.c 1996/07/25 19:32:29 1.12 *************** *** 242,248 **** entry_dir = entry_core->d; this_conf = NULL; ! if (is_matchexp(entry_dir)) { if (!strcmp_match(test_filename, entry_dir)) this_conf = entry_config; } --- 242,252 ---- entry_dir = entry_core->d; this_conf = NULL; ! if (entry_core->r) { ! if (!regexec(entry_core->r, test_filename, 0, NULL, 0)) ! this_conf = entry_config; ! } ! else if (is_matchexp(entry_dir)) { if (!strcmp_match(test_filename, entry_dir)) this_conf = entry_config; } *************** *** 301,311 **** (core_dir_config *)get_module_config(entry_config, &core_module); entry_dir = entry_core->d; ! if (is_matchexp(entry_dir) && !strcmp_match(this_dir, entry_dir)) { ! /* Don't try this wildcard again --- if it ends in '*' ! * it'll match again, and subdirectories won't be able to ! * override it... ! */ sec[j] = NULL; this_conf = entry_config; } --- 305,323 ---- (core_dir_config *)get_module_config(entry_config, &core_module); entry_dir = entry_core->d; ! if (entry_core->r) { ! if (!regexec(entry_core->r, this_dir, 0, NULL, ! (j == num_sec) ? 0 : REG_NOTEOL)) { ! /* Don't try this wildcard again --- if it ends in '*' ! * it'll match again, and subdirectories won't be able to ! * override it... ! */ ! sec[j] = NULL; ! this_conf = entry_config; ! } ! } ! else if (is_matchexp(entry_dir) && ! !strcmp_match(this_dir, entry_dir)) { sec[j] = NULL; this_conf = entry_config; } *************** *** 359,365 **** void *per_dir_defaults = r->per_dir_config; core_dir_config **url = (core_dir_config **)url_array->elts; ! int num_url = url_array->nelts; char *test_location = pstrdup (r->pool, r->uri); /* Go through the location entries, and check for matches. */ --- 371,377 ---- void *per_dir_defaults = r->per_dir_config; core_dir_config **url = (core_dir_config **)url_array->elts; ! int len, num_url = url_array->nelts; char *test_location = pstrdup (r->pool, r->uri); /* Go through the location entries, and check for matches. */ *************** *** 383,394 **** get_module_config(entry_config, &core_module); entry_url = entry_core->d; this_conf = NULL; ! if (is_matchexp(entry_url)) { if (!strcmp_match(test_location, entry_url)) this_conf = entry_config; } ! else if (!strncmp (test_location, entry_url, strlen(entry_url))) this_conf = entry_config; if (this_conf) --- 395,474 ---- get_module_config(entry_config, &core_module); entry_url = entry_core->d; + len = strlen(entry_url); + this_conf = NULL; ! ! if (entry_core->r) { ! if (!regexec(entry_core->r, test_location, 0, NULL, 0)) ! this_conf = entry_config; ! } ! else if (is_matchexp(entry_url)) { if (!strcmp_match(test_location, entry_url)) this_conf = entry_config; } ! else if (!strncmp (test_location, entry_url, len) && ! (entry_url[len - 1] == '/' || ! test_location[len] == '/' || test_location[len] == '\0')) ! this_conf = entry_config; ! ! if (this_conf) ! per_dir_defaults = merge_per_dir_configs (r->pool, ! per_dir_defaults, this_conf); ! } ! ! r->per_dir_config = per_dir_defaults; ! } ! ! return OK; ! } ! ! int file_walk (request_rec *r) ! { ! core_dir_config *conf = get_module_config(r->per_dir_config, &core_module); ! array_header *file_array = copy_array (r->pool, conf->sec); ! void *per_dir_defaults = r->per_dir_config; ! ! core_dir_config **file = (core_dir_config **)file_array->elts; ! int len, num_files = file_array->nelts; ! char *test_file = pstrdup (r->pool, r->filename); ! ! /* Go through the file entries, and check for matches. */ ! ! if (num_files) { ! void *this_conf, *entry_config; ! core_dir_config *entry_core; ! char *entry_file; ! int j; ! ! /* ! * we apply the directive sections in some order; should really try them ! * with the most general first. ! */ ! for (j = 0; j < num_files; ++j) { ! ! entry_config = file[j]; ! if (!entry_config) continue; ! ! entry_core =(core_dir_config *) ! get_module_config(entry_config, &core_module); ! entry_file = entry_core->d; ! ! len = strlen(entry_file); ! ! this_conf = NULL; ! ! if (entry_core->r) { ! if (!regexec(entry_core->r, test_file, 0, NULL, 0)) ! this_conf = entry_config; ! } ! else if (is_matchexp(entry_file)) { ! if (!strcmp_match(test_file, entry_file)) ! this_conf = entry_config; ! } ! else if (!strncmp (test_file, entry_file, len) && ! (entry_file[len - 1] == '/' || ! test_file[len] == '/' || test_file[len] == '\0')) this_conf = entry_config; if (this_conf) *************** *** 513,518 **** --- 593,599 ---- */ if ((res = directory_walk (rnew)) + || (res = file_walk (rnew)) || (!some_auth_required (rnew) ? 0 : ((res = check_user_id (rnew)) || (res = check_auth (rnew)))) || (res = check_access (rnew)) *************** *** 555,560 **** --- 636,642 ---- make_full_path (rnew->pool, fdir, new_file)); if ((res = directory_walk (rnew)) + || (res = file_walk (rnew)) || (res = check_access (rnew)) || (!some_auth_required (rnew) ? 0 : ((res = check_user_id (rnew)) && (res = check_auth (rnew)))) *************** *** 732,742 **** die (access_status, r); return; } ! if ((access_status = location_walk (r))) { die (access_status, r); return; } if ((access_status = check_access (r)) != 0) { decl_die (access_status, "check access", r); --- 814,829 ---- die (access_status, r); return; } ! if ((access_status = location_walk (r))) { die (access_status, r); return; } + + if ((access_status = file_walk (r))) { + die (access_status, r); + return; + } if ((access_status = check_access (r)) != 0) { decl_die (access_status, "check access", r);