Skip to content

Commit

Permalink
HTTP: don't abort connections with pending Negotiate authentication
Browse files Browse the repository at this point in the history
... similarly to how NTLM works as Negotiate is in fact often NTLM with
another name.
  • Loading branch information
tvbuehler authored and bagder committed Dec 4, 2014
1 parent 557ca62 commit 5dc68dd
Showing 1 changed file with 82 additions and 30 deletions.
112 changes: 82 additions & 30 deletions lib/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
*
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand Down

0 comments on commit 5dc68dd

Please sign in to comment.