Author: markt
Date: Thu Mar 1 16:04:50 2018
New Revision: 1825658
URL: http://svn.apache.org/viewvc?rev=1825658&view=rev
Log:
Align the normalization performed by the ISAPI redirector with that implemented
by Tomcat.
Modified:
tomcat/jk/trunk/native/iis/jk_isapi_plugin.c
tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
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=1825658&r1=1825657&r2=1825658&view=diff
==============================================================================
--- tomcat/jk/trunk/native/iis/jk_isapi_plugin.c (original)
+++ tomcat/jk/trunk/native/iis/jk_isapi_plugin.c Thu Mar 1 16:04:50 2018
@@ -172,10 +172,11 @@ static char HTTP_WORKER_HEADER_INDEX[RES
#define CHUNKED_ENCODING_TRAILER "0\r\n\r\n"
#define CHUNKED_ENCODING_TRAILER_LEN 5
-#define BAD_REQUEST -1
-#define BAD_PATH -2
-#define MAX_SERVERNAME 1024
-#define MAX_INSTANCEID 32
+#define BAD_REQUEST -1
+#define BAD_PATH -2
+#define BAD_NORMALIZATION -3
+#define MAX_SERVERNAME 1024
+#define MAX_INSTANCEID 32
char HTML_ERROR_HEAD[] = "<!--\n"
" Licensed to the Apache Software Foundation
(ASF) under one or more\n"
@@ -659,69 +660,88 @@ static int unescape_url(char *url)
return 0;
}
-static void getparents(char *name)
+static int getparents(char *name)
{
int l, w;
- /* Four paseses, as per RFC 1808 */
- /* a) remove ./ path segments */
+ jk_log(logger, JK_LOG_DEBUG, "URI on entering getparents: [%s]", name);
- for (l = 0, w = 0; name[l] != '\0';) {
- if (name[l] == '.' && name[l + 1] == '/'
- && (l == 0 || name[l - 1] == '/'))
- l += 2;
+ // 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++];
}
-
- /* b) remove trailing . path, segment */
- if (w == 1 && name[0] == '.')
- w--;
- else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
- w--;
name[w] = '\0';
- /* c) 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++;
- }
+ /* 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
- ++l;
+ name[w++] = name[l++];
}
+ name[w] = '\0';
- /* d) 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++;
+ /* 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
- l = 0;
- name[l] = '\0';
+ 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 */
@@ -1870,7 +1890,23 @@ static DWORD handle_notify_event(PHTTP_F
rv = SF_STATUS_REQ_FINISHED;
goto cleanup;
}
- getparents(uri);
+ 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);
+ write_error_response(pfc, 404);
+ rv = SF_STATUS_REQ_FINISHED;
+ goto cleanup;
+ }
len = ISIZEOF(szHB) - 1;
if (pfc->GetServerVariable(pfc, "SERVER_NAME", &szHB[1], &len) && len > 1)
{
len = ISIZEOF(szPB);
Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1825658&r1=1825657&r2=1825658&view=diff
==============================================================================
--- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Thu Mar 1 16:04:50 2018
@@ -64,6 +64,10 @@
Update the ISAPI redirector installation documentation to reflect the
currently supported versions of Windows. (markt)
</fix>
+ <fix>
+ Align the normalization performed by the ISAPI redirector with that
+ implemented by Tomcat. (markt)
+ </fix>
</changelog>
</subsection>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]