mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
known bug #46: chunked-encoded CONNECT responses from a http proxy now works.
Added test case 1008 to verify. Note that #47 is still there.
This commit is contained in:
parent
8d1239c091
commit
119364741e
3
CHANGES
3
CHANGES
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel S (2 October 2007)
|
||||||
|
- libcurl now handles chunked-encoded CONNECT responses
|
||||||
|
|
||||||
Daniel S (1 October 2007)
|
Daniel S (1 October 2007)
|
||||||
- Alex Fishman reported a curl_easy_escape() problem that was made the
|
- Alex Fishman reported a curl_easy_escape() problem that was made the
|
||||||
function do wrong on all input bytes that are >= 0x80 (decimal 128) due to a
|
function do wrong on all input bytes that are >= 0x80 (decimal 128) due to a
|
||||||
|
@ -29,6 +29,7 @@ This release includes the following bugfixes:
|
|||||||
before SIZE
|
before SIZE
|
||||||
o re-used handle transfers with SFTP
|
o re-used handle transfers with SFTP
|
||||||
o curl_easy_escape() problem with byte values >= 128
|
o curl_easy_escape() problem with byte values >= 128
|
||||||
|
o handles chunked-encoded CONNECT responses
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
|
@ -7,9 +7,6 @@ may have been fixed since this was written!
|
|||||||
to be kept alive, the function will return prematurely and will confuse the
|
to be kept alive, the function will return prematurely and will confuse the
|
||||||
rest of the HTTP protocol code.
|
rest of the HTTP protocol code.
|
||||||
|
|
||||||
46. If a CONNECT response is chunked-encoded, the function may return
|
|
||||||
prematurely and will confuse the rest of the HTTP protocol code.
|
|
||||||
|
|
||||||
45. libcurl built to support ipv6 uses getaddrinfo() to resolve host names.
|
45. libcurl built to support ipv6 uses getaddrinfo() to resolve host names.
|
||||||
getaddrinfo() sorts the response list which effectively kills how libcurl
|
getaddrinfo() sorts the response list which effectively kills how libcurl
|
||||||
deals with round-robin DNS entries. All details:
|
deals with round-robin DNS entries. All details:
|
||||||
|
161
lib/http.c
161
lib/http.c
@ -1143,6 +1143,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
||||||
curl_off_t cl=0;
|
curl_off_t cl=0;
|
||||||
bool closeConnection = FALSE;
|
bool closeConnection = FALSE;
|
||||||
|
bool chunked_encoding = FALSE;
|
||||||
long check;
|
long check;
|
||||||
|
|
||||||
#define SELECT_OK 0
|
#define SELECT_OK 0
|
||||||
@ -1203,37 +1204,37 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
data->set.str[STRING_USERAGENT])
|
data->set.str[STRING_USERAGENT])
|
||||||
useragent = conn->allocptr.uagent;
|
useragent = conn->allocptr.uagent;
|
||||||
|
|
||||||
/* Send the connect request to the proxy */
|
/* Send the connect request to the proxy */
|
||||||
/* BLOCKING */
|
/* BLOCKING */
|
||||||
result =
|
result =
|
||||||
add_bufferf(req_buffer,
|
add_bufferf(req_buffer,
|
||||||
"CONNECT %s:%d HTTP/1.0\r\n"
|
"CONNECT %s:%d HTTP/1.0\r\n"
|
||||||
"%s" /* Host: */
|
"%s" /* Host: */
|
||||||
"%s" /* Proxy-Authorization */
|
"%s" /* Proxy-Authorization */
|
||||||
"%s" /* User-Agent */
|
"%s" /* User-Agent */
|
||||||
"%s", /* Proxy-Connection */
|
"%s", /* Proxy-Connection */
|
||||||
hostname, remote_port,
|
hostname, remote_port,
|
||||||
host,
|
host,
|
||||||
conn->allocptr.proxyuserpwd?
|
conn->allocptr.proxyuserpwd?
|
||||||
conn->allocptr.proxyuserpwd:"",
|
conn->allocptr.proxyuserpwd:"",
|
||||||
useragent,
|
useragent,
|
||||||
proxyconn);
|
proxyconn);
|
||||||
|
|
||||||
if(host && *host)
|
if(host && *host)
|
||||||
free(host);
|
free(host);
|
||||||
|
|
||||||
if(CURLE_OK == result)
|
if(CURLE_OK == result)
|
||||||
result = add_custom_headers(conn, req_buffer);
|
result = add_custom_headers(conn, req_buffer);
|
||||||
|
|
||||||
if(CURLE_OK == result)
|
if(CURLE_OK == result)
|
||||||
/* CRLF terminate the request */
|
/* CRLF terminate the request */
|
||||||
result = add_bufferf(req_buffer, "\r\n");
|
result = add_bufferf(req_buffer, "\r\n");
|
||||||
|
|
||||||
if(CURLE_OK == result) {
|
if(CURLE_OK == result) {
|
||||||
/* Now send off the request */
|
/* Now send off the request */
|
||||||
result = add_buffer_send(req_buffer, conn,
|
result = add_buffer_send(req_buffer, conn,
|
||||||
&data->info.request_size, 0, sockindex);
|
&data->info.request_size, 0, sockindex);
|
||||||
}
|
}
|
||||||
req_buffer = NULL;
|
req_buffer = NULL;
|
||||||
if(result)
|
if(result)
|
||||||
failf(data, "Failed sending CONNECT to proxy");
|
failf(data, "Failed sending CONNECT to proxy");
|
||||||
@ -1340,13 +1341,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
nread += gotbytes;
|
nread += gotbytes;
|
||||||
|
|
||||||
if(keepon > TRUE) {
|
if(keepon > TRUE) {
|
||||||
/* This means we are currently ignoring a response-body, so we
|
/* This means we are currently ignoring a response-body */
|
||||||
simply count down our counter and make sure to break out of
|
if(cl) {
|
||||||
the loop when we're done! */
|
/* A Content-Length based body: simply count down the counter
|
||||||
cl -= gotbytes;
|
and make sure to break out of the loop when we're done! */
|
||||||
if(cl<=0) {
|
cl -= gotbytes;
|
||||||
keepon = FALSE;
|
if(cl<=0) {
|
||||||
break;
|
keepon = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* chunked-encoded body, so we need to do the chunked dance
|
||||||
|
properly to know when the end of the body is reached */
|
||||||
|
CHUNKcode r;
|
||||||
|
ssize_t tookcareof=0;
|
||||||
|
|
||||||
|
/* now parse the chunked piece of data so that we can
|
||||||
|
properly tell when the stream ends */
|
||||||
|
r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
|
||||||
|
if(r == CHUNKE_STOP) {
|
||||||
|
/* we're done reading chunks! */
|
||||||
|
infof(data, "chunk reading DONE\n");
|
||||||
|
keepon = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
infof(data, "Read %d bytes of chunk, continue\n",
|
||||||
|
tookcareof);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1366,7 +1387,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
if(data->set.include_header)
|
if(data->set.include_header)
|
||||||
writetype |= CLIENTWRITE_BODY;
|
writetype |= CLIENTWRITE_BODY;
|
||||||
|
|
||||||
result = Curl_client_write(conn, writetype, line_start, perline);
|
result = Curl_client_write(conn, writetype, line_start,
|
||||||
|
perline);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -1377,19 +1399,60 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
if(('\r' == line_start[0]) ||
|
if(('\r' == line_start[0]) ||
|
||||||
('\n' == line_start[0])) {
|
('\n' == line_start[0])) {
|
||||||
/* end of response-headers from the proxy */
|
/* end of response-headers from the proxy */
|
||||||
if(cl && (407 == k->httpcode) &&
|
if((407 == k->httpcode) && !data->state.authproblem) {
|
||||||
!data->state.authproblem) {
|
|
||||||
/* If we get a 407 response code with content length
|
/* If we get a 407 response code with content length
|
||||||
* when we have no auth problem, we must ignore the
|
when we have no auth problem, we must ignore the
|
||||||
* whole response-body */
|
whole response-body */
|
||||||
keepon = 2;
|
keepon = 2;
|
||||||
infof(data, "Ignore %" FORMAT_OFF_T
|
|
||||||
" bytes of response-body\n", cl);
|
if(cl) {
|
||||||
cl -= (gotbytes - i);/* remove the remaining chunk of
|
|
||||||
what we already read */
|
infof(data, "Ignore %" FORMAT_OFF_T
|
||||||
if(cl<=0)
|
" bytes of response-body\n", cl);
|
||||||
/* if the whole thing was already read, we are done! */
|
/* remove the remaining chunk of what we already
|
||||||
|
read */
|
||||||
|
cl -= (gotbytes - i);
|
||||||
|
|
||||||
|
if(cl<=0)
|
||||||
|
/* if the whole thing was already read, we are done!
|
||||||
|
*/
|
||||||
|
keepon=FALSE;
|
||||||
|
}
|
||||||
|
else if(chunked_encoding) {
|
||||||
|
CHUNKcode r;
|
||||||
|
/* We set ignorebody true here since the chunked
|
||||||
|
decoder function will acknowledge that. Pay
|
||||||
|
attention so that this is cleared again when this
|
||||||
|
function returns! */
|
||||||
|
k->ignorebody = TRUE;
|
||||||
|
infof(data, "%d bytes of chunk left\n", gotbytes-i);
|
||||||
|
|
||||||
|
if(line_start[1] == '\n') {
|
||||||
|
/* this can only be a LF if the letter at index 0
|
||||||
|
was a CR */
|
||||||
|
line_start++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now parse the chunked piece of data so that we can
|
||||||
|
properly tell when the stream ends */
|
||||||
|
r = Curl_httpchunk_read(conn, line_start+1,
|
||||||
|
gotbytes -i, &gotbytes);
|
||||||
|
if(r == CHUNKE_STOP) {
|
||||||
|
/* we're done reading chunks! */
|
||||||
|
infof(data, "chunk reading DONE\n");
|
||||||
|
keepon = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
infof(data, "Read %d bytes of chunk, continue\n",
|
||||||
|
gotbytes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* without content-length or chunked encoding, we
|
||||||
|
can't keep the connection alive since the close is
|
||||||
|
the end signal so we bail out at once instead */
|
||||||
keepon=FALSE;
|
keepon=FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
keepon = FALSE;
|
keepon = FALSE;
|
||||||
@ -1415,6 +1478,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
else if(Curl_compareheader(line_start,
|
else if(Curl_compareheader(line_start,
|
||||||
"Connection:", "close"))
|
"Connection:", "close"))
|
||||||
closeConnection = TRUE;
|
closeConnection = TRUE;
|
||||||
|
else if(Curl_compareheader(line_start,
|
||||||
|
"Transfer-Encoding:", "chunked")) {
|
||||||
|
infof(data, "CONNECT responded chunked\n");
|
||||||
|
chunked_encoding = TRUE;
|
||||||
|
/* init our chunky engine */
|
||||||
|
Curl_httpchunk_init(conn);
|
||||||
|
}
|
||||||
else if(Curl_compareheader(line_start,
|
else if(Curl_compareheader(line_start,
|
||||||
"Proxy-Connection:", "close"))
|
"Proxy-Connection:", "close"))
|
||||||
closeConnection = TRUE;
|
closeConnection = TRUE;
|
||||||
@ -1472,6 +1542,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
data->state.authproxy.done = TRUE;
|
data->state.authproxy.done = TRUE;
|
||||||
|
|
||||||
infof (data, "Proxy replied OK to CONNECT request\n");
|
infof (data, "Proxy replied OK to CONNECT request\n");
|
||||||
|
k->ignorebody = FALSE; /* put it (back) to non-ignore state */
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
void Curl_httpchunk_init(struct connectdata *conn)
|
void Curl_httpchunk_init(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct Curl_chunker *chunk = &conn->data->reqdata.proto.http->chunk;
|
struct Curl_chunker *chunk = &conn->chunk;
|
||||||
chunk->hexindex=0; /* start at 0 */
|
chunk->hexindex=0; /* start at 0 */
|
||||||
chunk->dataleft=0; /* no data left yet! */
|
chunk->dataleft=0; /* no data left yet! */
|
||||||
chunk->state = CHUNK_HEX; /* we get hex first! */
|
chunk->state = CHUNK_HEX; /* we get hex first! */
|
||||||
@ -108,7 +108,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
{
|
{
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct Curl_chunker *ch = &data->reqdata.proto.http->chunk;
|
struct Curl_chunker *ch = &conn->chunk;
|
||||||
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
struct Curl_transfer_keeper *k = &data->reqdata.keep;
|
||||||
size_t piece;
|
size_t piece;
|
||||||
size_t length = (size_t)datalen;
|
size_t length = (size_t)datalen;
|
||||||
@ -124,11 +124,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
while(length) {
|
while(length) {
|
||||||
switch(ch->state) {
|
switch(ch->state) {
|
||||||
case CHUNK_HEX:
|
case CHUNK_HEX:
|
||||||
/* Check for an ASCII hex digit.
|
/* Check for an ASCII hex digit.
|
||||||
We avoid the use of isxdigit to accommodate non-ASCII hosts. */
|
We avoid the use of isxdigit to accommodate non-ASCII hosts. */
|
||||||
if((*datap >= 0x30 && *datap <= 0x39) /* 0-9 */
|
if((*datap >= 0x30 && *datap <= 0x39) /* 0-9 */
|
||||||
|| (*datap >= 0x41 && *datap <= 0x46) /* A-F */
|
|| (*datap >= 0x41 && *datap <= 0x46) /* A-F */
|
||||||
|| (*datap >= 0x61 && *datap <= 0x66)) { /* a-f */
|
|| (*datap >= 0x61 && *datap <= 0x66)) { /* a-f */
|
||||||
if(ch->hexindex < MAXNUM_SIZE) {
|
if(ch->hexindex < MAXNUM_SIZE) {
|
||||||
ch->hexbuffer[ch->hexindex] = *datap;
|
ch->hexbuffer[ch->hexindex] = *datap;
|
||||||
datap++;
|
datap++;
|
||||||
@ -218,39 +218,39 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
switch (conn->data->set.http_ce_skip?
|
switch (conn->data->set.http_ce_skip?
|
||||||
IDENTITY : data->reqdata.keep.content_encoding) {
|
IDENTITY : data->reqdata.keep.content_encoding) {
|
||||||
case IDENTITY:
|
case IDENTITY:
|
||||||
#endif
|
#endif
|
||||||
if(!k->ignorebody) {
|
if(!k->ignorebody) {
|
||||||
if ( !data->set.http_te_skip )
|
if ( !data->set.http_te_skip )
|
||||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
|
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
|
||||||
piece);
|
piece);
|
||||||
else
|
else
|
||||||
result = CURLE_OK;
|
result = CURLE_OK;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEFLATE:
|
case DEFLATE:
|
||||||
/* update data->reqdata.keep.str to point to the chunk data. */
|
/* update data->reqdata.keep.str to point to the chunk data. */
|
||||||
data->reqdata.keep.str = datap;
|
data->reqdata.keep.str = datap;
|
||||||
result = Curl_unencode_deflate_write(conn, &data->reqdata.keep,
|
result = Curl_unencode_deflate_write(conn, &data->reqdata.keep,
|
||||||
(ssize_t)piece);
|
(ssize_t)piece);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GZIP:
|
case GZIP:
|
||||||
/* update data->reqdata.keep.str to point to the chunk data. */
|
/* update data->reqdata.keep.str to point to the chunk data. */
|
||||||
data->reqdata.keep.str = datap;
|
data->reqdata.keep.str = datap;
|
||||||
result = Curl_unencode_gzip_write(conn, &data->reqdata.keep,
|
result = Curl_unencode_gzip_write(conn, &data->reqdata.keep,
|
||||||
(ssize_t)piece);
|
(ssize_t)piece);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMPRESS:
|
case COMPRESS:
|
||||||
default:
|
default:
|
||||||
failf (conn->data,
|
failf (conn->data,
|
||||||
"Unrecognized content encoding type. "
|
"Unrecognized content encoding type. "
|
||||||
"libcurl understands `identity', `deflate' and `gzip' "
|
"libcurl understands `identity', `deflate' and `gzip' "
|
||||||
"content encodings.");
|
"content encodings.");
|
||||||
return CHUNKE_BAD_ENCODING;
|
return CHUNKE_BAD_ENCODING;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
else {
|
else {
|
||||||
datap++;
|
datap++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHUNK_TRAILER_CR:
|
case CHUNK_TRAILER_CR:
|
||||||
@ -403,7 +403,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||||||
return CHUNKE_BAD_CHUNK;
|
return CHUNKE_BAD_CHUNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return CHUNKE_STATE_ERROR;
|
return CHUNKE_STATE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1262,7 +1262,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
We DO care about this data if we are pipelining.
|
We DO care about this data if we are pipelining.
|
||||||
Push it back to be read on the next pass. */
|
Push it back to be read on the next pass. */
|
||||||
|
|
||||||
dataleft = data->reqdata.proto.http->chunk.dataleft;
|
dataleft = conn->chunk.dataleft;
|
||||||
if (dataleft != 0) {
|
if (dataleft != 0) {
|
||||||
infof(conn->data, "Leftovers after chunking. "
|
infof(conn->data, "Leftovers after chunking. "
|
||||||
" Rewinding %d bytes\n",dataleft);
|
" Rewinding %d bytes\n",dataleft);
|
||||||
@ -1617,7 +1617,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
else if(!(conn->bits.no_body) &&
|
else if(!(conn->bits.no_body) &&
|
||||||
conn->bits.chunk &&
|
conn->bits.chunk &&
|
||||||
(data->reqdata.proto.http->chunk.state != CHUNK_STOP)) {
|
(conn->chunk.state != CHUNK_STOP)) {
|
||||||
/*
|
/*
|
||||||
* In chunked mode, return an error if the connection is closed prior to
|
* In chunked mode, return an error if the connection is closed prior to
|
||||||
* the empty (terminiating) chunk is read.
|
* the empty (terminiating) chunk is read.
|
||||||
|
@ -296,7 +296,6 @@ struct HTTP {
|
|||||||
|
|
||||||
/* For FORM posting */
|
/* For FORM posting */
|
||||||
struct Form form;
|
struct Form form;
|
||||||
struct Curl_chunker chunk;
|
|
||||||
|
|
||||||
struct back {
|
struct back {
|
||||||
curl_read_callback fread_func; /* backup storage for fread pointer */
|
curl_read_callback fread_func; /* backup storage for fread pointer */
|
||||||
@ -818,6 +817,11 @@ struct connectdata {
|
|||||||
connection is used! */
|
connection is used! */
|
||||||
struct SessionHandle *data;
|
struct SessionHandle *data;
|
||||||
|
|
||||||
|
/* chunk is for HTTP chunked encoding, but is in the general connectdata
|
||||||
|
struct only because we can do just about any protocol through a HTTP proxy
|
||||||
|
and a HTTP proxy may in fact respond using chunked encoding */
|
||||||
|
struct Curl_chunker chunk;
|
||||||
|
|
||||||
bool inuse; /* This is a marker for the connection cache logic. If this is
|
bool inuse; /* This is a marker for the connection cache logic. If this is
|
||||||
TRUE this handle is being used by an easy handle and cannot
|
TRUE this handle is being used by an easy handle and cannot
|
||||||
be used by any other easy handle without careful
|
be used by any other easy handle without careful
|
||||||
|
@ -44,7 +44,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
|
|||||||
test409 test613 test614 test700 test701 test702 test704 test705 test703 \
|
test409 test613 test614 test700 test701 test702 test704 test705 test703 \
|
||||||
test706 test707 test350 test351 test352 test353 test289 test540 test354 \
|
test706 test707 test350 test351 test352 test353 test289 test540 test354 \
|
||||||
test231 test1000 test1001 test1002 test1003 test1004 test1005 test1006 \
|
test231 test1000 test1001 test1002 test1003 test1004 test1005 test1006 \
|
||||||
test615 test1007 test541 test1010 test1011 test1012 test542 test543 test536
|
test615 test1007 test541 test1010 test1011 test1012 test542 test543 \
|
||||||
|
test536 test1008
|
||||||
|
|
||||||
filecheck:
|
filecheck:
|
||||||
@mkdir test-place; \
|
@mkdir test-place; \
|
||||||
|
112
tests/data/test1008
Normal file
112
tests/data/test1008
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<testcase>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
|
||||||
|
# this is returned first since we get no proxy-auth
|
||||||
|
<data1001>
|
||||||
|
HTTP/1.1 407 Authorization Required to proxy me my dear
|
||||||
|
Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
20
|
||||||
|
And you should ignore this data.
|
||||||
|
FA0
|
||||||
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
0
|
||||||
|
|
||||||
|
</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
|
||||||
|
Server: Microsoft-IIS/5.0
|
||||||
|
Content-Type: text/html; charset=iso-8859-1
|
||||||
|
|
||||||
|
</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 proxy-auth
|
||||||
|
<data1000>
|
||||||
|
HTTP/1.1 200 OK swsbounce
|
||||||
|
Server: no
|
||||||
|
|
||||||
|
Nice proxy auth sir!
|
||||||
|
</data1000>
|
||||||
|
|
||||||
|
<datacheck>
|
||||||
|
HTTP/1.1 407 Authorization Required to proxy me my dear
|
||||||
|
Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAAAGgoEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
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
|
||||||
|
</datacheck>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
NTLM
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
HTTP proxy CONNECT auth NTLM with chunked-encoded 407 response
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://test.remote.server.com:1008/path/10080002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-ntlm --proxytunnel
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent: curl/.*
|
||||||
|
</strip>
|
||||||
|
# We strip off a large chunk of the type-2 NTLM message since it depends on
|
||||||
|
# the local host name and thus differs on different machines!
|
||||||
|
<strippart>
|
||||||
|
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
|
||||||
|
</strippart>
|
||||||
|
<protocol>
|
||||||
|
CONNECT test.remote.server.com:1008 HTTP/1.0
|
||||||
|
Host: test.remote.server.com:1008
|
||||||
|
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||||
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
|
CONNECT test.remote.server.com:1008 HTTP/1.0
|
||||||
|
Host: test.remote.server.com:1008
|
||||||
|
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
|
||||||
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
|
GET /path/10080002 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:1008
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
Loading…
Reference in New Issue
Block a user