Author: markt
Date: Fri Aug 24 12:31:54 2018
New Revision: 1838836

URL: http://svn.apache.org/viewvc?rev=1838836&view=rev
Log:
Refactor normalisation of request URIs to a common location and align the 
normalisation implementation for mod_jk with that implemented by Tomcat.

Modified:
    tomcat/jk/trunk/native/apache-2.0/mod_jk.c
    tomcat/jk/trunk/native/common/jk_util.c
    tomcat/jk/trunk/native/common/jk_util.h
    tomcat/jk/trunk/native/iis/jk_isapi_plugin.c
    tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml

Modified: tomcat/jk/trunk/native/apache-2.0/mod_jk.c
URL: 
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/apache-2.0/mod_jk.c?rev=1838836&r1=1838835&r2=1838836&view=diff
==============================================================================
--- tomcat/jk/trunk/native/apache-2.0/mod_jk.c (original)
+++ tomcat/jk/trunk/native/apache-2.0/mod_jk.c Fri Aug 24 12:31:54 2018
@@ -3790,7 +3790,10 @@ static int jk_translate(request_rec * r)
                                                       &jk_module);
 
         if (conf) {
+            char *clean_uri;
+            int rc;
             const char *worker;
+
             if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) {
                 /* Somebody already set the handler, probably manual config
                  * or "native" configuration, no need for extra overhead
@@ -3810,6 +3813,12 @@ static int jk_translate(request_rec * r)
                 return DECLINED;
             }
 
+            clean_uri = apr_pstrdup(r->pool, r->uri);
+            rc = jk_servlet_normalize(clean_uri, conf->log);
+            if (rc != 0) {
+               return HTTP_NOT_FOUND;
+            }
+
             /* Special case to make sure that apache can serve a directory
                listing if there are no matches for the DirectoryIndex and
                Tomcat webapps are mapped into apache using JkAutoAlias. */
@@ -3819,11 +3828,8 @@ static int jk_translate(request_rec * r)
 
                 /* Append the request uri to the JkAutoAlias directory and
                    determine if the file exists. */
-                char *clean_uri;
                 apr_finfo_t finfo;
                 finfo.filetype = APR_NOFILE;
-                clean_uri = apr_pstrdup(r->pool, r->uri);
-                ap_no2slash(clean_uri);
                 /* Map uri to a context static file */
                 if (strlen(clean_uri) > 1) {
                     char *context_path = NULL;
@@ -3855,7 +3861,7 @@ static int jk_translate(request_rec * r)
             }
             else {
                 rule_extension_t *e;
-                worker = map_uri_to_worker_ext(conf->uw_map, r->uri,
+                worker = map_uri_to_worker_ext(conf->uw_map, clean_uri,
                                                NULL, &e, NULL, conf->log);
                 rconf->rule_extensions = e;
                 ap_set_module_config(r->request_config, &jk_module, rconf);
@@ -3875,8 +3881,6 @@ static int jk_translate(request_rec * r)
                 return OK;
             }
             else if (conf->alias_dir != NULL) {
-                char *clean_uri = apr_pstrdup(r->pool, r->uri);
-                ap_no2slash(clean_uri);
                 /* Automatically map uri to a context static file */
                 if (JK_IS_DEBUG_LEVEL(conf->log))
                     jk_log(conf->log, JK_LOG_DEBUG,
@@ -3994,7 +3998,10 @@ static int jk_map_to_storage(request_rec
                                                       &jk_module);
 
         if (conf) {
+            char *clean_uri;
+            int rc;
             const char *worker;
+
             if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) {
                 /* Somebody already set the handler, probably manual config
                  * or "native" configuration, no need for extra overhead
@@ -4013,6 +4020,13 @@ static int jk_map_to_storage(request_rec
 
                 return DECLINED;
             }
+
+            clean_uri = apr_pstrdup(r->pool, r->uri);
+            rc = jk_servlet_normalize(clean_uri, conf->log);
+            if (rc != 0) {
+               return HTTP_NOT_FOUND;
+            }
+
             if (!conf->uw_map) {
                 if (JK_IS_DEBUG_LEVEL(conf->log))
                     jk_log(conf->log, JK_LOG_DEBUG,
@@ -4023,7 +4037,7 @@ static int jk_map_to_storage(request_rec
             }
             else {
                 rule_extension_t *e;
-                worker = map_uri_to_worker_ext(conf->uw_map, r->uri,
+                worker = map_uri_to_worker_ext(conf->uw_map, clean_uri,
                                                NULL, &e, NULL, conf->log);
                 rconf->rule_extensions = e;
                 ap_set_module_config(r->request_config, &jk_module, rconf);

Modified: tomcat/jk/trunk/native/common/jk_util.c
URL: 
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_util.c?rev=1838836&r1=1838835&r2=1838836&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_util.c (original)
+++ tomcat/jk/trunk/native/common/jk_util.c Fri Aug 24 12:31:54 2018
@@ -2196,6 +2196,95 @@ void jk_no2slash(char *name)
     *d = '\0';
 }
 
+int jk_servlet_normalize(char *path, jk_logger_t *logger)
+{
+    int l, w;
+
+    jk_log(logger, JK_LOG_DEBUG, "URI on entering jk_servlet_normalize: [%s]", 
path);
+
+    // This test allows the loops below to start at index 1 rather than 0.
+    if (path[0] != '/') {
+        jk_log(logger, JK_LOG_EMERG, "[%s] does not start with '/'.", path);
+        return JK_NORMALIZE_BAD_PATH;
+    }
+
+    /*
+     * First pass.
+     * Collapse ///// sequences to /
+     */
+    for (l = 1, w = 1; path[l] != '\0';) {
+        if (path[w - 1] == '/' && (path[l] == '/')) {
+            l++;
+        }
+        else
+            path[w++] = path[l++];
+    }
+    path[w] = '\0';
+
+    /* Second pass.
+     * Remove /./ segments including those with path parameters such as
+     * /.;foo=bar/
+     * Both leading and trailing segments will be removed.
+     */
+    for (l = 1, w = 1; path[l] != '\0';) {
+        if (path[l] == '.' &&
+                (path[l + 1] == '/' || path[l + 1] == ';' || path[l + 1] == 
'\0') &&
+                (l == 0 || path[l - 1] == '/')) {
+            l++;
+            while (path[l] != '/' && path[l] != '\0') {
+                l++;
+            }
+            if (path[l] != '\0') {
+                l++;
+            }
+        }
+        else
+            path[w++] = path[l++];
+    }
+    path[w] = '\0';
+
+    /* Third pass.
+     * Remove /xx/../ segments including those with path parameters such as
+     * /xxx/..;foo=bar/
+     * Trailing segments will be removed but leading /../ segments are an error
+     * condition.
+     */
+    for (l = 1, w = 1; path[l] != '\0';) {
+        if (path[l] == '.' && path[l + 1] == '.' &&
+                (path[l + 2] == '/' || path[l + 2] == ';' || path[l + 2] == 
'\0') &&
+                (l == 0 || path[l - 1] == '/')) {
+
+            // Wind w back to remove the previous segment
+            if (w == 1) {
+                jk_log(logger,
+                        JK_LOG_EMERG,
+                        "[%s] contains a '/../' sequence that tries to escape 
above the root.",
+                        path);
+                return JK_NORMALIZE_TRAVERSAL;
+            }
+            do {
+                w--;
+            } while (w != 0 && path[w - 1] != '/');
+
+            // Move l forward to the next segment
+            l += 2;
+
+            while (path[l] != '/' && path [l] != '\0') {
+                l++;
+            }
+            if (path[l] != '\0') {
+                l++;
+            }
+        }
+        else
+            path[w++] = path[l++];
+    }
+    path[w] = '\0';
+
+    jk_log(logger, JK_LOG_DEBUG, "URI on exiting jk_servlet_normalize: [%s]", 
path);
+    return 0;
+}
+
 #ifdef _MT_CODE_PTHREAD
 jk_pthread_t jk_gettid()
 {

Modified: tomcat/jk/trunk/native/common/jk_util.h
URL: 
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_util.h?rev=1838836&r1=1838835&r2=1838836&view=diff
==============================================================================
--- tomcat/jk/trunk/native/common/jk_util.h (original)
+++ tomcat/jk/trunk/native/common/jk_util.h Fri Aug 24 12:31:54 2018
@@ -250,6 +250,11 @@ int jk_wildchar_match(const char *str, c
 
 void jk_no2slash(char *name);
 
+int jk_servlet_normalize(char *path, jk_logger_t *logger);
+
+#define JK_NORMALIZE_BAD_PATH  -1
+#define JK_NORMALIZE_TRAVERSAL -2
+
 #define TC32_BRIDGE_TYPE    32
 #define TC33_BRIDGE_TYPE    33
 #define TC40_BRIDGE_TYPE    40

Modified: tomcat/jk/trunk/native/iis/jk_isapi_plugin.c
URL: 
http://svn.apache.org/viewvc/tomcat/jk/trunk/native/iis/jk_isapi_plugin.c?rev=1838836&r1=1838835&r2=1838836&view=diff
==============================================================================
--- tomcat/jk/trunk/native/iis/jk_isapi_plugin.c (original)
+++ tomcat/jk/trunk/native/iis/jk_isapi_plugin.c Fri Aug 24 12:31:54 2018
@@ -174,7 +174,6 @@ static char HTTP_WORKER_HEADER_INDEX[RES
 
 #define BAD_REQUEST         -1
 #define BAD_PATH            -2
-#define BAD_NORMALIZATION   -3
 #define MAX_SERVERNAME      1024
 #define MAX_INSTANCEID      32
 
@@ -660,90 +659,6 @@ static int unescape_url(char *url)
         return 0;
 }
 
-static int getparents(char *name)
-{
-    int l, w;
-
-    jk_log(logger, JK_LOG_DEBUG, "URI on entering getparents: [%s]", name);
-
-    // This test allows the loops below to start at index 1 rather than 0.
-    if (name[0] != '/') {
-       return BAD_PATH;
-    }
-
-    /*
-     * First pass.
-     * Collapse ///// sequences to /
-     */
-    for (l = 1, w = 1; name[l] != '\0';) {
-        if (name[w - 1] == '/' && (name[l] == '/')) {
-               l++;
-        }
-        else
-            name[w++] = name[l++];
-    }
-    name[w] = '\0';
-
-    /* Second pass.
-     * Remove /./ segments including those with path parameters such as
-     * /.;foo=bar/
-     * Both leading and trailing segments will be removed.
-     */
-    for (l = 1, w = 1; name[l] != '\0';) {
-        if (name[l] == '.' &&
-                       (name[l + 1] == '/' || name[l + 1] == ';' || name[l + 
1] == '\0') &&
-                               (l == 0 || name[l - 1] == '/')) {
-               l++;
-               while (name[l] != '/' && name[l] != '\0') {
-                       l++;
-               }
-               if (name[l] != '\0') {
-                       l++;
-               }
-        }
-        else
-            name[w++] = name[l++];
-    }
-    name[w] = '\0';
-
-    /* Third pass.
-     * Remove /xx/../ segments including those with path parameters such as
-     * /xxx/..;foo=bar/
-     * Trailing segments will be removed but leading /../ segments are an error
-     * condition.
-     */
-    for (l = 1, w = 1; name[l] != '\0';) {
-        if (name[l] == '.' && name[l + 1] == '.' &&
-                       (name[l + 2] == '/' || name[l + 2] == ';' || name[l + 
2] == '\0') &&
-                               (l == 0 || name[l - 1] == '/')) {
-
-               // Wind w back to remove the previous segment
-               if (w == 1) {
-                       return BAD_NORMALIZATION;
-               }
-               do {
-                       w--;
-               } while (w != 0 && name[w - 1] != '/');
-
-               // Move l forward to the next segment
-               l += 2;
-
-               while (name[l] != '/' && name [l] != '\0') {
-                       l++;
-               }
-               if (name[l] != '\0') {
-                       l++;
-               }
-        }
-        else
-            name[w++] = name[l++];
-    }
-    name[w] = '\0';
-
-    jk_log(logger, JK_LOG_DEBUG, "URI on exiting getparents: [%s]", name);
-    return 0;
-}
-
 /* Apache code to escape a URL */
 
 #define T_OS_ESCAPE_PATH    (4)
@@ -1860,19 +1775,7 @@ static DWORD handle_notify_event(PHTTP_F
         rv = SF_STATUS_REQ_FINISHED;
         goto cleanup;
     }
-    rc = getparents(uri);
-    if (rc == BAD_PATH) {
-        jk_log(logger, JK_LOG_EMERG,
-               "[%s] does not start with '/'.",
-               uri);
-        write_error_response(pfc, 404);
-        rv = SF_STATUS_REQ_FINISHED;
-        goto cleanup;
-    }
-    if (rc == BAD_NORMALIZATION) {
-        jk_log(logger, JK_LOG_EMERG,
-               "[%s] contains a '/../' sequence that tries to escape above the 
root.",
-               uri);
+    if (jk_servlet_normalize(uri, logger)) {
         write_error_response(pfc, 404);
         rv = SF_STATUS_REQ_FINISHED;
         goto cleanup;
@@ -3098,7 +3001,7 @@ static int init_ws_service(isapi_private
             JK_TRACE_EXIT(logger);
             return JK_FALSE;
         }
-        getparents(s->req_uri);
+        jk_servlet_normalize(s->req_uri, logger);
     } else {
         GET_SERVER_VARIABLE_VALUE(HTTP_QUERY_HEADER_NAME, s->query_string, "");
         GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name), "");

Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1838836&r1=1838835&r2=1838836&view=diff
==============================================================================
--- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Fri Aug 24 12:31:54 2018
@@ -78,6 +78,11 @@
         to improve the control over the number of retries. Based on a patch
         provided by Frederik Nosi. (markt)
       </add>
+      <fix>
+        Refactor normalisation of request URIs to a common location and align
+        the normalisation implementation for mod_jk with that implemented by
+        Tomcat. (markt)
+      </fix>
    </changelog>
   </subsection>
 </section>



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to