Loading lib/http.c +101 −28 Original line number Diff line number Diff line Loading @@ -188,23 +188,23 @@ void Curl_http_auth_act(struct connectdata *conn) } } /* /** * Setup the authentication headers for the host/proxy and the correct * authentication method. * authentication method. @p conn->data->state.authdone set to TRUE * when authentication is done. * * @param conn all information about the current connection */ static CURLcode http_auth_headers(struct connectdata *conn, char *request, char *path, bool *ready) /* set TRUE when the auth phase is done and ready to do the *actual* request */ char *path) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; char *auth=NULL; *ready = FALSE; /* default is no */ curlassert(data); data->state.authdone = FALSE; /* default is no */ if(!data->state.authstage) { if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) Loading @@ -212,7 +212,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, else if(conn->bits.user_passwd) Curl_http_auth_stage(data, 401); else { *ready = TRUE; data->state.authdone = TRUE; return CURLE_OK; /* no authentication with no user or password */ } } Loading @@ -229,7 +229,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE, ready); result = Curl_output_ntlm(conn, TRUE); if(result) return result; } Loading @@ -244,7 +244,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, if(result) return result; } *ready = TRUE; data->state.authdone = TRUE; /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); } Loading @@ -262,14 +262,14 @@ static CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_negotiate(conn); if (result) return result; *ready = TRUE; data->state.authdone = TRUE; } else #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE, ready); result = Curl_output_ntlm(conn, FALSE); if(result) return result; } Loading @@ -284,7 +284,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, (unsigned char *)path); if(result) return result; *ready = TRUE; data->state.authdone = TRUE; } else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ if(conn->bits.user_passwd && Loading @@ -295,7 +295,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, return result; } /* basic is always ready */ *ready = TRUE; data->state.authdone = TRUE; } } if(auth) Loading @@ -304,7 +304,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, } } else *ready = TRUE; data->state.authdone = TRUE; return result; } Loading Loading @@ -438,6 +438,83 @@ CURLcode Curl_http_auth(struct connectdata *conn, return CURLE_OK; } /** * determine whether an http response has gotten us into an * error state or not. * * @param conn all information about the current connection * * @retval 0 communications should continue * * @retval 1 communications should not continue */ int Curl_http_should_fail(struct connectdata *conn) { struct SessionHandle *data; struct Curl_transfer_keeper *k; curlassert(conn); data = conn->data; curlassert(data); /* ** For readability */ k = &conn->keep; /* ** If we haven't been asked to fail on error, ** don't fail. */ if (!data->set.http_fail_on_error) return 0; /* ** Any code < 400 is never terminal. */ if (k->httpcode < 400) return 0; /* ** Any code >= 400 that's not 401 or 407 is always ** a terminal error */ if ((k->httpcode != 401) && (k->httpcode != 407)) return 1; /* ** All we have left to deal with is 401 and 407 */ curlassert((k->httpcode == 401) || (k->httpcode == 407)); /* ** Examine the current authentication state to see if this ** is an error. The idea is for this function to get ** called after processing all the headers in a response ** message. So, if we've been to asked to authenticate a ** particular stage, and we've done it, we're OK. But, if ** we're already completely authenticated, it's not OK to ** get another 401 or 407. ** ** It is possible for authentication to go stale such that ** the client needs to reauthenticate. Once that info is ** available, use it here. */ infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); if (data->state.authstage && (data->state.authstage == k->httpcode)) return data->state.authdone; /* ** Either we're not authenticating, or we're supposed to ** be authenticating something else. This is an error. */ return 1; } /* fread() emulation to provide POST and/or request data */ static size_t readmoredata(char *buffer, Loading Loading @@ -760,9 +837,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); do { bool auth; /* we don't really have to know when the auth phase is done, but this variable will be set to true then */ if(conn->newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() Loading @@ -776,7 +850,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ result = http_auth_headers(conn, (char *)"CONNECT", host_port, &auth); result = http_auth_headers(conn, (char *)"CONNECT", host_port); if(CURLE_OK == result) { /* OK, now send the connect request to the proxy */ Loading Loading @@ -1066,7 +1140,6 @@ CURLcode Curl_http(struct connectdata *conn) const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; bool authdone=TRUE; /* if the authentication phase is done */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ Loading Loading @@ -1105,7 +1178,7 @@ CURLcode Curl_http(struct connectdata *conn) } /* setup the authentication headers */ result = http_auth_headers(conn, request, ppath, &authdone); result = http_auth_headers(conn, request, ppath); if(result) return result; Loading Loading @@ -1535,8 +1608,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, authdone?FIRSTSOCKET:-1, authdone?&http->writebytecount:NULL); data->state.authdone?FIRSTSOCKET:-1, data->state.authdone?&http->writebytecount:NULL); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; Loading Loading @@ -1574,8 +1647,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, authdone?FIRSTSOCKET:-1, authdone?&http->writebytecount:NULL); data->state.authdone?FIRSTSOCKET:-1, data->state.authdone?&http->writebytecount:NULL); if(result) return result; break; Loading Loading @@ -1606,7 +1679,7 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.postfields) { if(authdone && (postsize < (100*1024))) { if(data->state.authdone && (postsize < (100*1024))) { /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ Loading Loading @@ -1642,7 +1715,7 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); if(!authdone && !checkheaders(data, "Expect:")) { if(!data->state.authdone && !checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ Loading lib/http.h +4 −0 Original line number Diff line number Diff line Loading @@ -42,9 +42,13 @@ CURLcode Curl_http_connect(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn); CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, ssize_t length, ssize_t *wrote); /* These functions are in http.c */ void Curl_http_auth_stage(struct SessionHandle *data, int stage); CURLcode Curl_http_auth(struct connectdata *conn, int httpcode, char *header); void Curl_http_auth_act(struct connectdata *conn); int Curl_http_should_fail(struct connectdata *conn); #endif #endif lib/transfer.c +24 −2 Original line number Diff line number Diff line Loading @@ -441,6 +441,16 @@ CURLcode Curl_readwrite(struct connectdata *conn, FD_ZERO(&k->wkeepfd); } /* ** Now that all of the headers have been parsed, see ** if we should give up and return an error. */ if (Curl_http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } /* now, only output this if the header AND body are requested: */ writetype = CLIENTWRITE_HEADER; Loading Loading @@ -576,9 +586,21 @@ CURLcode Curl_readwrite(struct connectdata *conn, data->info.httpcode = k->httpcode; data->info.httpversion = k->httpversion; /* 404 -> URL not found! */ /* ** This code executes as part of processing ** the header. As a result, it's not ** totally clear how to interpret the ** response code yet as that depends on what ** other headers may be present. 401 and ** 407 may be errors, but may be OK ** depending on how authentication is ** working. Other codes are definitely ** errors, so give up here. */ if (data->set.http_fail_on_error && (k->httpcode >= 400)) { (k->httpcode >= 400) && (k->httpcode != 401) && (k->httpcode != 407)) { /* If we have been told to fail hard on HTTP-errors, here is the check for that: */ /* serious error, go home! */ Loading Loading
lib/http.c +101 −28 Original line number Diff line number Diff line Loading @@ -188,23 +188,23 @@ void Curl_http_auth_act(struct connectdata *conn) } } /* /** * Setup the authentication headers for the host/proxy and the correct * authentication method. * authentication method. @p conn->data->state.authdone set to TRUE * when authentication is done. * * @param conn all information about the current connection */ static CURLcode http_auth_headers(struct connectdata *conn, char *request, char *path, bool *ready) /* set TRUE when the auth phase is done and ready to do the *actual* request */ char *path) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; char *auth=NULL; *ready = FALSE; /* default is no */ curlassert(data); data->state.authdone = FALSE; /* default is no */ if(!data->state.authstage) { if(conn->bits.httpproxy && conn->bits.proxy_user_passwd) Loading @@ -212,7 +212,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, else if(conn->bits.user_passwd) Curl_http_auth_stage(data, 401); else { *ready = TRUE; data->state.authdone = TRUE; return CURLE_OK; /* no authentication with no user or password */ } } Loading @@ -229,7 +229,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, TRUE, ready); result = Curl_output_ntlm(conn, TRUE); if(result) return result; } Loading @@ -244,7 +244,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, if(result) return result; } *ready = TRUE; data->state.authdone = TRUE; /* Switch to web authentication after proxy authentication is done */ Curl_http_auth_stage(data, 401); } Loading @@ -262,14 +262,14 @@ static CURLcode http_auth_headers(struct connectdata *conn, result = Curl_output_negotiate(conn); if (result) return result; *ready = TRUE; data->state.authdone = TRUE; } else #endif #ifdef USE_SSLEAY if(data->state.authwant == CURLAUTH_NTLM) { auth=(char *)"NTLM"; result = Curl_output_ntlm(conn, FALSE, ready); result = Curl_output_ntlm(conn, FALSE); if(result) return result; } Loading @@ -284,7 +284,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, (unsigned char *)path); if(result) return result; *ready = TRUE; data->state.authdone = TRUE; } else if(data->state.authwant == CURLAUTH_BASIC) {/* Basic */ if(conn->bits.user_passwd && Loading @@ -295,7 +295,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, return result; } /* basic is always ready */ *ready = TRUE; data->state.authdone = TRUE; } } if(auth) Loading @@ -304,7 +304,7 @@ static CURLcode http_auth_headers(struct connectdata *conn, } } else *ready = TRUE; data->state.authdone = TRUE; return result; } Loading Loading @@ -438,6 +438,83 @@ CURLcode Curl_http_auth(struct connectdata *conn, return CURLE_OK; } /** * determine whether an http response has gotten us into an * error state or not. * * @param conn all information about the current connection * * @retval 0 communications should continue * * @retval 1 communications should not continue */ int Curl_http_should_fail(struct connectdata *conn) { struct SessionHandle *data; struct Curl_transfer_keeper *k; curlassert(conn); data = conn->data; curlassert(data); /* ** For readability */ k = &conn->keep; /* ** If we haven't been asked to fail on error, ** don't fail. */ if (!data->set.http_fail_on_error) return 0; /* ** Any code < 400 is never terminal. */ if (k->httpcode < 400) return 0; /* ** Any code >= 400 that's not 401 or 407 is always ** a terminal error */ if ((k->httpcode != 401) && (k->httpcode != 407)) return 1; /* ** All we have left to deal with is 401 and 407 */ curlassert((k->httpcode == 401) || (k->httpcode == 407)); /* ** Examine the current authentication state to see if this ** is an error. The idea is for this function to get ** called after processing all the headers in a response ** message. So, if we've been to asked to authenticate a ** particular stage, and we've done it, we're OK. But, if ** we're already completely authenticated, it's not OK to ** get another 401 or 407. ** ** It is possible for authentication to go stale such that ** the client needs to reauthenticate. Once that info is ** available, use it here. */ infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); if (data->state.authstage && (data->state.authstage == k->httpcode)) return data->state.authdone; /* ** Either we're not authenticating, or we're supposed to ** be authenticating something else. This is an error. */ return 1; } /* fread() emulation to provide POST and/or request data */ static size_t readmoredata(char *buffer, Loading Loading @@ -760,9 +837,6 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); do { bool auth; /* we don't really have to know when the auth phase is done, but this variable will be set to true then */ if(conn->newurl) { /* This only happens if we've looped here due to authentication reasons, and we don't really use the newly cloned URL here then. Just free() Loading @@ -776,7 +850,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; /* Setup the proxy-authorization header, if any */ result = http_auth_headers(conn, (char *)"CONNECT", host_port, &auth); result = http_auth_headers(conn, (char *)"CONNECT", host_port); if(CURLE_OK == result) { /* OK, now send the connect request to the proxy */ Loading Loading @@ -1066,7 +1140,6 @@ CURLcode Curl_http(struct connectdata *conn) const char *te = ""; /* tranfer-encoding */ char *ptr; char *request; bool authdone=TRUE; /* if the authentication phase is done */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ Loading Loading @@ -1105,7 +1178,7 @@ CURLcode Curl_http(struct connectdata *conn) } /* setup the authentication headers */ result = http_auth_headers(conn, request, ppath, &authdone); result = http_auth_headers(conn, request, ppath); if(result) return result; Loading Loading @@ -1535,8 +1608,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, authdone?FIRSTSOCKET:-1, authdone?&http->writebytecount:NULL); data->state.authdone?FIRSTSOCKET:-1, data->state.authdone?&http->writebytecount:NULL); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; Loading Loading @@ -1574,8 +1647,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, authdone?FIRSTSOCKET:-1, authdone?&http->writebytecount:NULL); data->state.authdone?FIRSTSOCKET:-1, data->state.authdone?&http->writebytecount:NULL); if(result) return result; break; Loading Loading @@ -1606,7 +1679,7 @@ CURLcode Curl_http(struct connectdata *conn) if(data->set.postfields) { if(authdone && (postsize < (100*1024))) { if(data->state.authdone && (postsize < (100*1024))) { /* If we're not done with the authentication phase, we don't expect to actually send off any data yet. Hence, we delay the sending of the body until we receive that friendly 100-continue response */ Loading Loading @@ -1642,7 +1715,7 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); if(!authdone && !checkheaders(data, "Expect:")) { if(!data->state.authdone && !checkheaders(data, "Expect:")) { /* if not disabled explicitly we add a Expect: 100-continue to the headers which actually speeds up post operations (as there is one packet coming back from the web server) */ Loading
lib/http.h +4 −0 Original line number Diff line number Diff line Loading @@ -42,9 +42,13 @@ CURLcode Curl_http_connect(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn); CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, ssize_t length, ssize_t *wrote); /* These functions are in http.c */ void Curl_http_auth_stage(struct SessionHandle *data, int stage); CURLcode Curl_http_auth(struct connectdata *conn, int httpcode, char *header); void Curl_http_auth_act(struct connectdata *conn); int Curl_http_should_fail(struct connectdata *conn); #endif #endif
lib/transfer.c +24 −2 Original line number Diff line number Diff line Loading @@ -441,6 +441,16 @@ CURLcode Curl_readwrite(struct connectdata *conn, FD_ZERO(&k->wkeepfd); } /* ** Now that all of the headers have been parsed, see ** if we should give up and return an error. */ if (Curl_http_should_fail(conn)) { failf (data, "The requested URL returned error: %d", k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } /* now, only output this if the header AND body are requested: */ writetype = CLIENTWRITE_HEADER; Loading Loading @@ -576,9 +586,21 @@ CURLcode Curl_readwrite(struct connectdata *conn, data->info.httpcode = k->httpcode; data->info.httpversion = k->httpversion; /* 404 -> URL not found! */ /* ** This code executes as part of processing ** the header. As a result, it's not ** totally clear how to interpret the ** response code yet as that depends on what ** other headers may be present. 401 and ** 407 may be errors, but may be OK ** depending on how authentication is ** working. Other codes are definitely ** errors, so give up here. */ if (data->set.http_fail_on_error && (k->httpcode >= 400)) { (k->httpcode >= 400) && (k->httpcode != 401) && (k->httpcode != 407)) { /* If we have been told to fail hard on HTTP-errors, here is the check for that: */ /* serious error, go home! */ Loading