From 436fa04fbfaac4236b2ba94466ac751d35a97cd8 Mon Sep 17 00:00:00 2001 From: webbuilder_pel7ppc64lebuilder0 Date: Fri, 24 Apr 2020 15:37:53 +0200 Subject: [PATCH] httpd package update Signed-off-by: webbuilder_pel7ppc64lebuilder0 --- SOURCES/httpd-2.4.6-CVE-2018-1312.patch | 399 ++++++++++++++++++ SOURCES/httpd-2.4.6-CVE-2019-0217.patch | 113 +++++ SOURCES/httpd-2.4.6-CVE-2019-0220.patch | 244 +++++++++++ SOURCES/httpd-2.4.6-default-port-worker.patch | 13 + SOURCES/httpd-2.4.6-mpm-segfault.patch | 11 + SOURCES/httpd-2.4.6-r1515372.patch | 11 + SOURCES/httpd-2.4.6-r1555539.patch | 265 ++++++++++++ SOURCES/httpd-2.4.6-r1737363.patch | 26 ++ SOURCES/httpd-2.4.6-r1824872.patch | 25 ++ SOURCES/httpd-2.4.6-r1825120.patch | 96 +++++ SOURCES/httpd-2.4.6-r1826995.patch | 198 +++++++++ SOURCES/httpd-2.4.6-r1833014.patch | 83 ++++ SPECS/httpd.spec | 35 +- 13 files changed, 1513 insertions(+), 6 deletions(-) create mode 100644 SOURCES/httpd-2.4.6-CVE-2018-1312.patch create mode 100644 SOURCES/httpd-2.4.6-CVE-2019-0217.patch create mode 100644 SOURCES/httpd-2.4.6-CVE-2019-0220.patch create mode 100644 SOURCES/httpd-2.4.6-default-port-worker.patch create mode 100644 SOURCES/httpd-2.4.6-r1515372.patch create mode 100644 SOURCES/httpd-2.4.6-r1555539.patch create mode 100644 SOURCES/httpd-2.4.6-r1737363.patch create mode 100644 SOURCES/httpd-2.4.6-r1824872.patch create mode 100644 SOURCES/httpd-2.4.6-r1825120.patch create mode 100644 SOURCES/httpd-2.4.6-r1826995.patch create mode 100644 SOURCES/httpd-2.4.6-r1833014.patch diff --git a/SOURCES/httpd-2.4.6-CVE-2018-1312.patch b/SOURCES/httpd-2.4.6-CVE-2018-1312.patch new file mode 100644 index 0000000..4c694a5 --- /dev/null +++ b/SOURCES/httpd-2.4.6-CVE-2018-1312.patch @@ -0,0 +1,399 @@ +diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c +index cbb4434..b50bcf9 100644 +--- a/modules/aaa/mod_auth_digest.c ++++ b/modules/aaa/mod_auth_digest.c +@@ -26,20 +26,13 @@ + * reports to the Apache bug-database, or send them directly to me + * at ronald@innovation.ch. + * +- * Requires either /dev/random (or equivalent) or the truerand library, +- * available for instance from +- * ftp://research.att.com/dist/mab/librand.shar +- * + * Open Issues: + * - qop=auth-int (when streams and trailer support available) + * - nonce-format configurability + * - Proxy-Authorization-Info header is set by this module, but is + * currently ignored by mod_proxy (needs patch to mod_proxy) +- * - generating the secret takes a while (~ 8 seconds) if using the +- * truerand library + * - The source of the secret should be run-time directive (with server +- * scope: RSRC_CONF). However, that could be tricky when trying to +- * choose truerand vs. file... ++ * scope: RSRC_CONF) + * - shared-mem not completely tested yet. Seems to work ok for me, + * but... (definitely won't work on Windoze) + * - Sharing a realm among multiple servers has following problems: +@@ -52,6 +45,8 @@ + * captures a packet sent to one server and sends it to another + * one. Should we add "AuthDigestNcCheck Strict"? + * - expired nonces give amaya fits. ++ * - MD5-sess and auth-int are not yet implemented. An incomplete ++ * implementation has been removed and can be retrieved from svn history. + */ + + #include "apr_sha1.h" +@@ -94,7 +89,6 @@ typedef struct digest_config_struct { + apr_array_header_t *qop_list; + apr_sha1_ctx_t nonce_ctx; + apr_time_t nonce_lifetime; +- const char *nonce_format; + int check_nc; + const char *algorithm; + char *uri_list; +@@ -112,7 +106,8 @@ typedef struct digest_config_struct { + #define NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE) + #define NONCE_LEN (int )(NONCE_TIME_LEN + NONCE_HASH_LEN) + +-#define SECRET_LEN 20 ++#define SECRET_LEN 20 ++#define RETAINED_DATA_ID "mod_auth_digest" + + + /* client list definitions */ +@@ -121,7 +116,6 @@ typedef struct hash_entry { + unsigned long key; /* the key for this entry */ + struct hash_entry *next; /* next entry in the bucket */ + unsigned long nonce_count; /* for nonce-count checking */ +- char ha1[2*APR_MD5_DIGESTSIZE+1]; /* for algorithm=MD5-sess */ + char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */ + } client_entry; + +@@ -170,7 +164,7 @@ typedef union time_union { + unsigned char arr[sizeof(apr_time_t)]; + } time_rec; + +-static unsigned char secret[SECRET_LEN]; ++static unsigned char *secret; + + /* client-list, opaque, and one-time-nonce stuff */ + +@@ -228,35 +222,11 @@ static apr_status_t cleanup_tables(void *not_used) + return APR_SUCCESS; + } + +-static apr_status_t initialize_secret(server_rec *s) +-{ +- apr_status_t status; +- +- ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01757) +- "generating secret for digest authentication ..."); +- +-#if APR_HAS_RANDOM +- status = apr_generate_random_bytes(secret, sizeof(secret)); +-#else +-#error APR random number support is missing; you probably need to install the truerand library. +-#endif +- +- if (status != APR_SUCCESS) { +- ap_log_error(APLOG_MARK, APLOG_CRIT, status, s, APLOGNO(01758) +- "error generating secret"); +- return status; +- } +- +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01759) "done"); +- +- return APR_SUCCESS; +-} +- + static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s) + { + ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01760) +- "%s - all nonce-count checking, one-time nonces, and " +- "MD5-sess algorithm disabled", msg); ++ "%s - all nonce-count checking and one-time nonces" ++ "disabled", msg); + + cleanup_tables(NULL); + } +@@ -377,16 +347,32 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) + static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) + { + apr_status_t rv; ++ void *retained; + + rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0); +- if (rv == APR_SUCCESS) { +- rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, +- 0); +- } +- if (rv != APR_SUCCESS) { +- return rv; +- } ++ if (rv != APR_SUCCESS) ++ return !OK; ++ rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, 0); ++ if (rv != APR_SUCCESS) ++ return !OK; + ++ retained = ap_retained_data_get(RETAINED_DATA_ID); ++ if (retained == NULL) { ++ retained = ap_retained_data_create(RETAINED_DATA_ID, SECRET_LEN); ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01757) ++ "generating secret for digest authentication"); ++#if APR_HAS_RANDOM ++ rv = apr_generate_random_bytes(retained, SECRET_LEN); ++#else ++#error APR random number support is missing ++#endif ++ if (rv != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(01758) ++ "error generating secret"); ++ return !OK; ++ } ++ } ++ secret = retained; + return OK; + } + +@@ -399,10 +385,6 @@ static int initialize_module(apr_pool_t *p, apr_pool_t *plog, + if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) + return OK; + +- if (initialize_secret(s) != APR_SUCCESS) { +- return !OK; +- } +- + #if APR_HAS_SHARED_MEMORY + /* Note: this stuff is currently fixed for the lifetime of the server, + * i.e. even across restarts. This means that A) any shmem-size +@@ -483,6 +465,16 @@ static void *create_digest_dir_config(apr_pool_t *p, char *dir) + static const char *set_realm(cmd_parms *cmd, void *config, const char *realm) + { + digest_config_rec *conf = (digest_config_rec *) config; ++#ifdef AP_DEBUG ++ int i; ++ ++ /* check that we got random numbers */ ++ for (i = 0; i < SECRET_LEN; i++) { ++ if (secret[i] != 0) ++ break; ++ } ++ ap_assert(i < SECRET_LEN); ++#endif + + /* The core already handles the realm, but it's just too convenient to + * grab it ourselves too and cache some setups. However, we need to +@@ -496,7 +488,7 @@ static const char *set_realm(cmd_parms *cmd, void *config, const char *realm) + * and directives outside a virtual host section) + */ + apr_sha1_init(&conf->nonce_ctx); +- apr_sha1_update_binary(&conf->nonce_ctx, secret, sizeof(secret)); ++ apr_sha1_update_binary(&conf->nonce_ctx, secret, SECRET_LEN); + apr_sha1_update_binary(&conf->nonce_ctx, (const unsigned char *) realm, + strlen(realm)); + +@@ -590,8 +582,7 @@ static const char *set_nonce_lifetime(cmd_parms *cmd, void *config, + static const char *set_nonce_format(cmd_parms *cmd, void *config, + const char *fmt) + { +- ((digest_config_rec *) config)->nonce_format = fmt; +- return "AuthDigestNonceFormat is not implemented (yet)"; ++ return "AuthDigestNonceFormat is not implemented"; + } + + static const char *set_nc_check(cmd_parms *cmd, void *config, int flag) +@@ -612,7 +603,7 @@ static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg) + { + if (!strcasecmp(alg, "MD5-sess")) { + return "AuthDigestAlgorithm: ERROR: algorithm `MD5-sess' " +- "is not fully implemented"; ++ "is not implemented"; + } + else if (strcasecmp(alg, "MD5")) { + return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL); +@@ -1138,7 +1129,7 @@ static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque, + static client_entry *gen_client(const request_rec *r) + { + unsigned long op; +- client_entry new_entry = { 0, NULL, 0, "", "" }, *entry; ++ client_entry new_entry = { 0, NULL, 0, "" }, *entry; + + if (!opaque_cntr) { + return NULL; +@@ -1158,92 +1149,6 @@ static client_entry *gen_client(const request_rec *r) + } + + +-/* +- * MD5-sess code. +- * +- * If you want to use algorithm=MD5-sess you must write get_userpw_hash() +- * yourself (see below). The dummy provided here just uses the hash from +- * the auth-file, i.e. it is only useful for testing client implementations +- * of MD5-sess . +- */ +- +-/* +- * get_userpw_hash() will be called each time a new session needs to be +- * generated and is expected to return the equivalent of +- * +- * h_urp = ap_md5(r->pool, +- * apr_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd)) +- * ap_md5(r->pool, +- * (unsigned char *) apr_pstrcat(r->pool, h_urp, ":", resp->nonce, ":", +- * resp->cnonce, NULL)); +- * +- * or put differently, it must return +- * +- * MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce) +- * +- * If something goes wrong, the failure must be logged and NULL returned. +- * +- * You must implement this yourself, which will probably consist of code +- * contacting the password server with the necessary information (typically +- * the username, realm, nonce, and cnonce) and receiving the hash from it. +- * +- * TBD: This function should probably be in a separate source file so that +- * people need not modify mod_auth_digest.c each time they install a new +- * version of apache. +- */ +-static const char *get_userpw_hash(const request_rec *r, +- const digest_header_rec *resp, +- const digest_config_rec *conf) +-{ +- return ap_md5(r->pool, +- (unsigned char *) apr_pstrcat(r->pool, conf->ha1, ":", resp->nonce, +- ":", resp->cnonce, NULL)); +-} +- +- +-/* Retrieve current session H(A1). If there is none and "generate" is +- * true then a new session for MD5-sess is generated and stored in the +- * client struct; if generate is false, or a new session could not be +- * generated then NULL is returned (in case of failure to generate the +- * failure reason will have been logged already). +- */ +-static const char *get_session_HA1(const request_rec *r, +- digest_header_rec *resp, +- const digest_config_rec *conf, +- int generate) +-{ +- const char *ha1 = NULL; +- +- /* return the current sessions if there is one */ +- if (resp->opaque && resp->client && resp->client->ha1[0]) { +- return resp->client->ha1; +- } +- else if (!generate) { +- return NULL; +- } +- +- /* generate a new session */ +- if (!resp->client) { +- resp->client = gen_client(r); +- } +- if (resp->client) { +- ha1 = get_userpw_hash(r, resp, conf); +- if (ha1) { +- memcpy(resp->client->ha1, ha1, sizeof(resp->client->ha1)); +- } +- } +- +- return ha1; +-} +- +- +-static void clear_session(const digest_header_rec *resp) +-{ +- if (resp->client) { +- resp->client->ha1[0] = '\0'; +- } +-} +- + /* + * Authorization challenge generation code (for WWW-Authenticate) + */ +@@ -1282,8 +1187,7 @@ static void note_digest_auth_failure(request_rec *r, + + if (resp->opaque == NULL) { + /* new client */ +- if ((conf->check_nc || conf->nonce_lifetime == 0 +- || !strcasecmp(conf->algorithm, "MD5-sess")) ++ if ((conf->check_nc || conf->nonce_lifetime == 0) + && (resp->client = gen_client(r)) != NULL) { + opaque = ltox(r->pool, resp->client->key); + } +@@ -1323,15 +1227,6 @@ static void note_digest_auth_failure(request_rec *r, + memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1); + } + +- /* Setup MD5-sess stuff. Note that we just clear out the session +- * info here, since we can't generate a new session until the request +- * from the client comes in with the cnonce. +- */ +- +- if (!strcasecmp(conf->algorithm, "MD5-sess")) { +- clear_session(resp); +- } +- + /* setup domain attribute. We want to send this attribute wherever + * possible so that the client won't send the Authorization header + * unnecessarily (it's usually > 200 bytes!). +@@ -1597,24 +1492,9 @@ static const char *new_digest(const request_rec *r, + { + const char *ha1, *ha2, *a2; + +- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) { +- ha1 = get_session_HA1(r, resp, conf, 1); +- if (!ha1) { +- return NULL; +- } +- } +- else { +- ha1 = conf->ha1; +- } ++ ha1 = conf->ha1; + +- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) { +- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, ":", +- ap_md5(r->pool, (const unsigned char*) ""), NULL); +- /* TBD */ +- } +- else { +- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); +- } ++ a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); + + return ap_md5(r->pool, +@@ -1854,8 +1734,7 @@ static int authenticate_digest_user(request_rec *r) + } + + if (resp->algorithm != NULL +- && strcasecmp(resp->algorithm, "MD5") +- && strcasecmp(resp->algorithm, "MD5-sess")) { ++ && strcasecmp(resp->algorithm, "MD5")) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01789) + "unknown algorithm `%s' received: %s", + resp->algorithm, r->uri); +@@ -2007,27 +1886,9 @@ static int add_auth_info(request_rec *r) + + /* calculate rspauth attribute + */ +- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) { +- ha1 = get_session_HA1(r, resp, conf, 0); +- if (!ha1) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01795) +- "internal error: couldn't find session " +- "info for user %s", resp->username); +- return !OK; +- } +- } +- else { +- ha1 = conf->ha1; +- } ++ ha1 = conf->ha1; + +- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) { +- a2 = apr_pstrcat(r->pool, ":", resp->uri, ":", +- ap_md5(r->pool,(const unsigned char *) ""), NULL); +- /* TBD */ +- } +- else { +- a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); +- } ++ a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); + + resp_dig = ap_md5(r->pool, diff --git a/SOURCES/httpd-2.4.6-CVE-2019-0217.patch b/SOURCES/httpd-2.4.6-CVE-2019-0217.patch new file mode 100644 index 0000000..69702a1 --- /dev/null +++ b/SOURCES/httpd-2.4.6-CVE-2019-0217.patch @@ -0,0 +1,113 @@ +diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c +index b50bcf9..5bfec82 100644 +--- a/modules/aaa/mod_auth_digest.c ++++ b/modules/aaa/mod_auth_digest.c +@@ -92,7 +92,6 @@ typedef struct digest_config_struct { + int check_nc; + const char *algorithm; + char *uri_list; +- const char *ha1; + } digest_config_rec; + + +@@ -153,6 +152,7 @@ typedef struct digest_header_struct { + apr_time_t nonce_time; + enum hdr_sts auth_hdr_sts; + int needed_auth; ++ const char *ha1; + client_entry *client; + } digest_header_rec; + +@@ -1295,7 +1295,7 @@ static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type) + */ + + static authn_status get_hash(request_rec *r, const char *user, +- digest_config_rec *conf) ++ digest_config_rec *conf, const char **rethash) + { + authn_status auth_result; + char *password; +@@ -1347,7 +1347,7 @@ static authn_status get_hash(request_rec *r, const char *user, + } while (current_provider); + + if (auth_result == AUTH_USER_FOUND) { +- conf->ha1 = password; ++ *rethash = password; + } + + return auth_result; +@@ -1474,25 +1474,24 @@ static int check_nonce(request_rec *r, digest_header_rec *resp, + + /* RFC-2069 */ + static const char *old_digest(const request_rec *r, +- const digest_header_rec *resp, const char *ha1) ++ const digest_header_rec *resp) + { + const char *ha2; + + ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":", + resp->uri, NULL)); + return ap_md5(r->pool, +- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce, +- ":", ha2, NULL)); ++ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":", ++ resp->nonce, ":", ha2, NULL)); + } + + /* RFC-2617 */ + static const char *new_digest(const request_rec *r, +- digest_header_rec *resp, +- const digest_config_rec *conf) ++ digest_header_rec *resp) + { + const char *ha1, *ha2, *a2; + +- ha1 = conf->ha1; ++ ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); +@@ -1505,7 +1504,6 @@ static const char *new_digest(const request_rec *r, + NULL)); + } + +- + static void copy_uri_components(apr_uri_t *dst, + apr_uri_t *src, request_rec *r) { + if (src->scheme && src->scheme[0] != '\0') { +@@ -1742,7 +1740,7 @@ static int authenticate_digest_user(request_rec *r) + return HTTP_UNAUTHORIZED; + } + +- return_code = get_hash(r, r->user, conf); ++ return_code = get_hash(r, r->user, conf, &resp->ha1); + + if (return_code == AUTH_USER_NOT_FOUND) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790) +@@ -1772,7 +1770,7 @@ static int authenticate_digest_user(request_rec *r) + + if (resp->message_qop == NULL) { + /* old (rfc-2069) style digest */ +- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) { ++ if (strcmp(resp->digest, old_digest(r, resp))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792) + "user %s: password mismatch: %s", r->user, + r->uri); +@@ -1802,7 +1800,7 @@ static int authenticate_digest_user(request_rec *r) + return HTTP_UNAUTHORIZED; + } + +- exp_digest = new_digest(r, resp, conf); ++ exp_digest = new_digest(r, resp); + if (!exp_digest) { + /* we failed to allocate a client struct */ + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1886,7 +1884,7 @@ static int add_auth_info(request_rec *r) + + /* calculate rspauth attribute + */ +- ha1 = conf->ha1; ++ ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); diff --git a/SOURCES/httpd-2.4.6-CVE-2019-0220.patch b/SOURCES/httpd-2.4.6-CVE-2019-0220.patch new file mode 100644 index 0000000..94a76ee --- /dev/null +++ b/SOURCES/httpd-2.4.6-CVE-2019-0220.patch @@ -0,0 +1,244 @@ +diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en +index 86d9bee..e08034b 100644 +--- a/docs/manual/mod/core.html.en ++++ b/docs/manual/mod/core.html.en +@@ -90,6 +90,7 @@ available +
  • MaxRangeOverlaps
  • +
  • MaxRangeReversals
  • +
  • MaxRanges
  • ++
  • MergeSlashes
  • +
  • Mutex
  • +
  • NameVirtualHost
  • +
  • Options
  • +@@ -3170,6 +3171,30 @@ resource + + +
    top
    ++

    MergeSlashes Directive

    ++ ++ ++ ++ ++ ++ ++ ++ ++
    Description:Controls whether the server merges consecutive slashes in URLs.
    Syntax:MergeSlashes ON | OFF
    Default:MergeSlashes ON
    Context:server config, virtual host
    Status:Core
    Module:core
    Compatibility:Available in Apache HTTP Server 2.4.6 in Red Hat Enterprise Linux 7
    ++

    By default, the server merges (or collapses) multiple consecutive slash ++ ('/') characters in the path component of the request URL.

    ++ ++

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

    ++
    ++
    top
    +

    Mutex Directive

    + + + ldap-filter. Other authorization types may also be + used but may require that additional authorization modules be loaded.

    + ++

    Since v2.5.0, expressions are supported ++ within the LDAP require directives.

    ++ +

    Require ldap-user

    + +

    The Require ldap-user directive specifies what +@@ -576,6 +579,16 @@ Require ldap-group cn=Administrators, o=Example + + +

  • ++ Grant access to anybody in the group whose name matches the ++ hostname of the virtual host. In this example an ++ expression is used to build the filter. ++ ++AuthLDAPURL ldap://ldap.example.com/o=Example?uid ++Require ldap-group cn=%{SERVER_NAME}, o=Example ++ ++
  • ++ ++
  • + The next example assumes that everyone at Example who + carries an alphanumeric pager will have an LDAP attribute + of qpagePagerID. The example will grant access +diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c +index 2c25dbc..063debe 100644 +--- a/modules/aaa/mod_authnz_ldap.c ++++ b/modules/aaa/mod_authnz_ldap.c +@@ -607,6 +607,10 @@ static authz_status ldapuser_check_authorization(request_rec *r, + + util_ldap_connection_t *ldc = NULL; + ++ const char *err = NULL; ++ const ap_expr_info_t *expr = parsed_require_args; ++ const char *require; ++ + const char *t; + char *w; + +@@ -680,11 +684,19 @@ static authz_status ldapuser_check_authorization(request_rec *r, + return AUTHZ_DENIED; + } + ++ require = ap_expr_str_exec(r, expr, &err); ++ if (err) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02585) ++ "auth_ldap authorize: require user: Can't evaluate expression: %s", ++ err); ++ return AUTHZ_DENIED; ++ } ++ + /* + * First do a whole-line compare, in case it's something like + * require user Babs Jensen + */ +- result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require_args); ++ result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require); + switch(result) { + case LDAP_COMPARE_TRUE: { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01703) +@@ -704,7 +716,7 @@ static authz_status ldapuser_check_authorization(request_rec *r, + /* + * Now break apart the line and compare each word on it + */ +- t = require_args; ++ t = require; + while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { + result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w); + switch(result) { +@@ -744,6 +756,10 @@ static authz_status ldapgroup_check_authorization(request_rec *r, + + util_ldap_connection_t *ldc = NULL; + ++ const char *err = NULL; ++ const ap_expr_info_t *expr = parsed_require_args; ++ const char *require; ++ + const char *t; + + char filtbuf[FILTER_LENGTH]; +@@ -863,7 +879,15 @@ static authz_status ldapgroup_check_authorization(request_rec *r, + } + } + +- t = require_args; ++ require = ap_expr_str_exec(r, expr, &err); ++ if (err) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02586) ++ "auth_ldap authorize: require group: Can't evaluate expression: %s", ++ err); ++ return AUTHZ_DENIED; ++ } ++ ++ t = require; + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01713) + "auth_ldap authorize: require group: testing for group " +@@ -959,6 +983,10 @@ static authz_status ldapdn_check_authorization(request_rec *r, + + util_ldap_connection_t *ldc = NULL; + ++ const char *err = NULL; ++ const ap_expr_info_t *expr = parsed_require_args; ++ const char *require; ++ + const char *t; + + char filtbuf[FILTER_LENGTH]; +@@ -1021,7 +1049,15 @@ static authz_status ldapdn_check_authorization(request_rec *r, + req->user = r->user; + } + +- t = require_args; ++ require = ap_expr_str_exec(r, expr, &err); ++ if (err) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02587) ++ "auth_ldap authorize: require dn: Can't evaluate expression: %s", ++ err); ++ return AUTHZ_DENIED; ++ } ++ ++ t = require; + + if (req->dn == NULL || strlen(req->dn) == 0) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01725) +@@ -1068,6 +1104,10 @@ static authz_status ldapattribute_check_authorization(request_rec *r, + + util_ldap_connection_t *ldc = NULL; + ++ const char *err = NULL; ++ const ap_expr_info_t *expr = parsed_require_args; ++ const char *require; ++ + const char *t; + char *w, *value; + +@@ -1138,7 +1178,16 @@ static authz_status ldapattribute_check_authorization(request_rec *r, + return AUTHZ_DENIED; + } + +- t = require_args; ++ require = ap_expr_str_exec(r, expr, &err); ++ if (err) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02588) ++ "auth_ldap authorize: require ldap-attribute: Can't " ++ "evaluate expression: %s", err); ++ return AUTHZ_DENIED; ++ } ++ ++ t = require; ++ + while (t[0]) { + w = ap_getword(r->pool, &t, '='); + value = ap_getword_conf(r->pool, &t); +@@ -1183,6 +1232,11 @@ static authz_status ldapfilter_check_authorization(request_rec *r, + (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); + + util_ldap_connection_t *ldc = NULL; ++ ++ const char *err = NULL; ++ const ap_expr_info_t *expr = parsed_require_args; ++ const char *require; ++ + const char *t; + + char filtbuf[FILTER_LENGTH]; +@@ -1252,7 +1306,15 @@ static authz_status ldapfilter_check_authorization(request_rec *r, + return AUTHZ_DENIED; + } + +- t = require_args; ++ require = ap_expr_str_exec(r, expr, &err); ++ if (err) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02589) ++ "auth_ldap authorize: require ldap-filter: Can't " ++ "evaluate require expression: %s", err); ++ return AUTHZ_DENIED; ++ } ++ ++ t = require; + + if (t[0]) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01743) +@@ -1311,6 +1373,25 @@ static authz_status ldapfilter_check_authorization(request_rec *r, + return AUTHZ_DENIED; + } + ++static const char *ldap_parse_config(cmd_parms *cmd, const char *require_line, ++ const void **parsed_require_line) ++{ ++ const char *expr_err = NULL; ++ ap_expr_info_t *expr; ++ ++ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, ++ &expr_err, NULL); ++ ++ if (expr_err) ++ return apr_pstrcat(cmd->temp_pool, ++ "Cannot parse expression in require line: ", ++ expr_err, NULL); ++ ++ *parsed_require_line = expr; ++ ++ return NULL; ++} ++ + + /* + * Use the ldap url parsing routines to break up the ldap url into +@@ -1769,30 +1850,30 @@ static const authn_provider authn_ldap_provider = + static const authz_provider authz_ldapuser_provider = + { + &ldapuser_check_authorization, +- NULL, ++ &ldap_parse_config, + }; + static const authz_provider authz_ldapgroup_provider = + { + &ldapgroup_check_authorization, +- NULL, ++ &ldap_parse_config, + }; + + static const authz_provider authz_ldapdn_provider = + { + &ldapdn_check_authorization, +- NULL, ++ &ldap_parse_config, + }; + + static const authz_provider authz_ldapattribute_provider = + { + &ldapattribute_check_authorization, +- NULL, ++ &ldap_parse_config, + }; + + static const authz_provider authz_ldapfilter_provider = + { + &ldapfilter_check_authorization, +- NULL, ++ &ldap_parse_config, + }; + + static void ImportULDAPOptFn(void) diff --git a/SOURCES/httpd-2.4.6-r1737363.patch b/SOURCES/httpd-2.4.6-r1737363.patch new file mode 100644 index 0000000..90d3101 --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1737363.patch @@ -0,0 +1,26 @@ +# ./pullrev.sh 1737363 +http://svn.apache.org/viewvc?view=revision&revision=1737363 + +--- httpd-2.4.6/modules/proxy/mod_proxy_express.c ++++ httpd-2.4.6/modules/proxy/mod_proxy_express.c +@@ -145,16 +145,14 @@ + key.dsize = strlen(key.dptr); + + rv = apr_dbm_fetch(db, key, &val); ++ if (rv == APR_SUCCESS) { ++ backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); ++ } + apr_dbm_close(db); +- if (rv != APR_SUCCESS) { ++ if (rv != APR_SUCCESS || !backend) { + return DECLINED; + } + +- backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); +- if (!backend) { +- return DECLINED; +- } +- + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01004) + "proxy_express: found %s -> %s", name, backend); + r->filename = apr_pstrcat(r->pool, "proxy:", backend, r->uri, NULL); diff --git a/SOURCES/httpd-2.4.6-r1824872.patch b/SOURCES/httpd-2.4.6-r1824872.patch new file mode 100644 index 0000000..2cec77f --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1824872.patch @@ -0,0 +1,25 @@ +--- a/modules/ldap/util_ldap.c 2018/02/20 13:00:39 1824871 ++++ b/modules/ldap/util_ldap.c 2018/02/20 13:02:54 1824872 +@@ -2858,7 +2858,6 @@ + st->search_cache_size = base->search_cache_size; + st->compare_cache_ttl = base->compare_cache_ttl; + st->compare_cache_size = base->compare_cache_size; +- st->util_ldap_cache_lock = base->util_ldap_cache_lock; + + st->connections = NULL; + st->ssl_supported = 0; /* not known until post-config and re-merged */ +@@ -2977,12 +2976,12 @@ + st_vhost = (util_ldap_state_t *) + ap_get_module_config(s_vhost->module_config, + &ldap_module); +- ++ st_vhost->util_ldap_cache = st->util_ldap_cache; ++ st_vhost->util_ldap_cache_lock = st->util_ldap_cache_lock; + #if APR_HAS_SHARED_MEMORY + st_vhost->cache_shm = st->cache_shm; + st_vhost->cache_rmm = st->cache_rmm; + st_vhost->cache_file = st->cache_file; +- st_vhost->util_ldap_cache = st->util_ldap_cache; + ap_log_error(APLOG_MARK, APLOG_DEBUG, result, s, APLOGNO(01316) + "LDAP merging Shared Cache conf: shm=0x%pp rmm=0x%pp " + "for VHOST: %s", st->cache_shm, st->cache_rmm, diff --git a/SOURCES/httpd-2.4.6-r1825120.patch b/SOURCES/httpd-2.4.6-r1825120.patch new file mode 100644 index 0000000..f490839 --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1825120.patch @@ -0,0 +1,96 @@ +diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c +index 57b76c0..814ec4f 100644 +--- a/modules/ssl/ssl_engine_init.c ++++ b/modules/ssl/ssl_engine_init.c +@@ -1522,70 +1522,18 @@ void ssl_init_CheckServers(SSLModConfigRec *mc, server_rec *base_server, apr_poo + } + } + +-static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, +- const X509_NAME * const *b) +-{ +- return(X509_NAME_cmp(*a, *b)); +-} +- +-static void ssl_init_PushCAList(STACK_OF(X509_NAME) *ca_list, +- server_rec *s, apr_pool_t *ptemp, +- const char *file) +-{ +- int n; +- STACK_OF(X509_NAME) *sk; +- +- sk = (STACK_OF(X509_NAME) *) +- SSL_load_client_CA_file(file); +- +- if (!sk) { +- return; +- } +- +- for (n = 0; n < sk_X509_NAME_num(sk); n++) { +- X509_NAME *name = sk_X509_NAME_value(sk, n); +- +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02209) +- "CA certificate: %s", +- SSL_X509_NAME_to_string(ptemp, name, 0)); +- +- /* +- * note that SSL_load_client_CA_file() checks for duplicates, +- * but since we call it multiple times when reading a directory +- * we must also check for duplicates ourselves. +- */ +- +- if (sk_X509_NAME_find(ca_list, name) < 0) { +- /* this will be freed when ca_list is */ +- sk_X509_NAME_push(ca_list, name); +- } +- else { +- /* need to free this ourselves, else it will leak */ +- X509_NAME_free(name); +- } +- } +- +- sk_X509_NAME_free(sk); +-} +- + STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, + apr_pool_t *ptemp, + const char *ca_file, + const char *ca_path) + { +- STACK_OF(X509_NAME) *ca_list; +- +- /* +- * Start with a empty stack/list where new +- * entries get added in sorted order. +- */ +- ca_list = sk_X509_NAME_new(ssl_init_FindCAList_X509NameCmp); ++ STACK_OF(X509_NAME) *ca_list = sk_X509_NAME_new_null();; + + /* + * Process CA certificate bundle file + */ + if (ca_file) { +- ssl_init_PushCAList(ca_list, s, ptemp, ca_file); ++ SSL_add_file_cert_subjects_to_stack(ca_list, ca_file); + /* + * If ca_list is still empty after trying to load ca_file + * then the file failed to load, and users should hear about that. +@@ -1619,17 +1567,12 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, + continue; /* don't try to load directories */ + } + file = apr_pstrcat(ptemp, ca_path, "/", direntry.name, NULL); +- ssl_init_PushCAList(ca_list, s, ptemp, file); ++ SSL_add_file_cert_subjects_to_stack(ca_list, file); + } + + apr_dir_close(dir); + } + +- /* +- * Cleanup +- */ +- (void) sk_X509_NAME_set_cmp_func(ca_list, NULL); +- + return ca_list; + } + diff --git a/SOURCES/httpd-2.4.6-r1826995.patch b/SOURCES/httpd-2.4.6-r1826995.patch new file mode 100644 index 0000000..abbcb33 --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1826995.patch @@ -0,0 +1,198 @@ +diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en +index 4580f1c..fb8202e 100644 +--- a/docs/manual/mod/mod_ssl.html.en ++++ b/docs/manual/mod/mod_ssl.html.en +@@ -991,7 +991,8 @@ the certificate being verified.

    +

    This option enables OCSP validation of the client certificate + chain. If this option is enabled, certificates in the client's + certificate chain will be validated against an OCSP responder after +-normal verification (including CRL checks) have taken place.

    ++normal verification (including CRL checks) have taken place. In ++mode 'leaf', only the client certificate itself will be validated.

    + +

    The OCSP responder used is either extracted from the certificate + itself, or derived by configuration; see the +diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c +index 4a8b661..e637a9d 100644 +--- a/modules/ssl/mod_ssl.c ++++ b/modules/ssl/mod_ssl.c +@@ -227,8 +227,8 @@ static const command_rec ssl_config_cmds[] = { + "request body if a per-location SSL renegotiation is required due to " + "changed access control requirements") + +- SSL_CMD_SRV(OCSPEnable, FLAG, +- "Enable use of OCSP to verify certificate revocation ('on', 'off')") ++ SSL_CMD_SRV(OCSPEnable, RAW_ARGS, ++ "Enable use of OCSP to verify certificate revocation mode ('on', 'leaf', 'off')") + SSL_CMD_SRV(OCSPDefaultResponder, TAKE1, + "URL of the default OCSP Responder") + SSL_CMD_SRV(OCSPOverrideResponder, FLAG, +diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c +index 86a7f0f..714aee9 100644 +--- a/modules/ssl/ssl_engine_config.c ++++ b/modules/ssl/ssl_engine_config.c +@@ -130,7 +130,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx) + mctx->auth.verify_depth = UNSET; + mctx->auth.verify_mode = SSL_CVERIFY_UNSET; + +- mctx->ocsp_enabled = FALSE; ++ mctx->ocsp_mask = UNSET; + mctx->ocsp_force_default = FALSE; + mctx->ocsp_responder = NULL; + mctx->ocsp_resptime_skew = UNSET; +@@ -264,7 +264,7 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base, + cfgMergeInt(auth.verify_depth); + cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET); + +- cfgMergeBool(ocsp_enabled); ++ cfgMergeInt(ocsp_mask); + cfgMergeBool(ocsp_force_default); + cfgMerge(ocsp_responder, NULL); + cfgMergeInt(ocsp_resptime_skew); +@@ -1575,11 +1575,46 @@ const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, + return NULL; + } + +-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) ++static const char *ssl_cmd_ocspcheck_parse(cmd_parms *parms, ++ const char *arg, ++ int *mask) + { +- SSLSrvConfigRec *sc = mySrvConfig(cmd->server); ++ const char *w; ++ ++ w = ap_getword_conf(parms->temp_pool, &arg); ++ if (strcEQ(w, "off")) { ++ *mask = SSL_OCSPCHECK_NONE; ++ } ++ else if (strcEQ(w, "leaf")) { ++ *mask = SSL_OCSPCHECK_LEAF; ++ } ++ else if (strcEQ(w, "on")) { ++ *mask = SSL_OCSPCHECK_CHAIN; ++ } ++ else { ++ return apr_pstrcat(parms->temp_pool, parms->cmd->name, ++ ": Invalid argument '", w, "'", ++ NULL); ++ } ++ ++ while (*arg) { ++ w = ap_getword_conf(parms->temp_pool, &arg); ++ if (strcEQ(w, "no_ocsp_for_cert_ok")) { ++ *mask |= SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK; ++ } ++ else { ++ return apr_pstrcat(parms->temp_pool, parms->cmd->name, ++ ": Invalid argument '", w, "'", ++ NULL); ++ } ++ } + +- sc->server->ocsp_enabled = flag ? TRUE : FALSE; ++ return NULL; ++} ++ ++const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg) ++{ ++ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + #ifdef OPENSSL_NO_OCSP + if (flag) { +@@ -1588,7 +1623,7 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) + } + #endif + +- return NULL; ++ return ssl_cmd_ocspcheck_parse(cmd, arg, &sc->server->ocsp_mask); + } + + const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag) +diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c +index 672760c..57b76c0 100644 +--- a/modules/ssl/ssl_engine_init.c ++++ b/modules/ssl/ssl_engine_init.c +@@ -762,6 +762,10 @@ static void ssl_init_ctx_crl(server_rec *s, + unsigned long crlflags = 0; + char *cfgp = mctx->pkp ? "SSLProxy" : "SSL"; + ++ if (mctx->ocsp_mask == UNSET) { ++ mctx->ocsp_mask = SSL_OCSPCHECK_NONE; ++ } ++ + /* + * Configure Certificate Revocation List (CRL) Details + */ +diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c +index 5ff35f5..9dc236c 100644 +--- a/modules/ssl/ssl_engine_kernel.c ++++ b/modules/ssl/ssl_engine_kernel.c +@@ -1416,7 +1416,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) + /* + * Perform OCSP-based revocation checks + */ +- if (ok && sc->server->ocsp_enabled) { ++ if (ok && ((sc->server->ocsp_mask & SSL_OCSPCHECK_CHAIN) || ++ (errdepth == 0 && (sc->server->ocsp_mask & SSL_OCSPCHECK_LEAF)))) { + /* If there was an optional verification error, it's not + * possible to perform OCSP validation since the issuer may be + * missing/untrusted. Fail in that case. */ +diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c +index 90da5c2..58d267b 100644 +--- a/modules/ssl/ssl_engine_ocsp.c ++++ b/modules/ssl/ssl_engine_ocsp.c +@@ -136,7 +136,14 @@ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, + + ruri = determine_responder_uri(sc, cert, c, pool); + if (!ruri) { +- return V_OCSP_CERTSTATUS_UNKNOWN; ++ if (sc->server->ocsp_mask & SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK) { ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, ++ "Skipping OCSP check for certificate cos no OCSP URL" ++ " found and no_ocsp_for_cert_ok is set"); ++ return V_OCSP_CERTSTATUS_GOOD; ++ } else { ++ return V_OCSP_CERTSTATUS_UNKNOWN; ++ } + } + + request = create_request(ctx, cert, &certID, s, pool); +diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h +index b601316..2d505f9 100644 +--- a/modules/ssl/ssl_private.h ++++ b/modules/ssl/ssl_private.h +@@ -379,6 +379,16 @@ typedef enum { + } ssl_crlcheck_t; + + /** ++ * OCSP checking mask (mode | flags) ++ */ ++typedef enum { ++ SSL_OCSPCHECK_NONE = (0), ++ SSL_OCSPCHECK_LEAF = (1 << 0), ++ SSL_OCSPCHECK_CHAIN = (1 << 1), ++ SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK = (1 << 2) ++} ssl_ocspcheck_t; ++ ++/** + * Define the SSL pass phrase dialog types + */ + typedef enum { +@@ -668,7 +678,7 @@ typedef struct { + + modssl_auth_ctx_t auth; + +- BOOL ocsp_enabled; /* true if OCSP verification enabled */ ++ int ocsp_mask; + BOOL ocsp_force_default; /* true if the default responder URL is + * used regardless of per-cert URL */ + const char *ocsp_responder; /* default responder URL */ +@@ -796,7 +806,7 @@ const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const ch + const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg); + const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg); + const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); +-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); ++const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *flag); + + #ifndef OPENSSL_NO_SRP + const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg); diff --git a/SOURCES/httpd-2.4.6-r1833014.patch b/SOURCES/httpd-2.4.6-r1833014.patch new file mode 100644 index 0000000..9a8f455 --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1833014.patch @@ -0,0 +1,83 @@ +diff --git a/modules/http/http_request.c b/modules/http/http_request.c +index c97dc77..9885de4 100644 +--- a/modules/http/http_request.c ++++ b/modules/http/http_request.c +@@ -227,11 +227,21 @@ AP_DECLARE(void) ap_die(int type, request_rec *r) + ap_die_r(type, r, r->status); + } + +-static void check_pipeline(conn_rec *c) ++#define RETRIEVE_BRIGADE_FROM_POOL(bb, key, pool, allocator) do { \ ++ apr_pool_userdata_get((void **)&bb, key, pool); \ ++ if (bb == NULL) { \ ++ bb = apr_brigade_create(pool, allocator); \ ++ apr_pool_userdata_setn((const void *)bb, key, NULL, pool); \ ++ } \ ++ else { \ ++ apr_brigade_cleanup(bb); \ ++ } \ ++} while(0) ++ ++static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb) + { + if (c->keepalive != AP_CONN_CLOSE) { + apr_status_t rv; +- apr_bucket_brigade *bb = apr_brigade_create(c->pool, c->bucket_alloc); + + rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE, + APR_NONBLOCK_READ, 1); +@@ -245,11 +255,10 @@ static void check_pipeline(conn_rec *c) + else { + c->data_in_input_filters = 1; + } +- apr_brigade_destroy(bb); ++ apr_brigade_cleanup(bb); + } + } + +- + AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) + { + apr_bucket_brigade *bb; +@@ -260,11 +269,13 @@ AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) + * this bucket is destroyed, the request will be logged and + * its pool will be freed + */ +- bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc); ++ RETRIEVE_BRIGADE_FROM_POOL(bb, "ap_process_request_after_handler_brigade", ++ c->pool, c->bucket_alloc); + b = ap_bucket_eor_create(r->connection->bucket_alloc, r); + APR_BRIGADE_INSERT_HEAD(bb, b); + + ap_pass_brigade(r->connection->output_filters, bb); ++ apr_brigade_cleanup(bb); + + /* From here onward, it is no longer safe to reference r + * or r->pool, because r->pool may have been destroyed +@@ -273,7 +284,7 @@ AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) + + if (c->cs) + c->cs->state = CONN_STATE_WRITE_COMPLETION; +- check_pipeline(c); ++ check_pipeline(c, bb); + AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, r->status); + if (ap_extended_status) { + ap_time_process_request(c->sbh, STOP_PREQUEST); +@@ -363,7 +374,8 @@ void ap_process_request(request_rec *r) + ap_process_async_request(r); + + if (!c->data_in_input_filters) { +- bb = apr_brigade_create(c->pool, c->bucket_alloc); ++ RETRIEVE_BRIGADE_FROM_POOL(bb, "ap_process_request_after_handler_brigade", ++ c->pool, c->bucket_alloc); + b = apr_bucket_flush_create(c->bucket_alloc); + APR_BRIGADE_INSERT_HEAD(bb, b); + rv = ap_pass_brigade(c->output_filters, bb); +@@ -380,6 +392,7 @@ void ap_process_request(request_rec *r) + "Timeout while writing data for URI %s to the" + " client", r->unparsed_uri); + } ++ apr_brigade_cleanup(bb); + } + if (ap_extended_status) { + ap_time_process_request(c->sbh, STOP_PREQUEST); diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec index fbd1d03..b68a3b9 100644 --- a/SPECS/httpd.spec +++ b/SPECS/httpd.spec @@ -15,9 +15,10 @@ Summary: Apache HTTP Server Name: httpd Version: 2.4.6 -Release: 80%{?dist} +Release: 90%{?dist} URL: http://httpd.apache.org/ -Source0: http://archive.apache.org/dist/httpd/httpd-%{version}.tar.bz2 +Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 +### TODO: we need to create a powerel version #Source1: centos-noindex.tar.gz Source2: httpd.logrotate Source3: httpd.sysconf @@ -135,6 +136,7 @@ Patch111: httpd-2.4.6-r1348019.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1396197 Patch112: httpd-2.4.6-r1587053.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1376835 +# https://bugzilla.redhat.com/show_bug.cgi?id=1527295 Patch113: httpd-2.4.6-mpm-segfault.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1372692 Patch114: httpd-2.4.6-r1681114.patch @@ -174,6 +176,22 @@ Patch130: httpd-2.4.6-r1811976.patch Patch131: httpd-2.4.6-r1650310.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1557785 Patch132: httpd-2.4.6-r1530999.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1533793 +Patch133: httpd-2.4.6-r1555539.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1523536 +Patch134: httpd-2.4.6-r1737363.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1548501 +Patch135: httpd-2.4.6-r1826995.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1556761 +Patch136: httpd-2.4.6-default-port-worker.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1493181 +Patch137: httpd-2.4.6-r1825120.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1458364 +Patch138: httpd-2.4.6-r1515372.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1458364 +Patch139: httpd-2.4.6-r1824872.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1583218 +Patch140: httpd-2.4.6-r1833014.patch # Security fixes Patch200: httpd-2.4.6-CVE-2013-6438.patch @@ -197,6 +215,9 @@ Patch217: httpd-2.4.6-CVE-2017-7668.patch Patch218: httpd-2.4.6-CVE-2017-7679.patch Patch219: httpd-2.4.6-CVE-2017-9788.patch Patch220: httpd-2.4.6-CVE-2017-9798.patch +Patch221: httpd-2.4.6-CVE-2018-1312.patch +Patch222: httpd-2.4.6-CVE-2019-0217.patch +Patch223: httpd-2.4.6-CVE-2019-0220.patch License: ASL 2.0 Group: System Environment/Daemons @@ -504,6 +525,8 @@ export LYNX_PATH=/usr/bin/links --enable-cgid --enable-cgi \ --enable-authn-anon --enable-authn-alias \ --disable-imagemap \ + --disable-lua \ + --disable-luajit \ $* make %{?_smp_mflags} @@ -609,8 +632,8 @@ rm -v $RPM_BUILD_ROOT%{docroot}/html/*.html \ $RPM_BUILD_ROOT%{docroot}/cgi-bin/* # Symlink for the powered-by-$DISTRO image: -ln -s ../noindex/images/poweredby.png \ - $RPM_BUILD_ROOT%{contentdir}/icons/poweredby.png +#ln -s ../noindex/images/poweredby.png \ +# $RPM_BUILD_ROOT%{contentdir}/icons/poweredby.png # symlinks for /etc/httpd ln -s ../..%{_localstatedir}/log/httpd $RPM_BUILD_ROOT/etc/httpd/logs @@ -790,12 +813,12 @@ rm -rf $RPM_BUILD_ROOT %dir %{contentdir}/icons %dir %{contentdir}/error %dir %{contentdir}/error/include -%dir %{contentdir}/noindex +#%dir %{contentdir}/noindex %{contentdir}/icons/* %{contentdir}/error/README %{contentdir}/error/*.var %{contentdir}/error/include/*.html -%{contentdir}/noindex/* +#%{contentdir}/noindex/* %dir %{docroot} %dir %{docroot}/cgi-bin

  • Description:Configures mutex mechanism and lock file directory for all +diff --git a/include/http_core.h b/include/http_core.h +index c05d06e..76bf5a4 100644 +--- a/include/http_core.h ++++ b/include/http_core.h +@@ -465,6 +465,17 @@ typedef unsigned long etag_components_t; + /* This is the default value used */ + #define ETAG_BACKWARD (ETAG_MTIME | ETAG_SIZE) + ++/* Generic ON/OFF/UNSET for unsigned int foo :2 */ ++#define AP_CORE_CONFIG_OFF (0) ++#define AP_CORE_CONFIG_ON (1) ++#define AP_CORE_CONFIG_UNSET (2) ++ ++/* Generic merge of flag */ ++#define AP_CORE_MERGE_FLAG(field, to, base, over) to->field = \ ++ over->field != AP_CORE_CONFIG_UNSET \ ++ ? over->field \ ++ : base->field ++ + /** + * @brief Server Signature Enumeration + */ +@@ -682,7 +693,7 @@ typedef struct { + #define AP_HTTP_METHODS_LENIENT 1 + #define AP_HTTP_METHODS_REGISTERED 2 + char http_methods; +- ++ unsigned int merge_slashes; + } core_server_config; + + /* for AddOutputFiltersByType in core.c */ +diff --git a/include/httpd.h b/include/httpd.h +index 176ef5e..a552358 100644 +--- a/include/httpd.h ++++ b/include/httpd.h +@@ -1622,11 +1622,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes); + AP_DECLARE(int) ap_unescape_urlencoded(char *query); + + /** +- * Convert all double slashes to single slashes +- * @param name The string to convert ++ * Convert all double slashes to single slashes, except where significant ++ * to the filesystem on the current platform. ++ * @param name The string to convert, assumed to be a filesystem path + */ + AP_DECLARE(void) ap_no2slash(char *name); + ++/** ++ * Convert all double slashes to single slashes, except where significant ++ * to the filesystem on the current platform. ++ * @param name The string to convert ++ * @param is_fs_path if set to 0, the significance of any double-slashes is ++ * ignored. ++ */ ++AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path); ++ + /** + * Remove all ./ and xx/../ substrings from a file name. Also remove + * any leading ../ or /../ substrings. +diff --git a/server/core.c b/server/core.c +index 0e69f8c..67efd7e 100644 +--- a/server/core.c ++++ b/server/core.c +@@ -476,6 +476,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) + */ + + conf->trace_enable = AP_TRACE_UNSET; ++ conf->merge_slashes = AP_CORE_CONFIG_UNSET; + + return (void *)conf; + } +@@ -536,6 +537,8 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) + ? virt->merge_trailers + : base->merge_trailers; + ++ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt); ++ + return conf; + } + +@@ -1673,6 +1676,13 @@ static const char *set_override(cmd_parms *cmd, void *d_, const char *l) + return NULL; + } + ++static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag) ++{ ++ core_server_config *conf = ++ ap_get_core_module_config(cmd->server->module_config); ++ return ap_set_flag_slot(cmd, conf, flag); ++} ++ + static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) + { + core_dir_config *d = d_; +@@ -4216,6 +4226,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON + , + AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF, + "Registers non-standard HTTP methods"), ++AP_INIT_FLAG("MergeSlashes", set_core_server_flag, ++ (void *)APR_OFFSETOF(core_server_config, merge_slashes), ++ RSRC_CONF, ++ "Controls whether consecutive slashes in the URI path are merged"), + { NULL } + }; + +diff --git a/server/request.c b/server/request.c +index 4eef097..cba3891 100644 +--- a/server/request.c ++++ b/server/request.c +@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + int file_req = (r->main && r->filename); + int access_status; + core_dir_config *d; ++ core_server_config *sconf = ++ ap_get_core_module_config(r->server->module_config); + + /* Ignore embedded %2F's in path for proxy requests */ + if (!r->proxyreq && r->parsed_uri.path) { +@@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + } + + ap_getparents(r->uri); /* OK --- shrinking transformations... */ ++ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { ++ ap_no2slash(r->uri); ++ if (r->parsed_uri.path) { ++ ap_no2slash(r->parsed_uri.path); ++ } ++ } + + /* All file subrequests are a huge pain... they cannot bubble through the + * next several steps. Only file subrequests are allowed an empty uri, +@@ -1383,20 +1391,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) + + cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); + cached = (cache->cached != NULL); +- +- /* Location and LocationMatch differ on their behaviour w.r.t. multiple +- * slashes. Location matches multiple slashes with a single slash, +- * LocationMatch doesn't. An exception, for backwards brokenness is +- * absoluteURIs... in which case neither match multiple slashes. +- */ +- if (r->uri[0] != '/') { +- entry_uri = r->uri; +- } +- else { +- char *uri = apr_pstrdup(r->pool, r->uri); +- ap_no2slash(uri); +- entry_uri = uri; +- } ++ entry_uri = r->uri; + + /* If we have an cache->cached location that matches r->uri, + * and the vhost's list of locations hasn't changed, we can skip +@@ -1449,7 +1444,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) + * terminated (or at the end of the string) to match. + */ + if (entry_core->r +- ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0) ++ ? ap_regexec(entry_core->r, entry_uri, 0, NULL, 0) + : (entry_core->d_is_fnmatch + ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME) + : (strncmp(entry_core->d, cache->cached, len) +diff --git a/server/util.c b/server/util.c +index f9e3b51..4eac462 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -561,16 +561,20 @@ AP_DECLARE(void) ap_getparents(char *name) + name[l] = '\0'; + } + } +- +-AP_DECLARE(void) ap_no2slash(char *name) ++AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) + { ++ + char *d, *s; + ++ if (!*name) { ++ return; ++ } ++ + s = d = name; + + #ifdef HAVE_UNC_PATHS + /* Check for UNC names. Leave leading two slashes. */ +- if (s[0] == '/' && s[1] == '/') ++ if (is_fs_path && s[0] == '/' && s[1] == '/') + *d++ = *s++; + #endif + +@@ -587,6 +591,10 @@ AP_DECLARE(void) ap_no2slash(char *name) + *d = '\0'; + } + ++AP_DECLARE(void) ap_no2slash(char *name) ++{ ++ ap_no2slash_ex(name, 1); ++} + + /* + * copy at most n leading directories of s into d diff --git a/SOURCES/httpd-2.4.6-default-port-worker.patch b/SOURCES/httpd-2.4.6-default-port-worker.patch new file mode 100644 index 0000000..25315e2 --- /dev/null +++ b/SOURCES/httpd-2.4.6-default-port-worker.patch @@ -0,0 +1,13 @@ +diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c +index e672e4a..8be833a 100644 +--- a/modules/proxy/proxy_util.c ++++ b/modules/proxy/proxy_util.c +@@ -3557,6 +3557,8 @@ static proxy_schemes_t pschemes[] = + {"fcgi", 8000}, + {"ajp", AJP13_DEF_PORT}, + {"scgi", 4000}, ++ {"ws", 80}, ++ {"wss", 443}, + { NULL, 0xFFFF } /* unknown port */ + }; + diff --git a/SOURCES/httpd-2.4.6-mpm-segfault.patch b/SOURCES/httpd-2.4.6-mpm-segfault.patch index d42be44..55a6d08 100644 --- a/SOURCES/httpd-2.4.6-mpm-segfault.patch +++ b/SOURCES/httpd-2.4.6-mpm-segfault.patch @@ -8,3 +8,14 @@ if (one_process) { /* not worth thinking about */ + +--- a/server/mpm/worker/worker.c ++++ b/server/mpm/worker/worker.c +@@ -1902,6 +1902,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) + + /* we've been told to restart */ + apr_signal(SIGHUP, SIG_IGN); ++ apr_signal(AP_SIG_GRACEFUL, SIG_IGN); + + if (one_process) { + /* not worth thinking about */ diff --git a/SOURCES/httpd-2.4.6-r1515372.patch b/SOURCES/httpd-2.4.6-r1515372.patch new file mode 100644 index 0000000..dc782ac --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1515372.patch @@ -0,0 +1,11 @@ +--- a/modules/ldap/util_ldap_cache.c 2013/08/19 11:41:29 1515371 ++++ b/modules/ldap/util_ldap_cache.c 2013/08/19 11:45:19 1515372 +@@ -52,7 +52,7 @@ + + if (node) { + if (!(node->url = util_ald_strdup(cache, n->url))) { +- util_ald_free(cache, node->url); ++ util_ald_free(cache, node); + return NULL; + } + node->search_cache = n->search_cache; diff --git a/SOURCES/httpd-2.4.6-r1555539.patch b/SOURCES/httpd-2.4.6-r1555539.patch new file mode 100644 index 0000000..414d127 --- /dev/null +++ b/SOURCES/httpd-2.4.6-r1555539.patch @@ -0,0 +1,265 @@ +diff --git a/docs/manual/expr.html.en b/docs/manual/expr.html.en +index 5c3ae45..8bd941a 100644 +--- a/docs/manual/expr.html.en ++++ b/docs/manual/expr.html.en +@@ -46,7 +46,7 @@ +
  • Other
  • +
  • Comparison with SSLRequire
  • +
  • Version History
  • +-

    See also

    ++

    See also

    +
    top
    +
    +

    Grammar in Backus-Naur Form notation

    +diff --git a/docs/manual/mod/mod_authnz_ldap.html.en b/docs/manual/mod/mod_authnz_ldap.html.en +index 7199052..c86dc8a 100644 +--- a/docs/manual/mod/mod_authnz_ldap.html.en ++++ b/docs/manual/mod/mod_authnz_ldap.html.en +@@ -350,6 +350,9 @@ for HTTP Basic authentication.