302 lines
12 KiB
Diff
302 lines
12 KiB
Diff
|
|
-- backported bnotes needed by this CVE fix from https://svn.apache.org/viewvc?view=revision&revision=1887384
|
|
-- modified it a little bit so it actually doesn't store bnotes into req structure to not brake compatibility
|
|
-- but it stores AP_REQUEST_TRUSTED_CT info into r->notes
|
|
|
|
diff --git a/include/http_protocol.h b/include/http_protocol.h
|
|
index 8ed77ac..81949ca 100644
|
|
--- a/include/http_protocol.h
|
|
+++ b/include/http_protocol.h
|
|
@@ -402,6 +402,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 99f7f04..d8746c1 100644
|
|
--- a/include/httpd.h
|
|
+++ b/include/httpd.h
|
|
@@ -645,6 +645,7 @@ struct ap_method_list_t {
|
|
/** the array used for extension methods */
|
|
apr_array_header_t *method_list;
|
|
};
|
|
+/** @} */
|
|
|
|
/**
|
|
* @defgroup module_magic Module Magic mime types
|
|
@@ -715,6 +716,31 @@ struct ap_method_list_t {
|
|
|
|
/** @} // values_request_rec_used_path_info */
|
|
|
|
+#define AP_REQUEST_TRUSTED_CT "rh-bnotes-trusted-ct"
|
|
+
|
|
+/**
|
|
+ * This is a convenience macro to ease with getting specific request
|
|
+ * binary notes.
|
|
+ */
|
|
+#define AP_REQUEST_GET_BNOTE(r, mask) (apr_table_get(r->notes, mask) ? 1 : 0)
|
|
+
|
|
+/**
|
|
+ * This is a convenience macro to ease with setting specific request
|
|
+ * binary notes.
|
|
+ */
|
|
+#define AP_REQUEST_SET_BNOTE(r, mask, val) do { \
|
|
+ if (val) \
|
|
+ apr_table_setn(r->notes, mask, "1"); \
|
|
+ else \
|
|
+ apr_table_unset(r->notes, mask); \
|
|
+} while (0)
|
|
+
|
|
+/**
|
|
+ * 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))
|
|
+/** @} */
|
|
|
|
/*
|
|
* Things which may vary per file-lookup WITHIN a request ---
|
|
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
|
|
index df862e0..d003aea 100644
|
|
--- a/modules/http/http_protocol.c
|
|
+++ b/modules/http/http_protocol.c
|
|
@@ -1077,8 +1077,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 28c53be..4cd1c48 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;
|
|
}
|
|
|
|
@@ -837,7 +837,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;
|
|
}
|
|
}
|
|
@@ -846,7 +846,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;
|
|
}
|
|
|
|
@@ -951,33 +951,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 ac9c3b7..5e398b5 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 da68353..e91ba5f 100644
|
|
--- a/modules/mappers/mod_negotiation.c
|
|
+++ b/modules/mappers/mod_negotiation.c
|
|
@@ -1169,7 +1169,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);
|
|
}
|
|
|
|
/*
|
|
@@ -3008,14 +3008,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 a25c7ae..2b70d66 100644
|
|
--- a/modules/mappers/mod_rewrite.c
|
|
+++ b/modules/mappers/mod_rewrite.c
|
|
@@ -5477,7 +5477,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 1ea970d..55ab281 100644
|
|
--- a/modules/metadata/mod_headers.c
|
|
+++ b/modules/metadata/mod_headers.c
|
|
@@ -792,14 +792,14 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
|
|
break;
|
|
case hdr_set:
|
|
if (!strcasecmp(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 (!strcasecmp(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));
|
|
}
|
|
@@ -818,7 +818,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 c12529a..fe30f27 100644
|
|
--- a/modules/metadata/mod_mime_magic.c
|
|
+++ b/modules/metadata/mod_mime_magic.c
|
|
@@ -789,7 +789,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 f815b22..fc4d76b 100644
|
|
--- a/server/config.c
|
|
+++ b/server/config.c
|
|
@@ -419,7 +419,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 8575aae..82706cf 100644
|
|
--- a/server/core.c
|
|
+++ b/server/core.c
|
|
@@ -4722,7 +4722,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;
|