123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- 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
- ---
- lib/url.c | 62 ++++++++++++++++++++++++++++++++++++++++----------------------
- 1 file changed, 40 insertions(+), 22 deletions(-)
- --- a/lib/url.c
- +++ b/lib/url.c
- @@ -3044,11 +3044,16 @@ ConnectionExists(struct SessionHandle *d
- struct connectdata *check;
- struct connectdata *chosen = 0;
- bool canPipeline = IsPipeliningPossible(data, needle);
- - bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
- - (data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
- - (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE;
- struct connectbundle *bundle;
-
- + 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)));
- +
- *force_reuse = FALSE;
-
- /* We can't pipe if the site is blacklisted */
- @@ -3077,9 +3082,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;
-
- /*
- @@ -3185,21 +3187,14 @@ ConnectionExists(struct SessionHandle *d
- }
-
- if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) ||
- -#if defined(USE_NTLM)
- - (wantNTLMhttp || check->ntlm.state != NTLMSTATE_NONE)) {
- -#else
- wantNTLMhttp) {
- -#endif
- - /* This protocol requires credentials per connection or is HTTP+NTLM,
- + /* 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 ||
- @@ -3258,20 +3253,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
|