From 5ede86ae51b8f71be35152584815f80dbd5a327a Mon Sep 17 00:00:00 2001 From: Joe Mason Date: Mon, 20 Aug 2012 17:00:40 -0400 Subject: [PATCH] NTLM: re-use existing connection better If we need an NTLM connection and one already exists, always choose that one. --- lib/url.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/url.c b/lib/url.c index c2f488280..c05c50e62 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2928,10 +2928,14 @@ ConnectionExists(struct SessionHandle *data, { long i; struct connectdata *check; + struct connectdata *chosen = 0; bool canPipeline = IsPipeliningPossible(data, needle); + bool wantNTLM = (data->state.authhost.want==CURLAUTH_NTLM) || + (data->state.authhost.want==CURLAUTH_NTLM_WB); for(i=0; i< data->state.connc->num; i++) { bool match = FALSE; + bool credentialsMatch = FALSE; size_t pipeLen = 0; /* * Note that if we use a HTTP proxy, we check connections to that @@ -3102,9 +3106,7 @@ ConnectionExists(struct SessionHandle *data, } } if((needle->handler->protocol & CURLPROTO_FTP) || - ((needle->handler->protocol & CURLPROTO_HTTP) && - ((data->state.authhost.want==CURLAUTH_NTLM) || - (data->state.authhost.want==CURLAUTH_NTLM_WB)))) { + ((needle->handler->protocol & CURLPROTO_HTTP) && wantNTLM)) { /* This is FTP or HTTP+NTLM, verify that we're using the same name and password as well */ if(!strequal(needle->user, check->user) || @@ -3112,6 +3114,7 @@ ConnectionExists(struct SessionHandle *data, /* one of them was different */ continue; } + credentialsMatch = TRUE; } match = TRUE; } @@ -3129,14 +3132,29 @@ ConnectionExists(struct SessionHandle *data, } if(match) { - check->inuse = TRUE; /* mark this as being in use so that no other - handle in a multi stack may nick it */ + chosen = check; - *usethis = check; - return TRUE; /* yes, we found one to use! */ + /* If we are not looking for an NTLM connection, we can choose this one + immediately. */ + if(!wantNTLM) + break; + + /* Otherwise, check if this is already authenticating with the right + credentials. If not, keep looking so that we can reuse NTLM + connections if possible. (Especially we must reuse the same + connection if partway through a handshake!) */ + if(credentialsMatch && chosen->ntlm.state != NTLMSTATE_NONE) + break; } } + if(chosen) { + chosen->inuse = TRUE; /* mark this as being in use so that no other + handle in a multi stack may nick it */ + *usethis = chosen; + return TRUE; /* yes, we found one to use! */ + } + return FALSE; /* no matching connecting exists */ }