From: Daniel Earl Poirier
Date: Wed, 16 Mar 2011 16:45:25 +0000 (+0000)
Subject: core: AllowEncodedSlashes new option NoDecode to allow encoded slashes
X-Git-Tag: 2.3.12~221
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fdaaf209c5cfb8ef0c8b3a173b9c3d1f053279dd;p=apache
core: AllowEncodedSlashes new option NoDecode to allow encoded slashes
in request URL path info but not decode them. Change behavior of option
"On" to decode the encoded slashes as 2.0 and 2.2 do. PR 35256,
PR 46830.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1082196 13f79535-47bb-0310-9956-ffa450edef68
---
diff --git a/CHANGES b/CHANGES
index fdc20dcf09..20807cd370 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
Changes with Apache 2.3.12
+ *) core: AllowEncodedSlashes new option NoDecode to allow encoded slashes
+ in request URL path info but not decode them. Change behavior of option
+ "On" to decode the encoded slashes as 2.0 and 2.2 do. PR 35256,
+ PR 46830. [Dan Poirier]
+
*) mod_ssl: Check SNI hostname against Host header case-insensitively.
PR 49491. [Mayank Agrawal ]
diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml
index a3c7d2dec0..a219feccd6 100644
--- a/docs/manual/mod/core.xml
+++ b/docs/manual/mod/core.xml
@@ -269,26 +269,35 @@ content-type is text/plain
or text/html
AllowEncodedSlashes
Determines whether encoded path separators in URLs are allowed to
be passed through
-AllowEncodedSlashes On|Off
+AllowEncodedSlashes On|Off|NoDecode
AllowEncodedSlashes Off
server configvirtual host
-Available in Apache httpd 2.0.46 and later
+Available in Apache httpd 2.0.46 and later.
+NoDecode option available in 2.3.12 and later.
The AllowEncodedSlashes directive allows URLs
which contain encoded path separators (%2F
for /
and additionally %5C
for \
on according systems)
- to be used. Normally such URLs are refused with a 404 (Not found) error.
+ to be used in the path info.
+
+ With the default value, Off
, such URLs are refused
+ with a 404 (Not found) error.
+
+ With the value On
, such URLs are accepted, and encoded
+ slashes are decoded like all other encoded characters.
+
+ With the value NoDecode
, such URLs are accepted, but
+ encoded slashes are not decoded but left in their encoded state.
Turning AllowEncodedSlashes On
is
mostly useful when used in conjunction with PATH_INFO
.
Note
- Allowing encoded slashes does not imply decoding.
- Occurrences of %2F
or %5C
(only on
- according systems) will be left as such in the otherwise decoded URL
- string.
+ If encoded slashes are needed in path info, use of NoDecode
is
+ strongly recommended as a security measure. Allowing slashes
+ to be decoded could potentially allow unsafe paths.
AcceptPathInfo
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 70f25ce42d..fbc9dfd5fc 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -306,6 +306,7 @@
util_ldap_state_t.connectionPoolTTL,
util_ldap_connection_t.freed, and
util_ldap_connection_t.rebind_pool.
+ * 20110312.1 (2.3.12-dev) Add core_dir_config.decode_encoded_slashes.
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -313,7 +314,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20110312
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/include/http_core.h b/include/http_core.h
index 277b271061..e674915b8a 100644
--- a/include/http_core.h
+++ b/include/http_core.h
@@ -540,6 +540,8 @@ typedef struct {
/** per-dir log config */
struct ap_logconf *log;
+
+ unsigned int decode_encoded_slashes : 1; /* whether to decode encoded slashes in URLs */
} core_dir_config;
/* macro to implement off by default behaviour */
diff --git a/include/httpd.h b/include/httpd.h
index a7650a7df7..8086ff8e1c 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -1496,7 +1496,7 @@ AP_DECLARE(int) ap_unescape_url(char *url);
* @param url The url to unescape
* @return 0 on success, non-zero otherwise
*/
-AP_DECLARE(int) ap_unescape_url_keep2f(char *url);
+AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
/**
* Convert all double slashes to single slashes
diff --git a/server/core.c b/server/core.c
index f764df667a..6600df332e 100644
--- a/server/core.c
+++ b/server/core.c
@@ -169,6 +169,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
conf->enable_mmap = ENABLE_MMAP_UNSET;
conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
conf->allow_encoded_slashes = 0;
+ conf->decode_encoded_slashes = 0;
return (void *)conf;
}
@@ -372,6 +373,7 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
}
conf->allow_encoded_slashes = new->allow_encoded_slashes;
+ conf->decode_encoded_slashes = new->decode_encoded_slashes;
if (new->log) {
if (!conf->log) {
@@ -2634,11 +2636,24 @@ static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg)
return NULL;
}
-static const char *set_allow2f(cmd_parms *cmd, void *d_, int arg)
+static const char *set_allow2f(cmd_parms *cmd, void *d_, const char *arg)
{
core_dir_config *d = d_;
- d->allow_encoded_slashes = arg != 0;
+ if (0 == strcasecmp(arg, "on")) {
+ d->allow_encoded_slashes = 1;
+ d->decode_encoded_slashes = 1; /* for compatibility with 2.0 & 2.2 */
+ } else if (0 == strcasecmp(arg, "off")) {
+ d->allow_encoded_slashes = 0;
+ d->decode_encoded_slashes = 0;
+ } else if (0 == strcasecmp(arg, "nodecode")) {
+ d->allow_encoded_slashes = 1;
+ d->decode_encoded_slashes = 0;
+ } else {
+ return apr_pstrcat(cmd->pool,
+ cmd->cmd->name, " must be On, Off, or NoDecode",
+ NULL);
+ }
return NULL;
}
@@ -3780,7 +3795,7 @@ AP_INIT_TAKE1("SetOutputFilter", ap_set_string_slot,
AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot,
(void *)APR_OFFSETOF(core_dir_config, input_filters), OR_FILEINFO,
"filter (or ; delimited list of filters) to be run on the request body"),
-AP_INIT_FLAG("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF,
+AP_INIT_TAKE1("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF,
"Allow URLs containing '/' encoded as '%2F'"),
/* scoreboard.c directives */
diff --git a/server/request.c b/server/request.c
index fa6d9b7d82..b0ec847361 100644
--- a/server/request.c
+++ b/server/request.c
@@ -124,7 +124,7 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
if (!r->proxyreq && r->parsed_uri.path) {
d = ap_get_module_config(r->per_dir_config, &core_module);
if (d->allow_encoded_slashes) {
- access_status = ap_unescape_url_keep2f(r->parsed_uri.path);
+ access_status = ap_unescape_url_keep2f(r->parsed_uri.path, d->decode_encoded_slashes);
}
else {
access_status = ap_unescape_url(r->parsed_uri.path);
diff --git a/server/util.c b/server/util.c
index c443c942a3..a6bdfd0c41 100644
--- a/server/util.c
+++ b/server/util.c
@@ -79,8 +79,10 @@
*/
#ifdef CASE_BLIND_FILESYSTEM
#define IS_SLASH(s) ((s == '/') || (s == '\\'))
+#define SLASHES "/\\"
#else
#define IS_SLASH(s) (s == '/')
+#define SLASHES "/"
#endif
APLOG_USE_MODULE(core);
@@ -1514,16 +1516,18 @@ static int unescape_url(char *url, const char *forbid, const char *reserved)
AP_DECLARE(int) ap_unescape_url(char *url)
{
/* Traditional */
-#ifdef CASE_BLIND_FILESYSTEM
- return unescape_url(url, "/\\", NULL);
-#else
- return unescape_url(url, "/", NULL);
-#endif
+ return unescape_url(url, SLASHES, NULL);
}
-AP_DECLARE(int) ap_unescape_url_keep2f(char *url)
+AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes)
{
/* AllowEncodedSlashes (corrected) */
- return unescape_url(url, NULL, "/");
+ if (decode_slashes) {
+ /* no chars reserved */
+ return unescape_url(url, NULL, NULL);
+ } else {
+ /* reserve (do not decode) encoded slashes */
+ return unescape_url(url, NULL, SLASHES);
+ }
}
#ifdef NEW_APIS
/* IFDEF these out until they've been thought through.