Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
apache2-mod_jk.9478
apache2-mod_jk-1.2.43-CVE-2018-11759.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File apache2-mod_jk-1.2.43-CVE-2018-11759.patch of Package apache2-mod_jk.9478
commit 75a168cae5409a00340035160e5aa26f64a66def Author: Mark Thomas <markt@apache.org> Date: Fri Aug 24 12:31:54 2018 +0000 Refactor normalisation of request URIs to a common location and align the normalisation implementation for mod_jk with that implemented by Tomcat. git-svn-id: https://svn.apache.org/repos/asf/tomcat/jk/trunk@1838836 13f79535-47bb-0310-9956-ffa450edef68 Index: tomcat-connectors-1.2.43-src/native/apache-2.0/mod_jk.c =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/apache-2.0/mod_jk.c +++ tomcat-connectors-1.2.43-src/native/apache-2.0/mod_jk.c @@ -261,6 +261,7 @@ typedef struct struct jk_request_conf { rule_extension_t *rule_extensions; + char *orig_uri; int jk_handled; }; @@ -722,18 +723,6 @@ static void dump_options(server_rec *srv jk_log(conf->log, JK_LOG_DEBUG, "JkOption '%s' set in server '%s'%s", "RejectUnsafeURI", server_name, JK_OPT_DEFAULT & JK_OPT_REJECTUNSAFE ? " (default)" : ""); - if (options & JK_OPT_COLLAPSEALL) - jk_log(conf->log, JK_LOG_DEBUG, "JkOption '%s' set in server '%s'%s", - "CollapseSlashesAll", server_name, - JK_OPT_DEFAULT & JK_OPT_COLLAPSEALL ? " (default)" : ""); - if (options & JK_OPT_COLLAPSENONE) - jk_log(conf->log, JK_LOG_DEBUG, "JkOption '%s' set in server '%s'%s", - "CollapseSlashesNone", server_name, - JK_OPT_DEFAULT & JK_OPT_COLLAPSENONE ? " (default)" : ""); - if (options & JK_OPT_COLLAPSEUNMOUNT) - jk_log(conf->log, JK_LOG_DEBUG, "JkOption '%s' set in server '%s'%s", - "CollapseSlashesUnmount", server_name, - JK_OPT_DEFAULT & JK_OPT_COLLAPSEUNMOUNT ? " (default)" : ""); } /* ========================================================================= */ @@ -819,6 +808,7 @@ static int init_ws_service(apache_privat int size; request_rec *r = private_data->r; char *ssl_temp = NULL; + char *uri = NULL; const char *reply_timeout = NULL; const char *sticky_ignore = NULL; const char *stateless = NULL; @@ -1009,6 +999,8 @@ static int init_ws_service(apache_privat * uri is use for compatibilty with mod_rewrite with old Tomcats */ + uri = rconf->orig_uri ? rconf->orig_uri : r->uri; + switch (conf->options & JK_OPT_FWDURIMASK) { case JK_OPT_FWDURICOMPATUNPARSED: @@ -1023,17 +1015,17 @@ static int init_ws_service(apache_privat break; case JK_OPT_FWDURICOMPAT: - s->req_uri = r->uri; + s->req_uri = uri; break; case JK_OPT_FWDURIPROXY: - size = 3 * (int)strlen(r->uri) + 1; + size = 3 * (int)strlen(uri) + 1; s->req_uri = apr_palloc(r->pool, size); - jk_canonenc(r->uri, s->req_uri, size); + jk_canonenc(uri, s->req_uri, size); break; case JK_OPT_FWDURIESCAPED: - s->req_uri = ap_escape_uri(r->pool, r->uri); + s->req_uri = ap_escape_uri(r->pool, uri); break; default: @@ -2316,11 +2308,10 @@ static const char *jk_set_options(cmd_pa mask = 0; if (action == '-' && - (!strncasecmp(w, "ForwardURI", strlen("ForwardURI")) || - !strncasecmp(w, "CollapseSlashes", strlen("CollapseSlashes")))) + (!strncasecmp(w, "ForwardURI", strlen("ForwardURI")))) { return apr_pstrcat(cmd->pool, "JkOptions: Illegal option '-", w, "': option can not be disabled", NULL); - + } if (!strcasecmp(w, "ForwardURICompat")) { opt = JK_OPT_FWDURICOMPAT; mask = JK_OPT_FWDURIMASK; @@ -2751,6 +2742,15 @@ static int jk_handler(request_rec * r) return DECLINED; } + rconf = (jk_request_conf_t *)ap_get_module_config(r->request_config, &jk_module); + if (rconf == NULL) { + rconf = apr_palloc(r->pool, sizeof(jk_request_conf_t)); + rconf->jk_handled = JK_FALSE; + rconf->rule_extensions = NULL; + rconf->orig_uri = NULL; + ap_set_module_config(r->request_config, &jk_module, rconf); + } + worker_name = apr_table_get(r->notes, JK_NOTE_WORKER_NAME); if (worker_name == NULL) { @@ -2774,8 +2774,6 @@ static int jk_handler(request_rec * r) worker_name_extension = JK_TRUE; parse_rule_extensions(w, e, xconf->log); worker_name = w; - rconf = (jk_request_conf_t *)ap_get_module_config(r->request_config, - &jk_module); rconf->rule_extensions = e; } } @@ -2800,11 +2798,20 @@ static int jk_handler(request_rec * r) } else { rule_extension_t *e; - worker_name = map_uri_to_worker_ext(xconf->uw_map, r->uri, + char *clean_uri; + clean_uri = apr_pstrdup(r->pool, r->uri); + rc = jk_servlet_normalize(clean_uri, xconf->log); + if (rc != 0) { + return HTTP_BAD_REQUEST; + } + + worker_name = map_uri_to_worker_ext(xconf->uw_map, clean_uri, NULL, &e, NULL, xconf->log); - rconf = (jk_request_conf_t *)ap_get_module_config(r->request_config, - &jk_module); - rconf->rule_extensions = e; + if (worker_name) { + rconf->rule_extensions = e; + rconf->orig_uri = r->uri; + r->uri = clean_uri; + } } if (worker_name == NULL && worker_env.num_of_workers) { @@ -2824,8 +2831,6 @@ static int jk_handler(request_rec * r) " r->proxyreq=%d", r->handler, STRNULL_FOR_NULL(worker_name), r->proxyreq); - rconf = (jk_request_conf_t *)ap_get_module_config(r->request_config, - &jk_module); rconf->jk_handled = JK_TRUE; /* If this is a proxy request, we'll notify an error */ @@ -3702,21 +3707,9 @@ static int jk_post_config(apr_pool_t * p uri_worker_map_switch(sconf->uw_map, sconf->log); uri_worker_map_load(sconf->uw_map, sconf->log); } - switch (sconf->options & JK_OPT_COLLAPSEMASK) { - case JK_OPT_COLLAPSEALL: - sconf->uw_map->collapse_slashes = JK_COLLAPSE_ALL; - break; - case JK_OPT_COLLAPSENONE: - sconf->uw_map->collapse_slashes = JK_COLLAPSE_NONE; - break; - case JK_OPT_COLLAPSEUNMOUNT: - sconf->uw_map->collapse_slashes = JK_COLLAPSE_UNMOUNT; - break; - default: + if (sconf->options & JK_OPT_COLLAPSEMASK) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "Collapse slashes value %d ignored, setting to %d", - sconf->options & JK_OPT_COLLAPSEMASK, JK_COLLAPSE_DEFAULT); - sconf->uw_map->collapse_slashes = JK_COLLAPSE_DEFAULT; + "Deprecated CollapseSlashes setting ignored"); } } else { @@ -3790,6 +3783,7 @@ static int jk_translate(request_rec * r) jk_request_conf_t *rconf = apr_palloc(r->pool, sizeof(jk_request_conf_t)); rconf->jk_handled = JK_FALSE; rconf->rule_extensions = NULL; + rconf->orig_uri = NULL; ap_set_module_config(r->request_config, &jk_module, rconf); if (!r->proxyreq) { @@ -3799,7 +3793,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 @@ -3819,6 +3816,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_BAD_REQUEST; + } + /* 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. */ @@ -3828,11 +3831,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; @@ -3864,10 +3864,13 @@ 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); + if (worker) { + rconf->rule_extensions = e; + rconf->orig_uri = r->uri; + r->uri = clean_uri; + } } if (worker) { @@ -3884,8 +3887,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, @@ -3993,6 +3994,7 @@ static int jk_map_to_storage(request_rec rconf = apr_palloc(r->pool, sizeof(jk_request_conf_t)); rconf->jk_handled = JK_FALSE; rconf->rule_extensions = NULL; + rconf->orig_uri = NULL; ap_set_module_config(r->request_config, &jk_module, rconf); } @@ -4003,7 +4005,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 @@ -4022,6 +4027,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_BAD_REQUEST; + } + if (!conf->uw_map) { if (JK_IS_DEBUG_LEVEL(conf->log)) jk_log(conf->log, JK_LOG_DEBUG, @@ -4032,10 +4044,13 @@ 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); + if (worker) { + rconf->rule_extensions = e; + rconf->orig_uri = r->uri; + r->uri = clean_uri; + } } if (worker) { @@ -4052,23 +4067,12 @@ static int jk_map_to_storage(request_rec jk_log(conf->log, JK_LOG_DEBUG, "no match for %s found", r->uri); - if (conf->strip_session == JK_TRUE && - conf->strip_session_name) { - char *jsessionid; + if (conf->strip_session == JK_TRUE && conf->strip_session_name) { if (r->uri) { - jsessionid = strstr(r->uri, conf->strip_session_name); - if (jsessionid) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "removing session identifier [%s] for non servlet url [%s]", - jsessionid, r->uri); - *jsessionid = '\0'; - } + jk_strip_session_id(r->uri, conf->strip_session_name, conf->log); } if (r->filename) { - jsessionid = strstr(r->filename, conf->strip_session_name); - if (jsessionid) - *jsessionid = '\0'; + jk_strip_session_id(r->filename, conf->strip_session_name, conf->log); } return DECLINED; } Index: tomcat-connectors-1.2.43-src/native/common/jk_util.c =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_util.c +++ tomcat-connectors-1.2.43-src/native/common/jk_util.c @@ -1860,7 +1860,7 @@ static int jk_is_some_property(const cha size_t suffix_len = strlen(suffix); size_t sep_len = strlen(sep); size_t sep_off = sep_len + suffix_len; - + if (prp_name_len >= sep_off) { if (!strncmp(prp_name + prp_name_len - sep_off, sep, sep_len) && !strncmp(prp_name + prp_name_len - suffix_len, suffix, suffix_len)) { @@ -2193,23 +2193,147 @@ int jk_wildchar_match(const char *str, c return (str[x] != '\0'); } -void jk_no2slash(char *name) +int jk_servlet_normalize(char *path, jk_logger_t *logger) { - char *d, *s; + int l, w; + + if (JK_IS_DEBUG_LEVEL(logger)) { + 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] != '/') { + if (path[0] == '*' && path[1] == '\0') { + /* Most likely an "OPTIONS *" request */ + return 0; + } + jk_log(logger, JK_LOG_WARNING, "Uri [%s] does not start with '/'.", path); + return JK_NORMALIZE_BAD_PATH; + } + + /* First pass. + * Remove path parameters ;foo=bar/ from any path segment + */ + for (l = 1, w = 1; path[l] != '\0';) { + if (path[l] == ';') { + l++; + while (path[l] != '/' && path[l] != '\0') { + l++; + } + } + else + path[w++] = path[l++]; + } + path[w] = '\0'; - s = d = name; + /* + * Second 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'; + + /* Third pass. + * Remove /./ segments + * 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] == '\0') && + (l == 0 || path[l - 1] == '/')) { + l++; + if (path[l] == '/') { + l++; + } + } + else + path[w++] = path[l++]; + } + path[w] = '\0'; - while (*s) { - if ((*d++ = *s) == '/') { + /* Fourth pass. + * Remove /xx/../ segments + * 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] == '\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 { - ++s; - } while (*s == '/'); + w--; + } while (w != 0 && path[w - 1] != '/'); + + // Move l forward to the next segment + l += 2; + + if (path[l] == '/') { + l++; + } } - else { - ++s; + else + path[w++] = path[l++]; + } + path[w] = '\0'; + + if (JK_IS_DEBUG_LEVEL(logger)) { + jk_log(logger, JK_LOG_DEBUG, "URI on exiting jk_servlet_normalize: [%s]", path); + } + + return 0; +} + +int jk_strip_session_id(char* path, char* session_name, jk_logger_t *logger) { + + char *jsessionid; + + jsessionid = strstr(path, session_name); + if (jsessionid) { + int i; + int j; + if (JK_IS_DEBUG_LEVEL(logger)) { + jk_log(logger, JK_LOG_DEBUG, + "removing session identifier for non servlet uri [%s]", path); + } + // Found a session path parameter. + // Need to skip at least as many characters as there are in + // strip_session_name + i = (int) strlen(session_name); + j = 0; + // Increment i until the first character after the parameter + while (jsessionid[i] != '\0' && jsessionid[i] != ';' && jsessionid[i] != '/') { + i++; + } + // Copy until the end + while (jsessionid[i] != '\0') { + jsessionid[j++] = jsessionid[i++]; + } + // Terminate + jsessionid[j] = '\0'; + + if (JK_IS_DEBUG_LEVEL(logger)) { + jk_log(logger, JK_LOG_DEBUG, + "result of removing session identifier for non servlet uri is [%s]", path); } + return 1; } - *d = '\0'; + + return 0; } #ifdef _MT_CODE_PTHREAD Index: tomcat-connectors-1.2.43-src/native/common/jk_util.h =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_util.h +++ tomcat-connectors-1.2.43-src/native/common/jk_util.h @@ -60,7 +60,7 @@ int jk_log(jk_logger_t *l, int jk_check_attribute_length(const char *name, const char *value, jk_logger_t *l); - + const char *jk_get_worker_host(jk_map_t *m, const char *wname, const char *def); const char *jk_get_worker_source(jk_map_t *m, const char *wname, const char *def); @@ -190,7 +190,7 @@ int jk_is_unique_property(const char *pr int jk_is_deprecated_property(const char *prp_name); int jk_check_buffer_size(); - + int jk_is_valid_property(const char *prp_name); int jk_get_worker_stdout(jk_map_t *m, const char *wname, const char **stdout_name); @@ -248,7 +248,12 @@ int is_http_status_fail(unsigned int htt int jk_wildchar_match(const char *str, const char *exp, int icase); -void jk_no2slash(char *name); +int jk_servlet_normalize(char *path, jk_logger_t *logger); + +int jk_strip_session_id(char* path, char* session_name, 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 Index: tomcat-connectors-1.2.43-src/native/iis/jk_isapi_plugin.c =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/iis/jk_isapi_plugin.c +++ tomcat-connectors-1.2.43-src/native/iis/jk_isapi_plugin.c @@ -133,9 +133,6 @@ static char HTTP_WORKER_HEADER_INDEX[RES #define AUTH_COMPLETE_TAG "auth_complete" #define REJECT_UNSAFE_TAG "reject_unsafe" #define COLLAPSE_SLASHES_TAG "collapse_slashes" -#define COLLAPSE_SLASHES_ALL_VERB "all" -#define COLLAPSE_SLASHES_NONE_VERB "none" -#define COLLAPSE_SLASHES_UNMOUNT_VERB "unmount" #define WATCHDOG_INTERVAL_TAG "watchdog_interval" #define ENABLE_CHUNKED_ENCODING_TAG "enable_chunked_encoding" #define ERROR_PAGE_TAG "error_page" @@ -174,7 +171,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 @@ -511,7 +507,6 @@ static int strip_session = 0; static int use_auth_notification_flags = 1; static int chunked_encoding_enabled = JK_FALSE; static int reject_unsafe = 0; -static int collapse_slashes = JK_COLLAPSE_DEFAULT; static volatile int watchdog_interval = 0; static HANDLE watchdog_handle = NULL; static char error_page_buf[INTERNET_MAX_URL_LENGTH] = {0}; @@ -660,90 +655,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) @@ -1821,7 +1732,8 @@ static DWORD handle_notify_event(PHTTP_F jk_pool_t pool; char *uri_undec = NULL; - char *uri = NULL; + char *cleanuri = NULL; + char *uri = NULL; char *host = NULL; char *translate = NULL; char szHB[HDR_BUFFER_SIZE] = "/"; @@ -1869,10 +1781,10 @@ static DWORD handle_notify_event(PHTTP_F else query = NULL; } - if (uri_select_option == URI_SELECT_OPT_UNPARSED) { - /* Duplicate unparsed uri */ - uri_undec = jk_pool_strdup(&pool, uri); - } + + /* Duplicate unparsed uri */ + uri_undec = jk_pool_strdup(&pool, uri); + rc = unescape_url(uri); if (rc == BAD_REQUEST) { jk_log(logger, JK_LOG_ERROR, @@ -1890,19 +1802,8 @@ 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); + cleanuri = jk_pool_strdup(&pool, uri); + if (jk_servlet_normalize(cleanuri, logger)) { write_error_response(pfc, 404); rv = SF_STATUS_REQ_FINISHED; goto cleanup; @@ -1918,7 +1819,7 @@ static DWORD handle_notify_event(PHTTP_F else host = szHB; } - worker = map_uri_to_worker_ext(uw_map, uri, host, + worker = map_uri_to_worker_ext(uw_map, cleanuri, host, &extensions, &worker_index, logger); /* * Check if somebody is feading us with his own TOMCAT data headers. @@ -2074,18 +1975,11 @@ static DWORD handle_notify_event(PHTTP_F } else { if (JK_IS_DEBUG_LEVEL(logger)) - jk_log(logger, JK_LOG_DEBUG, - "[%s] is not a servlet url", uri); + jk_log(logger, JK_LOG_DEBUG, "[%s] is not a servlet url", uri_undec); if (strip_session) { - char *jsessionid = strstr(uri, JK_PATH_SESSION_IDENTIFIER); - if (jsessionid) { - if (JK_IS_DEBUG_LEVEL(logger)) - jk_log(logger, JK_LOG_DEBUG, - "removing session identifier [%s] for non servlet url [%s]", - jsessionid, uri); - *jsessionid = '\0'; - pfp->SetHeader(pfc, "url", uri); - } + if (jk_strip_session_id(uri_undec, JK_PATH_SESSION_IDENTIFIER, logger)) { + pfp->SetHeader(pfc, "url", uri_undec); + } } } cleanup: @@ -2229,7 +2123,7 @@ DWORD WINAPI HttpExtensionProc(LPEXTENSI lpEcb->ServerSupportFunction(lpEcb->ConnID, HSE_REQ_SET_FLUSH_FLAG, (LPVOID) TRUE, NULL, NULL); } - + if (init_ws_service(&private_data, &s, &worker_name)) { jk_endpoint_t *e = NULL; jk_worker_t *worker = wc_get_worker_for_name(worker_name, logger); @@ -2743,7 +2637,6 @@ static int init_jk(char *serverName) uw_map->reject_unsafe = 1; else uw_map->reject_unsafe = 0; - uw_map->collapse_slashes = collapse_slashes; uw_map->reload = worker_mount_reload; if (worker_mount_file[0]) { uw_map->fname = worker_mount_file; @@ -2873,17 +2766,6 @@ int parse_uri_select(const char *uri_sel return -1; } -int parse_collapse_slashes(const char *collapse_slashes) -{ - if (!strcasecmp(collapse_slashes, COLLAPSE_SLASHES_ALL_VERB)) - return JK_COLLAPSE_ALL; - if (!strcasecmp(collapse_slashes, COLLAPSE_SLASHES_NONE_VERB)) - return JK_COLLAPSE_NONE; - if (!strcasecmp(collapse_slashes, COLLAPSE_SLASHES_UNMOUNT_VERB)) - return JK_COLLAPSE_UNMOUNT; - return -1; -} - static int read_registry_init_data(void) { char tmpbuf[MAX_PATH]; @@ -2993,14 +2875,8 @@ static int read_registry_init_data(void) } } if (get_config_parameter(src, COLLAPSE_SLASHES_TAG, tmpbuf, sizeof(tmpbuf))) { - int opt = parse_collapse_slashes(tmpbuf); - if (opt >= 0) { - collapse_slashes = opt; - } - else { - jk_log(logger, JK_LOG_ERROR, "Invalid value '%s' for configuration item '" - COLLAPSE_SLASHES_TAG "'", tmpbuf); - } + jk_log(logger, JK_LOG_ERROR, "Configuration item '" COLLAPSE_SLASHES_TAG + "' is deprecated and will be ignored"); } shm_config_size = get_config_int(src, SHM_SIZE_TAG, -1); worker_mount_reload = get_config_int(src, WORKER_MOUNT_RELOAD_TAG, JK_URIMAP_DEF_RELOAD); @@ -3144,7 +3020,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), ""); Index: tomcat-connectors-1.2.43-src/xdocs/miscellaneous/changelog.xml =================================================================== --- tomcat-connectors-1.2.43-src.orig/xdocs/miscellaneous/changelog.xml +++ tomcat-connectors-1.2.43-src/xdocs/miscellaneous/changelog.xml @@ -427,6 +427,26 @@ <update> Minor documentation improvements. (rjung) </update> + <scode> + Common: Optimize path parameter handling. (rjung) + </scode> + <fix> + Improve path parameter parsing so that the session ID specified by the + <code>session_path</code> worker property for load-balanced workers can + be extracted from a path parameter in any segment of the URI, rather + than only from the final segment. (markt) + </fix> + <fix> + Apache: Improve path parameter handling so that + <code>JkStripSession</code> can remove session IDs that are specified on + path parameters in any segment of the URI rather than only the final + segment. (markt) + </fix> + <fix> + IIS: Improve path parameter handling so that <code>strip_session</code> + can remove session IDs that are specified on path parameters in any + segment of the URI rather than only the final segment. (markt) + </fix> </changelog> </subsection> </section> Index: tomcat-connectors-1.2.43-src/native/common/jk_uri_worker_map.c =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_uri_worker_map.c +++ tomcat-connectors-1.2.43-src/native/common/jk_uri_worker_map.c @@ -176,10 +176,9 @@ static void uri_worker_map_dump(jk_uri_w int i, off; if (JK_IS_DEBUG_LEVEL(l)) { jk_log(l, JK_LOG_DEBUG, "uri map dump %s: id=%d, index=%d file='%s' reject_unsafe=%d " - "collapse_slashes=%d reload=%d modified=%d checked=%d", + "reload=%d modified=%d checked=%d", reason, uw_map->id, uw_map->index, STRNULL_FOR_NULL(uw_map->fname), - uw_map->reject_unsafe, uw_map->collapse_slashes, - uw_map->reload, uw_map->modified, uw_map->checked); + uw_map->reject_unsafe, uw_map->reload, uw_map->modified, uw_map->checked); } for (i = 0; i <= 1; i++) { jk_log(l, JK_LOG_DEBUG, "generation %d: size=%d nosize=%d capacity=%d", @@ -245,7 +244,6 @@ int uri_worker_map_alloc(jk_uri_worker_m uw_map->index = 0; uw_map->fname = NULL; uw_map->reject_unsafe = 0; - uw_map->collapse_slashes = JK_COLLAPSE_DEFAULT; uw_map->reload = JK_URIMAP_DEF_RELOAD; uw_map->modified = 0; uw_map->checked = 0; @@ -1074,7 +1072,6 @@ const char *map_uri_to_worker_ext(jk_uri unsigned int i; unsigned int vhost_len; int reject_unsafe; - int collapse_slashes; size_t uri_len; size_t remain; int rv = -1; @@ -1115,7 +1112,6 @@ const char *map_uri_to_worker_ext(jk_uri } } reject_unsafe = uw_map->reject_unsafe; - collapse_slashes = uw_map->collapse_slashes; vhost_len = 0; /* * In case we got a vhost, we prepend a slash @@ -1143,8 +1139,8 @@ const char *map_uri_to_worker_ext(jk_uri } vhost_len += off; } - /* Make the copy of the provided uri and strip - * everything after the first ';' char. + /* Make the copy of the provided uri, check length + * and look for potentially unsafe constructs */ uri_len = strlen(uri); remain = JK_MAX_URI_LEN - vhost_len; @@ -1156,15 +1152,11 @@ const char *map_uri_to_worker_ext(jk_uri JK_TRACE_EXIT(l); return NULL; } - if (uri[i] == ';') - break; - else { - url[i + vhost_len] = uri[i]; - if (reject_unsafe && (uri[i] == '%' || uri[i] == '\\')) { - jk_log(l, JK_LOG_INFO, "Potentially unsafe request url '%s' rejected", uri); - JK_TRACE_EXIT(l); - return NULL; - } + url[i + vhost_len] = uri[i]; + if (reject_unsafe && (uri[i] == '%' || uri[i] == '\\')) { + jk_log(l, JK_LOG_INFO, "Potentially unsafe request url '%s' rejected", uri); + JK_TRACE_EXIT(l); + return NULL; } } url[i + vhost_len] = '\0'; @@ -1175,12 +1167,6 @@ const char *map_uri_to_worker_ext(jk_uri jk_log(l, JK_LOG_DEBUG, "Found session identifier '%s' in url '%s'", url_rewrite, uri); } - if (collapse_slashes == JK_COLLAPSE_ALL) { - /* Remove multiple slashes - * No need to copy url, because it is local and - * the unchanged url is no longer needed */ - jk_no2slash(url); - } if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Attempting to map URI '%s' from %d maps", url, IND_THIS(uw_map->size)); @@ -1193,13 +1179,6 @@ const char *map_uri_to_worker_ext(jk_uri /* In case we found a match, check for the unmounts. */ if (rv >= 0 && IND_THIS(uw_map->nosize)) { int rc; - if (collapse_slashes == JK_COLLAPSE_UNMOUNT) { - /* Remove multiple slashes when looking for - * unmount to prevent trivial unmount bypass attack. - * No need to copy url, because it is local and - * the unchanged url is no longer needed */ - jk_no2slash(url); - } /* Again first including vhost. */ rc = is_nomatch(uw_map, url, rv, l); /* If no unmount was found, try without vhost. */ Index: tomcat-connectors-1.2.43-src/native/common/jk_global.h =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_global.h +++ tomcat-connectors-1.2.43-src/native/common/jk_global.h @@ -292,7 +292,7 @@ extern "C" #define JK_OPT_COLLAPSENONE 0x2000 #define JK_OPT_COLLAPSEUNMOUNT 0x4000 -#define JK_OPT_DEFAULT (JK_OPT_FWDURIDEFAULT | JK_OPT_FWDKEYSIZE | JK_OPT_COLLAPSEUNMOUNT) +#define JK_OPT_DEFAULT (JK_OPT_FWDURIDEFAULT | JK_OPT_FWDKEYSIZE) /* Check for EBCDIC systems */ Index: tomcat-connectors-1.2.43-src/native/common/jk_uri_worker_map.h =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_uri_worker_map.h +++ tomcat-connectors-1.2.43-src/native/common/jk_uri_worker_map.h @@ -58,11 +58,6 @@ extern "C" #define MATCH_TYPE_STOPPED 0x4000 */ -#define JK_COLLAPSE_ALL 0x0001 -#define JK_COLLAPSE_NONE 0x0002 -#define JK_COLLAPSE_UNMOUNT 0x0003 -#define JK_COLLAPSE_DEFAULT JK_COLLAPSE_UNMOUNT - #define SOURCE_TYPE_WORKERDEF 0x0001 #define SOURCE_TYPE_JKMOUNT 0x0002 #define SOURCE_TYPE_URIMAP 0x0003 @@ -172,9 +167,7 @@ struct jk_uri_worker_map JK_CRIT_SEC cs; /* should we forward potentially unsafe URLs */ - int reject_unsafe; - /* how to handle multiple adjacent slashes in URLs */ - int collapse_slashes; + int reject_unsafe; /* uriworkermap filename */ const char *fname; /* uriworkermap reload check interval */ Index: tomcat-connectors-1.2.43-src/native/common/jk_lb_worker.c =================================================================== --- tomcat-connectors-1.2.43-src.orig/native/common/jk_lb_worker.c +++ tomcat-connectors-1.2.43-src/native/common/jk_lb_worker.c @@ -431,8 +431,7 @@ void jk_lb_push(lb_worker_t *p, int lock static char *get_path_param(jk_ws_service_t *s, const char *name) { char *id_start = NULL; - for (id_start = strstr(s->req_uri, name); - id_start; id_start = strstr(id_start + 1, name)) { + for (id_start = strstr(s->req_uri, name); id_start; id_start = strstr(id_start + 1, name)) { if (id_start[strlen(name)] == '=') { /* * Session path-cookie was found, get it's value @@ -455,6 +454,12 @@ static char *get_path_param(jk_ws_servic if ((id_end = strchr(id_start, ';')) != NULL) { *id_end = '\0'; } + /* + * Remove any trailing URI segments. + */ + if ((id_end = strchr(id_start, '/')) != NULL) { + *id_end = '\0'; + } return id_start; } } @@ -1225,9 +1230,11 @@ static int JK_METHOD service(jk_endpoint if (p->worker->sequence < p->worker->s->h.sequence) jk_lb_pull(p->worker, JK_FALSE, l); for (i = 0; i < num_of_workers; i++) { + lb_sub_worker_t *rec; + ajp_worker_t *aw; jk_log(l, JK_LOG_DEBUG, "LB - num_of_workers: %d, retry: %d, lb_retries: %d", num_of_workers, i, p->worker->lb_retries); - lb_sub_worker_t *rec = &(p->worker->lb_workers[i]); - ajp_worker_t *aw = (ajp_worker_t *)rec->worker->worker_private; + rec = &(p->worker->lb_workers[i]); + aw = (ajp_worker_t *)rec->worker->worker_private; if (rec->s->state == JK_LB_STATE_BUSY) { if ((aw->busy_limit <= 0 || aw->s->busy < aw->busy_limit) && ajp_has_endpoint(rec->worker, l)) { @@ -1764,7 +1771,7 @@ static int JK_METHOD validate(jk_worker_ jk_log(l, JK_LOG_DEBUG, "Balanced worker %s already configured (sequence=%d)", p->lb_workers[i].name, p->lb_workers[i].s->h.sequence); - } + } if (!wc_create_worker(p->lb_workers[i].name, 0, props, &(p->lb_workers[i].worker),
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor