diff --git a/CHANGES b/CHANGES index 8c9036c6e..da1b2cd4f 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,24 @@ Changelog +Daniel (4 July 2005) +- Andrew Bushnell provided enough info for me to tell that we badly needed to + fix the CONNECT authentication code with multi-pass auth methods (such as + NTLM) as it didn't previously properly ignore response-bodies - in fact it + stopped reading after all response headers had been received. This could + lead to libcurl sending the next request and reading the body from the first + request as response to the second request. (I also renamed the function, + which wasn't strictly necessary but...) + + The best fix would to once and for all make the CONNECT code use the + ordinary request sending/receiving code, treating it as any ordinary request + instead of the special-purpose function we have now. It should make it + better for multi-interface too. And possibly lead to less code... + + Added test case 265 for this. It doesn't work as a _really_ good test case + since the test proxy is too stupid, but the test case helps when running the + debugger to verify. + Daniel (23 June 2005) - David Shaw's fix that unifies proxy string treatment so that a proxy given with CURLOPT_PROXY can use a http:// prefix and user + password. The user diff --git a/RELEASE-NOTES b/RELEASE-NOTES index bf1b7066f..922ea35a8 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -16,6 +16,8 @@ This release includes the following changes: This release includes the following bugfixes: + o treats CONNECT 407 responses with bodies better during Digest/NTLM auth + o debug builds work on Tru64 o improved libcurl.m4 o possible memory leak in windows name resolves o c-ares enabled build with mingw @@ -37,6 +39,6 @@ This release would not have looked like this without help, code, reports and advice from friends like these: John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza, - Tupone Alfredo, Gisle Vanem, David Shaw + Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell Thanks! (and sorry if I forgot to mention someone) diff --git a/lib/ftp.c b/lib/ftp.c index f941fea37..d37f9dc40 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1670,8 +1670,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, /* BLOCKING */ /* We want "seamless" FTP operations through HTTP proxy tunnel */ - result = Curl_ConnectHTTPProxyTunnel(conn, SECONDARYSOCKET, - newhost, newport); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); if(CURLE_OK != result) return result; } @@ -2745,8 +2744,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn, if (conn->bits.tunnel_proxy) { /* BLOCKING */ /* We want "seamless" FTP operations through HTTP proxy tunnel */ - result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); + result = Curl_proxyCONNECT(conn, FIRSTSOCKET, + conn->host.name, conn->remote_port); if(CURLE_OK != result) return result; } diff --git a/lib/http.c b/lib/http.c index 84f357a9c..9d9bb3e42 100644 --- a/lib/http.c +++ b/lib/http.c @@ -96,6 +96,7 @@ #include "memory.h" #include "select.h" #include "parsedate.h" /* for the week day and month names */ +#include "strtoofft.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1053,10 +1054,9 @@ Curl_compareheader(char *headerline, /* line to check */ } /* - * ConnectHTTPProxyTunnel() requires that we're connected to a HTTP - * proxy. This function will issue the necessary commands to get a seamless - * tunnel through this proxy. After that, the socket can be used just as a - * normal socket. + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. * * This badly needs to be rewritten. CONNECT should be sent and dealt with * like any ordinary HTTP request, and not specially crafted like this. This @@ -1064,10 +1064,10 @@ Curl_compareheader(char *headerline, /* line to check */ * much work to do at the moment. */ -CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, - int sockindex, - char *hostname, - int remote_port) +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + char *hostname, + int remote_port) { int subversion=0; struct SessionHandle *data=conn->data; @@ -1076,7 +1076,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int res; size_t nread; /* total size read */ int perline; /* count bytes per line */ - bool keepon=TRUE; + int keepon=TRUE; ssize_t gotbytes; char *ptr; long timeout = @@ -1085,6 +1085,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, char *host_port; curl_socket_t tunnelsocket = conn->sock[sockindex]; send_buffer *req_buffer; + curl_off_t cl=0; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -1215,6 +1216,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int i; nread += gotbytes; + + if(keepon > TRUE) { + cl -= gotbytes; + if(!cl) + break; + } + else for(i = 0; i < gotbytes; ptr++, i++) { perline++; /* amount of bytes in this line so far */ if(*ptr=='\n') { @@ -1242,7 +1250,21 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(('\r' == line_start[0]) || ('\n' == line_start[0])) { /* end of response-headers from the proxy */ - keepon=FALSE; + if(cl && (407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length when we + * have no auth problem, we must ignore the whole + * response-body */ + keepon = 2; + infof(data, "Ignore %" FORMAT_OFF_T + " bytes of response-body\n", cl); + cl -= (gotbytes - i);/* remove the remaining chunk of what + we already read */ + if(cl<=0) + /* if the whole thing was already read, we are done! */ + keepon=FALSE; + } + else + keepon = FALSE; break; /* breaks out of for-loop, not switch() */ } @@ -1257,6 +1279,10 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, if(result) return result; } + else if(checkprefix("Content-Length:", line_start)) { + cl = curlx_strtoofft(line_start + strlen("Content-Length:"), + NULL, 10); + } else if(2 == sscanf(line_start, "HTTP/1.%d %d", &subversion, &k->httpcode)) { @@ -1323,9 +1349,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) if(conn->bits.tunnel_proxy) { /* either SSL over proxy, or explicitly asked for */ - result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET, - conn->host.name, - conn->remote_port); + result = Curl_proxyCONNECT(conn, FIRSTSOCKET, + conn->host.name, + conn->remote_port); if(CURLE_OK != result) return result; } diff --git a/lib/http.h b/lib/http.h index 23afc9115..599d067c0 100644 --- a/lib/http.h +++ b/lib/http.h @@ -29,9 +29,9 @@ bool Curl_compareheader(char *headerline, /* line to check */ const char *content); /* content string to find */ /* ftp can use this as well */ -CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, - int tunnelsocket, - char *hostname, int remote_port); +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, + char *hostname, int remote_port); /* protocol-specific functions set up to be called by the main engine */ CURLcode Curl_http(struct connectdata *conn, bool *done); diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index e198940a8..b32e9ee62 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -32,4 +32,5 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \ test231 test232 test228 test229 test233 test234 test235 test236 test520 \ test237 test238 test239 test243 test245 test246 test247 test248 test249 \ test250 test251 test252 test253 test254 test255 test521 test522 test523 \ - test256 test257 test258 test259 test260 test261 test262 test263 test264 + test256 test257 test258 test259 test260 test261 test262 test263 test264 \ + test265 diff --git a/tests/data/test265 b/tests/data/test265 new file mode 100644 index 000000000..9848f46a7 --- /dev/null +++ b/tests/data/test265 @@ -0,0 +1,104 @@ +# Server-side + + +# this is returned first since we get no proxy-auth + +HTTP/1.0 407 Authorization Required to proxy me my dear +Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA== +Content-Length: 1033 + +And you should ignore this data. +QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQz + + +# This is supposed to be returned when the server gets the second +# Authorization: NTLM line passed-in from the client + +HTTP/1.1 200 Things are fine in proxy land +Server: Microsoft-IIS/5.0 +Content-Type: text/html; charset=iso-8859-1 + + + +# this is returned when we get a GET! + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 14:49:00 GMT +Content-Length: 7 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +daniel + + +# then this is returned when we get proxý-auth + +HTTP/1.1 200 OK swsbounce +Server: no + +Nice proxy auth sir! + + + +HTTP/1.0 407 Authorization Required to proxy me my dear +Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA== +Content-Length: 1033 + +HTTP/1.1 200 Things are fine in proxy land +Server: Microsoft-IIS/5.0 +Content-Type: text/html; charset=iso-8859-1 + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 14:49:00 GMT +Content-Length: 7 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +daniel + + + +# Client-side + + +http + + +NTLM + + +HTTP proxy CONNECT auth NTLM and then POST, response-body in the 407 + + +http://test.remote.server.com:265/path/2650002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-ntlm --proxytunnel -d "postit" + + + +# Verify data after the test has been "shot" + + +^User-Agent: curl/.* + + +CONNECT test.remote.server.com:265 HTTP/1.0 +Host: test.remote.server.com:265 +Proxy-Authorization: NTLM TlRMTVNTUAABAAAAAgIAAAAAAAAgAAAAAAAAACAAAAA= +Proxy-Connection: Keep-Alive + +CONNECT test.remote.server.com:265 HTTP/1.0 +Host: test.remote.server.com:265 +Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEUAAAAYABgAXQAAAAAAAABAAAAABQAFAEAAAAAAAAAARQAAAAAAAAB1AAAAAYIAAHNpbGx5oB5CPMq0JDu5tbxLow3sHn3jfoYDE+7QJVE7DA0GyDEwvj2BxsBctP9tT4fnCtL1 +Proxy-Connection: Keep-Alive + +POST /path/2650002 HTTP/1.1 +User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4 +Host: test.remote.server.com:265 +Accept: */* +Content-Length: 6 +Content-Type: application/x-www-form-urlencoded + +postit + + diff --git a/tests/runtests.pl b/tests/runtests.pl index 572e06c51..939aa80e7 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -1614,10 +1614,10 @@ sub singletest { my $sofar= time()-$start; my $esttotal = $sofar/$count * $total; my $estleft = $esttotal - $sofar; - my $left=sprintf("remaining: %dm%ds", + my $left=sprintf("remaining: %02d:%02d", $estleft/60, $estleft%60); - printf "OK ($count out of $total, %s)\n", $left; + printf "OK (%-3d out of %-3d, %s)\n", $count, $total, $left; # the test succeeded, remove all log files if(!$keepoutfiles) {