summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2013-05-08 12:24:14 +0000
committerolavmrk <olavmrk@a716ebb1-153a-0410-b759-cfb97c6a1b53>2013-05-08 12:24:14 +0000
commit58c0029c34de146aff55eda4b1d1c1dca1db5d0e (patch)
treead580135cc833fadd664423d83d651ddc10bd652
parent1d2c882ba14c007d9cf966ac1c131fb3628bb810 (diff)
downloadmod_auth_mellon-58c0029c34de146aff55eda4b1d1c1dca1db5d0e.zip
mod_auth_mellon-58c0029c34de146aff55eda4b1d1c1dca1db5d0e.tar.gz
mod_auth_mellon-58c0029c34de146aff55eda4b1d1c1dca1db5d0e.tar.xz
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
-rw-r--r--auth_mellon_util.c76
1 files 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;
}