Skip to content

Commit

Permalink
NTLM: Fix ConnectionExists to compare Proxy credentials
Browse files Browse the repository at this point in the history
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
  • Loading branch information
iboukris authored and bagder committed Jan 26, 2016
1 parent 3017d8a commit d41dcba
Showing 1 changed file with 40 additions and 22 deletions.
62 changes: 40 additions & 22 deletions lib/url.c
Expand Up @@ -3128,12 +3128,17 @@ ConnectionExists(struct SessionHandle *data,
struct connectdata *chosen = 0;
bool foundPendingCandidate = FALSE;
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;
Expand Down Expand Up @@ -3188,9 +3193,6 @@ ConnectionExists(struct SessionHandle *data,
curr = bundle->conn_list->head;
while(curr) {
bool match = FALSE;
#if defined(USE_NTLM)
bool credentialsMatch = FALSE;
#endif
size_t pipeLen;

/*
Expand Down Expand Up @@ -3300,21 +3302,14 @@ ConnectionExists(struct SessionHandle *data,
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 ||
Expand Down Expand Up @@ -3374,20 +3369,43 @@ ConnectionExists(struct SessionHandle *data,
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
Expand Down

0 comments on commit d41dcba

Please sign in to comment.