1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

HTTP: don't abort connections with pending Negotiate authentication

... similarly to how NTLM works as Negotiate is in fact often NTLM with
another name.
This commit is contained in:
Stefan Bühler 2014-11-24 09:18:55 +01:00 committed by Daniel Stenberg
parent 557ca620e4
commit 5dc68dd609

View File

@ -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;
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;