File apache2-CVE-2019-0220.patch of Package apache2.10087
Index: httpd-2.4.10/server/core.c
===================================================================
--- httpd-2.4.10.orig/server/core.c 2019-04-02 17:01:58.638104690 +0200
+++ httpd-2.4.10/server/core.c 2019-04-02 17:03:57.162738059 +0200
@@ -474,6 +474,7 @@ static void *create_core_server_config(a
*/
conf->trace_enable = AP_TRACE_UNSET;
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET;
return (void *)conf;
}
@@ -531,6 +532,8 @@ static void *merge_core_server_configs(a
? virt->merge_trailers
: base->merge_trailers;
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
+
return conf;
}
@@ -1665,6 +1668,13 @@ static const char *set_override(cmd_parm
return NULL;
}
+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag)
+{
+ core_server_config *conf =
+ ap_get_core_module_config(cmd->server->module_config);
+ return ap_set_flag_slot(cmd, conf, flag);
+}
+
static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
{
core_dir_config *d = d_;
@@ -4243,6 +4253,10 @@ AP_INIT_FLAG("HttpExpectStrict", set_exp
"whether to return a 417 if a client doesn't send 100-Continue"),
AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF,
"merge request trailers into request headers or not"),
+AP_INIT_FLAG("MergeSlashes", set_core_server_flag,
+ (void *)APR_OFFSETOF(core_server_config, merge_slashes),
+ RSRC_CONF,
+ "Controls whether consecutive slashes in the URI path are merged"),
{ NULL }
};
Index: httpd-2.4.10/include/httpd.h
===================================================================
--- httpd-2.4.10.orig/include/httpd.h 2019-04-02 17:01:58.382103406 +0200
+++ httpd-2.4.10/include/httpd.h 2019-04-02 17:01:58.674104871 +0200
@@ -1610,12 +1610,22 @@ AP_DECLARE(int) ap_unescape_url_keep2f(c
AP_DECLARE(int) ap_unescape_urlencoded(char *query);
/**
- * Convert all double slashes to single slashes
- * @param name The string to convert
+ * Convert all double slashes to single slashes, except where significant
+ * to the filesystem on the current platform.
+ * @param name The string to convert, assumed to be a filesystem path
*/
AP_DECLARE(void) ap_no2slash(char *name);
/**
+ * Convert all double slashes to single slashes, except where significant
+ * to the filesystem on the current platform.
+ * @param name The string to convert
+ * @param is_fs_path if set to 0, the significance of any double-slashes is
+ * ignored.
+ */
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path);
+
+/**
* Remove all ./ and xx/../ substrings from a file name. Also remove
* any leading ../ or /../ substrings.
* @param name the file name to parse
Index: httpd-2.4.10/include/http_core.h
===================================================================
--- httpd-2.4.10.orig/include/http_core.h 2019-04-02 17:01:58.382103406 +0200
+++ httpd-2.4.10/include/http_core.h 2019-04-02 17:05:04.103195121 +0200
@@ -465,6 +465,14 @@ typedef unsigned long etag_components_t;
/* This is the default value used */
#define ETAG_BACKWARD (ETAG_MTIME | ETAG_SIZE)
+#define AP_CORE_CONFIG_OFF (0)
+#define AP_CORE_CONFIG_ON (1)
+#define AP_CORE_CONFIG_UNSET (2)
+
+#define AP_CORE_MERGE_FLAG(field, to, base, over) to->field = \
+ over->field != AP_CORE_CONFIG_UNSET \
+ ? over->field \
+ : base->field
/**
* @brief Server Signature Enumeration
*/
@@ -681,6 +689,7 @@ typedef struct {
#define AP_HTTP_EXPECT_STRICT_ENABLE 1
#define AP_HTTP_EXPECT_STRICT_DISABLE 2
int http_expect_strict;
+ unsigned int merge_slashes;
} core_server_config;
/* for AddOutputFiltersByType in core.c */
Index: httpd-2.4.10/server/util.c
===================================================================
--- httpd-2.4.10.orig/server/util.c 2014-02-19 13:43:58.000000000 +0100
+++ httpd-2.4.10/server/util.c 2019-04-02 17:01:58.674104871 +0200
@@ -562,16 +562,20 @@ AP_DECLARE(void) ap_getparents(char *nam
name[l] = '\0';
}
}
-
-AP_DECLARE(void) ap_no2slash(char *name)
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
{
+
char *d, *s;
+ if (!name || !*name) {
+ return;
+ }
+
s = d = name;
#ifdef HAVE_UNC_PATHS
/* Check for UNC names. Leave leading two slashes. */
- if (s[0] == '/' && s[1] == '/')
+ if (is_fs_path && s[0] == '/' && s[1] == '/')
*d++ = *s++;
#endif
@@ -588,6 +592,10 @@ AP_DECLARE(void) ap_no2slash(char *name)
*d = '\0';
}
+AP_DECLARE(void) ap_no2slash(char *name)
+{
+ ap_no2slash_ex(name, 1);
+}
/*
* copy at most n leading directories of s into d
Index: httpd-2.4.10/server/request.c
===================================================================
--- httpd-2.4.10.orig/server/request.c 2019-04-02 17:01:58.542104208 +0200
+++ httpd-2.4.10/server/request.c 2019-04-02 17:01:58.678104891 +0200
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_inter
int file_req = (r->main && r->filename);
int access_status;
core_dir_config *d;
+ core_server_config *sconf =
+ ap_get_core_module_config(r->server->module_config);
/* Ignore embedded %2F's in path for proxy requests */
if (!r->proxyreq && r->parsed_uri.path) {
@@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_inter
}
ap_getparents(r->uri); /* OK --- shrinking transformations... */
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
+ ap_no2slash(r->uri);
+ if (r->parsed_uri.path) {
+ ap_no2slash(r->parsed_uri.path);
+ }
+ }
/* All file subrequests are a huge pain... they cannot bubble through the
* next several steps. Only file subrequests are allowed an empty uri,
@@ -1411,20 +1419,7 @@ AP_DECLARE(int) ap_location_walk(request
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
cached = (cache->cached != NULL);
-
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple
- * slashes. Location matches multiple slashes with a single slash,
- * LocationMatch doesn't. An exception, for backwards brokenness is
- * absoluteURIs... in which case neither match multiple slashes.
- */
- if (r->uri[0] != '/') {
- entry_uri = r->uri;
- }
- else {
- char *uri = apr_pstrdup(r->pool, r->uri);
- ap_no2slash(uri);
- entry_uri = uri;
- }
+ entry_uri = r->uri;
/* If we have an cache->cached location that matches r->uri,
* and the vhost's list of locations hasn't changed, we can skip
@@ -1491,7 +1486,7 @@ AP_DECLARE(int) ap_location_walk(request
pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
}
- if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
+ if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
continue;
}
@@ -1501,7 +1496,7 @@ AP_DECLARE(int) ap_location_walk(request
apr_table_setn(r->subprocess_env,
((const char **)entry_core->refs->elts)[i],
apr_pstrndup(r->pool,
- r->uri + pmatch[i].rm_so,
+ entry_uri + pmatch[i].rm_so,
pmatch[i].rm_eo - pmatch[i].rm_so));
}
}