mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 14:11:29 +00:00
Use a separate boolean to remember whether Content-Length was set.
Previous content_length == 0 was overloaded to mean that Content-Length was set. But that was wrong when the Content-Length was actually 0. The error message you got when running an HTTP proxy that received 0-length POSTs was POST request with no Content-Length.
This commit is contained in:
10
ncat/http.c
10
ncat/http.c
@@ -843,6 +843,7 @@ void http_request_init(struct http_request *request)
|
|||||||
uri_init(&request->uri);
|
uri_init(&request->uri);
|
||||||
request->version = HTTP_UNKNOWN;
|
request->version = HTTP_UNKNOWN;
|
||||||
request->header = NULL;
|
request->header = NULL;
|
||||||
|
request->content_length_set = 0;
|
||||||
request->content_length = 0;
|
request->content_length = 0;
|
||||||
request->bytes_transferred = 0;
|
request->bytes_transferred = 0;
|
||||||
}
|
}
|
||||||
@@ -898,6 +899,7 @@ void http_response_init(struct http_response *response)
|
|||||||
response->code = 0;
|
response->code = 0;
|
||||||
response->phrase = NULL;
|
response->phrase = NULL;
|
||||||
response->header = NULL;
|
response->header = NULL;
|
||||||
|
response->content_length_set = 0;
|
||||||
response->content_length = 0;
|
response->content_length = 0;
|
||||||
response->bytes_transferred = 0;
|
response->bytes_transferred = 0;
|
||||||
}
|
}
|
||||||
@@ -1053,7 +1055,7 @@ int http_parse_header(struct http_header **result, const char *header)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_header_get_content_length(const struct http_header *header, unsigned long *content_length)
|
static int http_header_get_content_length(const struct http_header *header, int *content_length_set, unsigned long *content_length)
|
||||||
{
|
{
|
||||||
char *content_length_s;
|
char *content_length_s;
|
||||||
char *tail;
|
char *tail;
|
||||||
@@ -1061,6 +1063,7 @@ static int http_header_get_content_length(const struct http_header *header, unsi
|
|||||||
|
|
||||||
content_length_s = http_header_get_first(header, "Content-Length");
|
content_length_s = http_header_get_first(header, "Content-Length");
|
||||||
if (content_length_s == NULL) {
|
if (content_length_s == NULL) {
|
||||||
|
*content_length_set = 0;
|
||||||
*content_length = 0;
|
*content_length = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1068,6 +1071,7 @@ static int http_header_get_content_length(const struct http_header *header, unsi
|
|||||||
code = 0;
|
code = 0;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
*content_length_set = 1;
|
||||||
*content_length = parse_long(content_length_s, (char **) &tail);
|
*content_length = parse_long(content_length_s, (char **) &tail);
|
||||||
if (errno != 0 || *tail != '\0' || tail == content_length_s)
|
if (errno != 0 || *tail != '\0' || tail == content_length_s)
|
||||||
code = 400;
|
code = 400;
|
||||||
@@ -1084,7 +1088,7 @@ int http_request_parse_header(struct http_request *request, const char *header)
|
|||||||
code = http_parse_header(&request->header, header);
|
code = http_parse_header(&request->header, header);
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
return code;
|
return code;
|
||||||
code = http_header_get_content_length(request->header, &request->content_length);
|
code = http_header_get_content_length(request->header, &request->content_length_set, &request->content_length);
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
return code;
|
return code;
|
||||||
|
|
||||||
@@ -1099,7 +1103,7 @@ int http_response_parse_header(struct http_response *response, const char *heade
|
|||||||
code = http_parse_header(&response->header, header);
|
code = http_parse_header(&response->header, header);
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
return code;
|
return code;
|
||||||
code = http_header_get_content_length(response->header, &response->content_length);
|
code = http_header_get_content_length(response->header, &response->content_length_set, &response->content_length);
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
return code;
|
return code;
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ struct http_request {
|
|||||||
struct uri uri;
|
struct uri uri;
|
||||||
enum http_version version;
|
enum http_version version;
|
||||||
struct http_header *header;
|
struct http_header *header;
|
||||||
|
int content_length_set;
|
||||||
unsigned long content_length;
|
unsigned long content_length;
|
||||||
unsigned long bytes_transferred;
|
unsigned long bytes_transferred;
|
||||||
};
|
};
|
||||||
@@ -193,6 +194,7 @@ struct http_response {
|
|||||||
int code;
|
int code;
|
||||||
char *phrase;
|
char *phrase;
|
||||||
struct http_header *header;
|
struct http_header *header;
|
||||||
|
int content_length_set;
|
||||||
unsigned long content_length;
|
unsigned long content_length;
|
||||||
unsigned long bytes_transferred;
|
unsigned long bytes_transferred;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ static int do_transaction(struct http_request *request,
|
|||||||
request) if it cannot determine the length of the message, or with 411
|
request) if it cannot determine the length of the message, or with 411
|
||||||
(length required) if it wishes to insist on receiving a valid
|
(length required) if it wishes to insist on receiving a valid
|
||||||
Content-Length." */
|
Content-Length." */
|
||||||
if (strcmp(request->method, "POST") == 0 && request->content_length == 0) {
|
if (strcmp(request->method, "POST") == 0 && !request->content_length_set) {
|
||||||
if (o.debug)
|
if (o.debug)
|
||||||
logdebug("POST request with no Content-Length.\n");
|
logdebug("POST request with no Content-Length.\n");
|
||||||
return 400;
|
return 400;
|
||||||
@@ -771,14 +771,16 @@ static int do_transaction(struct http_request *request,
|
|||||||
/* If the Content-Length is 0, read until the connection is closed.
|
/* If the Content-Length is 0, read until the connection is closed.
|
||||||
Otherwise read until the Content-Length. At this point it's too late to
|
Otherwise read until the Content-Length. At this point it's too late to
|
||||||
return our own error code so return 0 in case of any error. */
|
return our own error code so return 0 in case of any error. */
|
||||||
while (response.content_length == 0
|
while (!response.content_length_set
|
||||||
|| response.bytes_transferred < response.content_length) {
|
|| response.bytes_transferred < response.content_length) {
|
||||||
size_t remaining = response.content_length - response.bytes_transferred;
|
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
count = sizeof(buf);
|
count = sizeof(buf);
|
||||||
if (response.content_length > 0 && remaining < count)
|
if (response.content_length_set) {
|
||||||
|
size_t remaining = response.content_length - response.bytes_transferred;
|
||||||
|
if (remaining < count)
|
||||||
count = remaining;
|
count = remaining;
|
||||||
|
}
|
||||||
n = socket_buffer_read(server_sock, buf, count);
|
n = socket_buffer_read(server_sock, buf, count);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user