dgaudet 98/02/18 02:01:18
Modified: htdocs/manual upgrading_to_1_3.html htdocs/manual/mod core.html src CHANGES src/include http_config.h src/main http_core.c http_request.c Log: Fix various parsing bugs with <Dir/Loc/Files> sections. Improve the error messages generated. Introduced cmd->end_token to make it easier to do nested sections with proper error reporting. (Note that it can't be used for <IfModule> or <Limit> unfortunately.) PR#379: <Files> is not allowed within <Location> because it has no effect. PR#1817: Change <Files> to work with basenames only. This fixes both the bug introduced by the wildcarding change (* doesn't match /) and bugs such as <Files a*b> not working. PR: 379, 1817 Revision Changes Path 1.13 +6 -0 apache-1.3/htdocs/manual/upgrading_to_1_3.html Index: upgrading_to_1_3.html =================================================================== RCS file: /export/home/cvs/apache-1.3/htdocs/manual/upgrading_to_1_3.html,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- upgrading_to_1_3.html 1998/02/05 20:04:16 1.12 +++ upgrading_to_1_3.html 1998/02/18 10:00:57 1.13 @@ -125,6 +125,12 @@ messages. After that all errors are logged in the error_log. This makes it more convenient to start Apache via rsh, ssh, or crontabs. + + <li><Files> sections previously could take a full pathname, and + were matched against the full pathnames. This had some + inconsistancies, and was removed. To emulate this older behaviour + use a <Files> section nested inside a <Directory> + section. </UL> 1.101 +10 -7 apache-1.3/htdocs/manual/mod/core.html Index: core.html =================================================================== RCS file: /export/home/cvs/apache-1.3/htdocs/manual/mod/core.html,v retrieving revision 1.100 retrieving revision 1.101 diff -u -r1.100 -r1.101 --- core.html 1998/02/15 00:18:14 1.100 +++ core.html 1998/02/18 10:01:01 1.101 @@ -811,12 +811,17 @@ filename. It is comparable to the <A HREF="#directory"><Directory></A> directive and <A HREF="#location"><Location></A> directives. It -should be matched with a </Files> directive. Directives that -apply to the filename given should be listed -within. <CODE><Files></CODE> sections are processed in the +should be matched with a </Files> directive. The +directives given within this section will be applied to any +object with a basename (last component of filename) matching +the specified filename. +<CODE><Files></CODE> sections are processed in the order they appear in the configuration file, after the <Directory> sections and <CODE>.htaccess</CODE> files are -read, but before <Location> sections.</P> +read, but before <Location> sections. Note that +<Files> can be nested inside <Directory> +sections to restrict the portion of the filesystem they +apply to.</P> <P>The <EM>filename</EM> argument should include a filename, or a wild-card string, where `?' matches any single character, and `*' matches any @@ -837,9 +842,7 @@ HREF="#location"><CODE><Location></CODE></A> sections, <CODE><Files></CODE> sections can be used inside .htaccess files. This allows users to control access to their own files, at a -file-by-file level. When used in an .htaccess file, if the -<EM>filename</EM> does not begin with a <CODE>/</CODE> character, -the directory being applied will be prefixed automatically. +file-by-file level. <P> 1.636 +14 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.635 retrieving revision 1.636 diff -u -r1.635 -r1.636 --- CHANGES 1998/02/18 08:55:30 1.635 +++ CHANGES 1998/02/18 10:01:05 1.636 @@ -1,5 +1,19 @@ Changes with Apache 1.3b6 + *) Previously Apache would permit </Files> to end <FilesMatch> (and + similary for Location and Directory), now this is diagnosed as an + error. Improve error messages for mismatched sections (<Files>, + <FilesMatch>, <Directory>, <DirectoryMatch>, ...). [Dean Gaudet] + + *) <Files> is not permitted within <Location> (because of the + semantic ordering). [Dean Gaudet] PR#379 + + *) <Files> with wildcards was broken by the change in wildcard + semantics (* does not match /). To fix this, <Files> now + apply only to the basename of the request filename. This + fixes some other inconsistencies in <Files> semantics + (such as <Files a*b> not working). [Dean Gaudet] PR#1817 + *) Removed bogus "dist.tar" target from Makefile.tmpl and make sure backup files are removed on "clean" target [Ralf S. Engelschall] 1.67 +3 -2 apache-1.3/src/include/http_config.h Index: http_config.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/include/http_config.h,v retrieving revision 1.66 retrieving revision 1.67 diff -u -r1.66 -r1.67 --- http_config.h 1998/02/18 08:35:55 1.66 +++ http_config.h 1998/02/18 10:01:10 1.67 @@ -80,7 +80,7 @@ }; typedef struct command_struct { - char *name; /* Name of this command */ + const char *name; /* Name of this command */ const char *(*func) (); /* Function invoked */ void *cmd_data; /* Extra data, for functions which * implement multiple commands... @@ -90,7 +90,7 @@ */ enum cmd_how args_how; /* What the command expects as arguments */ - char *errmsg; /* 'usage' message, in case of syntax errors */ + const char *errmsg; /* 'usage' message, in case of syntax errors */ } command_rec; /* The allowed locations for a configuration directive are the union of @@ -156,6 +156,7 @@ * or being called in a dir context (path != NULL). */ const command_rec *cmd; /* configuration command */ + const char *end_token; /* end token required to end a nested section */ } cmd_parms; /* This structure records the existence of handlers in a module... */ 1.159 +80 -62 apache-1.3/src/main/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_core.c,v retrieving revision 1.158 retrieving revision 1.159 diff -u -r1.158 -r1.159 --- http_core.c 1998/02/12 02:18:41 1.158 +++ http_core.c 1998/02/18 10:01:13 1.159 @@ -643,10 +643,20 @@ * commands, but most of the old srm.conf is in the the modules. */ +static const char end_directory_section[] = "</Directory>"; +static const char end_directorymatch_section[] = "</DirectoryMatch>"; +static const char end_location_section[] = "</Location>"; +static const char end_locationmatch_section[] = "</LocationMatch>"; +static const char end_files_section[] = "</Files>"; +static const char end_filesmatch_section[] = "</FilesMatch>"; +static const char end_virtualhost_section[] = "</VirtualHost>"; +static const char end_ifmodule_section[] = "</IfModule>"; + /* check_cmd_context(): Forbidden in: */ #define NOT_IN_VIRTUALHOST 0x01U /* <Virtualhost> */ #define NOT_IN_LIMIT 0x02U /* <Limit> */ #define NOT_IN_DIR_LOC_FILE 0x04U /* <Directory>/<Location>/<Files>*/ +#define NOT_IN_LOC 0x08U /* <Location> */ #define GLOBAL_ONLY (NOT_IN_VIRTUALHOST|NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE) @@ -666,6 +676,11 @@ if ((forbidden & NOT_IN_DIR_LOC_FILE) && cmd->path != NULL) return pstrcat(cmd->pool, cmd->cmd->name, gt, " cannot occur within <Directory/Location/Files> section", NULL); + + if ((forbidden & NOT_IN_LOC) && (cmd->end_token == end_location_section + || cmd->end_token == end_locationmatch_section)) + return pstrcat(cmd->pool, cmd->cmd->name, gt, + " cannot occur within <Location> section", NULL); return NULL; } @@ -908,11 +923,11 @@ char rply[100]; if (nest < 2) - ap_snprintf(rply, sizeof rply, "Missing </%s> directive at end-of-file", - &cmd->cmd->name[1]); + ap_snprintf(rply, sizeof rply, "Missing %s directive at end-of-file", + cmd->end_token); else - ap_snprintf(rply, sizeof rply, "%d missing </%s> directives at end-of-file", - nest, &cmd->cmd->name[1]); + ap_snprintf(rply, sizeof rply, "%d missing %s directives at end-of-file", + nest, cmd->end_token); return pstrdup(cmd->pool, rply); } @@ -927,10 +942,17 @@ #define USE_ICASE 0 #endif -static const char end_dir_magic[] = "</Directory> outside of any <Directory> section"; - -const char *end_dirsection (cmd_parms *cmd, void *dummy) { - return end_dir_magic; +static const char *end_nested_section(cmd_parms *cmd, void *dummy) +{ + if (cmd->end_token == NULL) { + return pstrcat(cmd->pool, cmd->cmd->name, + " without matching <", cmd->cmd->name + 2, " section", NULL); + } + if (cmd->cmd->name != cmd->end_token) { + return pstrcat(cmd->pool, "Expected ", cmd->end_token, " but saw ", + cmd->cmd->name, NULL); + } + return cmd->end_token; } const char *dirsection (cmd_parms *cmd, void *dummy, const char *arg) @@ -942,6 +964,7 @@ core_dir_config *conf; void *new_dir_conf = create_per_dir_config (cmd->pool); regex_t *r = NULL; + const char *old_end_token; const char *err = check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); if (err != NULL) return err; @@ -967,10 +990,14 @@ cmd->path = os_canonical_filename(cmd->pool, cmd->path); } + old_end_token = cmd->end_token; + cmd->end_token = cmd->info ? end_directorymatch_section : end_directory_section; errmsg = srm_command_loop (cmd, new_dir_conf); - if (errmsg == NULL) - return missing_endsection(cmd, 1); - else if (errmsg != end_dir_magic) + if (errmsg == NULL) { + errmsg = missing_endsection(cmd, 1); + } + cmd->end_token = old_end_token; + if (errmsg != (cmd->info ? end_directorymatch_section : end_directory_section)) return errmsg; conf = (core_dir_config *)get_module_config(new_dir_conf, &core_module); @@ -988,12 +1015,6 @@ return NULL; } -static const char end_url_magic[] = "</Location> outside of any <Location> section"; - -const char *end_urlsection (cmd_parms *cmd, void *dummy) { - return end_url_magic; -} - const char *urlsection (cmd_parms *cmd, void *dummy, const char *arg) { const char *errmsg; @@ -1002,6 +1023,7 @@ char *old_path = cmd->path; core_dir_config *conf; regex_t *r = NULL; + const char *old_end_token; void *new_url_conf = create_per_dir_config (cmd->pool); @@ -1021,10 +1043,14 @@ r = pregcomp(cmd->pool, cmd->path, REG_EXTENDED); } + old_end_token = cmd->end_token; + cmd->end_token = cmd->info ? end_locationmatch_section : end_location_section; errmsg = srm_command_loop (cmd, new_url_conf); - if (errmsg == NULL) - return missing_endsection(cmd, 1); - else if (errmsg != end_url_magic) + if (errmsg == NULL) { + errmsg = missing_endsection(cmd, 1); + } + cmd->end_token = old_end_token; + if (errmsg != (cmd->info ? end_locationmatch_section : end_location_section)) return errmsg; conf = (core_dir_config *)get_module_config(new_url_conf, &core_module); @@ -1044,12 +1070,6 @@ return NULL; } -static char *end_file_magic = "</Files> outside of any <Files> section"; - -const char *end_filesection (cmd_parms *cmd, void *dummy) { - return end_file_magic; -} - const char *filesection (cmd_parms *cmd, core_dir_config *c, const char *arg) { const char *errmsg; @@ -1058,53 +1078,49 @@ char *old_path = cmd->path; core_dir_config *conf; regex_t *r = NULL; + const char *old_end_token; void *new_file_conf = create_per_dir_config (cmd->pool); - const char *err = check_cmd_context(cmd, NOT_IN_LIMIT); + const char *err = check_cmd_context(cmd, NOT_IN_LIMIT | NOT_IN_LOC); if (err != NULL) return err; if (endp) *endp = '\0'; - if (cmd->limited != -1) return "Can't have <Files> within <Limit>"; - cmd->path = getword_conf (cmd->pool, &arg); /* Only if not an .htaccess file */ - if (cmd->path) + if (!old_path) cmd->override = OR_ALL|ACCESS_CONF; if (cmd->info) { /* <FilesMatch> */ - 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|USE_ICASE); } else 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|USE_ICASE); } else { - if (old_path && cmd->path[0] != '/') - cmd->path = pstrcat(cmd->pool, old_path, cmd->path, NULL); - /* Ensure that the pathname is canonical */ cmd->path = os_canonical_filename(cmd->pool, cmd->path); } + old_end_token = cmd->end_token; + cmd->end_token = cmd->info ? end_filesmatch_section : end_files_section; errmsg = srm_command_loop (cmd, new_file_conf); - if (errmsg == NULL) - return missing_endsection(cmd, 1); - else if (errmsg != end_file_magic) + if (errmsg == NULL) { + errmsg = missing_endsection(cmd, 1); + } + cmd->end_token = old_end_token; + if (errmsg != (cmd->info ? end_filesmatch_section : end_files_section)) return errmsg; conf = (core_dir_config *)get_module_config(new_file_conf, &core_module); - conf->d = pstrdup(cmd->pool, cmd->path); - conf->d_is_fnmatch = is_fnmatch( conf->d ) != 0; + conf->d = cmd->path; + conf->d_is_fnmatch = is_fnmatch(conf->d) != 0; conf->r = r; add_file_conf (c, new_file_conf); - + if (*arg != '\0') return pstrcat (cmd->pool, "Multiple <", (cmd->info) ? "FilesMatch" : "Files", "> arguments not (yet) supported.", NULL); @@ -1142,24 +1158,22 @@ nest--; } - return (nest == 0) ? NULL : missing_endsection(cmd, nest); + if (nest) { + cmd->end_token = end_ifmodule_section; + return missing_endsection(cmd, nest); + } + return NULL; } /* httpd.conf commands... beginning with the <VirtualHost> business */ -const char end_virthost_magic[] = "</Virtualhost> out of place"; - -const char *end_virtualhost_section (cmd_parms *cmd, void *dummy) -{ - return end_virthost_magic; -} - const char *virtualhost_section (cmd_parms *cmd, void *dummy, char *arg) { server_rec *main_server = cmd->server, *s; const char *errmsg; char *endp = strrchr (arg, '>'); pool *p = cmd->pool, *ptemp = cmd->temp_pool; + const char *old_end_token; const char *err = check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) return err; @@ -1181,9 +1195,15 @@ s->next = main_server->next; main_server->next = s; + old_end_token = cmd->end_token; + cmd->end_token = end_virtualhost_section; cmd->server = s; errmsg = srm_command_loop (cmd, s->lookup_defaults); cmd->server = main_server; + if (errmsg == NULL) { + errmsg = missing_endsection(cmd, 1); + } + cmd->end_token = old_end_token; if (s->srm_confname) process_resource_config (s, s->srm_confname, p, ptemp); @@ -1191,9 +1211,7 @@ if (s->access_confname) process_resource_config (s, s->access_confname, p, ptemp); - if (errmsg == NULL) - return missing_endsection(cmd, 1); - else if (errmsg == end_virthost_magic) + if (errmsg == end_virtualhost_section) return NULL; return errmsg; } @@ -1779,23 +1797,23 @@ /* Old access config file commands */ { "<Directory", dirsection, NULL, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources located in the specified directories" }, -{ "</Directory>", end_dirsection, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Directory>" }, +{ end_directory_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Directory>" }, { "<Location", urlsection, NULL, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources accessed through the specified URL paths" }, -{ "</Location>", end_urlsection, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Location>" }, +{ end_location_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Location>" }, { "<VirtualHost", virtualhost_section, NULL, RSRC_CONF, RAW_ARGS, "Container to map directives to a particular virtual host, takes one or more host addresses" }, -{ "</VirtualHost>", end_virtualhost_section, NULL, RSRC_CONF, NO_ARGS, "Marks end of <Directory>" }, +{ end_virtualhost_section, end_nested_section, NULL, RSRC_CONF, NO_ARGS, "Marks end of <VirtualHost>" }, { "<Files", filesection, NULL, OR_ALL, RAW_ARGS, "Container for directives affecting files matching specified patterns" }, -{ "</Files>", end_filesection, NULL, OR_ALL, NO_ARGS, "Marks end of <Files>" }, +{ end_files_section, end_nested_section, NULL, OR_ALL, NO_ARGS, "Marks end of <Files>" }, { "<Limit", limit_section, NULL, OR_ALL, RAW_ARGS, "Container for authentication directives when accessed using specified HTTP methods" }, { "</Limit>", endlimit_section, NULL, OR_ALL, NO_ARGS, "Marks end of <Limit>" }, { "<IfModule", start_ifmod, NULL, OR_ALL, RAW_ARGS, "Container for directives based on existance of specified modules" }, -{ "</IfModule>", end_ifmod, NULL, OR_ALL, NO_ARGS, "Marks end of <IfModule>" }, +{ end_ifmodule_section, end_ifmod, NULL, OR_ALL, NO_ARGS, "Marks end of <IfModule>" }, { "<DirectoryMatch", dirsection, (void*)1, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources located in the specified directories" }, -{ "</DirectoryMatch>", end_dirsection, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <DirectoryMatch>" }, +{ end_directorymatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <DirectoryMatch>" }, { "<LocationMatch", urlsection, (void*)1, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources accessed through the specified URL paths" }, -{ "</LocationMatch>", end_urlsection, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <LocationMatch>" }, +{ end_locationmatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <LocationMatch>" }, { "<FilesMatch", filesection, (void*)1, OR_ALL, RAW_ARGS, "Container for directives affecting files matching specified patterns" }, -{ "</FilesMatch>", end_filesection, NULL, OR_ALL, NO_ARGS, "Marks end of <FilesMatch>" }, +{ end_filesmatch_section, end_nested_section, NULL, OR_ALL, NO_ARGS, "Marks end of <FilesMatch>" }, { "AuthType", set_string_slot, (void*)XtOffsetOf(core_dir_config, auth_type), OR_AUTHCFG, TAKE1, "An HTTP authorization type (e.g., \"Basic\")" }, { "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1, 1.107 +11 -6 apache-1.3/src/main/http_request.c Index: http_request.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_request.c,v retrieving revision 1.106 retrieving revision 1.107 diff -u -r1.106 -r1.107 --- http_request.c 1998/02/08 18:16:03 1.106 +++ http_request.c 1998/02/18 10:01:14 1.107 @@ -561,10 +561,16 @@ void *per_dir_defaults = r->per_dir_config; void **file = (void **) conf->sec->elts; int len, num_files = conf->sec->nelts; - char *test_file = pstrdup(r->pool, r->filename); + char *test_file; - /* Collapse multiple slashes */ - no2slash(test_file); + /* get the basename */ + test_file = strrchr(r->filename, '/'); + if (test_file == NULL) { + test_file = r->filename; + } + else { + ++test_file; + } /* Go through the file entries, and check for matches. */ @@ -598,10 +604,9 @@ this_conf = entry_config; } } - else if (!strncmp(test_file, entry_file, len) && - (entry_file[len - 1] == '/' || - test_file[len] == '/' || test_file[len] == '\0')) + else if (!strcmp(test_file, entry_file)) { this_conf = entry_config; + } if (this_conf) per_dir_defaults = merge_per_dir_configs(r->pool,