From 0c4cf690741b3e28f26853f532a6cb7cb1a02a0b Mon Sep 17 00:00:00 2001 From: david Date: Fri, 7 Mar 2014 16:57:42 +0000 Subject: [PATCH] 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. --- ncat/http.c | 10 +++++++--- ncat/http.h | 2 ++ ncat/ncat_proxy.c | 12 +++++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ncat/http.c b/ncat/http.c index e11767c51..43a7eb4c2 100644 --- a/ncat/http.c +++ b/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; diff --git a/ncat/http.h b/ncat/http.h index cd06f86b5..66c9cb373 100644 --- a/ncat/http.h +++ b/ncat/http.h @@ -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; }; diff --git a/ncat/ncat_proxy.c b/ncat/ncat_proxy.c index d8fee2a46..618ed7012 100644 --- a/ncat/ncat_proxy.c +++ b/ncat/ncat_proxy.c @@ -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;