From 58c0029c34de146aff55eda4b1d1c1dca1db5d0e Mon Sep 17 00:00:00 2001 From: olavmrk Date: Wed, 8 May 2013 12:24:14 +0000 Subject: Fix am_urldecode handling of encoded slashes. Apache has fixed a bug/misfeature where ap_unescape_url_keep2f() decoded %2f-escapes. This leaves us with no functions that can be used to urldecode strings, so we have to roll our own. If we drop support for Apache 2.2, we can use ap_unescape_urlencoded(). See: http://svn.apache.org/viewvc?view=revision&revision=578332 git-svn-id: https://modmellon.googlecode.com/svn/trunk@206 a716ebb1-153a-0410-b759-cfb97c6a1b53 --- auth_mellon_util.c | 76 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/auth_mellon_util.c b/auth_mellon_util.c index 0fd31e2..ca25f7f 100644 --- a/auth_mellon_util.c +++ b/auth_mellon_util.c @@ -589,6 +589,27 @@ char *am_extract_query_parameter(apr_pool_t *pool, } } + +/* Convert a hexadecimal digit to an integer. + * + * Parameters: + * char c The digit we should convert. + * + * Returns: + * The digit as an integer, or -1 if it isn't a hex digit. + */ +static int am_unhex_digit(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 0xa; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 0xa; + } else { + return -1; + } +} + /* This function urldecodes a string in-place. * * Parameters: @@ -600,24 +621,51 @@ char *am_extract_query_parameter(apr_pool_t *pool, */ int am_urldecode(char *data) { - int rc; char *ip; + char *op; + int c1, c2; + + ip = data; + op = data; + while (*ip) { + switch (*ip) { + case '+': + *op = ' '; + ip++; + op++; + break; + case '%': + /* Decode the hex digits. Note that we need to check the + * result of the first conversion before attempting the + * second conversion -- otherwise we may read past the end + * of the string. + */ + c1 = am_unhex_digit(ip[1]); + if (c1 < 0) { + return HTTP_BAD_REQUEST; + } + c2 = am_unhex_digit(ip[2]); + if (c2 < 0) { + return HTTP_BAD_REQUEST; + } - /* First we replace all '+'-characters with space. */ - for (ip = strchr(data, '+'); ip != NULL; ip = strchr(ip, '+')) { - *ip = ' '; - } - - /* Then we call ap_unescape_url_keep2f to decode all the "%xx" - * escapes. This function returns HTTP_NOT_FOUND if the string - * contains a null-byte. - */ - rc = ap_unescape_url_keep2f(data); - if (rc == HTTP_NOT_FOUND) { - return HTTP_BAD_REQUEST; + *op = (c1 << 4) | c2; + if (*op == '\0') { + /* null-byte. */ + return HTTP_BAD_REQUEST; + } + ip += 3; + op++; + break; + default: + *op = *ip; + ip++; + op++; + } } + *op = '\0'; - return rc; + return OK; } -- cgit