1
0
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:
david
2014-03-07 16:57:42 +00:00
parent d5d8cd3033
commit 0c4cf69074
3 changed files with 16 additions and 8 deletions

View File

@@ -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;

View File

@@ -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;
}; };

View File

@@ -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;