From 5dc68dd6092a789bb5e0a67a1c1356ba87fdcbc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Mon, 24 Nov 2014 09:18:55 +0100 Subject: HTTP: don't abort connections with pending Negotiate authentication ... similarly to how NTLM works as Negotiate is in fact often NTLM with another name. --- lib/http.c | 112 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/http.c b/lib/http.c index 79d0592bb..d32a01271 100644 --- a/lib/http.c +++ b/lib/http.c @@ -347,6 +347,82 @@ static bool pickoneauth(struct auth *pick) return picked; } +/* whether to complete request (for authentication) in current connection */ +static bool complete_request(struct connectdata *conn, + curl_off_t remaining_bytes) +{ +#if defined(USE_NTLM) || defined(USE_SPNEGO) + struct SessionHandle *data = conn->data; + bool have_ntlm_or_negotiate = FALSE; + bool auth_started = FALSE; + + /* don't reset connection when we're in NTLM or Negotiate authentication; + * those authenticate the connection - creating a new connection breaks the + * authentication. + */ + +#if defined(USE_NTLM) + /* proxy NTLM authentication */ + if((data->state.authproxy.picked == CURLAUTH_NTLM) || + (data->state.authproxy.picked == CURLAUTH_NTLM_WB)) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (conn->proxyntlm.state != NTLMSTATE_NONE); + } + + /* normal NTLM authentication */ + if((data->state.authhost.picked == CURLAUTH_NTLM) || + (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (conn->ntlm.state != NTLMSTATE_NONE); + } +#endif + +#if defined(USE_SPNEGO) + /* proxy Negotiate authentication */ + if(data->state.authproxy.picked == CURLAUTH_NEGOTIATE) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (data->state.proxyneg.state != GSS_AUTHNONE); + } + + /* normal Negotiate authentication */ + if(data->state.authhost.picked == CURLAUTH_NEGOTIATE) { + have_ntlm_or_negotiate = TRUE; + auth_started = auth_started + || (data->state.negotiate.state != GSS_AUTHNONE); + } +#endif + + if(have_ntlm_or_negotiate) { + if(remaining_bytes < 2000 || auth_started) { + /* NTLM/Negotiation has started *OR* there is just a little (<2K) + * data left to send, keep on sending. + */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return TRUE; + } + + infof(data, "NTLM/Negotiate send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + remaining_bytes); + } +#else + /* unused parameters: */ + (void)conn; + (void)remaining_bytes; +#endif + + return FALSE; +} + /* * Curl_http_perhapsrewind() * @@ -420,36 +496,12 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) conn->bits.rewindaftersend = FALSE; /* default */ if((expectsend == -1) || (expectsend > bytessent)) { -#if defined(USE_NTLM) - /* There is still data left to send */ - if((data->state.authproxy.picked == CURLAUTH_NTLM) || - (data->state.authhost.picked == CURLAUTH_NTLM) || - (data->state.authproxy.picked == CURLAUTH_NTLM_WB) || - (data->state.authhost.picked == CURLAUTH_NTLM_WB)) { - if(((expectsend - bytessent) < 2000) || - (conn->ntlm.state != NTLMSTATE_NONE) || - (conn->proxyntlm.state != NTLMSTATE_NONE)) { - /* The NTLM-negotiation has started *OR* there is just a little (<2K) - data left to send, keep on sending. */ - - /* rewind data when completely done sending! */ - if(!conn->bits.authneg) { - conn->bits.rewindaftersend = TRUE; - infof(data, "Rewind stream after send\n"); - } - - return CURLE_OK; - } + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; - if(conn->bits.close) - /* this is already marked to get closed */ - return CURLE_OK; - - infof(data, "NTLM send, close instead of sending %" - CURL_FORMAT_CURL_OFF_T " bytes\n", - (curl_off_t)(expectsend - bytessent)); - } -#endif + if(complete_request(conn, (curl_off_t)(expectsend - bytessent))) + return CURLE_OK; /* This is not NTLM or many bytes left to send: close */ connclose(conn, "Mid-auth HTTP and much data left to send"); @@ -460,7 +512,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) } if(bytessent) - /* we rewind now at once since if we already sent something */ + /* we rewind now at once since we already sent something */ return Curl_readrewind(conn); return CURLE_OK; -- cgit v1.2.3