| From d41dcba4e9b69d6b761e3460cc6ae7e8fd8f621f Mon Sep 17 00:00:00 2001 |
| From: Isaac Boukris <iboukris@gmail.com> |
| Date: Wed, 13 Jan 2016 11:05:51 +0200 |
| Subject: [PATCH] NTLM: Fix ConnectionExists to compare Proxy credentials |
| |
| Proxy NTLM authentication should compare credentials when |
| re-using a connection similar to host authentication, as it |
| authenticate the connection. |
| |
| Example: |
| curl -v -x http://proxy:port http://host/ -U good_user:good_pwd |
| --proxy-ntlm --next -x http://proxy:port http://host/ |
| [-U fake_user:fake_pwd --proxy-ntlm] |
| |
| CVE-2016-0755 |
| |
| Bug: http://curl.haxx.se/docs/adv_20160127A.html |
| |
| Upstream-Status: Backport |
| http://curl.haxx.se/CVE-2016-0755.patch |
| |
| CVE: CVE-2016-0755 |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| lib/url.c | 62 ++++++++++++++++++++++++++++++++++++++++---------------------- |
| 1 file changed, 40 insertions(+), 22 deletions(-) |
| |
| Index: curl-7.44.0/lib/url.c |
| =================================================================== |
| --- curl-7.44.0.orig/lib/url.c |
| +++ curl-7.44.0/lib/url.c |
| @@ -3107,12 +3107,17 @@ ConnectionExists(struct SessionHandle *d |
| 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; |
| @@ -3152,9 +3157,6 @@ ConnectionExists(struct SessionHandle *d |
| curr = bundle->conn_list->head; |
| while(curr) { |
| bool match = FALSE; |
| -#if defined(USE_NTLM) |
| - bool credentialsMatch = FALSE; |
| -#endif |
| size_t pipeLen; |
| |
| /* |
| @@ -3262,21 +3264,14 @@ ConnectionExists(struct SessionHandle *d |
| 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 || |
| @@ -3335,20 +3330,43 @@ ConnectionExists(struct SessionHandle *d |
| 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 |