You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
12 KiB
304 lines
12 KiB
From 554554b0ebb14d6578adb70a389c57a0d5f18a3b Mon Sep 17 00:00:00 2001
|
|
From: Eric Covener <covener@apache.org>
|
|
Date: Mon, 24 Jun 2024 17:54:34 +0000
|
|
Subject: [PATCH] Merge r1918551 from trunk:
|
|
|
|
add ap_set_content_type_ex to differentiate
|
|
|
|
trusted sources
|
|
|
|
|
|
|
|
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1918560 13f79535-47bb-0310-9956-ffa450edef68
|
|
---
|
|
include/http_protocol.h | 11 +++++++++++
|
|
include/httpd.h | 7 +++++++
|
|
modules/http/http_protocol.c | 6 ++++++
|
|
modules/http/mod_mime.c | 20 ++++++++++----------
|
|
modules/mappers/mod_actions.c | 6 ++++--
|
|
modules/mappers/mod_negotiation.c | 8 ++++----
|
|
modules/mappers/mod_rewrite.c | 2 +-
|
|
modules/metadata/mod_headers.c | 6 +++---
|
|
modules/metadata/mod_mime_magic.c | 4 ++--
|
|
server/config.c | 2 +-
|
|
server/core.c | 2 +-
|
|
11 files changed, 50 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/include/http_protocol.h b/include/http_protocol.h
|
|
index 94c481e5f43..f2c99c9e86e 100644
|
|
--- a/include/http_protocol.h
|
|
+++ b/include/http_protocol.h
|
|
@@ -438,6 +438,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 826c46ef591..766df2bde00 100644
|
|
--- a/include/httpd.h
|
|
+++ b/include/httpd.h
|
|
@@ -667,6 +667,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
|
|
@@ -689,6 +690,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 d031f245188..c31e8737337 100644
|
|
--- a/modules/http/http_protocol.c
|
|
+++ b/modules/http/http_protocol.c
|
|
@@ -1097,8 +1097,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 700f824f32a..51095a0e74c 100644
|
|
--- a/modules/http/mod_mime.c
|
|
+++ b/modules/http/mod_mime.c
|
|
@@ -759,7 +759,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;
|
|
}
|
|
|
|
@@ -850,7 +850,7 @@ static int find_ct(request_rec *r)
|
|
if (exinfo == NULL || !exinfo->forced_type) {
|
|
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;
|
|
}
|
|
}
|
|
@@ -859,7 +859,7 @@ static int find_ct(request_rec *r)
|
|
|
|
/* empty string is treated as special case for RemoveType */
|
|
if (exinfo->forced_type && *exinfo->forced_type) {
|
|
- ap_set_content_type(r, exinfo->forced_type);
|
|
+ ap_set_content_type_ex(r, exinfo->forced_type, 1);
|
|
found = 1;
|
|
}
|
|
|
|
@@ -964,33 +964,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 ac9c3b7428f..5e398b53d9e 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 c056b284550..a528f814397 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 bbcc11b3c52..df6f16b83f0 100644
|
|
--- a/modules/mappers/mod_rewrite.c
|
|
+++ b/modules/mappers/mod_rewrite.c
|
|
@@ -5333,7 +5333,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 ef812cd3edc..4838bd6cd0d 100644
|
|
--- a/modules/metadata/mod_headers.c
|
|
+++ b/modules/metadata/mod_headers.c
|
|
@@ -783,14 +783,14 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
|
|
break;
|
|
case hdr_set:
|
|
if (!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;
|
|
case hdr_setifempty:
|
|
if (NULL == apr_table_get(headers, hdr->header)) {
|
|
if (!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));
|
|
}
|
|
@@ -809,7 +809,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;
|
|
- ap_set_content_type(r, repl);
|
|
+ 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 7dac4fdbd3d..1c96db4cd7a 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 3d11ff58a44..635b65def1d 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 f511bba4897..843b97320f8 100644
|
|
--- a/server/core.c
|
|
+++ b/server/core.c
|
|
@@ -4835,7 +4835,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;
|