diff options
| author | Stefan Bühler <buehler@teamviewer.com> | 2014-11-24 09:18:55 +0100 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2014-12-04 14:41:48 -0800 | 
| commit | 5dc68dd6092a789bb5e0a67a1c1356ba87fdcbc6 (patch) | |
| tree | 3404fcc942395ce32ab665439a65e75e8b8d5134 /lib | |
| parent | 557ca620e4f3a981043a8bbde3846e0dc9bb9388 (diff) | |
HTTP: don't abort connections with pending Negotiate authentication
... similarly to how NTLM works as Negotiate is in fact often NTLM with
another name.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/http.c | 112 | 
1 files changed, 82 insertions, 30 deletions
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;  | 
