You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by la...@apache.org on 2001/10/01 02:27:11 UTC
cvs commit: jakarta-tomcat/src/native/mod_jk/iis jk_isapi_plugin.c
larryi 01/09/30 17:27:11
Modified: src/native/mod_jk/iis jk_isapi_plugin.c
Log:
Port Apache routines to decode and normalize the URI from IIS. Also, block
access to META-INF and refactor the error response handling a little.
Revision Changes Path
1.9 +158 -20 jakarta-tomcat/src/native/mod_jk/iis/jk_isapi_plugin.c
Index: jk_isapi_plugin.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/iis/jk_isapi_plugin.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- jk_isapi_plugin.c 2001/09/22 21:08:16 1.8
+++ jk_isapi_plugin.c 2001/10/01 00:27:11 1.9
@@ -57,7 +57,7 @@
* Description: ISAPI plugin for IIS/PWS *
* Author: Gal Shachor <sh...@il.ibm.com> *
* Author: Ignacio J. Ortega <na...@apache.org> *
- * Version: $Revision: 1.8 $ *
+ * Version: $Revision: 1.9 $ *
***************************************************************************/
// This define is needed to include wincrypt,h, needed to get client certificates
@@ -96,6 +96,9 @@
#define REGISTRY_LOCATION ("Software\\Apache Software Foundation\\Jakarta Isapi Redirector\\1.0")
#define EXTENSION_URI_TAG ("extension_uri")
+#define BAD_REQUEST -1
+#define BAD_PATH -2
+
#define GET_SERVER_VARIABLE_VALUE(name, place) { \
(place) = NULL; \
huge_buf_sz = sizeof(huge_buf); \
@@ -189,6 +192,108 @@
int len);
+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 (!isxdigit(url[y + 1]) || !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 getparents(char *name)
+{
+ int l, w;
+
+ /* Four paseses, as per RFC 1808 */
+ /* a) 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++];
+ }
+
+ /* 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]))
+ (++n, ++m);
+ }
+ else
+ ++l;
+ }
+
+ /* 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++;
+ }
+ else
+ l = 0;
+ name[l] = '\0';
+ }
+}
+
static int uri_is_web_inf(char *uri)
{
char *c = uri;
@@ -199,10 +304,34 @@
if(strstr(uri, "web-inf")) {
return JK_TRUE;
}
+ if(strstr(uri, "meta-inf")) {
+ return JK_TRUE;
+ }
return JK_FALSE;
}
+static void write_error_response(PHTTP_FILTER_CONTEXT pfc,char *status,char * msg)
+{
+ char crlf[3] = { (char)13, (char)10, '\0' };
+ char ctype[30];
+ DWORD len = strlen(msg);
+
+ sprintf(ctype,
+ "Content-Type:text/html%s%s",
+ crlf,
+ crlf);
+
+ /* reject !!! */
+ pfc->ServerSupportFunction(pfc,
+ SF_REQ_SEND_RESPONSE_HEADER,
+ status,
+ (DWORD)crlf,
+ (DWORD)ctype);
+ pfc->WriteClient(pfc, msg, &len, 0);
+}
+
+
static int JK_METHOD start_response(jk_ws_service_t *s,
int status,
const char *reason,
@@ -439,11 +568,32 @@
}
if(strlen(uri)) {
+ int rc;
char *worker=0;
query = strchr(uri, '?');
if(query) {
*query = '\0';
}
+
+ rc = unescape_url(uri);
+ if (rc == BAD_REQUEST) {
+ jk_log(logger, JK_LOG_ERROR,
+ "HttpFilterProc [%s] contains on or more invalid escape sequences.\n",
+ uri);
+ write_error_response(pfc,"400 Bad Request",
+ "<HTML><BODY><H1>Request contains invalid encoding</H1></BODY></HTML>");
+ return SF_STATUS_REQ_FINISHED;
+ }
+ else if(rc == BAD_PATH) {
+ jk_log(logger, JK_LOG_EMERG,
+ "HttpFilterProc [%s] contains forbidden escape sequences.\n",
+ uri);
+ write_error_response(pfc,"403 Forbidden",
+ "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>");
+ return SF_STATUS_REQ_FINISHED;
+ }
+ getparents(uri);
+
if(p->GetHeader(pfc, "Host:", (LPVOID)Host, (LPDWORD)&szHost)) {
strcat(snuri,Host);
strcat(snuri,uri);
@@ -491,28 +641,12 @@
uri);
if(uri_is_web_inf(uri)) {
- char crlf[3] = { (char)13, (char)10, '\0' };
- char ctype[30];
- char *msg = "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>";
- DWORD len = strlen(msg);
-
jk_log(logger, JK_LOG_EMERG,
- "HttpFilterProc [%s] points to the web-inf directory.\nSomebody try to hack into the site!!!\n",
+ "HttpFilterProc [%s] points to the web-inf or meta-inf directory.\nSomebody try to hack into the site!!!\n",
uri);
-
- sprintf(ctype,
- "Content-Type:text/html%s%s",
- crlf,
- crlf);
-
- /* reject !!! */
- pfc->ServerSupportFunction(pfc,
- SF_REQ_SEND_RESPONSE_HEADER,
- "403 Forbidden",
- (DWORD)crlf,
- (DWORD)ctype);
- pfc->WriteClient(pfc, msg, &len, 0);
+ write_error_response(pfc,"403 Forbidden",
+ "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>");
return SF_STATUS_REQ_FINISHED;
}
}
@@ -867,6 +1001,9 @@
s->query_string = private_data->lpEcb->lpszQueryString;
*worker_name = JK_AJP12_WORKER_NAME;
GET_SERVER_VARIABLE_VALUE("URL", s->req_uri);
+ if (unescape_url(s->req_uri) < 0)
+ return JK_FALSE;
+ getparents(s->req_uri);
}
GET_SERVER_VARIABLE_VALUE("AUTH_TYPE", s->auth_type);
@@ -1164,3 +1301,4 @@
*p++ = '\0';
return p - encoded;
}
+