You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by st...@apache.org on 2001/10/02 23:01:31 UTC
cvs commit: apache-1.3/src/modules/standard mod_mime.c mod_negotiation.c
stoddard 01/10/02 14:01:31
Modified: src CHANGES
src/modules/standard mod_mime.c mod_negotiation.c
Log:
Modified mod_mime and mod_negotiation to prevent mod_negotiation
from serving any multiview variant containing one or more
'unknown' filename extensions. In PR #8130, mod_negotiation was
incorrectly serving index.html.zh.Big5 when better variants were
available. The httpd.conf file on the failing server did not have
an AddLanguage directive for .zh, which caused mod_mime to loose
the file_type information it gleened from parsing the .html
extension. The absence of any language preferences, either in
the browser or configured on the server, caused mod_negotiation
to consider all the variants equivalent. When that occurs,
mod_negotiation picks the 'smallest' variant available, which
just happened to be index.html.zh.Big5.
[Bill Stoddard, Bill Rowe] PR #8130
PR: 8130
Revision Changes Path
1.1718 +14 -0 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1717
retrieving revision 1.1718
diff -u -r1.1717 -r1.1718
--- CHANGES 2001/10/02 19:35:30 1.1717
+++ CHANGES 2001/10/02 21:01:30 1.1718
@@ -1,4 +1,18 @@
Changes with Apache 1.3.21
+ *) Modified mod_mime and mod_negotiation to prevent mod_negotiation
+ from serving any multiview variant containing one or more
+ 'unknown' filename extensions. In PR #8130, mod_negotiation was
+ incorrectly serving index.html.zh.Big5 when better variants were
+ available. The httpd.conf file on the failing server did not have
+ an AddLanguage directive for .zh, which caused mod_mime to loose
+ the file_type information it gleened from parsing the .html
+ extension. The absence of any language preferences, either in
+ the browser or configured on the server, caused mod_negotiation
+ to consider all the variants equivalent. When that occurs,
+ mod_negotiation picks the 'smallest' variant available, which
+ just happened to be index.html.zh.Big5.
+ [Bill Stoddard, Bill Rowe] PR #8130
+
*) Security: Close autoindex /?M=D directory listing hole reported
in bugtraq id 3009. In some configurations where multiviews and
indexes are enabled for a directory, requesting URI /?M=D could
1.60 +34 -23 apache-1.3/src/modules/standard/mod_mime.c
Index: mod_mime.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_mime.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- mod_mime.c 2001/01/15 17:05:45 1.59
+++ mod_mime.c 2001/10/02 21:01:31 1.60
@@ -615,27 +615,38 @@
static int find_ct(request_rec *r)
{
- const char *fn = strrchr(r->filename, '/');
- mime_dir_config *conf =
- (mime_dir_config *) ap_get_module_config(r->per_dir_config, &mime_module);
+ mime_dir_config *conf;
+ array_header *exception_list;
+ const char *fn;
char *ext;
- const char *orighandler = r->handler;
const char *type;
const char *charset = NULL;
+ int found_metadata = 0;
if (S_ISDIR(r->finfo.st_mode)) {
r->content_type = DIR_MAGIC_TYPE;
return OK;
}
- /* TM -- FIXME
- * if r->filename does not contain a '/', the following passes a null
- * pointer to getword, causing a SEGV ..
- */
+ conf = (mime_dir_config *) ap_get_module_config(r->per_dir_config,
+ &mime_module);
+
+ exception_list = ap_make_array(r->pool, 2, sizeof(char *));
- if (fn == NULL) {
+ /* Always drop the leading element */
+ fn = strrchr(r->filename, '/');
+ if (fn == NULL)
fn = r->filename;
- }
+ else
+ ++fn;
+
+ /* The exception list keeps track of those filename components that
+ * are not associated with extensions indicating metadata.
+ * The base name is always the first exception (i.e., "txt.html" has
+ * a basename of "txt" even though it might look like an extension).
+ */
+ ext = ap_getword(r->pool, &fn, '.');
+ *((const char **) ap_push_array(exception_list)) = ext;
/* Parse filename extensions, which can be in any order */
while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) {
@@ -683,19 +694,19 @@
found = 1;
}
- /* This is to deal with cases such as foo.gif.bak, which we want
- * to not have a type. So if we find an unknown extension, we
- * zap the type/language/encoding and reset the handler
- */
-
- if (!found) {
- r->content_type = NULL;
- r->content_language = NULL;
- r->content_languages = NULL;
- r->content_encoding = NULL;
- r->handler = orighandler;
- charset = NULL;
- }
+ if (found)
+ found_metadata = 1;
+ else
+ *((const char **) ap_push_array(exception_list)) = ext;
+ }
+
+ /* Need to see a notes entry on r for unrecognized elements.
+ * Somebody better claim them! If we did absolutly nothing,
+ * skip the notes to alert mod_negotiation we are clueless.
+ */
+ if (found_metadata) {
+ ap_table_setn(r->notes, "ap-mime-exceptions-list",
+ (void *) exception_list);
}
if (r->content_type) {
1.108 +50 -3 apache-1.3/src/modules/standard/mod_negotiation.c
Index: mod_negotiation.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_negotiation.c,v
retrieving revision 1.107
retrieving revision 1.108
diff -u -r1.107 -r1.108
--- mod_negotiation.c 2001/10/02 16:05:20 1.107
+++ mod_negotiation.c 2001/10/02 21:01:31 1.108
@@ -922,10 +922,10 @@
forbidden.all = 1;
while ((dir_entry = readdir(dirp))) {
+ array_header *exception_list;
request_rec *sub_req;
/* Do we have a match? */
-
if (strncmp(dir_entry->d_name, filp, prefix_len)) {
continue;
}
@@ -955,15 +955,62 @@
else if (sub_req->status == HTTP_FORBIDDEN)
forbidden.any = 1;
- if (sub_req->status != HTTP_OK || !sub_req->content_type) {
+ /*
+ * mod_mime will _always_ provide us the base name in the
+ * ap-mime-exception-list, if it processed anything. If
+ * this list is empty, give up immediately, there was
+ * nothing interesting. For example, looking at the files
+ * readme.txt and readme.foo, we will throw away .foo if
+ * it's an insignificant file (e.g. did not identify a
+ * language, charset, encoding, content type or handler,)
+ */
+ exception_list =
+ (array_header *) ap_table_get(sub_req->notes,
+ "ap-mime-exceptions-list");
+ if (!exception_list) {
ap_destroy_sub_req(sub_req);
continue;
}
+ /*
+ * Simple enough for now, every unreconized bit better match
+ * our base name. When we break up our base name and allow
+ * index.en to match index.html.en, this gets tricker.
+ * XXX: index.html.foo won't be caught by testing index.html
+ * since the exceptions result is index.foo - this should be
+ * fixed as part of a new match-parts logic here.
+ */
+ {
+ char *base = ap_array_pstrcat(sub_req->pool, exception_list, '.');
+ int base_len = strlen(base);
+ if (base_len > prefix_len
+#ifdef CASE_BLIND_FILESYSTEM
+ || strncasecmp(base, filp, base_len)
+#else
+ || strncmp(base, filp, base_len)
+#endif
+ || (prefix_len > base_len && filp[base_len] != '.')) {
+ /*
+ * Something you don't know is, something you don't know...
+ */
+ ap_destroy_sub_req(sub_req);
+ continue;
+ }
+ }
+
+ /*
+ * ###: be warned, the _default_ content type is already
+ * picked up here! If we failed the subrequest, or don't
+ * know what we are serving, then continue.
+ */
+ if (sub_req->status != HTTP_OK || (!sub_req->content_type)) {
+ ap_destroy_sub_req(sub_req);
+ continue;
+ }
+
/* If it's a map file, we use that instead of the map
* we're building...
*/
-
if (((sub_req->content_type) &&
!strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) ||
((sub_req->handler) &&