mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31: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);
|
||||
request->version = HTTP_UNKNOWN;
|
||||
request->header = NULL;
|
||||
request->content_length_set = 0;
|
||||
request->content_length = 0;
|
||||
request->bytes_transferred = 0;
|
||||
}
|
||||
@@ -898,6 +899,7 @@ void http_response_init(struct http_response *response)
|
||||
response->code = 0;
|
||||
response->phrase = NULL;
|
||||
response->header = NULL;
|
||||
response->content_length_set = 0;
|
||||
response->content_length = 0;
|
||||
response->bytes_transferred = 0;
|
||||
}
|
||||
@@ -1053,7 +1055,7 @@ int http_parse_header(struct http_header **result, const char *header)
|
||||
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 *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");
|
||||
if (content_length_s == NULL) {
|
||||
*content_length_set = 0;
|
||||
*content_length = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -1068,6 +1071,7 @@ static int http_header_get_content_length(const struct http_header *header, unsi
|
||||
code = 0;
|
||||
|
||||
errno = 0;
|
||||
*content_length_set = 1;
|
||||
*content_length = parse_long(content_length_s, (char **) &tail);
|
||||
if (errno != 0 || *tail != '\0' || tail == content_length_s)
|
||||
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);
|
||||
if (code != 0)
|
||||
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)
|
||||
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);
|
||||
if (code != 0)
|
||||
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)
|
||||
return code;
|
||||
|
||||
|
||||
@@ -184,6 +184,7 @@ struct http_request {
|
||||
struct uri uri;
|
||||
enum http_version version;
|
||||
struct http_header *header;
|
||||
int content_length_set;
|
||||
unsigned long content_length;
|
||||
unsigned long bytes_transferred;
|
||||
};
|
||||
@@ -193,6 +194,7 @@ struct http_response {
|
||||
int code;
|
||||
char *phrase;
|
||||
struct http_header *header;
|
||||
int content_length_set;
|
||||
unsigned long content_length;
|
||||
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
|
||||
(length required) if it wishes to insist on receiving a valid
|
||||
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)
|
||||
logdebug("POST request with no Content-Length.\n");
|
||||
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.
|
||||
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. */
|
||||
while (response.content_length == 0
|
||||
while (!response.content_length_set
|
||||
|| response.bytes_transferred < response.content_length) {
|
||||
size_t remaining = response.content_length - response.bytes_transferred;
|
||||
size_t count;
|
||||
|
||||
count = sizeof(buf);
|
||||
if (response.content_length > 0 && remaining < count)
|
||||
count = remaining;
|
||||
if (response.content_length_set) {
|
||||
size_t remaining = response.content_length - response.bytes_transferred;
|
||||
if (remaining < count)
|
||||
count = remaining;
|
||||
}
|
||||
n = socket_buffer_read(server_sock, buf, count);
|
||||
if (n <= 0)
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user