You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2021/10/07 12:27:43 UTC
svn commit: r1893977 - in /httpd/httpd/branches/2.4.x: ./ CHANGES
include/ap_mmn.h include/httpd.h server/gen_test_char.c server/request.c
server/util.c
Author: ylavic
Date: Thu Oct 7 12:27:43 2021
New Revision: 1893977
URL: http://svn.apache.org/viewvc?rev=1893977&view=rev
Log:
Merge r1893971 from trunk:
core: Add ap_unescape_url_ex() for better decoding control, and deprecate
unused AP_NORMALIZE_DROP_PARAMETERS flag.
Submitted by: ylavic
Reviewed by: ylavic, icing, gbechis
Modified:
httpd/httpd/branches/2.4.x/ (props changed)
httpd/httpd/branches/2.4.x/CHANGES
httpd/httpd/branches/2.4.x/include/ap_mmn.h
httpd/httpd/branches/2.4.x/include/httpd.h
httpd/httpd/branches/2.4.x/server/gen_test_char.c
httpd/httpd/branches/2.4.x/server/request.c
httpd/httpd/branches/2.4.x/server/util.c
Propchange: httpd/httpd/branches/2.4.x/
------------------------------------------------------------------------------
Merged /httpd/httpd/trunk:r1893971
Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Thu Oct 7 12:27:43 2021
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.4.51
+ *) core: Add ap_unescape_url_ex() for better decoding control, and deprecate
+ unused AP_NORMALIZE_DROP_PARAMETERS flag.
+ [Yann Ylavic, Ruediger Pluem, Stefan Eissing, Joe Orton]
+
Changes with Apache 2.4.50
*) SECURITY: CVE-2021-41773: Path traversal and file disclosure
Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
+++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Thu Oct 7 12:27:43 2021
@@ -579,6 +579,9 @@
* ap_proxy_define_worker_ex() to mod_proxy.h
* 20120211.116 (2.4.49-dev) add conn_rec->outgoing and ap_ssl_bind_outgoing()
* 20120211.117 (2.4.50-dev) Add ap_pre_connection
+ * 20210926.1 (2.5.1-dev) Add ap_unescape_url_ex() and deprecate
+ * AP_NORMALIZE_DROP_PARAMETERS
+ *
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
Modified: httpd/httpd/branches/2.4.x/include/httpd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/httpd.h?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/include/httpd.h (original)
+++ httpd/httpd/branches/2.4.x/include/httpd.h Thu Oct 7 12:27:43 2021
@@ -1741,6 +1741,18 @@ AP_DECLARE(int) ap_unescape_url(char *ur
*/
AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
+#define AP_UNESCAPE_URL_KEEP_UNRESERVED (1u << 0)
+#define AP_UNESCAPE_URL_FORBID_SLASHES (1u << 1)
+#define AP_UNESCAPE_URL_KEEP_SLASHES (1u << 2)
+
+/**
+ * Unescape a URL, with options
+ * @param url The url to unescape
+ * @param flags Bitmask of AP_UNESCAPE_URL_* flags
+ * @return 0 on success, non-zero otherwise
+ */
+AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags);
+
/**
* Unescape an application/x-www-form-urlencoded string
* @param query The query to unescape
@@ -1768,7 +1780,7 @@ AP_DECLARE(void) ap_no2slash_ex(char *na
#define AP_NORMALIZE_NOT_ABOVE_ROOT (1u << 1)
#define AP_NORMALIZE_DECODE_UNRESERVED (1u << 2)
#define AP_NORMALIZE_MERGE_SLASHES (1u << 3)
-#define AP_NORMALIZE_DROP_PARAMETERS (1u << 4)
+#define AP_NORMALIZE_DROP_PARAMETERS (0) /* deprecated */
/**
* Remove all ////, /./ and /xx/../ substrings from a path, and more
Modified: httpd/httpd/branches/2.4.x/server/gen_test_char.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/gen_test_char.c?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/server/gen_test_char.c (original)
+++ httpd/httpd/branches/2.4.x/server/gen_test_char.c Thu Oct 7 12:27:43 2021
@@ -54,6 +54,7 @@
#define T_ESCAPE_URLENCODED (0x40)
#define T_HTTP_CTRLS (0x80)
#define T_VCHAR_OBSTEXT (0x100)
+#define T_URI_UNRESERVED (0x200)
int main(int argc, char *argv[])
{
@@ -71,6 +72,7 @@ int main(int argc, char *argv[])
"#define T_ESCAPE_URLENCODED (%u)\n"
"#define T_HTTP_CTRLS (%u)\n"
"#define T_VCHAR_OBSTEXT (%u)\n"
+ "#define T_URI_UNRESERVED (%u)\n"
"\n"
"static const unsigned short test_char_table[256] = {",
T_ESCAPE_SHELL_CMD,
@@ -81,7 +83,9 @@ int main(int argc, char *argv[])
T_ESCAPE_FORENSIC,
T_ESCAPE_URLENCODED,
T_HTTP_CTRLS,
- T_VCHAR_OBSTEXT);
+ T_VCHAR_OBSTEXT,
+ T_URI_UNRESERVED
+ );
for (c = 0; c < 256; ++c) {
flags = 0;
@@ -164,6 +168,12 @@ int main(int argc, char *argv[])
flags |= T_ESCAPE_FORENSIC;
}
+ /* Characters in the RFC 3986 "unreserved" set.
+ * https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */
+ if (c && (apr_isalnum(c) || strchr("-._~", c))) {
+ flags |= T_URI_UNRESERVED;
+ }
+
printf("0x%03x%c", flags, (c < 255) ? ',' : ' ');
}
Modified: httpd/httpd/branches/2.4.x/server/request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/request.c?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/server/request.c (original)
+++ httpd/httpd/branches/2.4.x/server/request.c Thu Oct 7 12:27:43 2021
@@ -241,14 +241,15 @@ AP_DECLARE(int) ap_process_request_inter
/* Ignore URL unescaping for translated URIs already */
if (access_status != DONE && r->parsed_uri.path) {
core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
-
- if (d->allow_encoded_slashes) {
- access_status = ap_unescape_url_keep2f(r->parsed_uri.path,
- d->decode_encoded_slashes);
+ /* Unreserved chars were already decoded by ap_normalize_path() */
+ unsigned int unescape_flags = AP_UNESCAPE_URL_KEEP_UNRESERVED;
+ if (!d->allow_encoded_slashes) {
+ unescape_flags |= AP_UNESCAPE_URL_FORBID_SLASHES;
}
- else {
- access_status = ap_unescape_url(r->parsed_uri.path);
+ else if (!d->decode_encoded_slashes) {
+ unescape_flags |= AP_UNESCAPE_URL_KEEP_SLASHES;
}
+ access_status = ap_unescape_url_ex(r->parsed_uri.path, unescape_flags);
if (access_status) {
if (access_status == HTTP_NOT_FOUND) {
if (! d->allow_encoded_slashes) {
Modified: httpd/httpd/branches/2.4.x/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/util.c?rev=1893977&r1=1893976&r2=1893977&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/server/util.c (original)
+++ httpd/httpd/branches/2.4.x/server/util.c Thu Oct 7 12:27:43 2021
@@ -530,23 +530,20 @@ AP_DECLARE(int) ap_normalize_path(char *
* be decoded to their corresponding unreserved characters by
* URI normalizers.
*/
- if (decode_unreserved
- && path[l] == '%' && apr_isxdigit(path[l + 1])
- && apr_isxdigit(path[l + 2])) {
- const char c = x2c(&path[l + 1]);
- if (apr_isalnum(c) || (c && strchr("-._~", c))) {
- /* Replace last char and fall through as the current
- * read position */
- l += 2;
- path[l] = c;
+ if (decode_unreserved && path[l] == '%') {
+ if (apr_isxdigit(path[l + 1]) && apr_isxdigit(path[l + 2])) {
+ const char c = x2c(&path[l + 1]);
+ if (TEST_CHAR(c, T_URI_UNRESERVED)) {
+ /* Replace last char and fall through as the current
+ * read position */
+ l += 2;
+ path[l] = c;
+ }
+ }
+ else {
+ /* Invalid encoding */
+ ret = 0;
}
- }
-
- if ((flags & AP_NORMALIZE_DROP_PARAMETERS) && path[l] == ';') {
- do {
- l++;
- } while (!IS_SLASH_OR_NUL(path[l]));
- continue;
}
if (w == 0 || IS_SLASH(path[w - 1])) {
@@ -1889,8 +1886,12 @@ static char x2c(const char *what)
* decoding %00 or a forbidden character returns HTTP_NOT_FOUND
*/
-static int unescape_url(char *url, const char *forbid, const char *reserved)
+static int unescape_url(char *url, const char *forbid, const char *reserved,
+ unsigned int flags)
{
+ const int keep_slashes = (flags & AP_UNESCAPE_URL_KEEP_SLASHES) != 0,
+ forbid_slashes = (flags & AP_UNESCAPE_URL_FORBID_SLASHES) != 0,
+ keep_unreserved = (flags & AP_UNESCAPE_URL_KEEP_UNRESERVED) != 0;
int badesc, badpath;
char *x, *y;
@@ -1915,12 +1916,16 @@ static int unescape_url(char *url, const
char decoded;
decoded = x2c(y + 1);
if ((decoded == '\0')
+ || (forbid_slashes && IS_SLASH(decoded))
|| (forbid && ap_strchr_c(forbid, decoded))) {
badpath = 1;
*x = decoded;
y += 2;
}
- else if (reserved && ap_strchr_c(reserved, decoded)) {
+ else if ((keep_unreserved && TEST_CHAR(decoded,
+ T_URI_UNRESERVED))
+ || (keep_slashes && IS_SLASH(decoded))
+ || (reserved && ap_strchr_c(reserved, decoded))) {
*x++ = *y++;
*x++ = *y++;
*x = *y;
@@ -1946,19 +1951,24 @@ static int unescape_url(char *url, const
AP_DECLARE(int) ap_unescape_url(char *url)
{
/* Traditional */
- return unescape_url(url, SLASHES, NULL);
+ return unescape_url(url, SLASHES, NULL, 0);
}
AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes)
{
/* AllowEncodedSlashes (corrected) */
if (decode_slashes) {
/* no chars reserved */
- return unescape_url(url, NULL, NULL);
+ return unescape_url(url, NULL, NULL, 0);
} else {
/* reserve (do not decode) encoded slashes */
- return unescape_url(url, NULL, SLASHES);
+ return unescape_url(url, NULL, SLASHES, 0);
}
}
+AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags)
+{
+ return unescape_url(url, NULL, NULL, flags);
+}
+
#ifdef NEW_APIS
/* IFDEF these out until they've been thought through.
* Just a germ of an API extension for now
@@ -1968,7 +1978,7 @@ AP_DECLARE(int) ap_unescape_url_proxy(ch
/* leave RFC1738 reserved characters intact, * so proxied URLs
* don't get mangled. Where does that leave encoded '&' ?
*/
- return unescape_url(url, NULL, "/;?");
+ return unescape_url(url, NULL, "/;?", 0);
}
AP_DECLARE(int) ap_unescape_url_reserved(char *url, const char *reserved)
{
@@ -1990,7 +2000,7 @@ AP_DECLARE(int) ap_unescape_urlencoded(c
}
/* unescape everything else */
- return unescape_url(query, NULL, NULL);
+ return unescape_url(query, NULL, NULL, 0);
}
AP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
@@ -2006,7 +2016,7 @@ AP_DECLARE(char *) ap_construct_server(a
AP_DECLARE(int) ap_unescape_all(char *url)
{
- return unescape_url(url, NULL, NULL);
+ return unescape_url(url, NULL, NULL, 0);
}
/* c2x takes an unsigned, and expects the caller has guaranteed that
Re: svn commit: r1893977 - in /httpd/httpd/branches/2.4.x: ./ CHANGES
include/ap_mmn.h include/httpd.h server/gen_test_char.c server/request.c server/util.c
Posted by Yann Ylavic <yl...@gmail.com>.
On Thu, Oct 7, 2021 at 2:31 PM Rainer Jung <ra...@kippdata.de> wrote:
>
> Am 07.10.2021 um 14:27 schrieb ylavic@apache.org:
> > Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
> > URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1893977&r1=1893976&r2=1893977&view=diff
> > ==============================================================================
> > --- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
> > +++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Thu Oct 7 12:27:43 2021
> > @@ -579,6 +579,9 @@
> > * ap_proxy_define_worker_ex() to mod_proxy.h
> > * 20120211.116 (2.4.49-dev) add conn_rec->outgoing and ap_ssl_bind_outgoing()
> > * 20120211.117 (2.4.50-dev) Add ap_pre_connection
> > + * 20210926.1 (2.5.1-dev) Add ap_unescape_url_ex() and deprecate
> > + * AP_NORMALIZE_DROP_PARAMETERS
> > + *
> > */
> >
> > #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
>
> Doesn't this need (a cosmetic) adjustment for 2.4.x?
Yeah, was wrong in original trunk r1893971 too so I fixed both.
Thanks Rainer (and RĂ¼diger) for noticing.
Re: svn commit: r1893977 - in /httpd/httpd/branches/2.4.x: ./ CHANGES
include/ap_mmn.h include/httpd.h server/gen_test_char.c server/request.c
server/util.c
Posted by Rainer Jung <ra...@kippdata.de>.
Am 07.10.2021 um 14:27 schrieb ylavic@apache.org:
> Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
> +++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Thu Oct 7 12:27:43 2021
> @@ -579,6 +579,9 @@
> * ap_proxy_define_worker_ex() to mod_proxy.h
> * 20120211.116 (2.4.49-dev) add conn_rec->outgoing and ap_ssl_bind_outgoing()
> * 20120211.117 (2.4.50-dev) Add ap_pre_connection
> + * 20210926.1 (2.5.1-dev) Add ap_unescape_url_ex() and deprecate
> + * AP_NORMALIZE_DROP_PARAMETERS
> + *
> */
>
> #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
Doesn't this need (a cosmetic) adjustment for 2.4.x?
Plus: if a minor bump is needed, this commit contains only a comment change.
Thanks for your intensive work!
Rainer
Re: svn commit: r1893977 - in /httpd/httpd/branches/2.4.x: ./ CHANGES
include/ap_mmn.h include/httpd.h server/gen_test_char.c server/request.c
server/util.c
Posted by Ruediger Pluem <rp...@apache.org>.
On 10/7/21 2:27 PM, ylavic@apache.org wrote:
> Author: ylavic
> Date: Thu Oct 7 12:27:43 2021
> New Revision: 1893977
>
> URL: http://svn.apache.org/viewvc?rev=1893977&view=rev
> Log:
> Merge r1893971 from trunk:
>
> core: Add ap_unescape_url_ex() for better decoding control, and deprecate
> unused AP_NORMALIZE_DROP_PARAMETERS flag.
>
> Submitted by: ylavic
> Reviewed by: ylavic, icing, gbechis
>
> Modified:
> httpd/httpd/branches/2.4.x/ (props changed)
> httpd/httpd/branches/2.4.x/CHANGES
> httpd/httpd/branches/2.4.x/include/ap_mmn.h
> httpd/httpd/branches/2.4.x/include/httpd.h
> httpd/httpd/branches/2.4.x/server/gen_test_char.c
> httpd/httpd/branches/2.4.x/server/request.c
> httpd/httpd/branches/2.4.x/server/util.c
>
> Propchange: httpd/httpd/branches/2.4.x/
> ------------------------------------------------------------------------------
> Merged /httpd/httpd/trunk:r1893971
>
> Modified: httpd/httpd/branches/2.4.x/CHANGES
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
> +++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Thu Oct 7 12:27:43 2021
> @@ -1,6 +1,10 @@
> -*- coding: utf-8 -*-
> Changes with Apache 2.4.51
>
> + *) core: Add ap_unescape_url_ex() for better decoding control, and deprecate
> + unused AP_NORMALIZE_DROP_PARAMETERS flag.
> + [Yann Ylavic, Ruediger Pluem, Stefan Eissing, Joe Orton]
> +
> Changes with Apache 2.4.50
>
> *) SECURITY: CVE-2021-41773: Path traversal and file disclosure
>
> Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
> +++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Thu Oct 7 12:27:43 2021
> @@ -579,6 +579,9 @@
> * ap_proxy_define_worker_ex() to mod_proxy.h
> * 20120211.116 (2.4.49-dev) add conn_rec->outgoing and ap_ssl_bind_outgoing()
> * 20120211.117 (2.4.50-dev) Add ap_pre_connection
> + * 20210926.1 (2.5.1-dev) Add ap_unescape_url_ex() and deprecate
> + * AP_NORMALIZE_DROP_PARAMETERS
> + *
> */
>
This is wrong and needs fixing. I have the below fix in my working copy that I can commit instantly:
Index: include/ap_mmn.h
===================================================================
--- include/ap_mmn.h (revision 1893979)
+++ include/ap_mmn.h (working copy)
@@ -579,7 +579,7 @@
* ap_proxy_define_worker_ex() to mod_proxy.h
* 20120211.116 (2.4.49-dev) add conn_rec->outgoing and ap_ssl_bind_outgoing()
* 20120211.117 (2.4.50-dev) Add ap_pre_connection
- * 20210926.1 (2.5.1-dev) Add ap_unescape_url_ex() and deprecate
+ * 20120211.118 (2.4.51-dev) Add ap_unescape_url_ex() and deprecate
* AP_NORMALIZE_DROP_PARAMETERS
*
*/
@@ -589,7 +589,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 117 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 118 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Regards
RĂ¼diger
> #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
>
> Modified: httpd/httpd/branches/2.4.x/include/httpd.h
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/httpd.h?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/include/httpd.h (original)
> +++ httpd/httpd/branches/2.4.x/include/httpd.h Thu Oct 7 12:27:43 2021
> @@ -1741,6 +1741,18 @@ AP_DECLARE(int) ap_unescape_url(char *ur
> */
> AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
>
> +#define AP_UNESCAPE_URL_KEEP_UNRESERVED (1u << 0)
> +#define AP_UNESCAPE_URL_FORBID_SLASHES (1u << 1)
> +#define AP_UNESCAPE_URL_KEEP_SLASHES (1u << 2)
> +
> +/**
> + * Unescape a URL, with options
> + * @param url The url to unescape
> + * @param flags Bitmask of AP_UNESCAPE_URL_* flags
> + * @return 0 on success, non-zero otherwise
> + */
> +AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags);
> +
> /**
> * Unescape an application/x-www-form-urlencoded string
> * @param query The query to unescape
> @@ -1768,7 +1780,7 @@ AP_DECLARE(void) ap_no2slash_ex(char *na
> #define AP_NORMALIZE_NOT_ABOVE_ROOT (1u << 1)
> #define AP_NORMALIZE_DECODE_UNRESERVED (1u << 2)
> #define AP_NORMALIZE_MERGE_SLASHES (1u << 3)
> -#define AP_NORMALIZE_DROP_PARAMETERS (1u << 4)
> +#define AP_NORMALIZE_DROP_PARAMETERS (0) /* deprecated */
>
> /**
> * Remove all ////, /./ and /xx/../ substrings from a path, and more
>
> Modified: httpd/httpd/branches/2.4.x/server/gen_test_char.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/gen_test_char.c?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/server/gen_test_char.c (original)
> +++ httpd/httpd/branches/2.4.x/server/gen_test_char.c Thu Oct 7 12:27:43 2021
> @@ -54,6 +54,7 @@
> #define T_ESCAPE_URLENCODED (0x40)
> #define T_HTTP_CTRLS (0x80)
> #define T_VCHAR_OBSTEXT (0x100)
> +#define T_URI_UNRESERVED (0x200)
>
> int main(int argc, char *argv[])
> {
> @@ -71,6 +72,7 @@ int main(int argc, char *argv[])
> "#define T_ESCAPE_URLENCODED (%u)\n"
> "#define T_HTTP_CTRLS (%u)\n"
> "#define T_VCHAR_OBSTEXT (%u)\n"
> + "#define T_URI_UNRESERVED (%u)\n"
> "\n"
> "static const unsigned short test_char_table[256] = {",
> T_ESCAPE_SHELL_CMD,
> @@ -81,7 +83,9 @@ int main(int argc, char *argv[])
> T_ESCAPE_FORENSIC,
> T_ESCAPE_URLENCODED,
> T_HTTP_CTRLS,
> - T_VCHAR_OBSTEXT);
> + T_VCHAR_OBSTEXT,
> + T_URI_UNRESERVED
> + );
>
> for (c = 0; c < 256; ++c) {
> flags = 0;
> @@ -164,6 +168,12 @@ int main(int argc, char *argv[])
> flags |= T_ESCAPE_FORENSIC;
> }
>
> + /* Characters in the RFC 3986 "unreserved" set.
> + * https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */
> + if (c && (apr_isalnum(c) || strchr("-._~", c))) {
> + flags |= T_URI_UNRESERVED;
> + }
> +
> printf("0x%03x%c", flags, (c < 255) ? ',' : ' ');
> }
>
>
> Modified: httpd/httpd/branches/2.4.x/server/request.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/request.c?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/server/request.c (original)
> +++ httpd/httpd/branches/2.4.x/server/request.c Thu Oct 7 12:27:43 2021
> @@ -241,14 +241,15 @@ AP_DECLARE(int) ap_process_request_inter
> /* Ignore URL unescaping for translated URIs already */
> if (access_status != DONE && r->parsed_uri.path) {
> core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
> -
> - if (d->allow_encoded_slashes) {
> - access_status = ap_unescape_url_keep2f(r->parsed_uri.path,
> - d->decode_encoded_slashes);
> + /* Unreserved chars were already decoded by ap_normalize_path() */
> + unsigned int unescape_flags = AP_UNESCAPE_URL_KEEP_UNRESERVED;
> + if (!d->allow_encoded_slashes) {
> + unescape_flags |= AP_UNESCAPE_URL_FORBID_SLASHES;
> }
> - else {
> - access_status = ap_unescape_url(r->parsed_uri.path);
> + else if (!d->decode_encoded_slashes) {
> + unescape_flags |= AP_UNESCAPE_URL_KEEP_SLASHES;
> }
> + access_status = ap_unescape_url_ex(r->parsed_uri.path, unescape_flags);
> if (access_status) {
> if (access_status == HTTP_NOT_FOUND) {
> if (! d->allow_encoded_slashes) {
>
> Modified: httpd/httpd/branches/2.4.x/server/util.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/util.c?rev=1893977&r1=1893976&r2=1893977&view=diff
> ==============================================================================
> --- httpd/httpd/branches/2.4.x/server/util.c (original)
> +++ httpd/httpd/branches/2.4.x/server/util.c Thu Oct 7 12:27:43 2021
> @@ -530,23 +530,20 @@ AP_DECLARE(int) ap_normalize_path(char *
> * be decoded to their corresponding unreserved characters by
> * URI normalizers.
> */
> - if (decode_unreserved
> - && path[l] == '%' && apr_isxdigit(path[l + 1])
> - && apr_isxdigit(path[l + 2])) {
> - const char c = x2c(&path[l + 1]);
> - if (apr_isalnum(c) || (c && strchr("-._~", c))) {
> - /* Replace last char and fall through as the current
> - * read position */
> - l += 2;
> - path[l] = c;
> + if (decode_unreserved && path[l] == '%') {
> + if (apr_isxdigit(path[l + 1]) && apr_isxdigit(path[l + 2])) {
> + const char c = x2c(&path[l + 1]);
> + if (TEST_CHAR(c, T_URI_UNRESERVED)) {
> + /* Replace last char and fall through as the current
> + * read position */
> + l += 2;
> + path[l] = c;
> + }
> + }
> + else {
> + /* Invalid encoding */
> + ret = 0;
> }
> - }
> -
> - if ((flags & AP_NORMALIZE_DROP_PARAMETERS) && path[l] == ';') {
> - do {
> - l++;
> - } while (!IS_SLASH_OR_NUL(path[l]));
> - continue;
> }
>
> if (w == 0 || IS_SLASH(path[w - 1])) {
> @@ -1889,8 +1886,12 @@ static char x2c(const char *what)
> * decoding %00 or a forbidden character returns HTTP_NOT_FOUND
> */
>
> -static int unescape_url(char *url, const char *forbid, const char *reserved)
> +static int unescape_url(char *url, const char *forbid, const char *reserved,
> + unsigned int flags)
> {
> + const int keep_slashes = (flags & AP_UNESCAPE_URL_KEEP_SLASHES) != 0,
> + forbid_slashes = (flags & AP_UNESCAPE_URL_FORBID_SLASHES) != 0,
> + keep_unreserved = (flags & AP_UNESCAPE_URL_KEEP_UNRESERVED) != 0;
> int badesc, badpath;
> char *x, *y;
>
> @@ -1915,12 +1916,16 @@ static int unescape_url(char *url, const
> char decoded;
> decoded = x2c(y + 1);
> if ((decoded == '\0')
> + || (forbid_slashes && IS_SLASH(decoded))
> || (forbid && ap_strchr_c(forbid, decoded))) {
> badpath = 1;
> *x = decoded;
> y += 2;
> }
> - else if (reserved && ap_strchr_c(reserved, decoded)) {
> + else if ((keep_unreserved && TEST_CHAR(decoded,
> + T_URI_UNRESERVED))
> + || (keep_slashes && IS_SLASH(decoded))
> + || (reserved && ap_strchr_c(reserved, decoded))) {
> *x++ = *y++;
> *x++ = *y++;
> *x = *y;
> @@ -1946,19 +1951,24 @@ static int unescape_url(char *url, const
> AP_DECLARE(int) ap_unescape_url(char *url)
> {
> /* Traditional */
> - return unescape_url(url, SLASHES, NULL);
> + return unescape_url(url, SLASHES, NULL, 0);
> }
> AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes)
> {
> /* AllowEncodedSlashes (corrected) */
> if (decode_slashes) {
> /* no chars reserved */
> - return unescape_url(url, NULL, NULL);
> + return unescape_url(url, NULL, NULL, 0);
> } else {
> /* reserve (do not decode) encoded slashes */
> - return unescape_url(url, NULL, SLASHES);
> + return unescape_url(url, NULL, SLASHES, 0);
> }
> }
> +AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags)
> +{
> + return unescape_url(url, NULL, NULL, flags);
> +}
> +
> #ifdef NEW_APIS
> /* IFDEF these out until they've been thought through.
> * Just a germ of an API extension for now
> @@ -1968,7 +1978,7 @@ AP_DECLARE(int) ap_unescape_url_proxy(ch
> /* leave RFC1738 reserved characters intact, * so proxied URLs
> * don't get mangled. Where does that leave encoded '&' ?
> */
> - return unescape_url(url, NULL, "/;?");
> + return unescape_url(url, NULL, "/;?", 0);
> }
> AP_DECLARE(int) ap_unescape_url_reserved(char *url, const char *reserved)
> {
> @@ -1990,7 +2000,7 @@ AP_DECLARE(int) ap_unescape_urlencoded(c
> }
>
> /* unescape everything else */
> - return unescape_url(query, NULL, NULL);
> + return unescape_url(query, NULL, NULL, 0);
> }
>
> AP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
> @@ -2006,7 +2016,7 @@ AP_DECLARE(char *) ap_construct_server(a
>
> AP_DECLARE(int) ap_unescape_all(char *url)
> {
> - return unescape_url(url, NULL, NULL);
> + return unescape_url(url, NULL, NULL, 0);
> }
>
> /* c2x takes an unsigned, and expects the caller has guaranteed that
>
>
>