diff options
-rw-r--r-- | include/http_protocol.h | 11 | ||||
-rw-r--r-- | include/httpd.h | 7 | ||||
-rw-r--r-- | modules/http/http_protocol.c | 6 | ||||
-rw-r--r-- | modules/http/mod_mime.c | 20 | ||||
-rw-r--r-- | modules/mappers/mod_actions.c | 6 | ||||
-rw-r--r-- | modules/mappers/mod_negotiation.c | 8 | ||||
-rw-r--r-- | modules/mappers/mod_rewrite.c | 2 | ||||
-rw-r--r-- | modules/metadata/mod_headers.c | 8 | ||||
-rw-r--r-- | modules/metadata/mod_mime_magic.c | 4 | ||||
-rw-r--r-- | server/config.c | 2 | ||||
-rw-r--r-- | server/core.c | 2 |
11 files changed, 51 insertions, 25 deletions
diff --git a/include/http_protocol.h b/include/http_protocol.h index 6979dc06e7..2b509b341f 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -465,6 +465,17 @@ AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l); AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct); /** + * Set the content type for this request (r->content_type). + * @param r The current request + * @param ct The new content type + * @param trusted If non-zero, The content-type should come from a + * trusted source such as server configuration rather + * than application output. + * for the AddOutputFilterByType directive to work correctly. + */ +AP_DECLARE(void) ap_set_content_type_ex(request_rec *r, const char *ct, int trusted); + +/** * Set the Accept-Ranges header for this response * @param r The current request */ diff --git a/include/httpd.h b/include/httpd.h index 6b7e10223e..02ad323893 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -684,6 +684,7 @@ typedef apr_uint64_t ap_request_bnotes_t; * */ #define AP_REQUEST_STRONG_ETAG 1 >> 0 +#define AP_REQUEST_TRUSTED_CT 1 << 1 /** * This is a convenience macro to ease with getting specific request @@ -706,6 +707,12 @@ typedef apr_uint64_t ap_request_bnotes_t; AP_REQUEST_GET_BNOTE((r), AP_REQUEST_STRONG_ETAG) /** @} */ +/** + * Returns true if the content-type field is from a trusted source + */ +#define AP_REQUEST_IS_TRUSTED_CT(r) \ + (!!AP_REQUEST_GET_BNOTE((r), AP_REQUEST_TRUSTED_CT)) +/** @} */ /** * @defgroup module_magic Module Magic mime types diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index f1ed1f6cc2..701a7dd6bc 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -927,8 +927,14 @@ AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct) } else if (!r->content_type || strcmp(r->content_type, ct)) { r->content_type = ct; + AP_REQUEST_SET_BNOTE(r, AP_REQUEST_TRUSTED_CT, 0); } } +AP_DECLARE(void) ap_set_content_type_ex(request_rec *r, const char *ct, int trusted) +{ + ap_set_content_type(r, ct); + AP_REQUEST_SET_BNOTE(r, AP_REQUEST_TRUSTED_CT, trusted ? AP_REQUEST_TRUSTED_CT : 0); +} AP_DECLARE(void) ap_set_accept_ranges(request_rec *r) { diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c index 13d2589456..a710c4ad0f 100644 --- a/modules/http/mod_mime.c +++ b/modules/http/mod_mime.c @@ -817,7 +817,7 @@ static int find_ct(request_rec *r) int found_metadata = 0; if (r->finfo.filetype == APR_DIR) { - ap_set_content_type(r, DIR_MAGIC_TYPE); + ap_set_content_type_ex(r, DIR_MAGIC_TYPE, 1); return OK; } @@ -918,7 +918,7 @@ static int find_ct(request_rec *r) if ((exinfo == NULL || !exinfo->forced_type) && !skipct) { if ((type = apr_hash_get(mime_type_extensions, ext, APR_HASH_KEY_STRING)) != NULL) { - ap_set_content_type(r, (char*) type); + ap_set_content_type_ex(r, (char*) type, 1); found = 1; } } @@ -927,7 +927,7 @@ static int find_ct(request_rec *r) /* empty string is treated as special case for RemoveType */ if ((exinfo->forced_type && *exinfo->forced_type) && !skipct) { - ap_set_content_type(r, exinfo->forced_type); + ap_set_content_type_ex(r, exinfo->forced_type, 1); found = 1; } @@ -1032,33 +1032,33 @@ static int find_ct(request_rec *r) memcpy(tmp, ctp->subtype, ctp->subtype_len); tmp += ctp->subtype_len; *tmp = 0; - ap_set_content_type(r, base_content_type); + ap_set_content_type_ex(r, base_content_type, AP_REQUEST_IS_TRUSTED_CT(r)); while (pp != NULL) { if (charset && !strcmp(pp->attr, "charset")) { if (!override) { - ap_set_content_type(r, + ap_set_content_type_ex(r, apr_pstrcat(r->pool, r->content_type, "; charset=", charset, - NULL)); + NULL), AP_REQUEST_IS_TRUSTED_CT(r)); override = 1; } } else { - ap_set_content_type(r, + ap_set_content_type_ex(r, apr_pstrcat(r->pool, r->content_type, "; ", pp->attr, "=", pp->val, - NULL)); + NULL), AP_REQUEST_IS_TRUSTED_CT(r)); } pp = pp->next; } if (charset && !override) { - ap_set_content_type(r, apr_pstrcat(r->pool, r->content_type, + ap_set_content_type_ex(r, apr_pstrcat(r->pool, r->content_type, "; charset=", charset, - NULL)); + NULL), AP_REQUEST_IS_TRUSTED_CT(r)); } } } diff --git a/modules/mappers/mod_actions.c b/modules/mappers/mod_actions.c index ac9c3b7428..5e398b53d9 100644 --- a/modules/mappers/mod_actions.c +++ b/modules/mappers/mod_actions.c @@ -182,8 +182,10 @@ static int action_handler(request_rec *r) return DECLINED; /* Second, check for actions (which override the method scripts) */ - action = r->handler ? r->handler : - ap_field_noparam(r->pool, r->content_type); + action = r->handler; + if (!action && AP_REQUEST_IS_TRUSTED_CT(r)) { + action = ap_field_noparam(r->pool, r->content_type); + } if (action && (t = apr_table_get(conf->action_types, action))) { int virtual = (*t++ == '0' ? 0 : 1); diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index c056b28455..a528f81439 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -1167,7 +1167,7 @@ static int read_types_multi(negotiation_state *neg) * might be doing. */ if (sub_req->handler && !sub_req->content_type) { - ap_set_content_type(sub_req, CGI_MAGIC_TYPE); + ap_set_content_type_ex(sub_req, CGI_MAGIC_TYPE, 1); } /* @@ -3003,14 +3003,14 @@ static int handle_map_file(request_rec *r) /* set MIME type and charset as negotiated */ if (best->mime_type && *best->mime_type) { if (best->content_charset && *best->content_charset) { - ap_set_content_type(r, apr_pstrcat(r->pool, + ap_set_content_type_ex(r, apr_pstrcat(r->pool, best->mime_type, "; charset=", best->content_charset, - NULL)); + NULL), 1); } else { - ap_set_content_type(r, apr_pstrdup(r->pool, best->mime_type)); + ap_set_content_type_ex(r, apr_pstrdup(r->pool, best->mime_type), 1); } } diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index b70c878210..79732d106a 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -5419,7 +5419,7 @@ static int hook_mimetype(request_rec *r) rewritelog(r, 1, NULL, "force filename %s to have MIME-type '%s'", r->filename, t); - ap_set_content_type(r, t); + ap_set_content_type_ex(r, t, 1); } /* handler */ diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index 77737d90ca..ae3f33069f 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -870,7 +870,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, case hdr_set: if (r->headers_in != headers && !ap_cstr_casecmp(hdr->header, "Content-Type")) { - ap_set_content_type(r, process_tags(hdr, r)); + ap_set_content_type_ex(r, process_tags(hdr, r), 1); } apr_table_setn(headers, hdr->header, process_tags(hdr, r)); break; @@ -878,7 +878,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, if (NULL == apr_table_get(headers, hdr->header)) { if (r->headers_in != headers && !ap_cstr_casecmp(hdr->header, "Content-Type")) { - ap_set_content_type(r, process_tags(hdr, r)); + ap_set_content_type_ex(r, process_tags(hdr, r), 1); } apr_table_setn(headers, hdr->header, process_tags(hdr, r)); } @@ -887,7 +887,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, apr_table_unset(headers, hdr->header); if (r->headers_in != headers && !ap_cstr_casecmp(hdr->header, "Content-Type")) { - ap_set_content_type(r, NULL); + ap_set_content_type_ex(r, NULL, 1); } break; case hdr_echo: @@ -901,7 +901,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, const char *repl = process_regexp(hdr, r->content_type, r); if (repl == NULL) return 0; - if (r->headers_in != headers) ap_set_content_type(r, repl); + if (r->headers_in != headers) ap_set_content_type_ex(r, repl, 1); } if (apr_table_get(headers, hdr->header)) { edit_do ed; diff --git a/modules/metadata/mod_mime_magic.c b/modules/metadata/mod_mime_magic.c index e45f209b73..05585ba776 100644 --- a/modules/metadata/mod_mime_magic.c +++ b/modules/metadata/mod_mime_magic.c @@ -788,7 +788,7 @@ static int magic_rsl_to_request(request_rec *r) /* XXX: this could be done at config time I'm sure... but I'm * confused by all this magic_rsl stuff. -djg */ ap_content_type_tolower(tmp); - ap_set_content_type(r, tmp); + ap_set_content_type_ex(r, tmp, 1); if (state == rsl_encoding) { tmp = rsl_strdup(r, encoding_frag, @@ -2326,7 +2326,7 @@ static int revision_suffix(request_rec *r) /* extract content type/encoding/language from sub-request */ if (sub->content_type) { - ap_set_content_type(r, apr_pstrdup(r->pool, sub->content_type)); + ap_set_content_type_ex(r, apr_pstrdup(r->pool, sub->content_type), 1); #if MIME_MAGIC_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01557) MODNAME ": subrequest %s got %s", diff --git a/server/config.c b/server/config.c index b59fea1d4f..712bcab3db 100644 --- a/server/config.c +++ b/server/config.c @@ -418,7 +418,7 @@ AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r) } if (!r->handler) { - if (r->content_type) { + if (r->content_type && AP_REQUEST_IS_TRUSTED_CT(r)) { handler = r->content_type; if ((p=ap_strchr_c(handler, ';')) != NULL) { char *new_handler = (char *)apr_pmemdup(r->pool, handler, diff --git a/server/core.c b/server/core.c index 3585382460..9f92981ef0 100644 --- a/server/core.c +++ b/server/core.c @@ -5098,7 +5098,7 @@ static int core_override_type(request_rec *r) /* Check for overrides with ForceType / SetHandler */ if (conf->mime_type && strcmp(conf->mime_type, "none")) - ap_set_content_type(r, (char*) conf->mime_type); + ap_set_content_type_ex(r, (char*) conf->mime_type, 1); if (conf->expr_handler) { const char *err; |