Author: mturk Date: Mon Jun 4 05:08:33 2007 New Revision: 544137 URL: http://svn.apache.org/viewvc?view=rev&rev=544137 Log: Add simple URI normalizer that can deal with things like %252e%252e. This is mostly copy/paste from the IIS module
Modified: tomcat/connectors/trunk/jk/native/common/jk_uri_worker_map.c Modified: tomcat/connectors/trunk/jk/native/common/jk_uri_worker_map.c URL: http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_uri_worker_map.c?view=diff&rev=544137&r1=544136&r2=544137 ============================================================================== --- tomcat/connectors/trunk/jk/native/common/jk_uri_worker_map.c (original) +++ tomcat/connectors/trunk/jk/native/common/jk_uri_worker_map.c Mon Jun 4 05:08:33 2007 @@ -36,6 +36,8 @@ #define JK_STRCMP strcmp #define JK_STRNCMP strncmp #endif +#define BAD_REQUEST -1 +#define BAD_PATH -2 static const char *uri_worker_map_source_type[] = { @@ -47,6 +49,116 @@ NULL }; +#define JK_ISXDIGIT(x) isxdigit((int)(unsigned char)((x))) + +static char x2c(const char *what) +{ + register char digit; + + digit = ((what[0] >= 'A') ? + ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); + digit *= 16; + digit += ((what[1] >= 'A') ? + ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); + return (digit); +} + +static int unescape_url(char *url) +{ + register int x, y, badesc, badpath; + + badesc = 0; + badpath = 0; + for (x = 0, y = 0; url[y]; ++x, ++y) { + if (url[y] != '%') + url[x] = url[y]; + else { + if (!JK_ISXDIGIT(url[y + 1]) || !JK_ISXDIGIT(url[y + 2])) { + badesc = 1; + url[x] = '%'; + } + else { + url[x] = x2c(&url[y + 1]); + y += 2; + if (url[x] == '/' || url[x] == '\0') + badpath = 1; + } + } + } + url[x] = '\0'; + if (badesc) + return BAD_REQUEST; + else if (badpath) + return BAD_PATH; + else + return 0; +} + +static void normalize_url(char *name) +{ + int l, w; + + /* Four paseses, as per RFC 1808 */ + /* 1. remove ./ path segments */ + + for (l = 0, w = 0; name[l] != '\0';) { + if (name[l] == '.' && name[l + 1] == '/' + && (l == 0 || name[l - 1] == '/')) + l += 2; + else + name[w++] = name[l++]; + } + + /* 2. remove trailing . path, segment */ + if (w == 1 && name[0] == '.') + w--; + else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/') + w--; + name[w] = '\0'; + + /* 3. remove all xx/../ segments. (including leading ../ and /../) */ + l = 0; + + while (name[l] != '\0') { + if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' && + (l == 0 || name[l - 1] == '/')) { + register int m = l + 3, n; + + l = l - 2; + if (l >= 0) { + while (l >= 0 && name[l] != '/') + l--; + l++; + } + else + l = 0; + n = l; + while ((name[n] = name[m]) != '\0') { + n++; + m++; + } + } + else + ++l; + } + + /* 4. remove trailing xx/.. segment. */ + if (l == 2 && name[0] == '.' && name[1] == '.') + name[0] = '\0'; + else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' + && name[l - 3] == '/') { + l = l - 4; + if (l >= 0) { + while (l >= 0 && name[l] != '/') + l--; + l++; + } + else + l = 0; + name[l] = '\0'; + } +} + /* Return the string representation of the uwr source */ const char *uri_worker_map_get_source(uri_worker_record_t *uwr, jk_logger_t *l) @@ -535,6 +647,7 @@ const char *uri, jk_logger_t *l) { unsigned int i; + int rc; const char *rv = NULL; char url[JK_MAX_URI_LEN+1]; @@ -578,6 +691,22 @@ url[i] = uri[i]; } url[i] = '\0'; + if (JK_IS_DEBUG_LEVEL(l)) + jk_log(l, JK_LOG_DEBUG, "Attempting to map original URI '%s' from %d maps", + url, uw_map->size); + rc = unescape_url(url); + if (rc == BAD_REQUEST) { + jk_log(l, JK_LOG_INFO, "Invalid request while unescaping original URI '%s'", url); + return NULL; + } + else if (rc == BAD_PATH) { + jk_log(l, JK_LOG_INFO, "Invalid path while unescaping URI '%s'", url); + return NULL; + } + normalize_url(url); + if (JK_IS_DEBUG_LEVEL(l)) + jk_log(l, JK_LOG_DEBUG, "Attempting to map normalized URI '%s' from %d maps", + url, uw_map->size); if (JK_IS_DEBUG_LEVEL(l)) { char *url_rewrite = strstr(uri, JK_PATH_SESSION_IDENTIFIER); @@ -585,10 +714,6 @@ jk_log(l, JK_LOG_DEBUG, "separating session identifier '%s' from url '%s'", url_rewrite, uri); } - if (JK_IS_DEBUG_LEVEL(l)) - jk_log(l, JK_LOG_DEBUG, "Attempting to map URI '%s' from %d maps", - url, uw_map->size); - for (i = 0; i < uw_map->size; i++) { uri_worker_record_t *uwr = uw_map->maps[i]; --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]