diff --git a/.gitignore b/.gitignore
index 260a2d6..9969f1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1 @@
 SOURCES/httpd-2.4.6.tar.bz2
-SOURCES/centos-noindex.tar.gz
diff --git a/.httpd.metadata b/.httpd.metadata
index 17ede1b..d335a99 100644
--- a/.httpd.metadata
+++ b/.httpd.metadata
@@ -1,2 +1 @@
 16d8ec72535ded65d035122b0d944b0e64eaa2a2 SOURCES/httpd-2.4.6.tar.bz2
-6ce5ab3c765b9efeceb2e636e32373bc6e6ed489 SOURCES/centos-noindex.tar.gz
diff --git a/SOURCES/httpd-2.4.6-CVE-2016-0736.patch b/SOURCES/httpd-2.4.6-CVE-2016-0736.patch
new file mode 100644
index 0000000..cb80fa0
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-CVE-2016-0736.patch
@@ -0,0 +1,325 @@
+diff --git a/modules/session/mod_session_crypto.c b/modules/session/mod_session_crypto.c
+index 4d65bb8..9231a5e 100644
+--- a/modules/session/mod_session_crypto.c
++++ b/modules/session/mod_session_crypto.c
+@@ -18,6 +18,7 @@
+ #include "apu_version.h"
+ #include "apr_base64.h"                /* for apr_base64_decode et al */
+ #include "apr_lib.h"
++#include "apr_md5.h"
+ #include "apr_strings.h"
+ #include "http_log.h"
+ #include "http_core.h"
+@@ -57,6 +58,146 @@ typedef struct {
+     int library_set;
+ } session_crypto_conf;
+ 
++/* Wrappers around apr_siphash24() and apr_crypto_equals(),
++ * available in APU-1.6/APR-2.0 only.
++ */
++#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 6)
++
++#include "apr_siphash.h"
++
++#define AP_SIPHASH_DSIZE    APR_SIPHASH_DSIZE
++#define AP_SIPHASH_KSIZE    APR_SIPHASH_KSIZE
++#define ap_siphash24_auth   apr_siphash24_auth
++
++#define ap_crypto_equals    apr_crypto_equals
++
++#else
++
++#define AP_SIPHASH_DSIZE    8
++#define AP_SIPHASH_KSIZE    16
++
++#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
++
++#define U8TO64_LE(p) \
++    (((apr_uint64_t)((p)[0])      ) | \
++     ((apr_uint64_t)((p)[1]) <<  8) | \
++     ((apr_uint64_t)((p)[2]) << 16) | \
++     ((apr_uint64_t)((p)[3]) << 24) | \
++     ((apr_uint64_t)((p)[4]) << 32) | \
++     ((apr_uint64_t)((p)[5]) << 40) | \
++     ((apr_uint64_t)((p)[6]) << 48) | \
++     ((apr_uint64_t)((p)[7]) << 56))
++
++#define U64TO8_LE(p, v) \
++do { \
++    (p)[0] = (unsigned char)((v)      ); \
++    (p)[1] = (unsigned char)((v) >>  8); \
++    (p)[2] = (unsigned char)((v) >> 16); \
++    (p)[3] = (unsigned char)((v) >> 24); \
++    (p)[4] = (unsigned char)((v) >> 32); \
++    (p)[5] = (unsigned char)((v) >> 40); \
++    (p)[6] = (unsigned char)((v) >> 48); \
++    (p)[7] = (unsigned char)((v) >> 56); \
++} while (0)
++
++#define SIPROUND() \
++do { \
++    v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
++    v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
++    v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
++    v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
++} while(0)
++
++static apr_uint64_t ap_siphash24(const void *src, apr_size_t len,
++                                 const unsigned char key[AP_SIPHASH_KSIZE])
++{
++    const unsigned char *ptr, *end;
++    apr_uint64_t v0, v1, v2, v3, m;
++    apr_uint64_t k0, k1;
++    unsigned int rem;
++
++    k0 = U8TO64_LE(key + 0);
++    k1 = U8TO64_LE(key + 8);
++    v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL;
++    v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL;
++    v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL;
++    v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL;
++
++    rem = (unsigned int)(len & 0x7);
++    for (ptr = src, end = ptr + len - rem; ptr < end; ptr += 8) {
++        m = U8TO64_LE(ptr);
++        v3 ^= m;
++        SIPROUND();
++        SIPROUND();
++        v0 ^= m;
++    }
++    m = (apr_uint64_t)(len & 0xff) << 56;
++    switch (rem) {
++        case 7: m |= (apr_uint64_t)ptr[6] << 48;
++        case 6: m |= (apr_uint64_t)ptr[5] << 40;
++        case 5: m |= (apr_uint64_t)ptr[4] << 32;
++        case 4: m |= (apr_uint64_t)ptr[3] << 24;
++        case 3: m |= (apr_uint64_t)ptr[2] << 16;
++        case 2: m |= (apr_uint64_t)ptr[1] << 8;
++        case 1: m |= (apr_uint64_t)ptr[0];
++        case 0: break;
++    }
++    v3 ^= m;
++    SIPROUND();
++    SIPROUND();
++    v0 ^= m;
++
++    v2 ^= 0xff;
++    SIPROUND();
++    SIPROUND();
++    SIPROUND();
++    SIPROUND();
++
++    return v0 ^ v1 ^ v2 ^ v3;
++}
++
++static void ap_siphash24_auth(unsigned char out[AP_SIPHASH_DSIZE],
++                              const void *src, apr_size_t len,
++                              const unsigned char key[AP_SIPHASH_KSIZE])
++{
++    apr_uint64_t h;
++    h = ap_siphash24(src, len, key);
++    U64TO8_LE(out, h);
++}
++
++static int ap_crypto_equals(const void *buf1, const void *buf2,
++                            apr_size_t size)
++{
++    const unsigned char *p1 = buf1;
++    const unsigned char *p2 = buf2;
++    unsigned char diff = 0;
++    apr_size_t i;
++
++    for (i = 0; i < size; ++i) {
++        diff |= p1[i] ^ p2[i];
++    }
++
++    return 1 & ((diff - 1) >> 8);
++}
++
++#endif
++
++static void compute_auth(const void *src, apr_size_t len,
++                         const char *passphrase, apr_size_t passlen,
++                         unsigned char auth[AP_SIPHASH_DSIZE])
++{
++    unsigned char key[APR_MD5_DIGESTSIZE];
++
++    /* XXX: if we had a way to get the raw bytes from an apr_crypto_key_t
++     *      we could use them directly (not available in APR-1.5.x).
++     * MD5 is 128bit too, so use it to get a suitable siphash key
++     * from the passphrase.
++     */
++    apr_md5(key, passphrase, passlen);
++
++    ap_siphash24_auth(auth, src, len, key);
++}
++
+ /**
+  * Initialise the encryption as per the current config.
+  *
+@@ -128,21 +269,14 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
+     apr_crypto_block_t *block = NULL;
+     unsigned char *encrypt = NULL;
+     unsigned char *combined = NULL;
+-    apr_size_t encryptlen, tlen;
++    apr_size_t encryptlen, tlen, combinedlen;
+     char *base64;
+     apr_size_t blockSize = 0;
+     const unsigned char *iv = NULL;
+     apr_uuid_t salt;
+     apr_crypto_block_key_type_e *cipher;
+     const char *passphrase;
+-
+-    /* by default, return an empty string */
+-    *out = "";
+-
+-    /* don't attempt to encrypt an empty string, trying to do so causes a segfault */
+-    if (!in || !*in) {
+-        return APR_SUCCESS;
+-    }
++    apr_size_t passlen;
+ 
+     /* use a uuid as a salt value, and prepend it to our result */
+     apr_uuid_get(&salt);
+@@ -152,9 +286,9 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
+     }
+ 
+     /* encrypt using the first passphrase in the list */
+-    passphrase = APR_ARRAY_IDX(dconf->passphrases, 0, char *);
+-    res = apr_crypto_passphrase(&key, &ivSize, passphrase,
+-            strlen(passphrase),
++    passphrase = APR_ARRAY_IDX(dconf->passphrases, 0, const char *);
++    passlen = strlen(passphrase);
++    res = apr_crypto_passphrase(&key, &ivSize, passphrase, passlen,
+             (unsigned char *) (&salt), sizeof(apr_uuid_t),
+             *cipher, APR_MODE_CBC, 1, 4096, f, r->pool);
+     if (APR_STATUS_IS_ENOKEY(res)) {
+@@ -183,8 +317,9 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
+     }
+ 
+     /* encrypt the given string */
+-    res = apr_crypto_block_encrypt(&encrypt, &encryptlen, (unsigned char *)in,
+-            strlen(in), block);
++    res = apr_crypto_block_encrypt(&encrypt, &encryptlen,
++                                   (const unsigned char *)in, strlen(in),
++                                   block);
+     if (APR_SUCCESS != res) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, APLOGNO(01830)
+                 "apr_crypto_block_encrypt failed");
+@@ -198,18 +333,20 @@ static apr_status_t encrypt_string(request_rec * r, const apr_crypto_t *f,
+     }
+     encryptlen += tlen;
+ 
+-    /* prepend the salt and the iv to the result */
+-    combined = apr_palloc(r->pool, ivSize + encryptlen + sizeof(apr_uuid_t));
+-    memcpy(combined, &salt, sizeof(apr_uuid_t));
+-    memcpy(combined + sizeof(apr_uuid_t), iv, ivSize);
+-    memcpy(combined + sizeof(apr_uuid_t) + ivSize, encrypt, encryptlen);
+-
+-    /* base64 encode the result */
+-    base64 = apr_palloc(r->pool, apr_base64_encode_len(ivSize + encryptlen +
+-                    sizeof(apr_uuid_t) + 1)
+-            * sizeof(char));
+-    apr_base64_encode(base64, (const char *) combined,
+-            ivSize + encryptlen + sizeof(apr_uuid_t));
++    /* prepend the salt and the iv to the result (keep room for the MAC) */
++    combinedlen = AP_SIPHASH_DSIZE + sizeof(apr_uuid_t) + ivSize + encryptlen;
++    combined = apr_palloc(r->pool, combinedlen);
++    memcpy(combined + AP_SIPHASH_DSIZE, &salt, sizeof(apr_uuid_t));
++    memcpy(combined + AP_SIPHASH_DSIZE + sizeof(apr_uuid_t), iv, ivSize);
++    memcpy(combined + AP_SIPHASH_DSIZE + sizeof(apr_uuid_t) + ivSize,
++           encrypt, encryptlen);
++    /* authenticate the whole salt+IV+ciphertext with a leading MAC */
++    compute_auth(combined + AP_SIPHASH_DSIZE, combinedlen - AP_SIPHASH_DSIZE,
++                 passphrase, passlen, combined);
++
++    /* base64 encode the result (APR handles the trailing '\0') */
++    base64 = apr_palloc(r->pool, apr_base64_encode_len(combinedlen));
++    apr_base64_encode(base64, (const char *) combined, combinedlen);
+     *out = base64;
+ 
+     return res;
+@@ -234,6 +371,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+     char *decoded;
+     apr_size_t blockSize = 0;
+     apr_crypto_block_key_type_e *cipher;
++    unsigned char auth[AP_SIPHASH_DSIZE];
+     int i = 0;
+ 
+     /* strip base64 from the string */
+@@ -241,6 +379,13 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+     decodedlen = apr_base64_decode(decoded, in);
+     decoded[decodedlen] = '\0';
+ 
++    /* sanity check - decoded too short? */
++    if (decodedlen < (AP_SIPHASH_DSIZE + sizeof(apr_uuid_t))) {
++        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO()
++                "too short to decrypt, aborting");
++        return APR_ECRYPT;
++    }
++
+     res = crypt_init(r, f, &cipher, dconf);
+     if (res != APR_SUCCESS) {
+         return res;
+@@ -249,14 +394,25 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+     /* try each passphrase in turn */
+     for (; i < dconf->passphrases->nelts; i++) {
+         const char *passphrase = APR_ARRAY_IDX(dconf->passphrases, i, char *);
+-        apr_size_t len = decodedlen;
+-        char *slider = decoded;
++        apr_size_t passlen = strlen(passphrase);
++        apr_size_t len = decodedlen - AP_SIPHASH_DSIZE;
++        unsigned char *slider = (unsigned char *)decoded + AP_SIPHASH_DSIZE;
++
++        /* Verify authentication of the whole salt+IV+ciphertext by computing
++         * the MAC and comparing it (timing safe) with the one in the payload.
++         */
++        compute_auth(slider, len, passphrase, passlen, auth);
++        if (!ap_crypto_equals(auth, decoded, AP_SIPHASH_DSIZE)) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO()
++                    "auth does not match, skipping");
++            continue;
++        }
+ 
+         /* encrypt using the first passphrase in the list */
+-        res = apr_crypto_passphrase(&key, &ivSize, passphrase,
+-                strlen(passphrase),
+-                (unsigned char *)decoded, sizeof(apr_uuid_t),
+-                *cipher, APR_MODE_CBC, 1, 4096, f, r->pool);
++        res = apr_crypto_passphrase(&key, &ivSize, passphrase, passlen,
++                                    slider, sizeof(apr_uuid_t),
++                                    *cipher, APR_MODE_CBC, 1, 4096,
++                                    f, r->pool);
+         if (APR_STATUS_IS_ENOKEY(res)) {
+             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01832)
+                     "the passphrase '%s' was empty", passphrase);
+@@ -279,7 +435,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+         }
+ 
+         /* sanity check - decoded too short? */
+-        if (decodedlen < (sizeof(apr_uuid_t) + ivSize)) {
++        if (len < (sizeof(apr_uuid_t) + ivSize)) {
+             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(01836)
+                     "too short to decrypt, skipping");
+             res = APR_ECRYPT;
+@@ -290,8 +446,8 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+         slider += sizeof(apr_uuid_t);
+         len -= sizeof(apr_uuid_t);
+ 
+-        res = apr_crypto_block_decrypt_init(&block, &blockSize, (unsigned char *)slider, key,
+-                r->pool);
++        res = apr_crypto_block_decrypt_init(&block, &blockSize, slider, key,
++                                            r->pool);
+         if (APR_SUCCESS != res) {
+             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01837)
+                     "apr_crypto_block_decrypt_init failed");
+@@ -304,7 +460,7 @@ static apr_status_t decrypt_string(request_rec * r, const apr_crypto_t *f,
+ 
+         /* decrypt the given string */
+         res = apr_crypto_block_decrypt(&decrypted, &decryptedlen,
+-                (unsigned char *)slider, len, block);
++                                       slider, len, block);
+         if (res) {
+             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, APLOGNO(01838)
+                     "apr_crypto_block_decrypt failed");
+
diff --git a/SOURCES/httpd-2.4.6-CVE-2016-2161.patch b/SOURCES/httpd-2.4.6-CVE-2016-2161.patch
new file mode 100644
index 0000000..d45c2d9
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-CVE-2016-2161.patch
@@ -0,0 +1,121 @@
+diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
+index 44b5fc8..6a50ba7 100644
+--- a/modules/aaa/mod_auth_digest.c
++++ b/modules/aaa/mod_auth_digest.c
+@@ -261,6 +261,26 @@ static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
+     cleanup_tables(NULL);
+ }
+ 
++/* RMM helper functions that behave like single-step malloc/free. */
++
++static void *rmm_malloc(apr_rmm_t *rmm, apr_size_t size)
++{
++    apr_rmm_off_t offset = apr_rmm_malloc(rmm, size);
++
++    if (!offset) {
++        return NULL;
++    }
++
++    return apr_rmm_addr_get(rmm, offset);
++}
++
++static apr_status_t rmm_free(apr_rmm_t *rmm, void *alloc)
++{
++    apr_rmm_off_t offset = apr_rmm_offset_get(rmm, alloc);
++
++    return apr_rmm_free(rmm, offset);
++}
++
+ #if APR_HAS_SHARED_MEMORY
+ 
+ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
+@@ -299,8 +319,8 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
+         return !OK;
+     }
+ 
+-    client_list = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*client_list) +
+-                                                          sizeof(client_entry*)*num_buckets));
++    client_list = rmm_malloc(client_rmm, sizeof(*client_list) +
++                                         sizeof(client_entry *) * num_buckets);
+     if (!client_list) {
+         log_error_and_cleanup("failed to allocate shared memory", -1, s);
+         return !OK;
+@@ -322,7 +342,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
+ 
+     /* setup opaque */
+ 
+-    opaque_cntr = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*opaque_cntr)));
++    opaque_cntr = rmm_malloc(client_rmm, sizeof(*opaque_cntr));
+     if (opaque_cntr == NULL) {
+         log_error_and_cleanup("failed to allocate shared memory", -1, s);
+         return !OK;
+@@ -339,7 +359,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
+ 
+     /* setup one-time-nonce counter */
+ 
+-    otn_counter = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*otn_counter)));
++    otn_counter = rmm_malloc(client_rmm, sizeof(*otn_counter));
+     if (otn_counter == NULL) {
+         log_error_and_cleanup("failed to allocate shared memory", -1, s);
+         return !OK;
+@@ -779,7 +799,7 @@ static client_entry *get_client(unsigned long key, const request_rec *r)
+  * last entry in each bucket and updates the counters. Returns the
+  * number of removed entries.
+  */
+-static long gc(void)
++static long gc(server_rec *s)
+ {
+     client_entry *entry, *prev;
+     unsigned long num_removed = 0, idx;
+@@ -789,6 +809,12 @@ static long gc(void)
+     for (idx = 0; idx < client_list->tbl_len; idx++) {
+         entry = client_list->table[idx];
+         prev  = NULL;
++
++        if (!entry) {
++            /* This bucket is empty. */
++            continue;
++        }
++
+         while (entry->next) {   /* find last entry */
+             prev  = entry;
+             entry = entry->next;
+@@ -800,8 +826,16 @@ static long gc(void)
+             client_list->table[idx] = NULL;
+         }
+         if (entry) {                    /* remove entry */
+-            apr_rmm_free(client_rmm, apr_rmm_offset_get(client_rmm, entry));
++            apr_status_t err;
++
++            err = rmm_free(client_rmm, entry);
+             num_removed++;
++
++            if (err) {
++                /* Nothing we can really do but log... */
++                ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO()
++                             "Failed to free auth_digest client allocation");
++            }
+         }
+     }
+ 
+@@ -835,16 +869,16 @@ static client_entry *add_client(unsigned long key, client_entry *info,
+ 
+     /* try to allocate a new entry */
+ 
+-    entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
++    entry = rmm_malloc(client_rmm, sizeof(client_entry));
+     if (!entry) {
+-        long num_removed = gc();
++        long num_removed = gc(s);
+         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01766)
+                      "gc'd %ld client entries. Total new clients: "
+                      "%ld; Total removed clients: %ld; Total renewed clients: "
+                      "%ld", num_removed,
+                      client_list->num_created - client_list->num_renewed,
+                      client_list->num_removed, client_list->num_renewed);
+-        entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
++        entry = rmm_malloc(client_rmm, sizeof(client_entry));
+         if (!entry) {
+             ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01767)
+                          "unable to allocate new auth_digest client");
+
diff --git a/SOURCES/httpd-2.4.6-CVE-2016-8743.patch b/SOURCES/httpd-2.4.6-CVE-2016-8743.patch
new file mode 100644
index 0000000..5a6fd58
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-CVE-2016-8743.patch
@@ -0,0 +1,2124 @@
+
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-8743
+
+diff -uap httpd-2.4.6/docs/manual/mod/core.html.en.cve8743 httpd-2.4.6/docs/manual/mod/core.html.en
+--- httpd-2.4.6/docs/manual/mod/core.html.en.cve8743
++++ httpd-2.4.6/docs/manual/mod/core.html.en
+@@ -67,6 +67,7 @@
+ <li><img alt="" src="../images/down.gif" /> <a href="#forcetype">ForceType</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#gprofdir">GprofDir</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#hostnamelookups">HostnameLookups</a></li>
++<li><img alt="" src="../images/down.gif" /> <a href="#httpprotocoloptions">HttpProtocolOptions</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#if">&lt;If&gt;</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#ifdefine">&lt;IfDefine&gt;</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#ifmodule">&lt;IfModule&gt;</a></li>
+@@ -93,6 +94,7 @@
+ <li><img alt="" src="../images/down.gif" /> <a href="#namevirtualhost">NameVirtualHost</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#options">Options</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#protocol">Protocol</a></li>
++<li><img alt="" src="../images/down.gif" /> <a href="#registerhttpmethod">RegisterHttpMethod</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#rlimitcpu">RLimitCPU</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#rlimitmem">RLimitMEM</a></li>
+ <li><img alt="" src="../images/down.gif" /> <a href="#rlimitnproc">RLimitNPROC</a></li>
+@@ -1918,6 +1920,74 @@
+ 
+ </div>
+ <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
++<div class="directive-section"><h2><a name="HttpProtocolOptions" id="HttpProtocolOptions">HttpProtocolOptions</a> <a name="httpprotocoloptions" id="httpprotocoloptions">Directive</a></h2>
++<table class="directive">
++<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Modify restrictions on HTTP Request Messages</td></tr>
++<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>HttpProtocolOptions [Strict|Unsafe] [RegisteredMethods|LenientMethods]
++ [Allow0.9|Require1.0]</code></td></tr>
++<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>HttpProtocolOptions Strict LenientMethods Allow0.9</code></td></tr>
++<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr>
++<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
++<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
++<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>2.2.32 or 2.4.24 and later</td></tr>
++</table>
++    <p>This directive changes the rules applied to the HTTP Request Line
++    (<a href="https://tools.ietf.org/html/rfc7230#section-3.1.1">RFC 7230 §3.1.1</a>) and the HTTP Request Header Fields
++    (<a href="https://tools.ietf.org/html/rfc7230#section-3.2">RFC 7230 §3.2</a>), which are now applied by default or using
++    the <code>Strict</code> option. Due to legacy modules, applications or
++    custom user-agents which must be deperecated the <code>Unsafe</code>
++    option has been added to revert to the legacy behaviors. These rules
++    are applied prior to request processing, so must be configured at the
++    global or default (first) matching virtual host section, by IP/port
++    interface (and not by name) to be honored.</p>
++
++    <p>Prior to the introduction of this directive, the Apache HTTP Server
++    request message parsers were tolerant of a number of forms of input
++    which did not conform to the protocol.
++    <a href="https://tools.ietf.org/html/rfc7230#section-9.4">RFC 7230 §9.4 Request Splitting</a> and
++    <a href="https://tools.ietf.org/html/rfc7230#section-9.5">§9.5 Response Smuggling</a> call out only two of the potential
++    risks of accepting non-conformant request messages, while
++    <a href="https://tools.ietf.org/html/rfc7230#section-3.5">RFC 7230 §3.5</a> "Message Parsing Robustness" identify the
++    risks of accepting obscure whitespace and request message formatting. 
++    As of the introduction of this directive, all grammer rules of the
++    specification are enforced in the default <code>Strict</code> operating
++    mode, and the strict whitespace suggested by section 3.5 is enforced
++    and cannot be relaxed.</p>
++
++    <p>Users are strongly cautioned against toggling the <code>Unsafe</code>
++    mode of operation, particularly on outward-facing, publicly accessible
++    server deployments.  If an interface is required for faulty monitoring
++    or other custom service consumers running on an intranet, users should
++    toggle the Unsafe option only on a specific virtual host configured
++    to service their internal private network.</p>
++
++    <p>Reviewing the messages logged to the <code class="directive">ErrorLog</code>,
++    configured with <code class="directive">LogLevel</code> <code>debug</code> level,
++    can help identify such faulty requests along with their origin.
++    Users should pay particular attention to the 400 responses in the access
++    log for invalid requests which were unexpectedly rejected.</p>
++
++    <p><a href="https://tools.ietf.org/html/rfc7231#section-4.1">RFC 7231 §4.1</a> "Request Methods" "Overview" requires that
++    origin servers shall respond with an error when an unsupported method
++    is encountered in the request line. This already happens when the
++    <code>LenientMethods</code> option is used, but administrators may wish
++    to toggle the <code>RegisteredMethods</code> option and register any
++    non-standard methods using the <code class="directive">RegisterHttpMethod</code>
++    directive, particularly if the <code>Unsafe</code> option has been toggled.
++    The <code>RegisteredMethods</code> option should <strong>not</strong>
++    be toggled for forward proxy hosts, as the methods supported by the
++    origin servers are unknown to the proxy server.</p>
++
++    <p><a href="https://tools.ietf.org/html/rfc2616#section-19.6">RFC 2616 §19.6</a> "Compatibility With Previous Versions" had
++    encouraged HTTP servers to support legacy HTTP/0.9 requests. RFC 7230
++    superceeds this with "The expectation to support HTTP/0.9 requests has
++    been removed" and offers additional comments in 
++    <a href="https://tools.ietf.org/html/rfc7230#appendix-A">RFC 7230 Appendix A</a>. The <code>Require1.0</code> option allows
++    the user to remove support of the default <code>Allow0.9</code> option's
++    behavior.</p>
++
++</div>
++<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+ <div class="directive-section"><h2><a name="If" id="If">&lt;If&gt;</a> <a name="if" id="if">Directive</a></h2>
+ <table class="directive">
+ <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Contains directives that apply only if a condition is
+@@ -3541,6 +3611,23 @@
+ </ul>
+ </div>
+ <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
++<div class="directive-section"><h2><a name="RegisterHttpMethod" id="RegisterHttpMethod">RegisterHttpMethod</a> <a name="registerhttpmethod" id="registerhttpmethod">Directive</a></h2>
++<table class="directive">
++<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Register non-standard HTTP methods</td></tr>
++<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>RegisterHttpMethod <var>method</var> [<var>method</var> [...]]</code></td></tr>
++<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr>
++<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
++<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
++</table>
++<p>HTTP Methods that are not conforming to the relvant RFCs are normally
++rejected by request processing in Apache HTTPD. To avoid this, modules
++can register non-standard HTTP methods they support.
++The <code class="directive">RegisterHttpMethod</code> allows to register such
++methods manually. This can be useful for if such methods are forwared
++for external processing, e.g. to a CGI script.</p>
++
++</div>
++<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+ <div class="directive-section"><h2><a name="RLimitCPU" id="RLimitCPU">RLimitCPU</a> <a name="rlimitcpu" id="rlimitcpu">Directive</a></h2>
+ <table class="directive">
+ <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Limits the CPU consumption of processes launched
+diff -uap httpd-2.4.6/include/http_core.h.cve8743 httpd-2.4.6/include/http_core.h
+--- httpd-2.4.6/include/http_core.h.cve8743
++++ httpd-2.4.6/include/http_core.h
+@@ -668,6 +668,21 @@
+ #define AP_MERGE_TRAILERS_DISABLE  2
+     int merge_trailers;
+ 
++#define AP_HTTP09_UNSET   0
++#define AP_HTTP09_ENABLE  1
++#define AP_HTTP09_DISABLE 2
++    char http09_enable;
++
++#define AP_HTTP_CONFORMANCE_UNSET     0
++#define AP_HTTP_CONFORMANCE_UNSAFE    1
++#define AP_HTTP_CONFORMANCE_STRICT    2
++    char http_conformance;
++
++#define AP_HTTP_METHODS_UNSET         0
++#define AP_HTTP_METHODS_LENIENT       1
++#define AP_HTTP_METHODS_REGISTERED    2
++    char http_methods;
++
+ } core_server_config;
+ 
+ /* for AddOutputFiltersByType in core.c */
+diff -uap httpd-2.4.6/include/httpd.h.cve8743 httpd-2.4.6/include/httpd.h
+--- httpd-2.4.6/include/httpd.h.cve8743
++++ httpd-2.4.6/include/httpd.h
+@@ -1584,6 +1584,28 @@
+  */
+ AP_DECLARE(int) ap_unescape_url(char *url);
+ 
++/* Scan a string for field content chars, as defined by RFC7230 section 3.2
++ * including VCHAR/obs-text, as well as HT and SP
++ * @param ptr The string to scan
++ * @return A pointer to the first (non-HT) ASCII ctrl character.
++ * @note lws and trailing whitespace are scanned, the caller is responsible
++ * for trimming leading and trailing whitespace
++ */
++AP_DECLARE(const char *) ap_scan_http_field_content(const char *ptr);
++
++/* Scan a string for token characters, as defined by RFC7230 section 3.2.6
++ * @param ptr The string to scan
++ * @return A pointer to the first non-token character.
++ */
++AP_DECLARE(const char *) ap_scan_http_token(const char *ptr);
++
++/* Scan a string for visible ASCII (0x21-0x7E) or obstext (0x80+)
++ * and return a pointer to the first SP/CTL/NUL character encountered.
++ * @param ptr The string to scan
++ * @return A pointer to the first SP/CTL character.
++ */
++AP_DECLARE(const char *) ap_scan_vchar_obstext(const char *ptr);
++
+ /**
+  * Unescape a URL, but leaving %2f (slashes) escaped
+  * @param url The url to unescape
+diff -uap httpd-2.4.6/include/http_protocol.h.cve8743 httpd-2.4.6/include/http_protocol.h
+--- httpd-2.4.6/include/http_protocol.h.cve8743
++++ httpd-2.4.6/include/http_protocol.h
+@@ -582,17 +582,22 @@
+  */
+ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri);
+ 
++#define AP_GETLINE_FOLD 1 /* Whether to merge continuation lines */
++#define AP_GETLINE_CRLF 2 /*Whether line ends must be in the form CR LF */
++
+ /**
+  * Get the next line of input for the request
+  * @param s The buffer into which to read the line
+  * @param n The size of the buffer
+  * @param r The request
+- * @param fold Whether to merge continuation lines
++ * @param flags Bit flag of multiple parsing options
++ *              AP_GETLINE_FOLD Whether to merge continuation lines
++ *              AP_GETLINE_CRLF Whether line ends must be in the form CR LF
+  * @return The length of the line, if successful
+  *         n, if the line is too big to fit in the buffer
+  *         -1 for miscellaneous errors
+  */
+-AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold);
++AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int flags);
+ 
+ /**
+  * Get the next line of input for the request
+@@ -610,7 +615,9 @@
+  * @param n The size of the buffer
+  * @param read The length of the line.
+  * @param r The request
+- * @param fold Whether to merge continuation lines
++ * @param flags Bit flag of multiple parsing options
++ *              AP_GETLINE_FOLD Whether to merge continuation lines
++ *              AP_GETLINE_CRLF Whether line ends must be in the form CR LF
+  * @param bb Working brigade to use when reading buckets
+  * @return APR_SUCCESS, if successful
+  *         APR_ENOSPC, if the line is too big to fit in the buffer
+@@ -619,7 +626,7 @@
+ #if APR_CHARSET_EBCDIC
+ AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n,
+                                      apr_size_t *read,
+-                                     request_rec *r, int fold,
++                                     request_rec *r, int flags,
+                                      apr_bucket_brigade *bb);
+ #else /* ASCII box */
+ #define ap_rgetline(s, n, read, r, fold, bb) \
+@@ -629,7 +636,7 @@
+ /** @see ap_rgetline */
+ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n,
+                                           apr_size_t *read,
+-                                          request_rec *r, int fold,
++                                          request_rec *r, int flags,
+                                           apr_bucket_brigade *bb);
+ 
+ /**
+diff -uap httpd-2.4.6/modules/http/http_filters.c.cve8743 httpd-2.4.6/modules/http/http_filters.c
+--- httpd-2.4.6/modules/http/http_filters.c.cve8743
++++ httpd-2.4.6/modules/http/http_filters.c
+@@ -126,14 +126,15 @@
+ 
+ /**
+  * Parse a chunk line with optional extension, detect overflow.
+- * There are two error cases:
+- *  1) If the conversion would require too many bits, APR_EGENERAL is returned.
+- *  2) If the conversion used the correct number of bits, but an overflow
++ * There are several error cases:
++ *  1) If the chunk link is misformatted, APR_EINVAL is returned.
++ *  2) If the conversion would require too many bits, APR_EGENERAL is returned.
++ *  3) If the conversion used the correct number of bits, but an overflow
+  *     caused only the sign bit to flip, then APR_ENOSPC is returned.
+- * In general, any negative number can be considered an overflow error.
++ * A negative chunk length always indicates an overflow error.
+  */
+ static apr_status_t parse_chunk_size(http_ctx_t *ctx, const char *buffer,
+-                                     apr_size_t len, int linelimit)
++                                     apr_size_t len, int linelimit, int strict)
+ {
+     apr_size_t i = 0;
+ 
+@@ -146,6 +147,12 @@
+         if (ctx->state == BODY_CHUNK_END
+                 || ctx->state == BODY_CHUNK_END_LF) {
+             if (c == LF) {
++                if (strict && (ctx->state != BODY_CHUNK_END_LF)) {
++                    /*
++                     * CR missing before LF.
++                     */
++                    return APR_EINVAL;
++                }
+                 ctx->state = BODY_CHUNK;
+             }
+             else if (c == CR && ctx->state == BODY_CHUNK_END) {
+@@ -153,7 +160,7 @@
+             }
+             else {
+                 /*
+-                 * LF expected.
++                 * CRLF expected.
+                  */
+                 return APR_EINVAL;
+             }
+@@ -180,6 +187,12 @@
+         }
+ 
+         if (c == LF) {
++            if (strict && (ctx->state != BODY_CHUNK_LF)) {
++                /*
++                 * CR missing before LF.
++                 */
++                return APR_EINVAL;
++            }
+             if (ctx->remaining) {
+                 ctx->state = BODY_CHUNK_DATA;
+             }
+@@ -201,14 +214,17 @@
+         }
+         else if (ctx->state == BODY_CHUNK_EXT) {
+             /*
+-             * Control chars (but tabs) are invalid.
++             * Control chars (excluding tabs) are invalid.
++             * TODO: more precisely limit input
+              */
+             if (c != '\t' && apr_iscntrl(c)) {
+                 return APR_EINVAL;
+             }
+         }
+         else if (c == ' ' || c == '\t') {
+-            /* Be lenient up to 10 BWS (term from rfc7230 - 3.2.3).
++            /* Be lenient up to 10 implied *LWS, a legacy of RFC 2616,
++             * and noted as errata to RFC7230;
++             * https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4667
+              */
+             ctx->state = BODY_CHUNK_CR;
+             if (++ctx->chunk_bws > 10) {
+@@ -324,7 +340,10 @@
+                             ap_input_mode_t mode, apr_read_type_e block,
+                             apr_off_t readbytes)
+ {
+-    core_server_config *conf;
++    core_server_config *conf =
++        (core_server_config *) ap_get_module_config(f->r->server->module_config,
++                                                    &core_module);
++    int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
+     apr_bucket *e;
+     http_ctx_t *ctx = f->ctx;
+     apr_status_t rv;
+@@ -332,9 +351,6 @@
+     apr_bucket_brigade *bb;
+     int again;
+ 
+-    conf = (core_server_config *)
+-        ap_get_module_config(f->r->server->module_config, &core_module);
+-
+     /* just get out of the way of things we don't want. */
+     if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
+         return ap_get_brigade(f->next, b, mode, block, readbytes);
+@@ -526,7 +542,7 @@
+                     if (rv == APR_SUCCESS) {
+                         parsing = 1;
+                         rv = parse_chunk_size(ctx, buffer, len,
+-                                f->r->server->limit_req_fieldsize);
++                                f->r->server->limit_req_fieldsize, strict);
+                     }
+                     if (rv != APR_SUCCESS) {
+                         ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01590)
+@@ -668,14 +684,121 @@
+     return APR_SUCCESS;
+ }
+ 
++struct check_header_ctx {
++    request_rec *r;
++    int strict;
++};
++
++/* check a single header, to be used with apr_table_do() */
++static int check_header(struct check_header_ctx *ctx,
++                        const char *name, const char **val)
++{
++    const char *pos, *end;
++    char *dst = NULL;
++
++    if (name[0] == '\0') {
++        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02428)
++                      "Empty response header name, aborting request");
++        return 0;
++    }
++
++    if (ctx->strict) {
++        end = ap_scan_http_token(name);
++    }
++    else {
++        end = ap_scan_vchar_obstext(name);
++    }
++    if (*end) {
++        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02429)
++                      "Response header name '%s' contains invalid "
++                      "characters, aborting request",
++                      name);
++        return 0;
++    }
++
++    for (pos = *val; *pos; pos = end) {
++        end = ap_scan_http_field_content(pos);
++        if (*end) {
++            if (end[0] != CR || end[1] != LF || (end[2] != ' ' &&
++                                                 end[2] != '\t')) {
++                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02430)
++                              "Response header '%s' value of '%s' contains "
++                              "invalid characters, aborting request",
++                              name, pos);
++                return 0;
++            }
++            if (!dst) {
++                *val = dst = apr_palloc(ctx->r->pool, strlen(*val) + 1);
++            }
++        }
++        if (dst) {
++            memcpy(dst, pos, end - pos);
++            dst += end - pos;
++            if (*end) {
++                /* skip folding and replace with a single space */
++                end += 3 + strspn(end + 3, "\t ");
++                *dst++ = ' ';
++            }
++        }
++    }
++    if (dst) {
++        *dst = '\0';
++    }
++    return 1;
++}
++
++static int check_headers_table(apr_table_t *t, struct check_header_ctx *ctx)
++{
++    const apr_array_header_t *headers = apr_table_elts(t);
++    apr_table_entry_t *header;
++    int i;
++
++    for (i = 0; i < headers->nelts; ++i) {
++        header = &APR_ARRAY_IDX(headers, i, apr_table_entry_t);
++        if (!header->key) {
++            continue;
++        }
++        if (!check_header(ctx, header->key, (const char **)&header->val)) {
++            return 0;
++        }
++    }
++    return 1;
++}
++
++/**
++ * Check headers for HTTP conformance
++ * @return 1 if ok, 0 if bad
++ */
++static APR_INLINE int check_headers(request_rec *r)
++{
++    struct check_header_ctx ctx;
++    core_server_config *conf =
++            ap_get_core_module_config(r->server->module_config);
++
++    ctx.r = r;
++    ctx.strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
++    return check_headers_table(r->headers_out, &ctx) &&
++           check_headers_table(r->err_headers_out, &ctx);
++}
++
++static int check_headers_recursion(request_rec *r)
++{
++    void *check = NULL;
++    apr_pool_userdata_get(&check, "check_headers_recursion", r->pool);
++    if (check) {
++        return 1;
++    }
++    apr_pool_userdata_setn("true", "check_headers_recursion", NULL, r->pool);
++    return 0;
++}
++
+ typedef struct header_struct {
+     apr_pool_t *pool;
+     apr_bucket_brigade *bb;
+ } header_struct;
+ 
+ /* Send a single HTTP header field to the client.  Note that this function
+- * is used in calls to table_do(), so their interfaces are co-dependent.
+- * In other words, don't change this one without checking table_do in alloc.c.
++ * is used in calls to apr_table_do(), so don't change its interface.
+  * It returns true unless there was a write error of some kind.
+  */
+ static int form_header_field(header_struct *h,
+@@ -1160,6 +1283,7 @@
+ 
+ typedef struct header_filter_ctx {
+     int headers_sent;
++    int headers_error;
+ } header_filter_ctx;
+ 
+ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
+@@ -1175,19 +1299,23 @@
+     header_filter_ctx *ctx = f->ctx;
+     const char *ctype;
+     ap_bucket_error *eb = NULL;
++    apr_bucket *eos = NULL;
+ 
+     AP_DEBUG_ASSERT(!r->main);
+ 
+-    if (r->header_only) {
+-        if (!ctx) {
+-            ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));
+-        }
+-        else if (ctx->headers_sent) {
++    if (!ctx) {
++        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));
++    }
++    if (ctx->headers_sent) {
++        /* Eat body if response must not have one. */
++        if (r->header_only || r->status == HTTP_NO_CONTENT) {
+             apr_brigade_cleanup(b);
+-            return OK;
++            return APR_SUCCESS;
+         }
+     }
+-
++    else if (!ctx->headers_error && !check_headers(r)) {
++        ctx->headers_error = 1;
++    }
+     for (e = APR_BRIGADE_FIRST(b);
+          e != APR_BRIGADE_SENTINEL(b);
+          e = APR_BUCKET_NEXT(e))
+@@ -1204,10 +1332,44 @@
+             ap_remove_output_filter(f);
+             return ap_pass_brigade(f->next, b);
+         }
++        if (ctx->headers_error && APR_BUCKET_IS_EOS(e)) {
++            eos = e;
++        }
+     }
+-    if (eb) {
+-        int status;
++    if (ctx->headers_error) {
++        if (!eos) {
++            /* Eat body until EOS */
++            apr_brigade_cleanup(b);
++            return APR_SUCCESS;
++        }
+ 
++        /* We may come back here from ap_die() below,
++         * so clear anything from this response.
++         */
++        ctx->headers_error = 0;
++        apr_table_clear(r->headers_out);
++        apr_table_clear(r->err_headers_out);
++
++        /* Don't recall ap_die() if we come back here (from its own internal
++         * redirect or error response), otherwise we can end up in infinite
++         * recursion; better fall through with 500, minimal headers and an
++         * empty body (EOS only).
++         */
++        if (!check_headers_recursion(r)) {
++            apr_brigade_cleanup(b);
++            ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
++            return AP_FILTER_ERROR;
++        }
++        APR_BUCKET_REMOVE(eos);
++        apr_brigade_cleanup(b);
++        APR_BRIGADE_INSERT_TAIL(b, eos);
++        r->status = HTTP_INTERNAL_SERVER_ERROR;
++        r->content_type = r->content_encoding = NULL;
++        r->content_languages = NULL;
++        ap_set_content_length(r, 0);
++    }
++    else if (eb) {
++        int status;
+         status = eb->status;
+         apr_brigade_cleanup(b);
+         ap_die(status, r);
+@@ -1264,6 +1426,10 @@
+         apr_table_unset(r->headers_out, "Content-Length");
+     }
+ 
++    if (r->status == HTTP_NO_CONTENT) {
++        apr_table_unset(r->headers_out, "Content-Length");
++    }
++
+     ctype = ap_make_content_type(r, r->content_type);
+     if (ctype) {
+         apr_table_setn(r->headers_out, "Content-Type", ctype);
+@@ -1352,11 +1518,11 @@
+     terminate_header(b2);
+ 
+     ap_pass_brigade(f->next, b2);
++    ctx->headers_sent = 1;
+ 
+-    if (r->header_only) {
++    if (r->header_only || r->status == HTTP_NO_CONTENT) {
+         apr_brigade_cleanup(b);
+-        ctx->headers_sent = 1;
+-        return OK;
++        return APR_SUCCESS;
+     }
+ 
+     r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
+diff -uap httpd-2.4.6/server/core.c.cve8743 httpd-2.4.6/server/core.c
+--- httpd-2.4.6/server/core.c.cve8743
++++ httpd-2.4.6/server/core.c
+@@ -506,6 +506,15 @@
+     if (virt->trace_enable != AP_TRACE_UNSET)
+         conf->trace_enable = virt->trace_enable;
+ 
++    if (virt->http09_enable != AP_HTTP09_UNSET)
++        conf->http09_enable = virt->http09_enable;
++
++    if (virt->http_conformance != AP_HTTP_CONFORMANCE_UNSET)
++        conf->http_conformance = virt->http_conformance;
++
++    if (virt->http_methods != AP_HTTP_METHODS_UNSET)
++        conf->http_methods = virt->http_methods;
++
+     /* no action for virt->accf_map, not allowed per-vhost */
+ 
+     if (virt->protocol)
+@@ -3632,6 +3641,57 @@
+     return NULL;
+ }
+ 
++static const char *set_http_protocol_options(cmd_parms *cmd, void *dummy,
++                                             const char *arg)
++{
++    core_server_config *conf =
++        ap_get_core_module_config(cmd->server->module_config);
++
++    if (strcasecmp(arg, "allow0.9") == 0)
++        conf->http09_enable |= AP_HTTP09_ENABLE;
++    else if (strcasecmp(arg, "require1.0") == 0)
++        conf->http09_enable |= AP_HTTP09_DISABLE;
++    else if (strcasecmp(arg, "strict") == 0)
++        conf->http_conformance |= AP_HTTP_CONFORMANCE_STRICT;
++    else if (strcasecmp(arg, "unsafe") == 0)
++        conf->http_conformance |= AP_HTTP_CONFORMANCE_UNSAFE;
++    else if (strcasecmp(arg, "registeredmethods") == 0)
++        conf->http_methods |= AP_HTTP_METHODS_REGISTERED;
++    else if (strcasecmp(arg, "lenientmethods") == 0)
++        conf->http_methods |= AP_HTTP_METHODS_LENIENT;
++    else
++        return "HttpProtocolOptions accepts "
++               "'Unsafe' or 'Strict' (default), "
++               "'RegisteredMethods' or 'LenientMethods' (default), and "
++               "'Require1.0' or 'Allow0.9' (default)";
++
++    if ((conf->http09_enable & AP_HTTP09_ENABLE)
++            && (conf->http09_enable & AP_HTTP09_DISABLE))
++        return "HttpProtocolOptions 'Allow0.9' and 'Require1.0'"
++               " are mutually exclusive";
++
++    if ((conf->http_conformance & AP_HTTP_CONFORMANCE_STRICT)
++            && (conf->http_conformance & AP_HTTP_CONFORMANCE_UNSAFE))
++        return "HttpProtocolOptions 'Strict' and 'Unsafe'"
++               " are mutually exclusive";
++
++    if ((conf->http_methods & AP_HTTP_METHODS_REGISTERED)
++            && (conf->http_methods & AP_HTTP_METHODS_LENIENT))
++        return "HttpProtocolOptions 'RegisteredMethods' and 'LenientMethods'"
++               " are mutually exclusive";
++
++    return NULL;
++}
++
++static const char *set_http_method(cmd_parms *cmd, void *conf, const char *arg)
++{
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++    if (err != NULL)
++        return err;
++    ap_method_register(cmd->pool, arg);
++    return NULL;
++}
++
+ static apr_hash_t *errorlog_hash;
+ 
+ static int log_constant_item(const ap_errorlog_info *info, const char *arg,
+@@ -4143,6 +4203,13 @@
+               "'on' (default), 'off' or 'extended' to trace request body content"),
+ AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF,
+               "merge request trailers into request headers or not"),
++AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CONF,
++                "'Allow0.9' or 'Require1.0' (default); "
++                "'RegisteredMethods' or 'LenientMethods' (default); "
++                "'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules")
++,
++AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
++                "Registers non-standard HTTP methods"),
+ { NULL }
+ };
+ 
+diff -uap httpd-2.4.6/server/gen_test_char.c.cve8743 httpd-2.4.6/server/gen_test_char.c
+--- httpd-2.4.6/server/gen_test_char.c.cve8743
++++ httpd-2.4.6/server/gen_test_char.c
+@@ -16,11 +16,11 @@
+ 
+ #ifdef CROSS_COMPILE
+ 
++#include <ctype.h>
+ #define apr_isalnum(c) (isalnum(((unsigned char)(c))))
+ #define apr_isalpha(c) (isalpha(((unsigned char)(c))))
+ #define apr_iscntrl(c) (iscntrl(((unsigned char)(c))))
+ #define apr_isprint(c) (isprint(((unsigned char)(c))))
+-#include <ctype.h>
+ #define APR_HAVE_STDIO_H 1
+ #define APR_HAVE_STRING_H 1
+ 
+@@ -52,11 +52,13 @@
+ #define T_ESCAPE_LOGITEM      (0x10)
+ #define T_ESCAPE_FORENSIC     (0x20)
+ #define T_ESCAPE_URLENCODED   (0x40)
++#define T_HTTP_CTRLS          (0x80)
++#define T_VCHAR_OBSTEXT      (0x100)
+ 
+ int main(int argc, char *argv[])
+ {
+     unsigned c;
+-    unsigned char flags;
++    unsigned short flags;
+ 
+     printf("/* this file is automatically generated by gen_test_char, "
+            "do not edit */\n"
+@@ -67,19 +69,23 @@
+            "#define T_ESCAPE_LOGITEM       (%u)\n"
+            "#define T_ESCAPE_FORENSIC      (%u)\n"
+            "#define T_ESCAPE_URLENCODED    (%u)\n"
++           "#define T_HTTP_CTRLS           (%u)\n"
++           "#define T_VCHAR_OBSTEXT        (%u)\n"
+            "\n"
+-           "static const unsigned char test_char_table[256] = {",
++           "static const unsigned short test_char_table[256] = {",
+            T_ESCAPE_SHELL_CMD,
+            T_ESCAPE_PATH_SEGMENT,
+            T_OS_ESCAPE_PATH,
+            T_HTTP_TOKEN_STOP,
+            T_ESCAPE_LOGITEM,
+            T_ESCAPE_FORENSIC,
+-           T_ESCAPE_URLENCODED);
++           T_ESCAPE_URLENCODED,
++           T_HTTP_CTRLS,
++           T_VCHAR_OBSTEXT);
+ 
+     for (c = 0; c < 256; ++c) {
+         flags = 0;
+-        if (c % 20 == 0)
++        if (c % 8 == 0)
+             printf("\n    ");
+ 
+         /* escape_shell_cmd */
+@@ -107,7 +113,7 @@
+             flags |= T_ESCAPE_PATH_SEGMENT;
+         }
+ 
+-        if (!apr_isalnum(c) && !strchr("$-_.+!*'(),:@&=/~", c)) {
++        if (!apr_isalnum(c) && !strchr("$-_.+!*'(),:;@&=/~", c)) {
+             flags |= T_OS_ESCAPE_PATH;
+         }
+ 
+@@ -115,11 +121,32 @@
+             flags |= T_ESCAPE_URLENCODED;
+         }
+ 
+-        /* these are the "tspecials" (RFC2068) or "separators" (RFC2616) */
+-        if (c && (apr_iscntrl(c) || strchr(" \t()<>@,;:\\\"/[]?={}", c))) {
++        /* Stop for any non-'token' character, including ctrls, obs-text,
++         * and "tspecials" (RFC2068) a.k.a. "separators" (RFC2616), which
++         * is easer to express as characters remaining in the ASCII token set
++         */
++        if (!c || !(apr_isalnum(c) || strchr("!#$%&'*+-.^_`|~", c))) {
+             flags |= T_HTTP_TOKEN_STOP;
+         }
+ 
++        /* Catch CTRLs other than VCHAR, HT and SP, and obs-text (RFC7230 3.2)
++         * This includes only the C0 plane, not C1 (which is obs-text itself.)
++         * XXX: We should verify that all ASCII C0 ctrls/DEL corresponding to
++         * the current EBCDIC translation are captured, and ASCII C1 ctrls
++         * corresponding are all permitted (as they fall under obs-text rule)
++         */
++        if (!c || (apr_iscntrl(c) && c != '\t')) {
++            flags |= T_HTTP_CTRLS;
++        }
++
++        /* From RFC3986, the specific sets of gen-delims, sub-delims (2.2),
++         * and unreserved (2.3) that are possible somewhere within a URI.
++         * Spec requires all others to be %XX encoded, including obs-text.
++         */
++        if (c && !apr_iscntrl(c) && c != ' ') {
++            flags |= T_VCHAR_OBSTEXT;
++        }
++
+         /* For logging, escape all control characters,
+          * double quotes (because they delimit the request in the log file)
+          * backslashes (because we use backslash for escaping)
+@@ -137,7 +164,7 @@
+             flags |= T_ESCAPE_FORENSIC;
+         }
+ 
+-        printf("%u%c", flags, (c < 255) ? ',' : ' ');
++        printf("0x%03x%c", flags, (c < 255) ? ',' : ' ');
+     }
+ 
+     printf("\n};\n");
+diff -uap httpd-2.4.6/server/protocol.c.cve8743 httpd-2.4.6/server/protocol.c
+--- httpd-2.4.6/server/protocol.c.cve8743
++++ httpd-2.4.6/server/protocol.c
+@@ -189,6 +189,10 @@
+  * caused by MIME folding (or broken clients) if fold != 0, and place it
+  * in the buffer s, of size n bytes, without the ending newline.
+  *
++ * Pulls from r->proto_input_filters instead of r->input_filters for
++ * stricter protocol adherence and better input filter behavior during
++ * chunked trailer processing (for http).
++ *
+  * If s is NULL, ap_rgetline_core will allocate necessary memory from r->pool.
+  *
+  * Returns APR_SUCCESS if there are no problems and sets *read to be
+@@ -197,7 +201,7 @@
+  * APR_ENOSPC is returned if there is not enough buffer space.
+  * Other errors may be returned on other errors.
+  *
+- * The LF is *not* returned in the buffer.  Therefore, a *read of 0
++ * The [CR]LF are *not* returned in the buffer.  Therefore, a *read of 0
+  * indicates that an empty line was read.
+  *
+  * Notes: Because the buffer uses 1 char for NUL, the most we can return is
+@@ -208,13 +212,15 @@
+  */
+ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n,
+                                           apr_size_t *read, request_rec *r,
+-                                          int fold, apr_bucket_brigade *bb)
++                                          int flags, apr_bucket_brigade *bb)
+ {
+     apr_status_t rv;
+     apr_bucket *e;
+     apr_size_t bytes_handled = 0, current_alloc = 0;
+     char *pos, *last_char = *s;
+     int do_alloc = (*s == NULL), saw_eos = 0;
++    int fold = flags & AP_GETLINE_FOLD;
++    int crlf = flags & AP_GETLINE_CRLF;
+ 
+     /*
+      * Initialize last_char as otherwise a random value will be compared
+@@ -226,13 +232,15 @@
+ 
+     for (;;) {
+         apr_brigade_cleanup(bb);
+-        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,
++        rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE,
+                             APR_BLOCK_READ, 0);
+         if (rv != APR_SUCCESS) {
+             return rv;
+         }
+ 
+-        /* Something horribly wrong happened.  Someone didn't block! */
++        /* Something horribly wrong happened.  Someone didn't block! 
++         * (this also happens at the end of each keepalive connection)
++         */
+         if (APR_BRIGADE_EMPTY(bb)) {
+             return APR_EGENERAL;
+         }
+@@ -318,6 +326,13 @@
+         }
+     }
+ 
++    if (crlf && (last_char <= *s || last_char[-1] != APR_ASCII_CR)) {
++        *last_char = '\0';
++        bytes_handled = last_char - *s;
++        *read = bytes_handled;
++        return APR_EINVAL;
++    }
++
+     /* Now NUL-terminate the string at the end of the line;
+      * if the last-but-one character is a CR, terminate there */
+     if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
+@@ -340,7 +355,7 @@
+             apr_brigade_cleanup(bb);
+ 
+             /* We only care about the first byte. */
+-            rv = ap_get_brigade(r->input_filters, bb, AP_MODE_SPECULATIVE,
++            rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE,
+                                 APR_BLOCK_READ, 1);
+             if (rv != APR_SUCCESS) {
+                 return rv;
+@@ -391,7 +406,8 @@
+                      */
+                     if (do_alloc) {
+                         tmp = NULL;
+-                    } else {
++                    }
++                    else {
+                         /* We're null terminated. */
+                         tmp = last_char;
+                     }
+@@ -461,7 +477,7 @@
+ }
+ #endif
+ 
+-AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold)
++AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int flags)
+ {
+     char *tmp_s = s;
+     apr_status_t rv;
+@@ -469,7 +485,7 @@
+     apr_bucket_brigade *tmp_bb;
+ 
+     tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+-    rv = ap_rgetline(&tmp_s, n, &len, r, fold, tmp_bb);
++    rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb);
+     apr_brigade_destroy(tmp_bb);
+ 
+     /* Map the out-of-space condition to the old API. */
+@@ -549,16 +565,29 @@
+     }
+ }
+ 
+-static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
++/* get the length of the field name for logging, but no more than 80 bytes */
++#define LOG_NAME_MAX_LEN 80
++static int field_name_len(const char *field)
+ {
+-    const char *ll;
+-    const char *uri;
+-    const char *pro;
++    const char *end = ap_strchr_c(field, ':');
++    if (end == NULL || end - field > LOG_NAME_MAX_LEN)
++        return LOG_NAME_MAX_LEN;
++    return end - field;
++}
+ 
+-    int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
+-    char http[5];
++static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
++{
++    enum {
++        rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace,
++        rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext,
++        rrl_badmethod09, rrl_reject09
++    } deferred_error = rrl_none;
++    char *ll;
++    char *uri;
+     apr_size_t len;
+     int num_blank_lines = 0;
++    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
++    int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
+     int max_blank_lines = r->server->limit_req_fields;
+ 
+     if (max_blank_lines <= 0) {
+@@ -588,7 +617,7 @@
+          */
+         r->the_request = NULL;
+         rv = ap_rgetline(&(r->the_request), (apr_size_t)(r->server->limit_req_line + 2),
+-                         &len, r, 0, bb);
++                         &len, r, strict ? AP_GETLINE_CRLF : 0, bb);
+ 
+         if (rv != APR_SUCCESS) {
+             r->request_time = apr_time_now();
+@@ -599,8 +628,6 @@
+              */
+             if (APR_STATUS_IS_ENOSPC(rv)) {
+                 r->status    = HTTP_REQUEST_URI_TOO_LARGE;
+-                r->proto_num = HTTP_VERSION(1,0);
+-                r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
+             }
+             else if (APR_STATUS_IS_TIMEUP(rv)) {
+                 r->status = HTTP_REQUEST_TIME_OUT;
+@@ -608,6 +635,8 @@
+             else if (APR_STATUS_IS_EINVAL(rv)) {
+                 r->status = HTTP_BAD_REQUEST;
+             }
++            r->proto_num = HTTP_VERSION(1,0);
++            r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
+             return 0;
+         }
+     } while ((len <= 0) && (++num_blank_lines < max_blank_lines));
+@@ -619,46 +648,263 @@
+     }
+ 
+     r->request_time = apr_time_now();
+-    ll = r->the_request;
+-    r->method = ap_getword_white(r->pool, &ll);
++    r->method = r->the_request;
++
++    /* If there is whitespace before a method, skip it and mark in error */
++    if (apr_isspace(*r->method)) {
++        deferred_error = rrl_badwhitespace;
++        for ( ; apr_isspace(*r->method); ++r->method)
++            ;
++    }
+ 
+-    uri = ap_getword_white(r->pool, &ll);
++    /* Scan the method up to the next whitespace, ensure it contains only
++     * valid http-token characters, otherwise mark in error
++     */
++    if (strict) {
++        ll = (char*) ap_scan_http_token(r->method);
++    }
++    else {
++        ll = (char*) ap_scan_vchar_obstext(r->method);
++    }
+ 
+-    /* Provide quick information about the request method as soon as known */
++    if (((ll == r->method) || (*ll && !apr_isspace(*ll)))
++            && deferred_error == rrl_none) {
++        deferred_error = rrl_badmethod;
++        ll = strpbrk(ll, "\t\n\v\f\r ");
++    }
+ 
+-    r->method_number = ap_method_number_of(r->method);
+-    if (r->method_number == M_GET && r->method[0] == 'H') {
+-        r->header_only = 1;
++    /* Verify method terminated with a single SP, or mark as specific error */
++    if (!ll) {
++        if (deferred_error == rrl_none)
++            deferred_error = rrl_missinguri;
++        r->protocol = uri = "";
++        len = 0;
++        goto rrl_done;
++    }
++    else if (strict && ll[0] && apr_isspace(ll[1])
++             && deferred_error == rrl_none) {
++        deferred_error = rrl_excesswhitespace;
+     }
+ 
+-    ap_parse_uri(r, uri);
++    /* Advance uri pointer over leading whitespace, NUL terminate the method
++     * If non-SP whitespace is encountered, mark as specific error
++     */
++    for (uri = ll; apr_isspace(*uri); ++uri)
++        if (*uri != ' ' && deferred_error == rrl_none)
++            deferred_error = rrl_badwhitespace;
++    *ll = '\0';
++
++    if (!*uri && deferred_error == rrl_none)
++        deferred_error = rrl_missinguri;
++
++    /* Scan the URI up to the next whitespace, ensure it contains no raw
++     * control characters, otherwise mark in error
++     */
++    ll = (char*) ap_scan_vchar_obstext(uri);
++    if (ll == uri || (*ll && !apr_isspace(*ll))) {
++        deferred_error = rrl_baduri;
++        ll = strpbrk(ll, "\t\n\v\f\r ");
++    }
+ 
+-    if (ll[0]) {
++    /* Verify URI terminated with a single SP, or mark as specific error */
++    if (!ll) {
++        r->protocol = "";
++        len = 0;
++        goto rrl_done;
++    }
++    else if (strict && ll[0] && apr_isspace(ll[1])
++             && deferred_error == rrl_none) {
++        deferred_error = rrl_excesswhitespace;
++    }
++
++    /* Advance protocol pointer over leading whitespace, NUL terminate the uri
++     * If non-SP whitespace is encountered, mark as specific error
++     */
++    for (r->protocol = ll; apr_isspace(*r->protocol); ++r->protocol)
++        if (*r->protocol != ' ' && deferred_error == rrl_none)
++            deferred_error = rrl_badwhitespace;
++    *ll = '\0';
++
++    /* Scan the protocol up to the next whitespace, validation comes later */
++    if (!(ll = (char*) ap_scan_vchar_obstext(r->protocol))) {
++        len = strlen(r->protocol);
++        goto rrl_done;
++    }
++    len = ll - r->protocol;
++
++    /* Advance over trailing whitespace, if found mark in error,
++     * determine if trailing text is found, unconditionally mark in error,
++     * finally NUL terminate the protocol string
++     */
++    if (*ll && !apr_isspace(*ll)) {
++        deferred_error = rrl_badprotocol;
++    }
++    else if (strict && *ll) {
++        deferred_error = rrl_excesswhitespace;
++    }
++    else {
++        for ( ; apr_isspace(*ll); ++ll)
++            if (*ll != ' ' && deferred_error == rrl_none)
++                deferred_error = rrl_badwhitespace;
++        if (*ll && deferred_error == rrl_none)
++            deferred_error = rrl_trailingtext;
++    }
++    *((char *)r->protocol + len) = '\0';
++
++rrl_done:
++    /* For internal integrety and palloc efficiency, reconstruct the_request
++     * in one palloc, using only single SP characters, per spec.
++     */
++    r->the_request = apr_pstrcat(r->pool, r->method, *uri ? " " : NULL, uri,
++                                 *r->protocol ? " " : NULL, r->protocol, NULL);
++
++    if (len == 8
++            && r->protocol[0] == 'H' && r->protocol[1] == 'T'
++            && r->protocol[2] == 'T' && r->protocol[3] == 'P'
++            && r->protocol[4] == '/' && apr_isdigit(r->protocol[5])
++            && r->protocol[6] == '.' && apr_isdigit(r->protocol[7])
++            && r->protocol[5] != '0') {
++        r->assbackwards = 0;
++        r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
++    }
++    else if (len == 8
++                 && (r->protocol[0] == 'H' || r->protocol[0] == 'h')
++                 && (r->protocol[1] == 'T' || r->protocol[1] == 't')
++                 && (r->protocol[2] == 'T' || r->protocol[2] == 't')
++                 && (r->protocol[3] == 'P' || r->protocol[3] == 'p')
++                 && r->protocol[4] == '/' && apr_isdigit(r->protocol[5])
++                 && r->protocol[6] == '.' && apr_isdigit(r->protocol[7])
++                 && r->protocol[5] != '0') {
+         r->assbackwards = 0;
+-        pro = ll;
+-        len = strlen(ll);
+-    } else {
++        r->proto_num = HTTP_VERSION(r->protocol[5] - '0', r->protocol[7] - '0');
++        if (strict && deferred_error == rrl_none)
++            deferred_error = rrl_badprotocol;
++        else
++            memcpy((char*)r->protocol, "HTTP", 4);
++    } else if (r->protocol[0]) {
++        r->proto_num = HTTP_VERSION(0, 9);
++        /* Defer setting the r->protocol string till error msg is composed */
++        if (deferred_error == rrl_none)
++            deferred_error = rrl_badprotocol;
++    }
++    else {
+         r->assbackwards = 1;
+-        pro = "HTTP/0.9";
+-        len = 8;
++        r->protocol  = apr_pstrdup(r->pool, "HTTP/0.9");
++        r->proto_num = HTTP_VERSION(0, 9);
+     }
+-    r->protocol = apr_pstrmemdup(r->pool, pro, len);
+ 
+-    /* Avoid sscanf in the common case */
+-    if (len == 8
+-        && pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P'
+-        && pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.'
+-        && apr_isdigit(pro[7])) {
+-        r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
+-    }
+-    else if (3 == sscanf(r->protocol, "%4s/%u.%u", http, &major, &minor)
+-             && (strcasecmp("http", http) == 0)
+-             && (minor < HTTP_VERSION(1, 0)) ) /* don't allow HTTP/0.1000 */
+-        r->proto_num = HTTP_VERSION(major, minor);
+-    else
+-        r->proto_num = HTTP_VERSION(1, 0);
++    /* Determine the method_number and parse the uri prior to invoking error
++     * handling, such that these fields are available for subsitution
++     */
++    r->method_number = ap_method_number_of(r->method);
++    if (r->method_number == M_GET && r->method[0] == 'H')
++        r->header_only = 1;
++
++    ap_parse_uri(r, uri);
++
++    /* With the request understood, we can consider HTTP/0.9 specific errors */
++    if (r->proto_num == HTTP_VERSION(0, 9) && deferred_error == rrl_none) {
++        if (conf->http09_enable == AP_HTTP09_DISABLE)
++            deferred_error = rrl_reject09;
++        else if (strict && (r->method_number != M_GET || r->header_only))
++            deferred_error = rrl_badmethod09;
++    }
++
++    /* Now that the method, uri and protocol are all processed,
++     * we can safely resume any deferred error reporting
++     */
++    if (deferred_error != rrl_none) {
++        if (deferred_error == rrl_badmethod)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03445)
++                          "HTTP Request Line; Invalid method token: '%.*s'",
++                          field_name_len(r->method), r->method);
++        else if (deferred_error == rrl_badmethod09)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03444)
++                          "HTTP Request Line; Invalid method token: '%.*s'"
++                          " (only GET is allowed for HTTP/0.9 requests)",
++                          field_name_len(r->method), r->method);
++        else if (deferred_error == rrl_missinguri)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03446)
++                          "HTTP Request Line; Missing URI");
++        else if (deferred_error == rrl_baduri)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03454)
++                          "HTTP Request Line; URI incorrectly encoded: '%.*s'",
++                          field_name_len(r->uri), r->uri);
++        else if (deferred_error == rrl_badwhitespace)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03447)
++                          "HTTP Request Line; Invalid whitespace");
++        else if (deferred_error == rrl_excesswhitespace)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03448)
++                          "HTTP Request Line; Excess whitespace "
++                          "(disallowed by HttpProtocolOptions Strict");
++        else if (deferred_error == rrl_trailingtext)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03449)
++                          "HTTP Request Line; Extraneous text found '%.*s' "
++                          "(perhaps whitespace was injected?)",
++                          field_name_len(ll), ll);
++        else if (deferred_error == rrl_reject09)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02401)
++                          "HTTP Request Line; Rejected HTTP/0.9 request");
++        else if (deferred_error == rrl_badprotocol)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02418)
++                          "HTTP Request Line; Unrecognized protocol '%.*s' "
++                          "(perhaps whitespace was injected?)",
++                          field_name_len(r->protocol), r->protocol);
++        r->status = HTTP_BAD_REQUEST;
++        goto rrl_failed;
++    }
++
++    if (conf->http_methods == AP_HTTP_METHODS_REGISTERED
++            && r->method_number == M_INVALID) {
++        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02423)
++                      "HTTP Request Line; Unrecognized HTTP method: '%.*s' "
++                      "(disallowed by RegisteredMethods)",
++                      field_name_len(r->method), r->method);
++        r->status = HTTP_NOT_IMPLEMENTED;
++        /* This can't happen in an HTTP/0.9 request, we verified GET above */
++        return 0;
++    }
++
++    if (r->status != HTTP_OK) {
++        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03450)
++                      "HTTP Request Line; Unable to parse URI: '%.*s'",
++                      field_name_len(r->uri), r->uri);
++        goto rrl_failed;
++    }
++
++    if (strict) {
++        if (r->parsed_uri.fragment) {
++            /* RFC3986 3.5: no fragment */
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02421)
++                          "HTTP Request Line; URI must not contain a fragment");
++            r->status = HTTP_BAD_REQUEST;
++            goto rrl_failed;
++        }
++        if (r->parsed_uri.user || r->parsed_uri.password) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02422)
++                          "HTTP Request Line; URI must not contain a "
++                          "username/password");
++            r->status = HTTP_BAD_REQUEST;
++            goto rrl_failed;
++        }
++    }
+ 
+     return 1;
++rrl_failed:
++    if (r->proto_num == HTTP_VERSION(0, 9)) {
++        /* Send all parsing and protocol error response with 1.x behavior,
++         * and reserve 505 errors for actual HTTP protocols presented.
++         * As called out in RFC7230 3.5, any errors parsing the protocol
++         * from the request line are nearly always misencoded HTTP/1.x
++         * requests. Only a valid 0.9 request with no parsing errors
++         * at all may be treated as a simple request, if allowed.
++         */
++        r->assbackwards = 0;
++        r->connection->keepalive = AP_CONN_CLOSE;
++        r->proto_num = HTTP_VERSION(1, 0);
++        r->protocol  = apr_pstrdup(r->pool, "HTTP/1.0");
++    }
++    return 0;
+ }
+ 
+ static int table_do_fn_check_lengths(void *r_, const char *key,
+@@ -670,26 +916,13 @@
+ 
+     r->status = HTTP_BAD_REQUEST;
+     apr_table_setn(r->notes, "error-notes",
+-                   apr_pstrcat(r->pool, "Size of a request header field "
+-                               "after merging exceeds server limit.<br />"
+-                               "\n<pre>\n",
+-                               ap_escape_html(r->pool, key),
+-                               "</pre>\n", NULL));
+-    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00560) "Request header "
+-                  "exceeds LimitRequestFieldSize after merging: %s", key);
++                   "Size of a request header field exceeds server limit.");
++    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00560) "Request "
++                  "header exceeds LimitRequestFieldSize after merging: %.*s",
++                  field_name_len(key), key);
+     return 0;
+ }
+ 
+-/* get the length of the field name for logging, but no more than 80 bytes */
+-#define LOG_NAME_MAX_LEN 80
+-static int field_name_len(const char *field)
+-{
+-    const char *end = ap_strchr_c(field, ':');
+-    if (end == NULL || end - field > LOG_NAME_MAX_LEN)
+-        return LOG_NAME_MAX_LEN;
+-    return end - field;
+-}
+-
+ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb)
+ {
+     char *last_field = NULL;
+@@ -700,6 +933,8 @@
+     apr_size_t len;
+     int fields_read = 0;
+     char *tmp_field;
++    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
++    int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
+ 
+     /*
+      * Read header lines until we get the empty separator line, a read error,
+@@ -707,11 +942,10 @@
+      */
+     while(1) {
+         apr_status_t rv;
+-        int folded = 0;
+ 
+         field = NULL;
+         rv = ap_rgetline(&field, r->server->limit_req_fieldsize + 2,
+-                         &len, r, 0, bb);
++                         &len, r, strict ? AP_GETLINE_CRLF : 0, bb);
+ 
+         if (rv != APR_SUCCESS) {
+             if (APR_STATUS_IS_TIMEUP(rv)) {
+@@ -728,153 +962,217 @@
+              * exceeds the configured limit for a field size.
+              */
+             if (rv == APR_ENOSPC) {
+-                const char *field_escaped;
+-                if (field) {
+-                    /* ensure ap_escape_html will terminate correctly */
+-                    field[len - 1] = '\0';
+-                    field_escaped = ap_escape_html(r->pool, field);
+-                }
+-                else {
+-                    field_escaped = field = "";
+-                }
+-
+                 apr_table_setn(r->notes, "error-notes",
+-                               apr_psprintf(r->pool,
+-                                           "Size of a request header field "
+-                                           "exceeds server limit.<br />\n"
+-                                           "<pre>\n%.*s\n</pre>\n", 
+-                                           field_name_len(field_escaped),
+-                                           field_escaped));
++                               "Size of a request header field "
++                               "exceeds server limit.");
+                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00561)
+                               "Request header exceeds LimitRequestFieldSize%s"
+                               "%.*s",
+-                              *field ? ": " : "",
+-                              field_name_len(field), field);
++                              (field && *field) ? ": " : "",
++                              (field) ? field_name_len(field) : 0,
++                              (field) ? field : "");
+             }
+             return;
+         }
+ 
+-        if (last_field != NULL) {
+-            if ((len > 0) && ((*field == '\t') || *field == ' ')) {
+-                /* This line is a continuation of the preceding line(s),
+-                 * so append it to the line that we've set aside.
+-                 * Note: this uses a power-of-two allocator to avoid
+-                 * doing O(n) allocs and using O(n^2) space for
+-                 * continuations that span many many lines.
+-                 */
+-                apr_size_t fold_len = last_len + len + 1; /* trailing null */
+ 
+-                if (fold_len >= (apr_size_t)(r->server->limit_req_fieldsize)) {
+-                    r->status = HTTP_BAD_REQUEST;
+-                    /* report what we have accumulated so far before the
+-                     * overflow (last_field) as the field with the problem
+-                     */
+-                    apr_table_setn(r->notes, "error-notes",
+-                                   apr_psprintf(r->pool,
+-                                               "Size of a request header field "
+-                                               "after folding "
+-                                               "exceeds server limit.<br />\n"
+-                                               "<pre>\n%.*s\n</pre>\n", 
+-                                               field_name_len(last_field), 
+-                                               ap_escape_html(r->pool, last_field)));
+-                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00562)
+-                                  "Request header exceeds LimitRequestFieldSize "
+-                                  "after folding: %.*s",
+-                                  field_name_len(last_field), last_field);
+-                    return;
+-                }
++        /* For all header values, and all obs-fold lines, the presence of
++         * additional whitespace is a no-op, so collapse trailing whitespace
++         * to save buffer allocation and optimize copy operations.
++         * Do not remove the last single whitespace under any condition.
++         */
++        while (len > 1 && (field[len-1] == '\t' || field[len-1] == ' ')) {
++            field[--len] = '\0';
++        }
++
++        if (*field == '\t' || *field == ' ') {
++            /* Append any newly-read obs-fold line onto the preceding
++             * last_field line we are processing
++             */
++            apr_size_t fold_len;
+ 
++            if (last_field == NULL) {
++                r->status = HTTP_BAD_REQUEST;
++                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03442)
++                              "Line folding encountered before first"
++                              " header line");
++                return;
++            }
++
++            if (field[1] == '\0') {
++                r->status = HTTP_BAD_REQUEST;
++                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03443)
++                              "Empty folded line encountered");
++                return;
++            }
++
++            /* Leading whitespace on an obs-fold line can be
++             * similarly discarded */
++            while (field[1] == '\t' || field[1] == ' ') {
++                ++field; --len;
++            }
++
++            /* This line is a continuation of the preceding line(s),
++             * so append it to the line that we've set aside.
++             * Note: this uses a power-of-two allocator to avoid
++             * doing O(n) allocs and using O(n^2) space for
++             * continuations that span many many lines.
++             */
++            fold_len = last_len + len + 1; /* trailing null */
++
++            if (fold_len >= (apr_size_t)(r->server->limit_req_fieldsize)) {
++                r->status = HTTP_BAD_REQUEST;
++                /* report what we have accumulated so far before the
++                 * overflow (last_field) as the field with the problem
++                 */
++                apr_table_setn(r->notes, "error-notes",
++                               "Size of a request header field "
++                               "exceeds server limit.");
++                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00562)
++                              "Request header exceeds LimitRequestFieldSize "
++                              "after folding: %.*s",
++                              field_name_len(last_field), last_field);
++                return;
++            }
++
++            if (fold_len > alloc_len) {
++                char *fold_buf;
++                alloc_len += alloc_len;
+                 if (fold_len > alloc_len) {
+-                    char *fold_buf;
+-                    alloc_len += alloc_len;
+-                    if (fold_len > alloc_len) {
+-                        alloc_len = fold_len;
+-                    }
+-                    fold_buf = (char *)apr_palloc(r->pool, alloc_len);
+-                    memcpy(fold_buf, last_field, last_len);
+-                    last_field = fold_buf;
++                    alloc_len = fold_len;
+                 }
+-                memcpy(last_field + last_len, field, len +1); /* +1 for nul */
+-                last_len += len;
+-                folded = 1;
+-            }
+-            else /* not a continuation line */ {
++                fold_buf = (char *)apr_palloc(r->pool, alloc_len);
++                memcpy(fold_buf, last_field, last_len);
++                last_field = fold_buf;
++            }
++            memcpy(last_field + last_len, field, len +1); /* +1 for nul */
++            /* Replace obs-fold w/ SP per RFC 7230 3.2.4 */
++            last_field[last_len] = ' ';
++            last_len += len;
+ 
+-                if (r->server->limit_req_fields
++            /* We've appended this obs-fold line to last_len, proceed to
++             * read the next input line
++             */
++            continue;
++        }
++        else if (last_field != NULL) {
++            /* Process the previous last_field header line with all obs-folded
++             * segments already concatinated (this is not operating on the
++             * most recently read input line).
++             */
++            if (r->server->limit_req_fields
+                     && (++fields_read > r->server->limit_req_fields)) {
+-                    r->status = HTTP_BAD_REQUEST;
+-                    apr_table_setn(r->notes, "error-notes",
+-                                   "The number of request header fields "
+-                                   "exceeds this server's limit.");
+-                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00563)
+-                                  "Number of request headers exceeds "
+-                                  "LimitRequestFields");
+-                    return;
+-                }
++                r->status = HTTP_BAD_REQUEST;
++                apr_table_setn(r->notes, "error-notes",
++                               "The number of request header fields "
++                               "exceeds this server's limit.");
++                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00563)
++                               "Number of request headers exceeds "
++                               "LimitRequestFields");
++                return;
++            }
+ 
+-                if (!(value = strchr(last_field, ':'))) { /* Find ':' or    */
+-                    r->status = HTTP_BAD_REQUEST;      /* abort bad request */
+-                    apr_table_setn(r->notes, "error-notes",
+-                                   apr_psprintf(r->pool,
+-                                               "Request header field is "
+-                                               "missing ':' separator.<br />\n"
+-                                               "<pre>\n%.*s</pre>\n", 
+-                                               (int)LOG_NAME_MAX_LEN,
+-                                               ap_escape_html(r->pool,
+-                                                              last_field)));
+-                    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00564)
++            if (!strict)
++            {
++                /* Not Strict ('Unsafe' mode), using the legacy parser */
++
++                if (!(value = strchr(last_field, ':'))) { /* Find ':' or */
++                    r->status = HTTP_BAD_REQUEST;   /* abort bad request */
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00564)
+                                   "Request header field is missing ':' "
+                                   "separator: %.*s", (int)LOG_NAME_MAX_LEN,
+                                   last_field);
++
+                     return;
+                 }
+ 
+-                tmp_field = value - 1; /* last character of field-name */
++                /* last character of field-name */
++                tmp_field = value - (value > last_field ? 1 : 0);
+ 
+                 *value++ = '\0'; /* NUL-terminate at colon */
+ 
++                if (strpbrk(last_field, "\t\n\v\f\r ")) {
++                    r->status = HTTP_BAD_REQUEST;
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03452)
++                                  "Request header field name presented"
++                                  " invalid whitespace");
++                    return;
++                }
++
+                 while (*value == ' ' || *value == '\t') {
+-                    ++value;            /* Skip to start of value   */
++                     ++value;            /* Skip to start of value   */
++                }
++
++                if (strpbrk(value, "\n\v\f\r")) {
++                    r->status = HTTP_BAD_REQUEST;
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03451)
++                                  "Request header field value presented"
++                                  " bad whitespace");
++                    return;
+                 }
+ 
+-                /* Strip LWS after field-name: */
+-                while (tmp_field > last_field
+-                       && (*tmp_field == ' ' || *tmp_field == '\t')) {
+-                    *tmp_field-- = '\0';
++                if (tmp_field == last_field) {
++                    r->status = HTTP_BAD_REQUEST;
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03453)
++                                  "Request header field name was empty");
++                    return;
++                }
++            }
++            else /* Using strict RFC7230 parsing */
++            {
++                /* Ensure valid token chars before ':' per RFC 7230 3.2.4 */
++                value = (char *)ap_scan_http_token(last_field);
++                if ((value == last_field) || *value != ':') {
++                    r->status = HTTP_BAD_REQUEST;
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02426)
++                                  "Request header field name is malformed: "
++                                  "%.*s", (int)LOG_NAME_MAX_LEN, last_field);
++                    return;
+                 }
+ 
+-                /* Strip LWS after field-value: */
+-                tmp_field = last_field + last_len - 1;
+-                while (tmp_field > value
+-                       && (*tmp_field == ' ' || *tmp_field == '\t')) {
+-                    *tmp_field-- = '\0';
++                *value++ = '\0'; /* NUL-terminate last_field name at ':' */
++
++                while (*value == ' ' || *value == '\t') {
++                    ++value;     /* Skip LWS of value */
+                 }
+ 
+-                apr_table_addn(r->headers_in, last_field, value);
++                /* Find invalid, non-HT ctrl char, or the trailing NULL */
++                tmp_field = (char *)ap_scan_http_field_content(value);
+ 
+-                /* reset the alloc_len so that we'll allocate a new
+-                 * buffer if we have to do any more folding: we can't
+-                 * use the previous buffer because its contents are
+-                 * now part of r->headers_in
++                /* Reject value for all garbage input (CTRLs excluding HT)
++                 * e.g. only VCHAR / SP / HT / obs-text are allowed per
++                 * RFC7230 3.2.6 - leave all more explicit rule enforcement
++                 * for specific header handler logic later in the cycle
+                  */
+-                alloc_len = 0;
++                if (*tmp_field != '\0') {
++                    r->status = HTTP_BAD_REQUEST;
++                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02427)
++                                  "Request header value is malformed: "
++                                  "%.*s", (int)LOG_NAME_MAX_LEN, value);
++                    return;
++                }
++            }
++
++            apr_table_addn(r->headers_in, last_field, value);
+ 
+-            } /* end if current line is not a continuation starting with tab */
++            /* This last_field header is now stored in headers_in,
++             * resume processing of the current input line.
++             */
+         }
+ 
+-        /* Found a blank line, stop. */
++        /* Found the terminating empty end-of-headers line, stop. */
+         if (len == 0) {
+             break;
+         }
+ 
+-        /* Keep track of this line so that we can parse it on
+-         * the next loop iteration.  (In the folded case, last_field
+-         * has been updated already.)
++        /* Keep track of this new header line so that we can extend it across
++         * any obs-fold or parse it on the next loop iteration. We referenced
++         * our previously allocated buffer in r->headers_in,
++         * so allocate a fresh buffer if required.
+          */
+-        if (!folded) {
+-            last_field = field;
+-            last_len = len;
+-        }
++        alloc_len = 0;
++        last_field = field;
++        last_len = len;
+     }
+ 
+     /* Combine multiple message-header fields with the same
+@@ -899,7 +1197,7 @@
+     request_rec *r;
+     apr_pool_t *p;
+     const char *expect;
+-    int access_status = HTTP_OK;
++    int access_status;
+     apr_bucket_brigade *tmp_bb;
+     apr_socket_t *csd;
+     apr_interval_time_t cur_timeout;
+@@ -958,35 +1256,39 @@
+ 
+     /* Get the request... */
+     if (!read_request_line(r, tmp_bb)) {
+-        if (r->status == HTTP_REQUEST_URI_TOO_LARGE
+-            || r->status == HTTP_BAD_REQUEST) {
++        switch (r->status) {
++        case HTTP_REQUEST_URI_TOO_LARGE:
++        case HTTP_BAD_REQUEST:
++        case HTTP_VERSION_NOT_SUPPORTED:
++        case HTTP_NOT_IMPLEMENTED:
+             if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
+                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00565)
+                               "request failed: client's request-line exceeds LimitRequestLine (longer than %d)",
+                               r->server->limit_req_line);
+             }
+             else if (r->method == NULL) {
+-                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00566)
+-                              "request failed: invalid characters in URI");
++                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00566)
++                              "request failed: malformed request line");
+             }
+-            ap_send_error_response(r, 0);
++            access_status = r->status;
++            r->status = HTTP_OK;
++            ap_die(access_status, r);
+             ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+             ap_run_log_transaction(r);
++            r = NULL;
+             apr_brigade_destroy(tmp_bb);
+             goto traceout;
+-        }
+-        else if (r->status == HTTP_REQUEST_TIME_OUT) {
+-            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+-            if (!r->connection->keepalives) {
++        case HTTP_REQUEST_TIME_OUT:
++            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL);
++            if (!r->connection->keepalives)
+                 ap_run_log_transaction(r);
+-            }
+             apr_brigade_destroy(tmp_bb);
+             goto traceout;
++        default:
++            apr_brigade_destroy(tmp_bb);
++            r = NULL;
++            goto traceout;
+         }
+-
+-        apr_brigade_destroy(tmp_bb);
+-        r = NULL;
+-        goto traceout;
+     }
+ 
+     /* We may have been in keep_alive_timeout mode, so toggle back
+@@ -1003,7 +1305,7 @@
+     if (!r->assbackwards) {
+         ap_get_mime_headers_core(r, tmp_bb);
+         if (r->status != HTTP_OK) {
+-            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00567)
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00567)
+                           "request failed: error reading the headers");
+             ap_send_error_response(r, 0);
+             ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+@@ -1021,25 +1323,6 @@
+             apr_table_unset(r->headers_in, "Content-Length");
+         }
+     }
+-    else {
+-        if (r->header_only) {
+-            /*
+-             * Client asked for headers only with HTTP/0.9, which doesn't send
+-             * headers! Have to dink things just to make sure the error message
+-             * comes through...
+-             */
+-            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00568)
+-                          "client sent invalid HTTP/0.9 request: HEAD %s",
+-                          r->uri);
+-            r->header_only = 0;
+-            r->status = HTTP_BAD_REQUEST;
+-            ap_send_error_response(r, 0);
+-            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+-            ap_run_log_transaction(r);
+-            apr_brigade_destroy(tmp_bb);
+-            goto traceout;
+-        }
+-    }
+ 
+     apr_brigade_destroy(tmp_bb);
+ 
+@@ -1071,7 +1354,7 @@
+          * a Host: header, and the server MUST respond with 400 if it doesn't.
+          */
+         access_status = HTTP_BAD_REQUEST;
+-        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00569)
++        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569)
+                       "client sent HTTP/1.1 request without hostname "
+                       "(see RFC2616 section 14.23): %s", r->uri);
+     }
+diff -uap httpd-2.4.6/server/util.c.cve8743 httpd-2.4.6/server/util.c
+--- httpd-2.4.6/server/util.c.cve8743
++++ httpd-2.4.6/server/util.c
+@@ -79,7 +79,7 @@
+  * char in here and get it to work, because if char is signed then it
+  * will first be sign extended.
+  */
+-#define TEST_CHAR(c, f)        (test_char_table[(unsigned)(c)] & (f))
++#define TEST_CHAR(c, f)        (test_char_table[(unsigned char)(c)] & (f))
+ 
+ /* Win32/NetWare/OS2 need to check for both forward and back slashes
+  * in ap_getparents() and ap_escape_url.
+@@ -1449,6 +1449,37 @@
+     return find_list_item(p, line, tok, AP_ETAG_WEAK);
+ }
+ 
++/* Scan a string for HTTP VCHAR/obs-text characters including HT and SP
++ * (as used in header values, for example, in RFC 7230 section 3.2)
++ * returning the pointer to the first non-HT ASCII ctrl character.
++ */
++AP_DECLARE(const char *) ap_scan_http_field_content(const char *ptr)
++{
++    for ( ; !TEST_CHAR(*ptr, T_HTTP_CTRLS); ++ptr) ;
++
++    return ptr;
++}
++
++/* Scan a string for HTTP token characters, returning the pointer to
++ * the first non-token character.
++ */
++AP_DECLARE(const char *) ap_scan_http_token(const char *ptr)
++{
++    for ( ; !TEST_CHAR(*ptr, T_HTTP_TOKEN_STOP); ++ptr) ;
++
++    return ptr;
++}
++
++/* Scan a string for visible ASCII (0x21-0x7E) or obstext (0x80+)
++ * and return a pointer to the first ctrl/space character encountered.
++ */
++AP_DECLARE(const char *) ap_scan_vchar_obstext(const char *ptr)
++{
++    for ( ; TEST_CHAR(*ptr, T_VCHAR_OBSTEXT); ++ptr) ;
++
++    return ptr;
++}
++
+ /* Retrieve a token, spacing over it and returning a pointer to
+  * the first non-white byte afterwards.  Note that these tokens
+  * are delimited by semis and commas; and can also be delimited
+diff -uap httpd-2.4.6/server/vhost.c.cve8743 httpd-2.4.6/server/vhost.c
+--- httpd-2.4.6/server/vhost.c.cve8743
++++ httpd-2.4.6/server/vhost.c
+@@ -685,6 +685,116 @@
+  * run-time vhost matching functions
+  */
+ 
++static apr_status_t fix_hostname_v6_literal(request_rec *r, char *host)
++{
++    char *dst;
++    int double_colon = 0;
++
++    for (dst = host; *dst; dst++) {
++        if (apr_isxdigit(*dst)) {
++            if (apr_isupper(*dst)) {
++                *dst = apr_tolower(*dst);
++            }
++        }
++        else if (*dst == ':') {
++            if (*(dst + 1) == ':') {
++                if (double_colon)
++                    return APR_EINVAL;
++                double_colon = 1;
++            }
++            else if (*(dst + 1) == '.') {
++                return APR_EINVAL;
++            }
++        }
++        else if (*dst == '.') {
++            /* For IPv4-mapped IPv6 addresses like ::FFFF:129.144.52.38 */
++            if (*(dst + 1) == ':' || *(dst + 1) == '.')
++                return APR_EINVAL;
++        }
++        else {
++            return APR_EINVAL;
++        }
++    }
++    return APR_SUCCESS;
++}
++
++static apr_status_t fix_hostname_non_v6(request_rec *r, char *host)
++{
++    char *dst;
++
++    for (dst = host; *dst; dst++) {
++        if (apr_islower(*dst)) {
++            /* leave char unchanged */
++        }
++        else if (*dst == '.') {
++            if (*(dst + 1) == '.') {
++                return APR_EINVAL;
++            }
++        }
++        else if (apr_isupper(*dst)) {
++            *dst = apr_tolower(*dst);
++        }
++        else if (*dst == '/' || *dst == '\\') {
++            return APR_EINVAL;
++        }
++    }
++    /* strip trailing gubbins */
++    if (dst > host && dst[-1] == '.') {
++        dst[-1] = '\0';
++    }
++    return APR_SUCCESS;
++}
++
++/*
++ * If strict mode ever becomes the default, this should be folded into
++ * fix_hostname_non_v6()
++ */
++static apr_status_t strict_hostname_check(request_rec *r, char *host)
++{
++    char *ch;
++    int is_dotted_decimal = 1, leading_zeroes = 0, dots = 0;
++
++    for (ch = host; *ch; ch++) {
++        if (!apr_isascii(*ch)) {
++            goto bad;
++        }
++        else if (apr_isalpha(*ch) || *ch == '-') {
++            is_dotted_decimal = 0;
++        }
++        else if (ch[0] == '.') {
++            dots++;
++            if (ch[1] == '0' && apr_isdigit(ch[2]))
++                leading_zeroes = 1;
++        }
++        else if (!apr_isdigit(*ch)) {
++           /* also takes care of multiple Host headers by denying commas */
++            goto bad;
++        }
++    }
++    if (is_dotted_decimal) {
++        if (host[0] == '.' || (host[0] == '0' && apr_isdigit(host[1])))
++            leading_zeroes = 1;
++        if (leading_zeroes || dots != 3) {
++            /* RFC 3986 7.4 */
++            goto bad;
++        }
++    }
++    else {
++        /* The top-level domain must start with a letter (RFC 1123 2.1) */
++        while (ch > host && *ch != '.')
++            ch--;
++        if (ch[0] == '.' && ch[1] != '\0' && !apr_isalpha(ch[1]))
++            goto bad;
++    }
++    return APR_SUCCESS;
++
++bad:
++    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02415)
++                  "[strict] Invalid host name '%s'%s%.6s",
++                  host, *ch ? ", problem near: " : "", ch);
++    return APR_EINVAL;
++}
++
+ /* Lowercase and remove any trailing dot and/or :port from the hostname,
+  * and check that it is sane.
+  *
+@@ -698,79 +808,90 @@
+  * Instead we just check for filesystem metacharacters: directory
+  * separators / and \ and sequences of more than one dot.
+  */
+-static void fix_hostname(request_rec *r)
++static int fix_hostname(request_rec *r, const char *host_header,
++                        unsigned http_conformance)
+ {
++    const char *src;
+     char *host, *scope_id;
+-    char *dst;
+     apr_port_t port;
+     apr_status_t rv;
+     const char *c;
++    int is_v6literal = 0;
++    int strict = (http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
+ 
+-    /* According to RFC 2616, Host header field CAN be blank. */
+-    if (!*r->hostname) {
+-        return;
++    src = host_header ? host_header : r->hostname;
++
++    /* According to RFC 2616, Host header field CAN be blank */
++    if (!*src) {
++        return is_v6literal;
+     }
+ 
+     /* apr_parse_addr_port will interpret a bare integer as a port
+      * which is incorrect in this context.  So treat it separately.
+      */
+-    for (c = r->hostname; apr_isdigit(*c); ++c);
+-    if (!*c) {  /* pure integer */
+-        return;
++    for (c = src; apr_isdigit(*c); ++c);
++    if (!*c) {
++        /* pure integer */
++        if (strict) {
++            /* RFC 3986 7.4 */
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02416)
++                         "[strict] purely numeric host names not allowed: %s",
++                         src);
++            goto bad_nolog;
++        }
++        r->hostname = src;
++        return is_v6literal;
++    }
++
++    if (host_header) {
++        rv = apr_parse_addr_port(&host, &scope_id, &port, src, r->pool);
++        if (rv != APR_SUCCESS || scope_id)
++            goto bad;
++        if (port) {
++            /* Don't throw the Host: header's port number away:
++               save it in parsed_uri -- ap_get_server_port() needs it! */
++            /* @@@ XXX there should be a better way to pass the port.
++             *         Like r->hostname, there should be a r->portno
++             */
++            r->parsed_uri.port = port;
++            r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
++        }
++        if (host_header[0] == '[')
++            is_v6literal = 1;
++    }
++    else {
++        /*
++         * Already parsed, surrounding [ ] (if IPv6 literal) and :port have
++         * already been removed.
++         */
++        host = apr_pstrdup(r->pool, r->hostname);
++        if (ap_strchr(host, ':') != NULL)
++            is_v6literal = 1;
+     }
+ 
+-    rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
+-    if (rv != APR_SUCCESS || scope_id) {
+-        goto bad;
++    if (is_v6literal) {
++        rv = fix_hostname_v6_literal(r, host);
+     }
+-
+-    if (port) {
+-        /* Don't throw the Host: header's port number away:
+-           save it in parsed_uri -- ap_get_server_port() needs it! */
+-        /* @@@ XXX there should be a better way to pass the port.
+-         *         Like r->hostname, there should be a r->portno
+-         */
+-        r->parsed_uri.port = port;
+-        r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
++    else {
++        rv = fix_hostname_non_v6(r, host);
++        if (strict && rv == APR_SUCCESS)
++            rv = strict_hostname_check(r, host);
+     }
++    if (rv != APR_SUCCESS)
++        goto bad;
+ 
+-    /* if the hostname is an IPv6 numeric address string, it was validated
+-     * already; otherwise, further validation is needed
+-     */
+-    if (r->hostname[0] != '[') {
+-        for (dst = host; *dst; dst++) {
+-            if (apr_islower(*dst)) {
+-                /* leave char unchanged */
+-            }
+-            else if (*dst == '.') {
+-                if (*(dst + 1) == '.') {
+-                    goto bad;
+-                }
+-            }
+-            else if (apr_isupper(*dst)) {
+-                *dst = apr_tolower(*dst);
+-            }
+-            else if (*dst == '/' || *dst == '\\') {
+-                goto bad;
+-            }
+-        }
+-        /* strip trailing gubbins */
+-        if (dst > host && dst[-1] == '.') {
+-            dst[-1] = '\0';
+-        }
+-    }
+     r->hostname = host;
+-    return;
++    return is_v6literal;
+ 
+ bad:
+-    r->status = HTTP_BAD_REQUEST;
+     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00550)
+                   "Client sent malformed Host header: %s",
+-                  r->hostname);
+-    return;
++                  src);
++bad_nolog:
++    r->status = HTTP_BAD_REQUEST;
++    return is_v6literal;
+ }
+ 
+-
+ /* return 1 if host matches ServerName or ServerAliases */
+ static int matches_aliases(server_rec *s, const char *host)
+ {
+@@ -980,15 +1101,76 @@
+     }
+ }
+ 
++static APR_INLINE const char *construct_host_header(request_rec *r,
++                                                    int is_v6literal)
++{
++    struct iovec iov[5];
++    apr_size_t nvec = 0;
++    /*
++     * We cannot use ap_get_server_name/port here, because we must
++     * ignore UseCanonicalName/Port.
++     */
++    if (is_v6literal) {
++        iov[nvec].iov_base = "[";
++        iov[nvec].iov_len = 1;
++        nvec++;
++    }
++    iov[nvec].iov_base = (void *)r->hostname;
++    iov[nvec].iov_len = strlen(r->hostname);
++    nvec++;
++    if (is_v6literal) {
++        iov[nvec].iov_base = "]";
++        iov[nvec].iov_len = 1;
++        nvec++;
++    }
++    if (r->parsed_uri.port_str) {
++        iov[nvec].iov_base = ":";
++        iov[nvec].iov_len = 1;
++        nvec++;
++        iov[nvec].iov_base = r->parsed_uri.port_str;
++        iov[nvec].iov_len = strlen(r->parsed_uri.port_str);
++        nvec++;
++    }
++    return apr_pstrcatv(r->pool, iov, nvec, NULL);
++}
+ 
+ AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
+ {
+-    /* must set this for HTTP/1.1 support */
+-    if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
+-        fix_hostname(r);
+-        if (r->status != HTTP_OK)
+-            return;
++    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
++    const char *host_header = apr_table_get(r->headers_in, "Host");
++    int is_v6literal = 0;
++    int have_hostname_from_url = 0;
++
++    if (r->hostname) {
++        /*
++         * If there was a host part in the Request-URI, ignore the 'Host'
++         * header.
++         */
++        have_hostname_from_url = 1;
++        is_v6literal = fix_hostname(r, NULL, conf->http_conformance);
++    }
++    else if (host_header != NULL) {
++        is_v6literal = fix_hostname(r, host_header, conf->http_conformance);
++    }
++    if (r->status != HTTP_OK)
++        return;
++
++    if (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE) {
++        /*
++         * If we have both hostname from an absoluteURI and a Host header,
++         * we must ignore the Host header (RFC 2616 5.2).
++         * To enforce this, we reset the Host header to the value from the
++         * request line.
++         */
++        if (have_hostname_from_url && host_header != NULL) {
++            const char *repl = construct_host_header(r, is_v6literal);
++            apr_table_set(r->headers_in, "Host", repl);
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02417)
++                          "Replacing host header '%s' with host '%s' given "
++                          "in the request uri", host_header, repl);
++        }
+     }
++
+     /* check if we tucked away a name_chain */
+     if (r->connection->vhost_lookup_data) {
+         if (r->hostname)
diff --git a/SOURCES/httpd-2.4.6-r1570327.patch b/SOURCES/httpd-2.4.6-r1570327.patch
new file mode 100644
index 0000000..35cdce8
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-r1570327.patch
@@ -0,0 +1,20 @@
+# ./pullrev.sh 1570327
+http://svn.apache.org/viewvc?view=revision&revision=1570327
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1327624
+
+--- httpd-2.4.6/server/mpm_unix.c
++++ httpd-2.4.6/server/mpm_unix.c
+@@ -742,7 +742,12 @@
+      * readers stranded (a number of them could be tied up for
+      * a while serving time-consuming requests)
+      */
++    /* Recall: we only worry about IDLE child processes here */
+     for (i = 0; i < num && rv == APR_SUCCESS; i++) {
++        if (ap_scoreboard_image->servers[i][0].status != SERVER_READY ||
++            ap_scoreboard_image->servers[i][0].pid == 0) {
++            continue;
++        }
+         rv = dummy_connection(pod);
+     }
+ }
diff --git a/SOURCES/httpd-2.4.6-r1587053.patch b/SOURCES/httpd-2.4.6-r1587053.patch
new file mode 100644
index 0000000..5bee0b1
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-r1587053.patch
@@ -0,0 +1,92 @@
+diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
+index 525109a..eb34eee 100644
+--- a/modules/proxy/mod_proxy_wstunnel.c
++++ b/modules/proxy/mod_proxy_wstunnel.c
+@@ -103,10 +103,12 @@ static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o,
+         rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES,
+                             APR_NONBLOCK_READ, AP_IOBUFSIZE);
+         if (rv == APR_SUCCESS) {
+-            if (c_o->aborted)
++            if (c_o->aborted) {
+                 return APR_EPIPE;
+-            if (APR_BRIGADE_EMPTY(bb))
++            }
++            if (APR_BRIGADE_EMPTY(bb)){
+                 break;
++            }
+ #ifdef DEBUGGING
+             len = -1;
+             apr_brigade_length(bb, 0, &len);
+@@ -178,7 +180,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+     conn_rec *c = r->connection;
+     apr_socket_t *sock = conn->sock;
+     conn_rec *backconn = conn->connection;
+-    int client_error = 0;
+     char *buf;
+     apr_bucket_brigade *header_brigade;
+     apr_bucket *e;
+@@ -224,7 +225,7 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+ 
+     pollfd.p = p;
+     pollfd.desc_type = APR_POLL_SOCKET;
+-    pollfd.reqevents = APR_POLLIN;
++    pollfd.reqevents = APR_POLLIN | APR_POLLHUP;
+     pollfd.desc.s = sock;
+     pollfd.client_data = NULL;
+     apr_pollset_add(pollset, &pollfd);
+@@ -237,6 +238,9 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+     r->proto_output_filters = c->output_filters;
+     r->input_filters = c->input_filters;
+     r->proto_input_filters = c->input_filters;
++    /* This handler should take care of the entire connection; make it so that
++     * nothing else is attempted on the connection after returning. */
++    c->keepalive = AP_CONN_CLOSE;
+ 
+     remove_reqtimeout(r->input_filters);
+ 
+@@ -257,26 +261,28 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+ 
+             if (cur->desc.s == sock) {
+                 pollevent = cur->rtnevents;
+-                if (pollevent & APR_POLLIN) {
++                if (pollevent & (APR_POLLIN | APR_POLLHUP)) {
+                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02446)
+                                   "sock was readable");
+                     rv = proxy_wstunnel_transfer(r, backconn, c, bb, "sock");
+                     }
+-                else if ((pollevent & APR_POLLERR)
+-                         || (pollevent & APR_POLLHUP)) {
++                else if (pollevent & APR_POLLERR) {
+                          rv = APR_EPIPE;
+                          ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447)
+-                                       "err/hup on backconn");
++                                       "err on backconn");
+                 }
+-                if (rv != APR_SUCCESS)
+-                    client_error = 1;
+             }
+             else if (cur->desc.s == client_socket) {
+                 pollevent = cur->rtnevents;
+-                if (pollevent & APR_POLLIN) {
++                if (pollevent & (APR_POLLIN | APR_POLLHUP)) {
+                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02448)
+                                   "client was readable");
+                     rv = proxy_wstunnel_transfer(r, c, backconn, bb, "client");
++                } else if (pollevent & APR_POLLERR) {
++                    rv = APR_EPIPE;
++                    c->aborted = 1;
++                    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02607)
++                                  "error on client conn");
+                 }
+             }
+             else {
+@@ -294,9 +300,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
+     ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+                   "finished with poll() - cleaning up");
+ 
+-    if (client_error) {
+-        return HTTP_INTERNAL_SERVER_ERROR;
+-    }
+     return OK;
+ }
+ 
diff --git a/SOURCES/httpd-2.4.6-r1631119.patch b/SOURCES/httpd-2.4.6-r1631119.patch
new file mode 100644
index 0000000..f0f48e4
--- /dev/null
+++ b/SOURCES/httpd-2.4.6-r1631119.patch
@@ -0,0 +1,16 @@
+# ./pullrev.sh 1631119
+http://svn.apache.org/viewvc?view=revision&revision=1631119
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1415257
+
+--- httpd-2.4.6/modules/ldap/util_ldap.c
++++ httpd-2.4.6/modules/ldap/util_ldap.c
+@@ -1824,7 +1824,7 @@
+          * combination, which might be reused unintentionally next time this
+          * connection is used from the connection pool.
+          */
+-        ldc->must_rebind = 0;
++        ldc->must_rebind = 1;
+         ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "LDC %pp used for authn, must be rebound", ldc);
+     }
+ 
diff --git a/SOURCES/welcome.conf b/SOURCES/welcome.conf
index c1b6c11..5d1e452 100644
--- a/SOURCES/welcome.conf
+++ b/SOURCES/welcome.conf
@@ -16,7 +16,3 @@
 </Directory>
 
 Alias /.noindex.html /usr/share/httpd/noindex/index.html
-Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css
-Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css
-Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif
-Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png
diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec
index 7ce38f6..4280492 100644
--- a/SPECS/httpd.spec
+++ b/SPECS/httpd.spec
@@ -4,7 +4,7 @@
 %define mmn 20120211
 %define oldmmnisa %{mmn}-%{__isa_name}-%{__isa_bits}
 %define mmnisa %{mmn}%{__isa_name}%{__isa_bits}
-%define vstring CentOS
+%define vstring %(source /etc/os-release; echo ${REDHAT_SUPPORT_PRODUCT})
 
 # Drop automatic provides for module DSOs
 %{?filter_setup:
@@ -15,10 +15,10 @@
 Summary: Apache HTTP Server
 Name: httpd
 Version: 2.4.6
-Release: 45%{?dist}
+Release: 45%{?dist}.4
 URL: http://httpd.apache.org/
 Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
-Source1: centos-noindex.tar.gz
+Source1: index.html
 Source2: httpd.logrotate
 Source3: httpd.sysconf
 Source4: httpd-ssl-pass-dialog
@@ -124,6 +124,9 @@ Patch103: httpd-2.4.6-dhparams-free.patch
 Patch104: httpd-2.4.6-r1651658.patch
 Patch105: httpd-2.4.6-r1560093.patch
 Patch106: httpd-2.4.6-r1748212.patch
+Patch107: httpd-2.4.6-r1570327.patch
+Patch108: httpd-2.4.6-r1631119.patch
+Patch109: httpd-2.4.6-r1587053.patch
 # Security fixes
 Patch200: httpd-2.4.6-CVE-2013-6438.patch
 Patch201: httpd-2.4.6-CVE-2014-0098.patch
@@ -137,6 +140,9 @@ Patch208: httpd-2.4.6-CVE-2014-3581.patch
 Patch209: httpd-2.4.6-CVE-2015-3185.patch
 Patch210: httpd-2.4.6-CVE-2015-3183.patch
 Patch211: httpd-2.4.6-CVE-2016-5387.patch
+Patch212: httpd-2.4.6-CVE-2016-8743.patch
+Patch213: httpd-2.4.6-CVE-2016-0736.patch
+Patch214: httpd-2.4.6-CVE-2016-2161.patch
 License: ASL 2.0
 Group: System Environment/Daemons
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@@ -323,6 +329,9 @@ rm modules/ssl/ssl_engine_dh.c
 %patch104 -p1 -b .r1651658
 %patch105 -p1 -b .r1560093
 %patch106 -p1 -b .r1748212
+%patch107 -p1 -b .r1570327
+%patch108 -p1 -b .r1631119
+%patch109 -p1 -b .r1587053
 
 %patch200 -p1 -b .cve6438
 %patch201 -p1 -b .cve0098
@@ -336,6 +345,9 @@ rm modules/ssl/ssl_engine_dh.c
 %patch209 -p1 -b .cve3185
 %patch210 -p1 -b .cve3183
 %patch211 -p1 -b .cve5387
+%patch212 -p1 -b .cve8743
+%patch213 -p1 -b .cve0736
+%patch214 -p1 -b .cve2161
 
 # Patch in the vendor string and the release string
 sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h
@@ -489,10 +501,8 @@ EOF
 
 # Handle contentdir
 mkdir $RPM_BUILD_ROOT%{contentdir}/noindex
-tar xzf $RPM_SOURCE_DIR/centos-noindex.tar.gz \
-        -C $RPM_BUILD_ROOT%{contentdir}/noindex/ \
-        --strip-components=1
-
+install -m 644 -p $RPM_SOURCE_DIR/index.html \
+        $RPM_BUILD_ROOT%{contentdir}/noindex/index.html
 rm -rf %{contentdir}/htdocs
 
 # remove manual sources
@@ -515,7 +525,7 @@ 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 \
+ln -s ../../pixmaps/poweredby.png \
         $RPM_BUILD_ROOT%{contentdir}/icons/poweredby.png
 
 # symlinks for /etc/httpd
@@ -701,7 +711,7 @@ rm -rf $RPM_BUILD_ROOT
 %{contentdir}/error/README
 %{contentdir}/error/*.var
 %{contentdir}/error/include/*.html
-%{contentdir}/noindex/*
+%{contentdir}/noindex/index.html
 
 %dir %{docroot}
 %dir %{docroot}/cgi-bin
@@ -767,11 +777,20 @@ rm -rf $RPM_BUILD_ROOT
 %{_sysconfdir}/rpm/macros.httpd
 
 %changelog
-* Thu Nov 03 2016 CentOS Sources <bugs@centos.org> - 2.4.6-45.el7.centos
-- Remove index.html, add centos-noindex.tar.gz
-- change vstring
-- change symlink for poweredby.png
-- update welcome.conf with proper aliases
+* Wed Mar 08 2017 Luboš Uhliarik <luhliari@redhat.com> - 2.4.6-45.4
+- Resolves: #1396197 - Backport: mod_proxy_wstunnel - AH02447: err/hup
+  on backconn
+
+* Tue Feb 14 2017 Joe Orton <jorton@redhat.com> - 2.4.6-45.3
+- prefork: fix delay completing graceful restart (#1327624)
+- mod_ldap: fix authz regression, failing to rebind (#1415257)
+
+* Tue Feb 14 2017 Joe Orton <jorton@redhat.com> - 2.4.6-45.2
+- updated patch for CVE-2016-8743
+
+* Mon Jan 30 2017 Luboš Uhliarik <luhliari@redhat.com> - 2.4.6-45.1
+- Resolves: #1412975 - CVE-2016-0736 CVE-2016-2161 CVE-2016-8743 httpd: various
+  flaws
 
 * Wed Aug 03 2016 Luboš Uhliarik <luhliari@redhat.com> - 2.4.6-45
 - RFE: run mod_rewrite external mapping program as non-root (#1316900)