Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 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 | Upstream-Status: Backport |
| 20 | http://curl.haxx.se/CVE-2016-0755.patch |
| 21 | |
| 22 | CVE: CVE-2016-0755 |
| 23 | Signed-off-by: Armin Kuster <akuster@mvista.com> |
| 24 | |
| 25 | --- |
| 26 | lib/url.c | 62 ++++++++++++++++++++++++++++++++++++++++---------------------- |
| 27 | 1 file changed, 40 insertions(+), 22 deletions(-) |
| 28 | |
| 29 | Index: curl-7.44.0/lib/url.c |
| 30 | =================================================================== |
| 31 | --- curl-7.44.0.orig/lib/url.c |
| 32 | +++ curl-7.44.0/lib/url.c |
| 33 | @@ -3107,12 +3107,17 @@ ConnectionExists(struct SessionHandle *d |
| 34 | struct connectdata *check; |
| 35 | struct connectdata *chosen = 0; |
| 36 | bool canPipeline = IsPipeliningPossible(data, needle); |
| 37 | + struct connectbundle *bundle; |
| 38 | + |
| 39 | #ifdef USE_NTLM |
| 40 | - bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) || |
| 41 | - (data->state.authhost.want & CURLAUTH_NTLM_WB)) && |
| 42 | - (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE; |
| 43 | + bool wantNTLMhttp = ((data->state.authhost.want & |
| 44 | + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && |
| 45 | + (needle->handler->protocol & PROTO_FAMILY_HTTP)); |
| 46 | + bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && |
| 47 | + ((data->state.authproxy.want & |
| 48 | + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && |
| 49 | + (needle->handler->protocol & PROTO_FAMILY_HTTP))); |
| 50 | #endif |
| 51 | - struct connectbundle *bundle; |
| 52 | |
| 53 | *force_reuse = FALSE; |
| 54 | *waitpipe = FALSE; |
| 55 | @@ -3152,9 +3157,6 @@ ConnectionExists(struct SessionHandle *d |
| 56 | curr = bundle->conn_list->head; |
| 57 | while(curr) { |
| 58 | bool match = FALSE; |
| 59 | -#if defined(USE_NTLM) |
| 60 | - bool credentialsMatch = FALSE; |
| 61 | -#endif |
| 62 | size_t pipeLen; |
| 63 | |
| 64 | /* |
| 65 | @@ -3262,21 +3264,14 @@ ConnectionExists(struct SessionHandle *d |
| 66 | continue; |
| 67 | } |
| 68 | |
| 69 | - if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) |
| 70 | -#ifdef USE_NTLM |
| 71 | - || (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE) |
| 72 | -#endif |
| 73 | - ) { |
| 74 | - /* This protocol requires credentials per connection or is HTTP+NTLM, |
| 75 | + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { |
| 76 | + /* This protocol requires credentials per connection, |
| 77 | so verify that we're using the same name and password as well */ |
| 78 | if(!strequal(needle->user, check->user) || |
| 79 | !strequal(needle->passwd, check->passwd)) { |
| 80 | /* one of them was different */ |
| 81 | continue; |
| 82 | } |
| 83 | -#if defined(USE_NTLM) |
| 84 | - credentialsMatch = TRUE; |
| 85 | -#endif |
| 86 | } |
| 87 | |
| 88 | if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL || |
| 89 | @@ -3335,20 +3330,43 @@ ConnectionExists(struct SessionHandle *d |
| 90 | possible. (Especially we must not reuse the same connection if |
| 91 | partway through a handshake!) */ |
| 92 | if(wantNTLMhttp) { |
| 93 | - if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) { |
| 94 | - chosen = check; |
| 95 | + if(!strequal(needle->user, check->user) || |
| 96 | + !strequal(needle->passwd, check->passwd)) |
| 97 | + continue; |
| 98 | + } |
| 99 | + else if(check->ntlm.state != NTLMSTATE_NONE) { |
| 100 | + /* Connection is using NTLM auth but we don't want NTLM */ |
| 101 | + continue; |
| 102 | + } |
| 103 | + |
| 104 | + /* Same for Proxy NTLM authentication */ |
| 105 | + if(wantProxyNTLMhttp) { |
| 106 | + if(!strequal(needle->proxyuser, check->proxyuser) || |
| 107 | + !strequal(needle->proxypasswd, check->proxypasswd)) |
| 108 | + continue; |
| 109 | + } |
| 110 | + else if(check->proxyntlm.state != NTLMSTATE_NONE) { |
| 111 | + /* Proxy connection is using NTLM auth but we don't want NTLM */ |
| 112 | + continue; |
| 113 | + } |
| 114 | |
| 115 | + if(wantNTLMhttp || wantProxyNTLMhttp) { |
| 116 | + /* Credentials are already checked, we can use this connection */ |
| 117 | + chosen = check; |
| 118 | + |
| 119 | + if((wantNTLMhttp && |
| 120 | + (check->ntlm.state != NTLMSTATE_NONE)) || |
| 121 | + (wantProxyNTLMhttp && |
| 122 | + (check->proxyntlm.state != NTLMSTATE_NONE))) { |
| 123 | /* We must use this connection, no other */ |
| 124 | *force_reuse = TRUE; |
| 125 | break; |
| 126 | } |
| 127 | - else if(credentialsMatch) |
| 128 | - /* this is a backup choice */ |
| 129 | - chosen = check; |
| 130 | + |
| 131 | + /* Continue look up for a better connection */ |
| 132 | continue; |
| 133 | } |
| 134 | #endif |
| 135 | - |
| 136 | if(canPipeline) { |
| 137 | /* We can pipeline if we want to. Let's continue looking for |
| 138 | the optimal connection to use, i.e the shortest pipe that is not |