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
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
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)
/* 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;
}
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;
}
#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 <curl/mprintf.h>
}
/*
- * 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
* 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;
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 =
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
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') {
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() */
}
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)) {
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;
}
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);
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
--- /dev/null
+# Server-side
+<reply>
+
+# this is returned first since we get no proxy-auth
+<data1001>
+HTTP/1.0 407 Authorization Required to proxy me my dear\r
+Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==\r
+Content-Length: 1033\r
+\r
+And you should ignore this data.
+QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQz
+</data1001>
+
+# This is supposed to be returned when the server gets the second
+# Authorization: NTLM line passed-in from the client
+<data1002>
+HTTP/1.1 200 Things are fine in proxy land\r
+Server: Microsoft-IIS/5.0\r
+Content-Type: text/html; charset=iso-8859-1\r
+\r
+</data1002>
+
+# this is returned when we get a GET!
+<data2>
+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
+</data2>
+
+# then this is returned when we get proxĂ˝-auth
+<data1000>
+HTTP/1.1 200 OK swsbounce\r
+Server: no
+\r
+Nice proxy auth sir!
+</data1000>
+
+<datacheck>
+HTTP/1.0 407 Authorization Required to proxy me my dear\r
+Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==\r
+Content-Length: 1033\r
+\r
+HTTP/1.1 200 Things are fine in proxy land\r
+Server: Microsoft-IIS/5.0\r
+Content-Type: text/html; charset=iso-8859-1\r
+\r
+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
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+NTLM
+</features>
+ <name>
+HTTP proxy CONNECT auth NTLM and then POST, response-body in the 407
+ </name>
+ <command>
+http://test.remote.server.com:265/path/2650002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-ntlm --proxytunnel -d "postit"
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent: curl/.*
+</strip>
+<protocol nonewline=yes>
+CONNECT test.remote.server.com:265 HTTP/1.0\r
+Host: test.remote.server.com:265\r
+Proxy-Authorization: NTLM TlRMTVNTUAABAAAAAgIAAAAAAAAgAAAAAAAAACAAAAA=\r
+Proxy-Connection: Keep-Alive\r
+\r
+CONNECT test.remote.server.com:265 HTTP/1.0\r
+Host: test.remote.server.com:265\r
+Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEUAAAAYABgAXQAAAAAAAABAAAAABQAFAEAAAAAAAAAARQAAAAAAAAB1AAAAAYIAAHNpbGx5oB5CPMq0JDu5tbxLow3sHn3jfoYDE+7QJVE7DA0GyDEwvj2BxsBctP9tT4fnCtL1\r
+Proxy-Connection: Keep-Alive\r
+\r
+POST /path/2650002 HTTP/1.1\r
+User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4\r
+Host: test.remote.server.com:265\r
+Accept: */*\r
+Content-Length: 6\r
+Content-Type: application/x-www-form-urlencoded\r
+\r
+postit
+</protocol>
+</verify>
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) {