Blame SOURCES/httpd-2.4.34-CVE-2019-0220.patch

ad4e62
diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en
ad4e62
index 3035537..df55e3b 100644
ad4e62
--- a/docs/manual/mod/core.html.en
ad4e62
+++ b/docs/manual/mod/core.html.en
ad4e62
@@ -97,6 +97,7 @@ available
ad4e62
 
  • MaxRangeOverlaps
  • ad4e62
     
  • MaxRangeReversals
  • ad4e62
     
  • MaxRanges
  • ad4e62
    +
  • MergeSlashes
  • ad4e62
     
  • MergeTrailers
  • ad4e62
     
  • Mutex
  • ad4e62
     
  • NameVirtualHost
  • ad4e62
    @@ -3463,6 +3464,30 @@ resource 
    ad4e62
     
    ad4e62
     
    ad4e62
     
    top
    ad4e62
    +
    ad4e62
    +
    ad4e62
    +Description:Controls whether the server merges consecutive slashes in URLs. 
    ad4e62
    +Syntax:MergeSlashes ON | OFF
    ad4e62
    +Default:MergeSlashes ON
    ad4e62
    +Context:server config, virtual host
    ad4e62
    +Status:Core
    ad4e62
    +Module:core
    ad4e62
    +Compatibility:Available in Apache HTTP Server 2.4.6 in Red Hat Enterprise Linux 7
    ad4e62
    +
    ad4e62
    +    

    By default, the server merges (or collapses) multiple consecutive slash

    ad4e62
    +       ('/') characters in the path component of the request URL.

    ad4e62
    +
    ad4e62
    +    

    When mapping URL's to the filesystem, these multiple slashes are not

    ad4e62
    +       significant.  However, URL's handled other ways, such as by CGI or proxy,
    ad4e62
    +       might prefer to retain the significance of multiple consecutive slashes. 
    ad4e62
    +       In these cases MergeSlashes can be set to 
    ad4e62
    +       OFF to retain the multiple consecutive slashes.  In these
    ad4e62
    +       configurations, regular expressions used in the configuration file that match
    ad4e62
    +       the path component of the URL (LocationMatch,
    ad4e62
    +       RewriteRule, ...) need to take into account multiple 
    ad4e62
    +       consecutive slashes.

    ad4e62
    +
    ad4e62
    +
    top
    ad4e62
     
    ad4e62
     
    ad4e62
     Description:Determines whether trailers are merged into headers
    ad4e62
    diff --git a/include/http_core.h b/include/http_core.h
    ad4e62
    index 35df5dc..8e10988 100644
    ad4e62
    --- a/include/http_core.h
    ad4e62
    +++ b/include/http_core.h
    ad4e62
    @@ -740,7 +740,7 @@ typedef struct {
    ad4e62
     #define AP_HTTP_METHODS_LENIENT       1
    ad4e62
     #define AP_HTTP_METHODS_REGISTERED    2
    ad4e62
         char http_methods;
    ad4e62
    -
    ad4e62
    +    unsigned int merge_slashes;
    ad4e62
     } core_server_config;
    ad4e62
     
    ad4e62
     /* for AddOutputFiltersByType in core.c */
    ad4e62
    diff --git a/include/httpd.h b/include/httpd.h
    ad4e62
    index d792308..6c2d882 100644
    ad4e62
    --- a/include/httpd.h
    ad4e62
    +++ b/include/httpd.h
    ad4e62
    @@ -1693,11 +1693,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes);
    ad4e62
     AP_DECLARE(int) ap_unescape_urlencoded(char *query);
    ad4e62
     
    ad4e62
     /**
    ad4e62
    - * Convert all double slashes to single slashes
    ad4e62
    - * @param name The string to convert
    ad4e62
    + * Convert all double slashes to single slashes, except where significant
    ad4e62
    + * to the filesystem on the current platform.
    ad4e62
    + * @param name The string to convert, assumed to be a filesystem path
    ad4e62
      */
    ad4e62
     AP_DECLARE(void) ap_no2slash(char *name);
    ad4e62
     
    ad4e62
    +/**
    ad4e62
    + * Convert all double slashes to single slashes, except where significant
    ad4e62
    + * to the filesystem on the current platform.
    ad4e62
    + * @param name The string to convert
    ad4e62
    + * @param is_fs_path if set to 0, the significance of any double-slashes is 
    ad4e62
    + *        ignored.
    ad4e62
    + */
    ad4e62
    +AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path);
    ad4e62
    +
    ad4e62
     /**
    ad4e62
      * Remove all ./ and xx/../ substrings from a file name. Also remove
    ad4e62
      * any leading ../ or /../ substrings.
    ad4e62
    diff --git a/server/core.c b/server/core.c
    ad4e62
    index ed1e3b3..ea786a3 100644
    ad4e62
    --- a/server/core.c
    ad4e62
    +++ b/server/core.c
    ad4e62
    @@ -491,6 +491,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
    ad4e62
          */
    ad4e62
     
    ad4e62
         conf->trace_enable = AP_TRACE_UNSET;
    ad4e62
    +    conf->merge_slashes = AP_CORE_CONFIG_UNSET;
    ad4e62
     
    ad4e62
         conf->protocols = apr_array_make(a, 5, sizeof(const char *));
    ad4e62
         conf->protocols_honor_order = -1;
    ad4e62
    @@ -559,7 +560,9 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
    ad4e62
         conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
    ad4e62
                                            base->protocols_honor_order :
    ad4e62
                                            virt->protocols_honor_order);
    ad4e62
    -    
    ad4e62
    +
    ad4e62
    +    AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
    ad4e62
    +
    ad4e62
         return conf;
    ad4e62
     }
    ad4e62
     
    ad4e62
    @@ -1867,6 +1870,13 @@ static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag)
    ad4e62
         return NULL;
    ad4e62
     }
    ad4e62
     
    ad4e62
    +static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag)
    ad4e62
    +{
    ad4e62
    +    core_server_config *conf =
    ad4e62
    +        ap_get_core_module_config(cmd->server->module_config);
    ad4e62
    +    return ap_set_flag_slot(cmd, conf, flag);
    ad4e62
    +}
    ad4e62
    +
    ad4e62
     static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
    ad4e62
     {
    ad4e62
         core_dir_config *d = d_;
    ad4e62
    @@ -4570,6 +4580,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON
    ad4e62
                     "'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"),
    ad4e62
     AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
    ad4e62
                     "Registers non-standard HTTP methods"),
    ad4e62
    +AP_INIT_FLAG("MergeSlashes", set_core_server_flag,
    ad4e62
    +             (void *)APR_OFFSETOF(core_server_config, merge_slashes),
    ad4e62
    +             RSRC_CONF,
    ad4e62
    +             "Controls whether consecutive slashes in the URI path are merged"),
    ad4e62
     { NULL }
    ad4e62
     };
    ad4e62
     
    ad4e62
    diff --git a/server/request.c b/server/request.c
    ad4e62
    index dbe3e07..d5c558a 100644
    ad4e62
    --- a/server/request.c
    ad4e62
    +++ b/server/request.c
    ad4e62
    @@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
    ad4e62
         int file_req = (r->main && r->filename);
    ad4e62
         int access_status;
    ad4e62
         core_dir_config *d;
    ad4e62
    +    core_server_config *sconf =
    ad4e62
    +        ap_get_core_module_config(r->server->module_config);
    ad4e62
     
    ad4e62
         /* Ignore embedded %2F's in path for proxy requests */
    ad4e62
         if (!r->proxyreq && r->parsed_uri.path) {
    ad4e62
    @@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
    ad4e62
         }
    ad4e62
     
    ad4e62
         ap_getparents(r->uri);     /* OK --- shrinking transformations... */
    ad4e62
    +    if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { 
    ad4e62
    +        ap_no2slash(r->uri);
    ad4e62
    +        if (r->parsed_uri.path) {
    ad4e62
    +            ap_no2slash(r->parsed_uri.path);
    ad4e62
    +        }
    ad4e62
    +     }
    ad4e62
     
    ad4e62
         /* All file subrequests are a huge pain... they cannot bubble through the
    ad4e62
          * next several steps.  Only file subrequests are allowed an empty uri,
    ad4e62
    @@ -1411,20 +1419,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
    ad4e62
     
    ad4e62
         cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
    ad4e62
         cached = (cache->cached != NULL);
    ad4e62
    -
    ad4e62
    -    /* Location and LocationMatch differ on their behaviour w.r.t. multiple
    ad4e62
    -     * slashes.  Location matches multiple slashes with a single slash,
    ad4e62
    -     * LocationMatch doesn't.  An exception, for backwards brokenness is
    ad4e62
    -     * absoluteURIs... in which case neither match multiple slashes.
    ad4e62
    -     */
    ad4e62
    -    if (r->uri[0] != '/') {
    ad4e62
    -        entry_uri = r->uri;
    ad4e62
    -    }
    ad4e62
    -    else {
    ad4e62
    -        char *uri = apr_pstrdup(r->pool, r->uri);
    ad4e62
    -        ap_no2slash(uri);
    ad4e62
    -        entry_uri = uri;
    ad4e62
    -    }
    ad4e62
    +    entry_uri = r->uri;
    ad4e62
     
    ad4e62
         /* If we have an cache->cached location that matches r->uri,
    ad4e62
          * and the vhost's list of locations hasn't changed, we can skip
    ad4e62
    @@ -1491,7 +1486,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
    ad4e62
                         pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
    ad4e62
                     }
    ad4e62
     
    ad4e62
    -                if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
    ad4e62
    +                if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
    ad4e62
                         continue;
    ad4e62
                     }
    ad4e62
     
    ad4e62
    @@ -1501,7 +1496,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
    ad4e62
                             apr_table_setn(r->subprocess_env,
    ad4e62
                                            ((const char **)entry_core->refs->elts)[i],
    ad4e62
                                            apr_pstrndup(r->pool,
    ad4e62
    -                                       r->uri + pmatch[i].rm_so,
    ad4e62
    +                                       entry_uri + pmatch[i].rm_so,
    ad4e62
                                            pmatch[i].rm_eo - pmatch[i].rm_so));
    ad4e62
                         }
    ad4e62
                     }
    ad4e62
    diff --git a/server/util.c b/server/util.c
    ad4e62
    index 8df1a4c..1549ab1 100644
    ad4e62
    --- a/server/util.c
    ad4e62
    +++ b/server/util.c
    ad4e62
    @@ -561,16 +561,20 @@ AP_DECLARE(void) ap_getparents(char *name)
    ad4e62
             name[l] = '\0';
    ad4e62
         }
    ad4e62
     }
    ad4e62
    -
    ad4e62
    -AP_DECLARE(void) ap_no2slash(char *name)
    ad4e62
    +AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
    ad4e62
     {
    ad4e62
    +
    ad4e62
         char *d, *s;
    ad4e62
     
    ad4e62
    +    if (!*name) {
    ad4e62
    +        return;
    ad4e62
    +    }
    ad4e62
    +
    ad4e62
         s = d = name;
    ad4e62
     
    ad4e62
     #ifdef HAVE_UNC_PATHS
    ad4e62
         /* Check for UNC names.  Leave leading two slashes. */
    ad4e62
    -    if (s[0] == '/' && s[1] == '/')
    ad4e62
    +    if (is_fs_path && s[0] == '/' && s[1] == '/')
    ad4e62
             *d++ = *s++;
    ad4e62
     #endif
    ad4e62
     
    ad4e62
    @@ -587,6 +591,10 @@ AP_DECLARE(void) ap_no2slash(char *name)
    ad4e62
         *d = '\0';
    ad4e62
     }
    ad4e62
     
    ad4e62
    +AP_DECLARE(void) ap_no2slash(char *name)
    ad4e62
    +{
    ad4e62
    +    ap_no2slash_ex(name, 1);
    ad4e62
    +}
    ad4e62
     
    ad4e62
     /*
    ad4e62
      * copy at most n leading directories of s into d