|
1 CVE-2016-0755: libcurl will reuse NTLM-authenticated proxy connections without |
|
2 properly making sure that the connection was authenticated with the same |
|
3 credentials as set for this transfer. |
|
4 |
|
5 CVE webpage for this problem: |
|
6 http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-0755 |
|
7 |
|
8 Relevant upstream patch: |
|
9 http://curl.haxx.se/CVE-2016-0755.patch |
|
10 |
|
11 --- lib/url.c.orig |
|
12 +++ lib/url.c |
|
13 @@ -3126,15 +3126,20 @@ ConnectionExists(struct SessionHandle *data, |
|
14 { |
|
15 struct connectdata *check; |
|
16 struct connectdata *chosen = 0; |
|
17 bool canPipeline = IsPipeliningPossible(data, needle); |
|
18 + struct connectbundle *bundle; |
|
19 + |
|
20 #ifdef USE_NTLM |
|
21 - bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) || |
|
22 - (data->state.authhost.want & CURLAUTH_NTLM_WB)) && |
|
23 - (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE; |
|
24 + bool wantNTLMhttp = ((data->state.authhost.want & |
|
25 + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && |
|
26 + (needle->handler->protocol & PROTO_FAMILY_HTTP)); |
|
27 + bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && |
|
28 + ((data->state.authproxy.want & |
|
29 + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && |
|
30 + (needle->handler->protocol & PROTO_FAMILY_HTTP))); |
|
31 #endif |
|
32 - struct connectbundle *bundle; |
|
33 |
|
34 *force_reuse = FALSE; |
|
35 *waitpipe = FALSE; |
|
36 |
|
37 /* We can't pipe if the site is blacklisted */ |
|
38 @@ -3186,13 +3191,10 @@ ConnectionExists(struct SessionHandle *data, |
|
39 } |
|
40 |
|
41 curr = bundle->conn_list->head; |
|
42 while(curr) { |
|
43 bool match = FALSE; |
|
44 -#if defined(USE_NTLM) |
|
45 - bool credentialsMatch = FALSE; |
|
46 -#endif |
|
47 size_t pipeLen; |
|
48 |
|
49 /* |
|
50 * Note that if we use a HTTP proxy, we check connections to that |
|
51 * proxy and not to the actual remote server. |
|
52 @@ -3298,25 +3300,18 @@ ConnectionExists(struct SessionHandle *data, |
|
53 !needle->localdev || |
|
54 strcmp(check->localdev, needle->localdev)) |
|
55 continue; |
|
56 } |
|
57 |
|
58 - if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) |
|
59 -#ifdef USE_NTLM |
|
60 - || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE) |
|
61 -#endif |
|
62 - ) { |
|
63 - /* This protocol requires credentials per connection or is HTTP+NTLM, |
|
64 + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { |
|
65 + /* This protocol requires credentials per connection, |
|
66 so verify that we're using the same name and password as well */ |
|
67 if(!strequal(needle->user, check->user) || |
|
68 !strequal(needle->passwd, check->passwd)) { |
|
69 /* one of them was different */ |
|
70 continue; |
|
71 } |
|
72 -#if defined(USE_NTLM) |
|
73 - credentialsMatch = TRUE; |
|
74 -#endif |
|
75 } |
|
76 |
|
77 if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL || |
|
78 (needle->bits.httpproxy && check->bits.httpproxy && |
|
79 needle->bits.tunnel_proxy && check->bits.tunnel_proxy && |
|
80 @@ -3372,24 +3367,47 @@ ConnectionExists(struct SessionHandle *data, |
|
81 already authenticating with the right credentials. If not, keep |
|
82 looking so that we can reuse NTLM connections if |
|
83 possible. (Especially we must not reuse the same connection if |
|
84 partway through a handshake!) */ |
|
85 if(wantNTLMhttp) { |
|
86 - if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) { |
|
87 - chosen = check; |
|
88 + if(!strequal(needle->user, check->user) || |
|
89 + !strequal(needle->passwd, check->passwd)) |
|
90 + continue; |
|
91 + } |
|
92 + else if(check->ntlm.state != NTLMSTATE_NONE) { |
|
93 + /* Connection is using NTLM auth but we don't want NTLM */ |
|
94 + continue; |
|
95 + } |
|
96 + |
|
97 + /* Same for Proxy NTLM authentication */ |
|
98 + if(wantProxyNTLMhttp) { |
|
99 + if(!strequal(needle->proxyuser, check->proxyuser) || |
|
100 + !strequal(needle->proxypasswd, check->proxypasswd)) |
|
101 + continue; |
|
102 + } |
|
103 + else if(check->proxyntlm.state != NTLMSTATE_NONE) { |
|
104 + /* Proxy connection is using NTLM auth but we don't want NTLM */ |
|
105 + continue; |
|
106 + } |
|
107 + |
|
108 + if(wantNTLMhttp || wantProxyNTLMhttp) { |
|
109 + /* Credentials are already checked, we can use this connection */ |
|
110 + chosen = check; |
|
111 |
|
112 + if((wantNTLMhttp && |
|
113 + (check->ntlm.state != NTLMSTATE_NONE)) || |
|
114 + (wantProxyNTLMhttp && |
|
115 + (check->proxyntlm.state != NTLMSTATE_NONE))) { |
|
116 /* We must use this connection, no other */ |
|
117 *force_reuse = TRUE; |
|
118 break; |
|
119 } |
|
120 - else if(credentialsMatch) |
|
121 - /* this is a backup choice */ |
|
122 - chosen = check; |
|
123 + |
|
124 + /* Continue look up for a better connection */ |
|
125 continue; |
|
126 } |
|
127 #endif |
|
128 - |
|
129 if(canPipeline) { |
|
130 /* We can pipeline if we want to. Let's continue looking for |
|
131 the optimal connection to use, i.e the shortest pipe that is not |
|
132 blacklisted. */ |
|
133 |
|
134 -- |
|
135 2.7.0.rc3 |
|
136 |