CC: curl: fix CVE-2016-0755
[15.05/openwrt.git] / package / network / utils / curl / patches / 018-CVE-2016-0755.patch
1 From d41dcba4e9b69d6b761e3460cc6ae7e8fd8f621f Mon Sep 17 00:00:00 2001
2 From: Isaac Boukris <iboukris@gmail.com>
3 Date: Wed, 13 Jan 2016 11:05:51 +0200
4 Subject: [PATCH] NTLM: Fix ConnectionExists to compare Proxy credentials
5
6 Proxy NTLM authentication should compare credentials when
7 re-using a connection similar to host authentication, as it
8 authenticate the connection.
9
10 Example:
11 curl -v -x http://proxy:port http://host/ -U good_user:good_pwd
12   --proxy-ntlm --next -x http://proxy:port http://host/
13     [-U fake_user:fake_pwd --proxy-ntlm]
14
15 CVE-2016-0755
16
17 Bug: http://curl.haxx.se/docs/adv_20160127A.html
18 ---
19  lib/url.c | 62 ++++++++++++++++++++++++++++++++++++++++----------------------
20  1 file changed, 40 insertions(+), 22 deletions(-)
21
22 --- a/lib/url.c
23 +++ b/lib/url.c
24 @@ -3044,11 +3044,16 @@ ConnectionExists(struct SessionHandle *d
25    struct connectdata *check;
26    struct connectdata *chosen = 0;
27    bool canPipeline = IsPipeliningPossible(data, needle);
28 -  bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
29 -                       (data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
30 -    (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE;
31    struct connectbundle *bundle;
32  
33 +  bool wantNTLMhttp = ((data->state.authhost.want &
34 +                      (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
35 +                      (needle->handler->protocol & PROTO_FAMILY_HTTP));
36 +  bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
37 +                           ((data->state.authproxy.want &
38 +                           (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
39 +                           (needle->handler->protocol & PROTO_FAMILY_HTTP)));
40 +
41    *force_reuse = FALSE;
42  
43    /* We can't pipe if the site is blacklisted */
44 @@ -3077,9 +3082,6 @@ ConnectionExists(struct SessionHandle *d
45      curr = bundle->conn_list->head;
46      while(curr) {
47        bool match = FALSE;
48 -#if defined(USE_NTLM)
49 -      bool credentialsMatch = FALSE;
50 -#endif
51        size_t pipeLen;
52  
53        /*
54 @@ -3185,21 +3187,14 @@ ConnectionExists(struct SessionHandle *d
55        }
56  
57        if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) ||
58 -#if defined(USE_NTLM)
59 -         (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE)) {
60 -#else
61           wantNTLMhttp) {
62 -#endif
63 -        /* This protocol requires credentials per connection or is HTTP+NTLM,
64 +        /* This protocol requires credentials per connection,
65             so verify that we're using the same name and password as well */
66          if(!strequal(needle->user, check->user) ||
67             !strequal(needle->passwd, check->passwd)) {
68            /* one of them was different */
69            continue;
70          }
71 -#if defined(USE_NTLM)
72 -        credentialsMatch = TRUE;
73 -#endif
74        }
75  
76        if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
77 @@ -3258,20 +3253,43 @@ ConnectionExists(struct SessionHandle *d
78             possible. (Especially we must not reuse the same connection if
79             partway through a handshake!) */
80          if(wantNTLMhttp) {
81 -          if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) {
82 -            chosen = check;
83 +          if(!strequal(needle->user, check->user) ||
84 +             !strequal(needle->passwd, check->passwd))
85 +            continue;
86 +        }
87 +        else if(check->ntlm.state != NTLMSTATE_NONE) {
88 +          /* Connection is using NTLM auth but we don't want NTLM */
89 +          continue;
90 +        }
91  
92 +        /* Same for Proxy NTLM authentication */
93 +        if(wantProxyNTLMhttp) {
94 +          if(!strequal(needle->proxyuser, check->proxyuser) ||
95 +             !strequal(needle->proxypasswd, check->proxypasswd))
96 +            continue;
97 +        }
98 +        else if(check->proxyntlm.state != NTLMSTATE_NONE) {
99 +          /* Proxy connection is using NTLM auth but we don't want NTLM */
100 +          continue;
101 +        }
102 +
103 +        if(wantNTLMhttp || wantProxyNTLMhttp) {
104 +          /* Credentials are already checked, we can use this connection */
105 +          chosen = check;
106 +
107 +          if((wantNTLMhttp &&
108 +             (check->ntlm.state != NTLMSTATE_NONE)) ||
109 +              (wantProxyNTLMhttp &&
110 +               (check->proxyntlm.state != NTLMSTATE_NONE))) {
111              /* We must use this connection, no other */
112              *force_reuse = TRUE;
113              break;
114            }
115 -          else if(credentialsMatch)
116 -            /* this is a backup choice */
117 -            chosen = check;
118 +
119 +          /* Continue look up for a better connection */
120            continue;
121          }
122  #endif
123 -
124          if(canPipeline) {
125            /* We can pipeline if we want to. Let's continue looking for
126               the optimal connection to use, i.e the shortest pipe that is not