diff --git a/SOURCES/httpd-2.4.25-CVE-2017-3167.patch b/SOURCES/httpd-2.4.25-CVE-2017-3167.patch new file mode 100644 index 0000000..36cffc2 --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-3167.patch @@ -0,0 +1,163 @@ +diff --git a/include/http_protocol.h b/include/http_protocol.h +index a9e0990..29d887c 100644 +--- a/include/http_protocol.h ++++ b/include/http_protocol.h +@@ -558,7 +558,11 @@ AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r); + AP_DECLARE_HOOK(int, note_auth_failure, (request_rec *r, const char *auth_type)) + + /** +- * Get the password from the request headers ++ * Get the password from the request headers. This function has multiple side ++ * effects due to its prior use in the old authentication framework. ++ * ap_get_basic_auth_components() should be preferred. ++ * ++ * @deprecated @see ap_get_basic_auth_components + * @param r The current request + * @param pw The password as set in the headers + * @return 0 (OK) if it set the 'pw' argument (and assured +@@ -571,6 +575,25 @@ AP_DECLARE_HOOK(int, note_auth_failure, (request_rec *r, const char *auth_type)) + */ + AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw); + ++#define AP_GET_BASIC_AUTH_PW_NOTE "AP_GET_BASIC_AUTH_PW_NOTE" ++ ++/** ++ * Get the username and/or password from the request's Basic authentication ++ * headers. Unlike ap_get_basic_auth_pw(), calling this function has no side ++ * effects on the passed request_rec. ++ * ++ * @param r The current request ++ * @param username If not NULL, set to the username sent by the client ++ * @param password If not NULL, set to the password sent by the client ++ * @return APR_SUCCESS if the credentials were successfully parsed and returned; ++ * APR_EINVAL if there was no authentication header sent or if the ++ * client was not using the Basic authentication scheme. username and ++ * password are unchanged on failure. ++ */ ++AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r, ++ const char **username, ++ const char **password); ++ + /** + * parse_uri: break apart the uri + * @warning Side Effects: +diff --git a/server/protocol.c b/server/protocol.c +index 63b358d..32d6123 100644 +--- a/server/protocol.c ++++ b/server/protocol.c +@@ -1593,6 +1593,7 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw) + + t = ap_pbase64decode(r->pool, auth_line); + r->user = ap_getword_nulls (r->pool, &t, ':'); ++ apr_table_setn(r->notes, AP_GET_BASIC_AUTH_PW_NOTE, "1"); + r->ap_auth_type = "Basic"; + + *pw = t; +@@ -1600,6 +1601,53 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw) + return OK; + } + ++AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r, ++ const char **username, ++ const char **password) ++{ ++ const char *auth_header; ++ const char *credentials; ++ const char *decoded; ++ const char *user; ++ ++ auth_header = (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" ++ : "Authorization"; ++ credentials = apr_table_get(r->headers_in, auth_header); ++ ++ if (!credentials) { ++ /* No auth header. */ ++ return APR_EINVAL; ++ } ++ ++ if (ap_cstr_casecmp(ap_getword(r->pool, &credentials, ' '), "Basic")) { ++ /* These aren't Basic credentials. */ ++ return APR_EINVAL; ++ } ++ ++ while (*credentials == ' ' || *credentials == '\t') { ++ credentials++; ++ } ++ ++ /* XXX Our base64 decoding functions don't actually error out if the string ++ * we give it isn't base64; they'll just silently stop and hand us whatever ++ * they've parsed up to that point. ++ * ++ * Since this function is supposed to be a drop-in replacement for the ++ * deprecated ap_get_basic_auth_pw(), don't fix this for 2.4.x. ++ */ ++ decoded = ap_pbase64decode(r->pool, credentials); ++ user = ap_getword_nulls(r->pool, &decoded, ':'); ++ ++ if (username) { ++ *username = user; ++ } ++ if (password) { ++ *password = decoded; ++ } ++ ++ return APR_SUCCESS; ++} ++ + struct content_length_ctx { + int data_sent; /* true if the C-L filter has already sent at + * least one bucket on to the next output filter +diff --git a/server/request.c b/server/request.c +index 9377836..939e515 100644 +--- a/server/request.c ++++ b/server/request.c +@@ -124,6 +124,8 @@ static int decl_die(int status, const char *phase, request_rec *r) + AP_DECLARE(int) ap_some_authn_required(request_rec *r) + { + int access_status; ++ char *olduser = r->user; ++ int rv = FALSE; + + switch (ap_satisfies(r)) { + case SATISFY_ALL: +@@ -134,7 +136,7 @@ AP_DECLARE(int) ap_some_authn_required(request_rec *r) + + access_status = ap_run_access_checker_ex(r); + if (access_status == DECLINED) { +- return TRUE; ++ rv = TRUE; + } + + break; +@@ -145,13 +147,14 @@ AP_DECLARE(int) ap_some_authn_required(request_rec *r) + + access_status = ap_run_access_checker_ex(r); + if (access_status == DECLINED) { +- return TRUE; ++ rv = TRUE; + } + + break; + } + +- return FALSE; ++ r->user = olduser; ++ return rv; + } + + /* This is the master logic for processing requests. Do NOT duplicate +@@ -259,6 +262,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + r->ap_auth_type = r->main->ap_auth_type; + } + else { ++ /* A module using a confusing API (ap_get_basic_auth_pw) caused ++ ** r->user to be filled out prior to check_authn hook. We treat ++ ** it is inadvertent. ++ */ ++ if (r->user && apr_table_get(r->notes, AP_GET_BASIC_AUTH_PW_NOTE)) { ++ r->user = NULL; ++ } ++ + switch (ap_satisfies(r)) { + case SATISFY_ALL: + case SATISFY_NOSPEC: diff --git a/SOURCES/httpd-2.4.25-CVE-2017-3169.patch b/SOURCES/httpd-2.4.25-CVE-2017-3169.patch new file mode 100644 index 0000000..37c5885 --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-3169.patch @@ -0,0 +1,65 @@ +diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c +index 8829871..8fcbe2d 100644 +--- a/modules/ssl/ssl_engine_io.c ++++ b/modules/ssl/ssl_engine_io.c +@@ -878,20 +878,21 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, + * establish an outgoing SSL connection. */ + #define MODSSL_ERROR_BAD_GATEWAY (APR_OS_START_USERERR + 1) + +-static void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f) ++static void ssl_io_filter_disable(SSLConnRec *sslconn, ++ bio_filter_in_ctx_t *inctx) + { +- bio_filter_in_ctx_t *inctx = f->ctx; + SSL_free(inctx->ssl); + sslconn->ssl = NULL; + inctx->ssl = NULL; + inctx->filter_ctx->pssl = NULL; + } + +-static apr_status_t ssl_io_filter_error(ap_filter_t *f, ++static apr_status_t ssl_io_filter_error(bio_filter_in_ctx_t *inctx, + apr_bucket_brigade *bb, + apr_status_t status, + int is_init) + { ++ ap_filter_t *f = inctx->f; + SSLConnRec *sslconn = myConnConfig(f->c); + apr_bucket *bucket; + int send_eos = 1; +@@ -904,7 +905,7 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, + "trying to send HTML error page"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server); + +- ssl_io_filter_disable(sslconn, f); ++ ssl_io_filter_disable(sslconn, inctx); + f->c->keepalive = AP_CONN_CLOSE; + if (is_init) { + sslconn->non_ssl_request = NON_SSL_SEND_REQLINE; +@@ -1455,7 +1456,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, + * rather than have SSLEngine On configured. + */ + if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status, is_init); ++ return ssl_io_filter_error(inctx, bb, status, is_init); + } + + #ifdef HAVE_TLS_NPN +@@ -1541,7 +1542,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, + + /* Handle custom errors. */ + if (status != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status, 0); ++ return ssl_io_filter_error(inctx, bb, status, 0); + } + + /* Create a transient bucket out of the decrypted data. */ +@@ -1726,7 +1727,7 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, + inctx->block = APR_BLOCK_READ; + + if ((status = ssl_io_filter_handshake(filter_ctx)) != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status, 0); ++ return ssl_io_filter_error(inctx, bb, status, 0); + } + + while (!APR_BRIGADE_EMPTY(bb) && status == APR_SUCCESS) { diff --git a/SOURCES/httpd-2.4.25-CVE-2017-7659.patch b/SOURCES/httpd-2.4.25-CVE-2017-7659.patch new file mode 100644 index 0000000..e5b24ac --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-7659.patch @@ -0,0 +1,23 @@ +diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c +index 3f30949..8a7dbb9 100644 +--- a/modules/http2/h2_stream.c ++++ b/modules/http2/h2_stream.c +@@ -286,11 +286,13 @@ apr_status_t h2_stream_set_request_rec(h2_stream *stream, request_rec *r) + return APR_ECONNRESET; + } + status = h2_request_rcreate(&req, stream->pool, r); +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03058) +- "h2_request(%d): set_request_rec %s host=%s://%s%s", +- stream->id, req->method, req->scheme, req->authority, +- req->path); +- stream->rtmp = req; ++ if (status == APR_SUCCESS) { ++ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03058) ++ "h2_request(%d): set_request_rec %s host=%s://%s%s", ++ stream->id, req->method, req->scheme, req->authority, ++ req->path); ++ stream->rtmp = req; ++ } + return status; + } + diff --git a/SOURCES/httpd-2.4.25-CVE-2017-7668.patch b/SOURCES/httpd-2.4.25-CVE-2017-7668.patch new file mode 100644 index 0000000..d0c247f --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-7668.patch @@ -0,0 +1,17 @@ +diff --git a/server/util.c b/server/util.c +index fba34bd..7335a0f 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -1679,10 +1679,8 @@ AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok) + + s = (const unsigned char *)line; + for (;;) { +- /* find start of token, skip all stop characters, note NUL +- * isn't a token stop, so we don't need to test for it +- */ +- while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { ++ /* find start of token, skip all stop characters */ ++ while (*s && TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { + ++s; + } + if (!*s) { diff --git a/SOURCES/httpd-2.4.25-CVE-2017-7679.patch b/SOURCES/httpd-2.4.25-CVE-2017-7679.patch new file mode 100644 index 0000000..b34a0b2 --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-7679.patch @@ -0,0 +1,16 @@ +diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c +index f92119b..28c53be 100644 +--- a/modules/http/mod_mime.c ++++ b/modules/http/mod_mime.c +@@ -528,9 +528,9 @@ static int is_quoted_pair(const char *s) + int res = -1; + int c; + +- if (((s + 1) != NULL) && (*s == '\\')) { ++ if (*s == '\\') { + c = (int) *(s + 1); +- if (apr_isascii(c)) { ++ if (c && apr_isascii(c)) { + res = 1; + } + } diff --git a/SOURCES/httpd-2.4.25-CVE-2017-9788.patch b/SOURCES/httpd-2.4.25-CVE-2017-9788.patch new file mode 100644 index 0000000..b5501fc --- /dev/null +++ b/SOURCES/httpd-2.4.25-CVE-2017-9788.patch @@ -0,0 +1,29 @@ +diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c +index c22bb09..d391559 100644 +--- a/modules/aaa/mod_auth_digest.c ++++ b/modules/aaa/mod_auth_digest.c +@@ -965,13 +965,13 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp) + + /* find value */ + ++ vv = 0; + if (auth_line[0] == '=') { + auth_line++; + while (apr_isspace(auth_line[0])) { + auth_line++; + } + +- vv = 0; + if (auth_line[0] == '\"') { /* quoted string */ + auth_line++; + while (auth_line[0] != '\"' && auth_line[0] != '\0') { +@@ -990,8 +990,8 @@ static int get_digest_rec(request_rec *r, digest_header_rec *resp) + value[vv++] = *auth_line++; + } + } +- value[vv] = '\0'; + } ++ value[vv] = '\0'; + + while (auth_line[0] != ',' && auth_line[0] != '\0') { + auth_line++; diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec index 454209d..bf7d1c4 100644 --- a/SPECS/httpd.spec +++ b/SPECS/httpd.spec @@ -49,7 +49,7 @@ Summary: Apache HTTP Server Name: %{?scl:%scl_prefix}httpd Version: 2.4.25 -Release: 9%{?dist} +Release: 9%{?dist}.1 URL: http://httpd.apache.org/ Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source1: index.html @@ -123,6 +123,12 @@ Patch75: httpd-2.4.25-r1782332.patch Patch76: httpd-2.4.25-r1787301.patch # Security fixes +Patch200: httpd-2.4.25-CVE-2017-3167.patch +Patch201: httpd-2.4.25-CVE-2017-3169.patch +Patch202: httpd-2.4.25-CVE-2017-7659.patch +Patch203: httpd-2.4.25-CVE-2017-7668.patch +Patch204: httpd-2.4.25-CVE-2017-7679.patch +Patch205: httpd-2.4.25-CVE-2017-9788.patch License: ASL 2.0 Group: System Environment/Daemons @@ -315,6 +321,13 @@ export LD_LIBRARY_PATH=%{_libdir}:$LD_LIBRARY_PATH %patch75 -p1 -b .r1782332 %patch76 -p1 -b .r1787301 +%patch200 -p1 -b .cve3167 +%patch201 -p1 -b .cve3169 +%patch202 -p1 -b .cve7659 +%patch203 -p1 -b .cve7668 +%patch204 -p1 -b .cve7679 +%patch205 -p1 -b .cve9788 + # Patch in the vendor string and the release string sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h sed -i 's/@RELEASE@/%{release}/' server/core.c @@ -958,6 +971,10 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Wed Jul 26 2017 Luboš Uhliarik - 2.4.25-9.1 +- Resolves: #1473691 - CVE-2017-3167 CVE-2017-3169 CVE-2017-7659 CVE-2017-7668 + CVE-2017-7679 CVE-2017-9788 httpd24-httpd: various flaws + * Fri Mar 24 2017 Joe Orton - 2.4.25-9 - link only httpd, not support/* against -lselinux -lsystemd (#1433474) - don't enable SO_REUSEPORT in default configuration (#1432249)