diff options
author | Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com> | 2024-06-27 16:41:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-27 16:41:03 +0300 |
commit | 9f0c8c400e15d4200529551957309f8ffc27805a (patch) | |
tree | 4dd24451b4765c308cf52f05c717168ef474ee48 /src | |
parent | a4adc506d39b9b9cd90af87613b31d87cc310974 (diff) |
Fix proxy connect response (#18017)
* Fix proxy connect response
* Handle CONNECT to mqtt
* Fix typo
Diffstat (limited to 'src')
-rw-r--r-- | src/aclk/https_client.c | 59 | ||||
-rw-r--r-- | src/aclk/https_client.h | 8 | ||||
-rw-r--r-- | src/aclk/mqtt_websockets/mqtt_wss_client.c | 9 | ||||
-rw-r--r-- | src/streaming/sender.c | 2 |
4 files changed, 47 insertions, 31 deletions
diff --git a/src/aclk/https_client.c b/src/aclk/https_client.c index df647ce663..2bc768f24b 100644 --- a/src/aclk/https_client.c +++ b/src/aclk/https_client.c @@ -23,9 +23,9 @@ static const char *http_req_type_to_str(http_req_type_t req) { #define TRANSFER_ENCODING_CHUNKED (-2) -void http_parse_ctx_create(http_parse_ctx *ctx) +void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state) { - ctx->state = HTTP_PARSE_INITIAL; + ctx->state = parse_state; ctx->content_length = -1; ctx->http_code = 0; ctx->headers = c_rhash_new(0); @@ -51,6 +51,7 @@ void http_parse_ctx_destroy(http_parse_ctx *ctx) #define HTTP_LINE_TERM "\x0D\x0A" #define RESP_PROTO "HTTP/1.1 " +#define RESP_PROTO10 "HTTP/1.0 " #define HTTP_KEYVAL_SEPARATOR ": " #define HTTP_HDR_BUFFER_SIZE 1024 #define PORT_STR_MAX_BYTES 12 @@ -244,10 +245,20 @@ http_parse_rc parse_http_response(rbuf_t buf, http_parse_ctx *parse_ctx) if (parse_ctx->state != HTTP_PARSE_CONTENT && !rbuf_find_bytes(buf, HTTP_LINE_TERM, strlen(HTTP_LINE_TERM), &idx)) return HTTP_PARSE_NEED_MORE_DATA; switch (parse_ctx->state) { + case HTTP_PARSE_PROXY_CONNECT: case HTTP_PARSE_INITIAL: if (rbuf_memcmp_n(buf, RESP_PROTO, strlen(RESP_PROTO))) { - netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO); - return HTTP_PARSE_ERROR; + if (parse_ctx->state == HTTP_PARSE_PROXY_CONNECT) { + if (rbuf_memcmp_n(buf, RESP_PROTO10, strlen(RESP_PROTO10))) { + netdata_log_error( + "Expected response to start with \"%s\" or \"%s\"", RESP_PROTO, RESP_PROTO10); + return HTTP_PARSE_ERROR; + } + } + else { + netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO); + return HTTP_PARSE_ERROR; + } } rbuf_bump_tail(buf, strlen(RESP_PROTO)); if (rbuf_pop(buf, rc, 4) != 4) { @@ -489,36 +500,36 @@ static int read_parse_response(https_req_ctx_t *ctx) { return 0; } +static const char *http_methods[] = { + [HTTP_REQ_GET] = "GET ", + [HTTP_REQ_POST] = "POST ", + [HTTP_REQ_CONNECT] = "CONNECT ", +}; + + #define TX_BUFFER_SIZE 8192 #define RX_BUFFER_SIZE (TX_BUFFER_SIZE*2) static int handle_http_request(https_req_ctx_t *ctx) { BUFFER *hdr = buffer_create(TX_BUFFER_SIZE, &netdata_buffers_statistics.buffers_aclk); int rc = 0; - http_parse_ctx_create(&ctx->parse_ctx); + http_req_type_t req_type = ctx->request->request_type; - // Prepare data to send - switch (ctx->request->request_type) { - case HTTP_REQ_CONNECT: - buffer_strcat(hdr, "CONNECT "); - break; - case HTTP_REQ_GET: - buffer_strcat(hdr, "GET "); - break; - case HTTP_REQ_POST: - buffer_strcat(hdr, "POST "); - break; - default: - netdata_log_error("Unknown HTTPS request type!"); - rc = 1; - goto err_exit; + if (req_type >= HTTP_REQ_INVALID) { + netdata_log_error("Unknown HTTPS request type!"); + rc = 1; + goto err_exit; } + buffer_strcat(hdr, http_methods[req_type]); - if (ctx->request->request_type == HTTP_REQ_CONNECT) { + if (req_type == HTTP_REQ_CONNECT) { buffer_strcat(hdr, ctx->request->host); buffer_sprintf(hdr, ":%d", ctx->request->port); - } else { + http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_PROXY_CONNECT); + } + else { buffer_strcat(hdr, ctx->request->url); + http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_INITIAL); } buffer_strcat(hdr, HTTP_1_1 HTTP_ENDL); @@ -527,7 +538,7 @@ static int handle_http_request(https_req_ctx_t *ctx) { buffer_sprintf(hdr, "Host: %s\x0D\x0A", ctx->request->host); buffer_strcat(hdr, "User-Agent: Netdata/rocks newhttpclient\x0D\x0A"); - if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) { + if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) { buffer_sprintf(hdr, "Content-Length: %zu\x0D\x0A", ctx->request->payload_size); } if (ctx->request->proxy_username) { @@ -558,7 +569,7 @@ static int handle_http_request(https_req_ctx_t *ctx) { goto err_exit; } - if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) { + if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) { if (https_client_write_all(ctx, ctx->request->payload, ctx->request->payload_size)) { netdata_log_error("Couldn't write payload into SSL connection"); rc = 3; diff --git a/src/aclk/https_client.h b/src/aclk/https_client.h index 79d0a42b75..bc5ca30b8d 100644 --- a/src/aclk/https_client.h +++ b/src/aclk/https_client.h @@ -11,7 +11,8 @@ typedef enum http_req_type { HTTP_REQ_GET = 0, HTTP_REQ_POST, - HTTP_REQ_CONNECT + HTTP_REQ_CONNECT, + HTTP_REQ_INVALID } http_req_type_t; typedef struct { @@ -82,7 +83,8 @@ int https_request(https_req_t *request, https_req_response_t *response); // we expose previously internal parser as this is usefull also from // other parts of the code enum http_parse_state { - HTTP_PARSE_INITIAL = 0, + HTTP_PARSE_PROXY_CONNECT = 0, + HTTP_PARSE_INITIAL, HTTP_PARSE_HEADERS, HTTP_PARSE_CONTENT }; @@ -118,7 +120,7 @@ typedef struct { size_t chunk_got; } http_parse_ctx; -void http_parse_ctx_create(http_parse_ctx *ctx); +void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state); void http_parse_ctx_destroy(http_parse_ctx *ctx); typedef enum { diff --git a/src/aclk/mqtt_websockets/mqtt_wss_client.c b/src/aclk/mqtt_websockets/mqtt_wss_client.c index bc67ae7f5b..f5b4025d76 100644 --- a/src/aclk/mqtt_websockets/mqtt_wss_client.c +++ b/src/aclk/mqtt_websockets/mqtt_wss_client.c @@ -314,6 +314,7 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) #define PROXY_CONNECT "CONNECT" #define PROXY_HTTP "HTTP/1.1" +#define PROXY_HTTP10 "HTTP/1.0" #define HTTP_ENDLINE "\x0D\x0A" #define HTTP_HDR_TERMINATOR "\x0D\x0A\x0D\x0A" #define HTTP_CODE_LEN 4 @@ -326,14 +327,16 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf) int idx; if (rbuf_memcmp_n(buf, PROXY_HTTP, strlen(PROXY_HTTP))) { - mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\""); - return 1; + if (rbuf_memcmp_n(buf, PROXY_HTTP10, strlen(PROXY_HTTP10))) { + mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\""); + return 1; + } } rbuf_bump_tail(buf, strlen(PROXY_HTTP)); if (!rbuf_pop(buf, http_code_s, 1) || http_code_s[0] != 0x20) { - mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\""); + mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\""); return 2; } diff --git a/src/streaming/sender.c b/src/streaming/sender.c index d4c3cc0009..3432e69276 100644 --- a/src/streaming/sender.c +++ b/src/streaming/sender.c @@ -672,7 +672,7 @@ static int rrdpush_http_upgrade_prelude(RRDHOST *host, struct sender_state *s) { rbuf_push(buf, http, bytes); http_parse_ctx ctx; - http_parse_ctx_create(&ctx); + http_parse_ctx_create(&ctx, HTTP_PARSE_INITIAL); ctx.flags |= HTTP_PARSE_FLAG_DONT_WAIT_FOR_CONTENT; int rc; |