From dfaf4ec186a30e5ea7976db227920cb51735496f Mon Sep 17 00:00:00 2001 From: vector-of-bool Date: Fri, 9 Sep 2022 00:05:56 +0000 Subject: [PATCH 1/4] Fix: _mongoc_http_send does not set resp.status --- src/libmongoc/src/mongoc/mongoc-http.c | 36 ++++++++++++++++++++++++++ src/libmongoc/tests/test-mongoc-http.c | 4 +++ 2 files changed, 40 insertions(+) diff --git a/src/libmongoc/src/mongoc/mongoc-http.c b/src/libmongoc/src/mongoc/mongoc-http.c index 7c24c1c2566..910783a0b61 100644 --- a/src/libmongoc/src/mongoc/mongoc-http.c +++ b/src/libmongoc/src/mongoc/mongoc-http.c @@ -206,6 +206,42 @@ _mongoc_http_send (const mongoc_http_request_t *req, } http_response_str = (char *) http_response_buf.data; + const char *const resp_end_ptr = + http_response_str + http_response_buf.datalen; + + const char *proto_leader = "HTTP/1.0 "; + ptr = strstr (http_response_str, proto_leader); + if (!ptr) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "No HTTP version leader in HTTP response"); + goto fail; + } + + ptr += strlen (proto_leader); + ssize_t remain = resp_end_ptr - ptr; + if (remain < 4) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "Short read in HTTP response"); + goto fail; + } + + char status_buf[4] = {0}; + memcpy (status_buf, ptr, 3); + char *status_endptr; + res->status = strtol (status_buf, &status_endptr, 10); + if (status_endptr != status_buf + 3) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "Invalid HTTP response status string %*.s", + 4, + status_buf); + goto fail; + } /* Find the end of the headers. */ ptr = strstr (http_response_str, header_delimiter); diff --git a/src/libmongoc/tests/test-mongoc-http.c b/src/libmongoc/tests/test-mongoc-http.c index 62cbbabb379..dd912c42489 100644 --- a/src/libmongoc/tests/test-mongoc-http.c +++ b/src/libmongoc/tests/test-mongoc-http.c @@ -37,7 +37,9 @@ test_mongoc_http (void *unused) req.host = "example.com"; req.port = 80; r = _mongoc_http_send (&req, 10000, false, NULL, &res, &error); + ASSERT_CMPINT (res.status, ==, 200); ASSERT_OR_PRINT (r, error); + ASSERT_CMPINT (res.body_len, >, 0); _mongoc_http_response_cleanup (&res); /* Basic POST request with a body. */ @@ -46,7 +48,9 @@ test_mongoc_http (void *unused) req.body_len = 4; req.port = 80; r = _mongoc_http_send (&req, 10000, false, NULL, &res, &error); + ASSERT_CMPINT (res.status, ==, 200); ASSERT_OR_PRINT (r, error); + ASSERT_CMPINT (res.body_len, >, 0); _mongoc_http_response_cleanup (&res); } From 9055cd0727efff69baf79b65bb5cd5b796b40236 Mon Sep 17 00:00:00 2001 From: vector-of-bool Date: Fri, 9 Sep 2022 00:07:35 +0000 Subject: [PATCH 2/4] Fix: Don't attempt an empty write if HTTP req body is empty --- src/libmongoc/src/mongoc/mongoc-http.c | 2 +- src/libmongoc/tests/test-mongoc-http.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libmongoc/src/mongoc/mongoc-http.c b/src/libmongoc/src/mongoc/mongoc-http.c index 910783a0b61..04d324dce45 100644 --- a/src/libmongoc/src/mongoc/mongoc-http.c +++ b/src/libmongoc/src/mongoc/mongoc-http.c @@ -175,7 +175,7 @@ _mongoc_http_send (const mongoc_http_request_t *req, goto fail; } - if (req->body) { + if (req->body && req->body_len) { iovec.iov_base = (void *) req->body; iovec.iov_len = req->body_len; if (!_mongoc_stream_writev_full (stream, &iovec, 1, timeout_ms, error)) { diff --git a/src/libmongoc/tests/test-mongoc-http.c b/src/libmongoc/tests/test-mongoc-http.c index dd912c42489..b827d3ff590 100644 --- a/src/libmongoc/tests/test-mongoc-http.c +++ b/src/libmongoc/tests/test-mongoc-http.c @@ -36,6 +36,9 @@ test_mongoc_http (void *unused) req.method = "GET"; req.host = "example.com"; req.port = 80; + // Empty body is okay + req.body = ""; + req.body_len = 0; r = _mongoc_http_send (&req, 10000, false, NULL, &res, &error); ASSERT_CMPINT (res.status, ==, 200); ASSERT_OR_PRINT (r, error); From 009932430a4b398c00014295011d62acacbbadab Mon Sep 17 00:00:00 2001 From: vector-of-bool Date: Fri, 9 Sep 2022 00:08:02 +0000 Subject: [PATCH 3/4] Fix: Include host port in the Host header --- src/libmongoc/src/mongoc/mongoc-http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libmongoc/src/mongoc/mongoc-http.c b/src/libmongoc/src/mongoc/mongoc-http.c index 04d324dce45..39c4f7e01a8 100644 --- a/src/libmongoc/src/mongoc/mongoc-http.c +++ b/src/libmongoc/src/mongoc/mongoc-http.c @@ -69,7 +69,7 @@ _mongoc_http_render_request_head (const mongoc_http_request_t *req) bson_free (path); /* Always add Host header. */ - bson_string_append_printf (string, "Host: %s\r\n", req->host); + bson_string_append_printf (string, "Host: %s:%d\r\n", req->host, req->port); /* Always add Connection: close header to ensure server closes connection. */ bson_string_append_printf (string, "Connection: close\r\n"); /* Add Content-Length if body is included. */ From b9f8a4c57d5c2afc529aabbec19c52efb6c66eab Mon Sep 17 00:00:00 2001 From: vector-of-bool Date: Fri, 9 Sep 2022 20:34:50 +0000 Subject: [PATCH 4/4] Fix port setting for IMDS requests --- src/libmongoc/src/mongoc/mcd-azure.c | 1 + src/libmongoc/tests/test-mcd-azure-imds.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libmongoc/src/mongoc/mcd-azure.c b/src/libmongoc/src/mongoc/mcd-azure.c index b7cdb69270b..76d1b093811 100644 --- a/src/libmongoc/src/mongoc/mcd-azure.c +++ b/src/libmongoc/src/mongoc/mcd-azure.c @@ -32,6 +32,7 @@ mcd_azure_imds_request_init (mcd_azure_imds_request *req) _mongoc_http_request_init (&req->req); // The HTTP host of the IMDS server req->req.host = "169.254.169.254"; + req->req.port = 80; // No body req->req.body = ""; // We GET diff --git a/src/libmongoc/tests/test-mcd-azure-imds.c b/src/libmongoc/tests/test-mcd-azure-imds.c index 9d1dee73cb7..52bc0f38352 100644 --- a/src/libmongoc/tests/test-mcd-azure-imds.c +++ b/src/libmongoc/tests/test-mcd-azure-imds.c @@ -53,7 +53,7 @@ _test_http_req (void) "/metadata/identity/oauth2/" "token?api-version=2018-02-01&resource=https%3A%2F%2Fvault." "azure.net HTTP/1.0\r\n" - "Host: 169.254.169.254\r\n" + "Host: 169.254.169.254:80\r\n" "Connection: close\r\n" "Metadata: true\r\n" "Accept: application/json\r\n"