components/curl/patches/001-CVE-2016-0755.patch
author Yiteng Zhang <yiteng.zhang@oracle.com>
Tue, 04 Oct 2016 11:04:14 -0700
branchs11u3-sru
changeset 7033 a49f9f0272f2
permissions -rw-r--r--
22599190 problem in LIBRARY/CURL

CVE-2016-0755: libcurl will reuse NTLM-authenticated proxy connections without
properly making sure that the connection was authenticated with the same
credentials as set for this transfer. 

CVE webpage for this problem:
http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-0755

Relevant upstream patch:
http://curl.haxx.se/CVE-2016-0755.patch

--- lib/url.c.orig
+++ lib/url.c
@@ -3126,15 +3126,20 @@ ConnectionExists(struct SessionHandle *data,
 {
   struct connectdata *check;
   struct connectdata *chosen = 0;
   bool canPipeline = IsPipeliningPossible(data, needle);
+  struct connectbundle *bundle;
+
 #ifdef USE_NTLM
-  bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
-                       (data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
-    (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE;
+  bool wantNTLMhttp = ((data->state.authhost.want &
+                      (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+                      (needle->handler->protocol & PROTO_FAMILY_HTTP));
+  bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
+                           ((data->state.authproxy.want &
+                           (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+                           (needle->handler->protocol & PROTO_FAMILY_HTTP)));
 #endif
-  struct connectbundle *bundle;
 
   *force_reuse = FALSE;
   *waitpipe = FALSE;
 
   /* We can't pipe if the site is blacklisted */
@@ -3186,13 +3191,10 @@ ConnectionExists(struct SessionHandle *data,
     }
 
     curr = bundle->conn_list->head;
     while(curr) {
       bool match = FALSE;
-#if defined(USE_NTLM)
-      bool credentialsMatch = FALSE;
-#endif
       size_t pipeLen;
 
       /*
        * Note that if we use a HTTP proxy, we check connections to that
        * proxy and not to the actual remote server.
@@ -3298,25 +3300,18 @@ ConnectionExists(struct SessionHandle *data,
            !needle->localdev ||
            strcmp(check->localdev, needle->localdev))
           continue;
       }
 
-      if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST))
-#ifdef USE_NTLM
-         || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE)
-#endif
-        ) {
-        /* This protocol requires credentials per connection or is HTTP+NTLM,
+      if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
+        /* This protocol requires credentials per connection,
            so verify that we're using the same name and password as well */
         if(!strequal(needle->user, check->user) ||
            !strequal(needle->passwd, check->passwd)) {
           /* one of them was different */
           continue;
         }
-#if defined(USE_NTLM)
-        credentialsMatch = TRUE;
-#endif
       }
 
       if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
          (needle->bits.httpproxy && check->bits.httpproxy &&
           needle->bits.tunnel_proxy && check->bits.tunnel_proxy &&
@@ -3372,24 +3367,47 @@ ConnectionExists(struct SessionHandle *data,
            already authenticating with the right credentials. If not, keep
            looking so that we can reuse NTLM connections if
            possible. (Especially we must not reuse the same connection if
            partway through a handshake!) */
         if(wantNTLMhttp) {
-          if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) {
-            chosen = check;
+          if(!strequal(needle->user, check->user) ||
+             !strequal(needle->passwd, check->passwd))
+            continue;
+        }
+        else if(check->ntlm.state != NTLMSTATE_NONE) {
+          /* Connection is using NTLM auth but we don't want NTLM */
+          continue;
+        }
+
+        /* Same for Proxy NTLM authentication */
+        if(wantProxyNTLMhttp) {
+          if(!strequal(needle->proxyuser, check->proxyuser) ||
+             !strequal(needle->proxypasswd, check->proxypasswd))
+            continue;
+        }
+        else if(check->proxyntlm.state != NTLMSTATE_NONE) {
+          /* Proxy connection is using NTLM auth but we don't want NTLM */
+          continue;
+        }
+
+        if(wantNTLMhttp || wantProxyNTLMhttp) {
+          /* Credentials are already checked, we can use this connection */
+          chosen = check;
 
+          if((wantNTLMhttp &&
+             (check->ntlm.state != NTLMSTATE_NONE)) ||
+              (wantProxyNTLMhttp &&
+               (check->proxyntlm.state != NTLMSTATE_NONE))) {
             /* We must use this connection, no other */
             *force_reuse = TRUE;
             break;
           }
-          else if(credentialsMatch)
-            /* this is a backup choice */
-            chosen = check;
+
+          /* Continue look up for a better connection */
           continue;
         }
 #endif
-
         if(canPipeline) {
           /* We can pipeline if we want to. Let's continue looking for
              the optimal connection to use, i.e the shortest pipe that is not
              blacklisted. */
 
-- 
2.7.0.rc3