]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge https://svn.apache.org/r1796348 from trunk:
authorEric Covener <covener@apache.org>
Mon, 19 Jun 2017 17:01:50 +0000 (17:01 +0000)
committerEric Covener <covener@apache.org>
Mon, 19 Jun 2017 17:01:50 +0000 (17:01 +0000)
  *) SECURITY: CVE-2017-3167 (cve.mitre.org)
     Use of the ap_get_basic_auth_pw() by third-party modules outside of the
     authentication phase may lead to authentication requirements being
     bypassed.
     [Emmanuel Dreyfus <manu netbsd.org>, Jacob Champion, Eric Covener]

Submitted By: Emmanuel Dreyfus <manu netbsd.org>, Jacob Champion, Eric Covener
Reviewed By: covener, ylavic, wrowe

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1799232 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
include/ap_mmn.h
include/http_protocol.h
server/protocol.c
server/request.c

diff --git a/CHANGES b/CHANGES
index aea20c1e6c43ef0876ba28382d8f961815b9e050..b77503c31cd9bc74be29ff9c6e8d3b84a0f125b1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,12 @@ Changes with Apache 2.2.33
      ap_hook_process_connection() during an HTTP request to an HTTPS port.
      [Yann Ylavic]
 
+  *) SECURITY: CVE-2017-3167 (cve.mitre.org)
+     Use of the ap_get_basic_auth_pw() by third-party modules outside of the
+     authentication phase may lead to authentication requirements being
+     bypassed.
+     [Emmanuel Dreyfus <manu netbsd.org>, Jacob Champion, Eric Covener]
+  
   *) Fix HttpProtocolOptions to inherit from global to VirtualHost scope.
      [Joe Orton]
 
diff --git a/STATUS b/STATUS
index fef58fd72ce0f0bad2f4fef904ed44d6ff9d7561..095be39d23386046f9b6b3b88edd9941470c769f 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -104,12 +104,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) core: ap_get_basic_auth_pw deprecation
-     trunk patch: https://svn.apache.org/r1796348
-     2.2.x patch: http://people.apache.org/~covener/patches/httpd-2.2.x-ap_get_basic_auth_pw.diff
-                  (remove some_authn_required change, change to strcasecmp, mmn)
-     +1: covener, ylavic, wrowe
-
    *) mod_mime: Fix scanning of quoted-pairs.
       trunk patch: http://svn.apache.org/r1797550
       2.4.x patch: svn merge -c 1797550 ^/httpd/httpd/trunk .
index ce330a558107d0fe88c52ecc9a3e9972e61b2293..fcbce6ffadc774aaf5d1557983fbb98f1cbd69f4 100644 (file)
  *                      and ap_scan_vchar_obstext()
  *                      Replaced fold boolean with with multiple bit flags
  *                      to ap_[r]getline()
+ * 20051115.43 (2.2.33)  Add ap_get_basic_auth_components() and deprecate
+ *                       ap_get_basic_auth_pw()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20051115
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 42                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 43                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 1fed3b58d4e5cfeebdb1932b6ce018c91a3d73ff..3fed9b2566b1ffae09da411c95387a16b5c657f9 100644 (file)
@@ -486,7 +486,11 @@ AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r);
 AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r);
 
 /**
- * Get the password from the request headers
+ * Get the password from the request headers. This function has multiple side
+ * effects due to its prior use in the old authentication framework.
+ * ap_get_basic_auth_components() should be preferred.
+ *
+ * @deprecated @see ap_get_basic_auth_components
  * @param r The current request
  * @param pw The password as set in the headers
  * @return 0 (OK) if it set the 'pw' argument (and assured
@@ -499,6 +503,25 @@ AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r);
  */
 AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw);
 
+#define AP_GET_BASIC_AUTH_PW_NOTE "AP_GET_BASIC_AUTH_PW_NOTE"
+
+/**
+ * Get the username and/or password from the request's Basic authentication
+ * headers. Unlike ap_get_basic_auth_pw(), calling this function has no side
+ * effects on the passed request_rec.
+ *
+ * @param r The current request
+ * @param username If not NULL, set to the username sent by the client
+ * @param password If not NULL, set to the password sent by the client
+ * @return APR_SUCCESS if the credentials were successfully parsed and returned;
+ *         APR_EINVAL if there was no authentication header sent or if the
+ *         client was not using the Basic authentication scheme. username and
+ *         password are unchanged on failure.
+ */
+AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r,
+                                                      const char **username,
+                                                      const char **password);
+
 /**
  * parse_uri: break apart the uri
  * @warning Side Effects: 
index bd757666ff8f352fdce71b1122606b9c1f344828..2705bba812fc6dabd2a889acfd345bebf173dee1 100644 (file)
@@ -1594,6 +1594,7 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
 
     t = ap_pbase64decode(r->pool, auth_line);
     r->user = ap_getword_nulls (r->pool, &t, ':');
+    apr_table_setn(r->notes, AP_GET_BASIC_AUTH_PW_NOTE, "1");
     r->ap_auth_type = "Basic";
 
     *pw = t;
@@ -1601,6 +1602,53 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
     return OK;
 }
 
+AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r,
+                                                      const char **username,
+                                                      const char **password)
+{
+    const char *auth_header;
+    const char *credentials;
+    const char *decoded;
+    const char *user;
+
+    auth_header = (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
+                                                  : "Authorization";
+    credentials = apr_table_get(r->headers_in, auth_header);
+
+    if (!credentials) {
+        /* No auth header. */
+        return APR_EINVAL;
+    }
+
+    if (strcasecmp(ap_getword(r->pool, &credentials, ' '), "Basic")) {
+        /* These aren't Basic credentials. */
+        return APR_EINVAL;
+    }
+
+    while (*credentials == ' ' || *credentials == '\t') {
+        credentials++;
+    }
+
+    /* XXX Our base64 decoding functions don't actually error out if the string
+     * we give it isn't base64; they'll just silently stop and hand us whatever
+     * they've parsed up to that point.
+     *
+     * Since this function is supposed to be a drop-in replacement for the
+     * deprecated ap_get_basic_auth_pw(), don't fix this for 2.4.x.
+     */
+    decoded = ap_pbase64decode(r->pool, credentials);
+    user = ap_getword_nulls(r->pool, &decoded, ':');
+
+    if (username) {
+        *username = user;
+    }
+    if (password) {
+        *password = decoded;
+    }
+
+    return APR_SUCCESS;
+}
+
 struct content_length_ctx {
     int data_sent;  /* true if the C-L filter has already sent at
                      * least one bucket on to the next output filter
index 7005ca9bfae4a477c9c549922cd01238a683956f..f81bbe0044ba4e36c45d9a9622b83a3af1df7977 100644 (file)
@@ -179,6 +179,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
         r->ap_auth_type = r->prev->ap_auth_type;
     }
     else {
+        /* A module using a confusing API (ap_get_basic_auth_pw) caused
+        ** r->user to be filled out prior to check_authn hook. We treat
+        ** it is inadvertent.
+        */
+        if (r->user && apr_table_get(r->notes, AP_GET_BASIC_AUTH_PW_NOTE)) { 
+            r->user = NULL;
+        }
+
         switch (ap_satisfies(r)) {
         case SATISFY_ALL:
         case SATISFY_NOSPEC: