204 lines
7.3 KiB
Diff
204 lines
7.3 KiB
Diff
From 9bc1917a27a2323e535aadb081e38172ae0e3fc2 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Eissing <icing@apache.org>
|
|
Date: Mon, 18 Mar 2019 08:49:59 +0000
|
|
Subject: [PATCH] Merge of r1855705 from trunk:
|
|
|
|
core: merge consecutive slashes in the path
|
|
|
|
|
|
|
|
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855737 13f79535-47bb-0310-9956-ffa450edef68
|
|
---
|
|
include/http_core.h | 2 +-
|
|
include/httpd.h | 14 ++++++++++++--
|
|
server/core.c | 13 +++++++++++++
|
|
server/request.c | 25 +++++++++----------------
|
|
server/util.c | 10 +++++++---
|
|
5 files changed, 43 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/include/http_core.h b/include/http_core.h
|
|
index 35df5dc9601..8e109882244 100644
|
|
--- a/include/http_core.h
|
|
+++ b/include/http_core.h
|
|
@@ -740,7 +740,7 @@ typedef struct {
|
|
#define AP_HTTP_METHODS_LENIENT 1
|
|
#define AP_HTTP_METHODS_REGISTERED 2
|
|
char http_methods;
|
|
-
|
|
+ unsigned int merge_slashes;
|
|
} core_server_config;
|
|
|
|
/* for AddOutputFiltersByType in core.c */
|
|
diff --git a/include/httpd.h b/include/httpd.h
|
|
index 65392f83546..99f7f041aea 100644
|
|
--- a/include/httpd.h
|
|
+++ b/include/httpd.h
|
|
@@ -1697,11 +1697,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
|
|
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.
|
|
diff --git a/server/core.c b/server/core.c
|
|
index e2a91c7a0c6..eacb54fecec 100644
|
|
--- a/server/core.c
|
|
+++ b/server/core.c
|
|
@@ -490,6 +490,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
|
|
|
|
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
|
|
conf->protocols_honor_order = -1;
|
|
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET;
|
|
|
|
return (void *)conf;
|
|
}
|
|
@@ -555,6 +556,7 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
|
|
conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
|
|
base->protocols_honor_order :
|
|
virt->protocols_honor_order);
|
|
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
|
|
|
|
return conf;
|
|
}
|
|
@@ -1863,6 +1865,13 @@ static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag)
|
|
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_;
|
|
@@ -4562,6 +4571,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON
|
|
"'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"),
|
|
AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
|
|
"Registers non-standard HTTP methods"),
|
|
+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 }
|
|
};
|
|
|
|
diff --git a/server/request.c b/server/request.c
|
|
index dbe3e07f150..1ce8908824b 100644
|
|
--- a/server/request.c
|
|
+++ b/server/request.c
|
|
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
|
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,10 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
|
}
|
|
|
|
ap_getparents(r->uri); /* OK --- shrinking transformations... */
|
|
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
|
|
+ ap_no2slash(r->uri);
|
|
+ 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 +1417,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
|
|
|
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 +1484,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
|
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 +1494,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
|
|
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));
|
|
}
|
|
}
|
|
diff --git a/server/util.c b/server/util.c
|
|
index fd7a0a14763..607c4850d86 100644
|
|
--- a/server/util.c
|
|
+++ b/server/util.c
|
|
@@ -561,16 +561,16 @@ AP_DECLARE(void) ap_getparents(char *name)
|
|
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;
|
|
|
|
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
|
|
|
|
@@ -587,6 +587,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
|