Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:Update
apache2-mod_jk.15111
apache2-mod_jk-CVE-2014-8111.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File apache2-mod_jk-CVE-2014-8111.patch of Package apache2-mod_jk.15111
Index: tomcat-connectors-1.2.40-src/native/apache-2.0/mod_jk.c =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/apache-2.0/mod_jk.c +++ tomcat-connectors-1.2.40-src/native/apache-2.0/mod_jk.c @@ -2188,9 +2188,11 @@ static const char *jk_set_options(cmd_pa mask = 0; - if (action == '-' && !strncasecmp(w, "ForwardURI", strlen("ForwardURI"))) + if (action == '-' && + (!strncasecmp(w, "ForwardURI", strlen("ForwardURI")) || + !strncasecmp(w, "CollapseSlashes", strlen("CollapseSlashes")))) return apr_pstrcat(cmd->pool, "JkOptions: Illegal option '-", w, - "': ForwardURI* options can not be disabled", NULL); + "': option can not be disabled", NULL); if (!strcasecmp(w, "ForwardURICompat")) { opt = JK_OPT_FWDURICOMPAT; @@ -2208,6 +2210,18 @@ static const char *jk_set_options(cmd_pa opt = JK_OPT_FWDURIPROXY; mask = JK_OPT_FWDURIMASK; } + else if (!strcasecmp(w, "CollapseSlashesAll")) { + opt = JK_OPT_COLLAPSEALL; + mask = JK_OPT_COLLAPSEMASK; + } + else if (!strcasecmp(w, "CollapseSlashesNone")) { + opt = JK_OPT_COLLAPSENONE; + mask = JK_OPT_COLLAPSEMASK; + } + else if (!strcasecmp(w, "CollapseSlashesUnmount")) { + opt = JK_OPT_COLLAPSEUNMOUNT; + mask = JK_OPT_COLLAPSEMASK; + } else if (!strcasecmp(w, "ForwardDirectories")) { opt = JK_OPT_FWDDIRS; } @@ -3005,6 +3019,10 @@ static void *merge_jk_config(apr_pool_t overrides->options |= (base->options & ~base->exclude_options) & ~JK_OPT_FWDURIMASK; else overrides->options |= (base->options & ~base->exclude_options); + if (overrides->options & JK_OPT_COLLAPSEMASK) + overrides->options |= (base->options & ~base->exclude_options) & ~JK_OPT_COLLAPSEMASK; + else + overrides->options |= (base->options & ~base->exclude_options); if (base->envvars) { if (overrides->envvars && overrides->envvars_has_own) { @@ -3482,6 +3500,8 @@ 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); } + if (conf->options & JK_OPT_COLLAPSEMASK) + sconf->uw_map->collapse_slashes = conf->options & JK_OPT_COLLAPSEMASK; } else { if (sconf->mountcopy == JK_TRUE) { Index: tomcat-connectors-1.2.40-src/native/apache-1.3/mod_jk.c =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/apache-1.3/mod_jk.c +++ tomcat-connectors-1.2.40-src/native/apache-1.3/mod_jk.c @@ -2079,9 +2079,11 @@ const char *jk_set_options(cmd_parms * c mask = 0; - if (action == '-' && !strncasecmp(w, "ForwardURI", strlen("ForwardURI"))) + if (action == '-' && + (!strncasecmp(w, "ForwardURI", strlen("ForwardURI")) || + !strncasecmp(w, "CollapseSlashes", strlen("CollapseSlashes")))) return ap_pstrcat(cmd->pool, "JkOptions: Illegal option '-", w, - "': ForwardURI* options can not be disabled", NULL); + "': option can not be disabled", NULL); if (!strcasecmp(w, "ForwardURICompat")) { opt = JK_OPT_FWDURICOMPAT; @@ -2099,6 +2101,18 @@ const char *jk_set_options(cmd_parms * c opt = JK_OPT_FWDURIPROXY; mask = JK_OPT_FWDURIMASK; } + else if (!strcasecmp(w, "CollapseSlashesAll")) { + opt = JK_OPT_COLLAPSEALL; + mask = JK_OPT_COLLAPSEMASK; + } + else if (!strcasecmp(w, "CollapseSlashesNone")) { + opt = JK_OPT_COLLAPSENONE; + mask = JK_OPT_COLLAPSEMASK; + } + else if (!strcasecmp(w, "CollapseSlashesUnmount")) { + opt = JK_OPT_COLLAPSEUNMOUNT; + mask = JK_OPT_COLLAPSEMASK; + } else if (!strcasecmp(w, "ForwardDirectories")) { opt = JK_OPT_FWDDIRS; } @@ -2768,6 +2782,10 @@ static void *merge_jk_config(ap_pool * p overrides->options |= (base->options & ~base->exclude_options) & ~JK_OPT_FWDURIMASK; else overrides->options |= (base->options & ~base->exclude_options); + if (overrides->options & JK_OPT_COLLAPSEMASK) + overrides->options |= (base->options & ~base->exclude_options) & ~JK_OPT_COLLAPSEMASK; + else + overrides->options |= (base->options & ~base->exclude_options); if (base->envvars) { if (overrides->envvars && overrides->envvars_has_own) { @@ -2988,6 +3006,8 @@ static void jk_init(server_rec * s, ap_p uri_worker_map_switch(sconf->uw_map, sconf->log); uri_worker_map_load(sconf->uw_map, sconf->log); } + if (conf->options & JK_OPT_COLLAPSEMASK) + sconf->uw_map->collapse_slashes = conf->options & JK_OPT_COLLAPSEMASK; } else { if (sconf->mountcopy == JK_TRUE) { Index: tomcat-connectors-1.2.40-src/native/iis/jk_isapi_plugin.c =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/iis/jk_isapi_plugin.c +++ tomcat-connectors-1.2.40-src/native/iis/jk_isapi_plugin.c @@ -117,23 +117,27 @@ static char HTTP_WORKER_HEADER_INDEX[RES #define W3SVC_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters" #define EXTENSION_URI_TAG "extension_uri" -#define URI_SELECT_TAG "uri_select" -#define URI_SELECT_PARSED_VERB "parsed" -#define URI_SELECT_UNPARSED_VERB "unparsed" -#define URI_SELECT_ESCAPED_VERB "escaped" -#define URI_SELECT_PROXY_VERB "proxy" -#define URI_REWRITE_TAG "rewrite_rule_file" -#define SHM_SIZE_TAG "shm_size" -#define WORKER_MOUNT_RELOAD_TAG "worker_mount_reload" -#define STRIP_SESSION_TAG "strip_session" -#define AUTH_COMPLETE_TAG "auth_complete" -#define REJECT_UNSAFE_TAG "reject_unsafe" -#define WATCHDOG_INTERVAL_TAG "watchdog_interval" -#define ENABLE_CHUNKED_ENCODING_TAG "enable_chunked_encoding" -#define ERROR_PAGE_TAG "error_page" +#define URI_SELECT_TAG "uri_select" +#define URI_SELECT_PARSED_VERB "parsed" +#define URI_SELECT_UNPARSED_VERB "unparsed" +#define URI_SELECT_ESCAPED_VERB "escaped" +#define URI_SELECT_PROXY_VERB "proxy" +#define URI_REWRITE_TAG "rewrite_rule_file" +#define SHM_SIZE_TAG "shm_size" +#define WORKER_MOUNT_RELOAD_TAG "worker_mount_reload" +#define STRIP_SESSION_TAG "strip_session" +#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" -#define LOG_ROTATION_TIME_TAG "log_rotationtime" -#define LOG_FILESIZE_TAG "log_filesize" +#define LOG_ROTATION_TIME_TAG "log_rotationtime" +#define LOG_FILESIZE_TAG "log_filesize" /* HTTP standard headers */ #define TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE "Transfer-Encoding: chunked" @@ -500,6 +504,7 @@ 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}; @@ -2790,6 +2795,7 @@ 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; @@ -2919,6 +2925,17 @@ 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_OPT_COLLAPSEALL; + if (!strcasecmp(collapse_slashes, COLLAPSE_SLASHES_NONE_VERB)) + return JK_OPT_COLLAPSENONE; + if (!strcasecmp(collapse_slashes, COLLAPSE_SLASHES_UNMOUNT_VERB)) + return JK_OPT_COLLAPSEUNMOUNT; + return -1; +} + static int read_registry_init_data(void) { char tmpbuf[MAX_PATH]; @@ -3016,7 +3033,18 @@ static int read_registry_init_data(void) uri_select_option = opt; } else { - goto cleanup; + jk_log(logger, JK_LOG_ERROR, "Invalid value '%s' for configuration item '" + URI_SELECT_TAG "'", tmpbuf); + } + } + 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); } } shm_config_size = get_config_int(src, SHM_SIZE_TAG, -1); Index: tomcat-connectors-1.2.40-src/native/common/jk_uri_worker_map.c =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/common/jk_uri_worker_map.c +++ tomcat-connectors-1.2.40-src/native/common/jk_uri_worker_map.c @@ -176,9 +176,10 @@ 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 " - "reload=%d modified=%d checked=%d", + "collapse_slashes=%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->reload, uw_map->modified, uw_map->checked); + uw_map->reject_unsafe, uw_map->collapse_slashes, + 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", @@ -244,6 +245,7 @@ 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; @@ -697,48 +699,42 @@ void parse_rule_extensions(char *rule, r else if (!strncmp(param, JK_UWMAP_EXTENSION_ACTIVE, strlen(JK_UWMAP_EXTENSION_ACTIVE))) { if (extensions->active) jk_log(l, JK_LOG_WARNING, - "rule extension '%s' only allowed once", - JK_UWMAP_EXTENSION_ACTIVE); + "rule extension '" JK_UWMAP_EXTENSION_ACTIVE "' only allowed once"); else extensions->active = param + strlen(JK_UWMAP_EXTENSION_ACTIVE); } else if (!strncmp(param, JK_UWMAP_EXTENSION_DISABLED, strlen(JK_UWMAP_EXTENSION_DISABLED))) { if (extensions->disabled) jk_log(l, JK_LOG_WARNING, - "rule extension '%s' only allowed once", - JK_UWMAP_EXTENSION_DISABLED); + "rule extension '" JK_UWMAP_EXTENSION_DISABLED "' only allowed once"); else extensions->disabled = param + strlen(JK_UWMAP_EXTENSION_DISABLED); } else if (!strncmp(param, JK_UWMAP_EXTENSION_STOPPED, strlen(JK_UWMAP_EXTENSION_STOPPED))) { if (extensions->stopped) jk_log(l, JK_LOG_WARNING, - "rule extension '%s' only allowed once", - JK_UWMAP_EXTENSION_STOPPED); + "rule extension '" JK_UWMAP_EXTENSION_STOPPED "' only allowed once"); else extensions->stopped = param + strlen(JK_UWMAP_EXTENSION_STOPPED); } else if (!strncmp(param, JK_UWMAP_EXTENSION_FAIL_ON_STATUS, strlen(JK_UWMAP_EXTENSION_FAIL_ON_STATUS))) { if (extensions->fail_on_status_str) jk_log(l, JK_LOG_WARNING, - "rule extension '%s' only allowed once", - JK_UWMAP_EXTENSION_FAIL_ON_STATUS); + "rule extension '" JK_UWMAP_EXTENSION_FAIL_ON_STATUS "' only allowed once"); else extensions->fail_on_status_str = param + strlen(JK_UWMAP_EXTENSION_FAIL_ON_STATUS); } else if (!strncmp(param, JK_UWMAP_EXTENSION_SESSION_COOKIE, strlen(JK_UWMAP_EXTENSION_SESSION_COOKIE))) { if (extensions->session_cookie) jk_log(l, JK_LOG_WARNING, - "extension '%s' in uri worker map only allowed once", - JK_UWMAP_EXTENSION_SESSION_COOKIE); + "extension '" JK_UWMAP_EXTENSION_SESSION_COOKIE "' in uri worker map only allowed once"); else extensions->session_cookie = param + strlen(JK_UWMAP_EXTENSION_SESSION_COOKIE); } else if (!strncmp(param, JK_UWMAP_EXTENSION_SESSION_PATH, strlen(JK_UWMAP_EXTENSION_SESSION_PATH))) { if (extensions->session_path) jk_log(l, JK_LOG_WARNING, - "extension '%s' in uri worker map only allowed once", - JK_UWMAP_EXTENSION_SESSION_PATH); + "extension '" JK_UWMAP_EXTENSION_SESSION_PATH "' in uri worker map only allowed once"); else { // Check if the session identifier starts with semicolon. if (!strcmp(param, JK_UWMAP_EXTENSION_SESSION_PATH)) { @@ -755,8 +751,7 @@ void parse_rule_extensions(char *rule, r else if (!strncmp(param, JK_UWMAP_EXTENSION_SET_SESSION_COOKIE, strlen(JK_UWMAP_EXTENSION_SET_SESSION_COOKIE))) { if (extensions->set_session_cookie) jk_log(l, JK_LOG_WARNING, - "extension '%s' in uri worker map only allowed once", - JK_UWMAP_EXTENSION_SET_SESSION_COOKIE); + "extension '" JK_UWMAP_EXTENSION_SET_SESSION_COOKIE "' in uri worker map only allowed once"); else { int val = atoi(param + strlen(JK_UWMAP_EXTENSION_SET_SESSION_COOKIE)); if (val) { @@ -770,8 +765,7 @@ void parse_rule_extensions(char *rule, r else if (!strncmp(param, JK_UWMAP_EXTENSION_SESSION_COOKIE_PATH, strlen(JK_UWMAP_EXTENSION_SESSION_COOKIE_PATH))) { if (extensions->session_cookie_path) jk_log(l, JK_LOG_WARNING, - "extension '%s' in uri worker map only allowed once", - JK_UWMAP_EXTENSION_SESSION_COOKIE_PATH); + "extension '" JK_UWMAP_EXTENSION_SESSION_COOKIE_PATH "' in uri worker map only allowed once"); else extensions->session_cookie_path = param + strlen(JK_UWMAP_EXTENSION_SESSION_COOKIE_PATH); } @@ -1073,12 +1067,12 @@ static int is_nomatch(jk_uri_worker_map_ const char *map_uri_to_worker_ext(jk_uri_worker_map_t *uw_map, const char *uri, const char *vhost, rule_extension_t **extensions, - int *index, - jk_logger_t *l) + int *index, jk_logger_t *l) { unsigned int i; unsigned int vhost_len; int reject_unsafe; + int collapse_slashes; int rv = -1; char url[JK_MAX_URI_LEN+1]; @@ -1108,10 +1102,8 @@ const char *map_uri_to_worker_ext(jk_uri return NULL; } } - /* Make the copy of the provided uri and strip - * everything after the first ';' char. - */ 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 @@ -1139,6 +1131,9 @@ 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. + */ for (i = 0; i < strlen(uri); i++) { if (i == JK_MAX_URI_LEN) { jk_log(l, JK_LOG_WARNING, @@ -1166,6 +1161,12 @@ 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)); @@ -1177,6 +1178,13 @@ 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)) { + 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. */ int rc = is_nomatch(uw_map, url, rv, l); /* If no unmount was find, try without vhost. */ Index: tomcat-connectors-1.2.40-src/native/common/jk_uri_worker_map.h =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/common/jk_uri_worker_map.h +++ tomcat-connectors-1.2.40-src/native/common/jk_uri_worker_map.h @@ -58,6 +58,11 @@ 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 @@ -168,6 +173,8 @@ 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; /* uriworkermap filename */ const char *fname; /* uriworkermap reload check interval */ Index: tomcat-connectors-1.2.40-src/native/common/jk_util.c =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/common/jk_util.c +++ tomcat-connectors-1.2.40-src/native/common/jk_util.c @@ -2123,6 +2123,25 @@ int jk_wildchar_match(const char *str, c return (str[x] != '\0'); } +void jk_no2slash(char *name) +{ + char *d, *s; + + s = d = name; + + while (*s) { + if ((*d++ = *s) == '/') { + do { + ++s; + } while (*s == '/'); + } + else { + ++s; + } + } + *d = '\0'; +} + #ifdef _MT_CODE_PTHREAD jk_pthread_t jk_gettid() { Index: tomcat-connectors-1.2.40-src/native/common/jk_util.h =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/common/jk_util.h +++ tomcat-connectors-1.2.40-src/native/common/jk_util.h @@ -244,6 +244,8 @@ 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); + #define TC32_BRIDGE_TYPE 32 #define TC33_BRIDGE_TYPE 33 #define TC40_BRIDGE_TYPE 40 Index: tomcat-connectors-1.2.40-src/native/common/jk_global.h =================================================================== --- tomcat-connectors-1.2.40-src.orig/native/common/jk_global.h +++ tomcat-connectors-1.2.40-src/native/common/jk_global.h @@ -272,8 +272,12 @@ extern "C" /* Forward physical tcp peer address instead of * client address as provided e.g. by httpd mod_remoteip. */ #define JK_OPT_FWDPHYSICAL 0x0800 +#define JK_OPT_COLLAPSEMASK 0x7000 +#define JK_OPT_COLLAPSEALL 0x1000 +#define JK_OPT_COLLAPSENONE 0x2000 +#define JK_OPT_COLLAPSEUNMOUNT 0x4000 -#define JK_OPT_DEFAULT (JK_OPT_FWDURIDEFAULT | JK_OPT_FWDKEYSIZE) +#define JK_OPT_DEFAULT (JK_OPT_FWDURIDEFAULT | JK_OPT_FWDKEYSIZE | JK_OPT_COLLAPSEUNMOUNT) /* Check for EBCDIC systems */
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