Fix proxy connect response (#18017)
* Fix proxy connect response * Handle CONNECT to mqtt * Fix typo
Stelios Fragkakis committed
Jun 27, 2024 at 16:41 UTC
9f0c8c400e15d4200529551957309f8ffc27805a
4 files changed
+47
-31
src/aclk/https_client.c
+35
-24
@@ -23,9 +23,9 @@ static const char *http_req_type_to_str(http_req_type_t req) {
23
24
#define TRANSFER_ENCODING_CHUNKED (-2)
25
26
-void http_parse_ctx_create(http_parse_ctx *ctx)
26
+void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state)
27
{
28
- ctx->state = HTTP_PARSE_INITIAL;
28
+ ctx->state = parse_state;
29
ctx->content_length = -1;
30
ctx->http_code = 0;
31
ctx->headers = c_rhash_new(0);
@@ -51,6 +51,7 @@ void http_parse_ctx_destroy(http_parse_ctx *ctx)
51
52
#define HTTP_LINE_TERM "\x0D\x0A"
53
#define RESP_PROTO "HTTP/1.1 "
54
+#define RESP_PROTO10 "HTTP/1.0 "
55
#define HTTP_KEYVAL_SEPARATOR ": "
56
#define HTTP_HDR_BUFFER_SIZE 1024
57
#define PORT_STR_MAX_BYTES 12
@@ -244,10 +245,20 @@ http_parse_rc parse_http_response(rbuf_t buf, http_parse_ctx *parse_ctx)
245
if (parse_ctx->state != HTTP_PARSE_CONTENT && !rbuf_find_bytes(buf, HTTP_LINE_TERM, strlen(HTTP_LINE_TERM), &idx))
246
return HTTP_PARSE_NEED_MORE_DATA;
247
switch (parse_ctx->state) {
248
+ case HTTP_PARSE_PROXY_CONNECT:
249
case HTTP_PARSE_INITIAL:
250
if (rbuf_memcmp_n(buf, RESP_PROTO, strlen(RESP_PROTO))) {
249
- netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO);
250
- return HTTP_PARSE_ERROR;
251
+ if (parse_ctx->state == HTTP_PARSE_PROXY_CONNECT) {
252
+ if (rbuf_memcmp_n(buf, RESP_PROTO10, strlen(RESP_PROTO10))) {
253
+ netdata_log_error(
254
+ "Expected response to start with \"%s\" or \"%s\"", RESP_PROTO, RESP_PROTO10);
255
+ return HTTP_PARSE_ERROR;
256
+ }
257
+ }
258
+ else {
259
+ netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO);
260
+ return HTTP_PARSE_ERROR;
261
+ }
262
}
263
rbuf_bump_tail(buf, strlen(RESP_PROTO));
264
if (rbuf_pop(buf, rc, 4) != 4) {
@@ -489,36 +500,36 @@ static int read_parse_response(https_req_ctx_t *ctx) {
500
return 0;
501
}
502
503
+static const char *http_methods[] = {
504
+ [HTTP_REQ_GET] = "GET ",
505
+ [HTTP_REQ_POST] = "POST ",
506
+ [HTTP_REQ_CONNECT] = "CONNECT ",
507
+};
508
+
509
+
510
#define TX_BUFFER_SIZE 8192
511
#define RX_BUFFER_SIZE (TX_BUFFER_SIZE*2)
512
static int handle_http_request(https_req_ctx_t *ctx) {
513
BUFFER *hdr = buffer_create(TX_BUFFER_SIZE, &netdata_buffers_statistics.buffers_aclk);
514
int rc = 0;
515
498
- http_parse_ctx_create(&ctx->parse_ctx);
516
+ http_req_type_t req_type = ctx->request->request_type;
517
500
- // Prepare data to send
501
- switch (ctx->request->request_type) {
502
- case HTTP_REQ_CONNECT:
503
- buffer_strcat(hdr, "CONNECT ");
504
- break;
505
- case HTTP_REQ_GET:
506
- buffer_strcat(hdr, "GET ");
507
- break;
508
- case HTTP_REQ_POST:
509
- buffer_strcat(hdr, "POST ");
510
- break;
511
- default:
512
- netdata_log_error("Unknown HTTPS request type!");
513
- rc = 1;
514
- goto err_exit;
518
+ if (req_type >= HTTP_REQ_INVALID) {
519
+ netdata_log_error("Unknown HTTPS request type!");
520
+ rc = 1;
521
+ goto err_exit;
522
}
523
+ buffer_strcat(hdr, http_methods[req_type]);
524
517
- if (ctx->request->request_type == HTTP_REQ_CONNECT) {
525
+ if (req_type == HTTP_REQ_CONNECT) {
526
buffer_strcat(hdr, ctx->request->host);
527
buffer_sprintf(hdr, ":%d", ctx->request->port);
520
- } else {
528
+ http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_PROXY_CONNECT);
529
+ }
530
+ else {
531
buffer_strcat(hdr, ctx->request->url);
532
+ http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_INITIAL);
533
}
534
535
buffer_strcat(hdr, HTTP_1_1 HTTP_ENDL);
@@ -527,7 +538,7 @@ static int handle_http_request(https_req_ctx_t *ctx) {
538
buffer_sprintf(hdr, "Host: %s\x0D\x0A", ctx->request->host);
539
buffer_strcat(hdr, "User-Agent: Netdata/rocks newhttpclient\x0D\x0A");
540
530
- if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
541
+ if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
542
buffer_sprintf(hdr, "Content-Length: %zu\x0D\x0A", ctx->request->payload_size);
543
}
544
if (ctx->request->proxy_username) {
@@ -558,7 +569,7 @@ static int handle_http_request(https_req_ctx_t *ctx) {
569
goto err_exit;
570
}
571
561
- if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
572
+ if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
573
if (https_client_write_all(ctx, ctx->request->payload, ctx->request->payload_size)) {
574
netdata_log_error("Couldn't write payload into SSL connection");
575
rc = 3;
src/aclk/https_client.h
+5
-3
@@ -11,7 +11,8 @@
11
typedef enum http_req_type {
12
HTTP_REQ_GET = 0,
13
HTTP_REQ_POST,
14
- HTTP_REQ_CONNECT
14
+ HTTP_REQ_CONNECT,
15
+ HTTP_REQ_INVALID
16
} http_req_type_t;
17
18
typedef struct {
@@ -82,7 +83,8 @@ int https_request(https_req_t *request, https_req_response_t *response);
83
// we expose previously internal parser as this is usefull also from
84
// other parts of the code
85
enum http_parse_state {
85
- HTTP_PARSE_INITIAL = 0,
86
+ HTTP_PARSE_PROXY_CONNECT = 0,
87
+ HTTP_PARSE_INITIAL,
88
HTTP_PARSE_HEADERS,
89
HTTP_PARSE_CONTENT
90
};
@@ -118,7 +120,7 @@ typedef struct {
120
size_t chunk_got;
121
} http_parse_ctx;
122
121
-void http_parse_ctx_create(http_parse_ctx *ctx);
123
+void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state);
124
void http_parse_ctx_destroy(http_parse_ctx *ctx);
125
126
typedef enum {
src/aclk/mqtt_websockets/mqtt_wss_client.c
+6
-3
@@ -314,6 +314,7 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
314
315
#define PROXY_CONNECT "CONNECT"
316
#define PROXY_HTTP "HTTP/1.1"
317
+#define PROXY_HTTP10 "HTTP/1.0"
318
#define HTTP_ENDLINE "\x0D\x0A"
319
#define HTTP_HDR_TERMINATOR "\x0D\x0A\x0D\x0A"
320
#define HTTP_CODE_LEN 4
@@ -326,14 +327,16 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
327
int idx;
328
329
if (rbuf_memcmp_n(buf, PROXY_HTTP, strlen(PROXY_HTTP))) {
329
- mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\"");
330
- return 1;
330
+ if (rbuf_memcmp_n(buf, PROXY_HTTP10, strlen(PROXY_HTTP10))) {
331
+ mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
332
+ return 1;
333
+ }
334
}
335
336
rbuf_bump_tail(buf, strlen(PROXY_HTTP));
337
338
if (!rbuf_pop(buf, http_code_s, 1) || http_code_s[0] != 0x20) {
336
- mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\"");
339
+ mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
340
return 2;
341
}
342
src/streaming/sender.c
+1
-1
@@ -672,7 +672,7 @@ static int rrdpush_http_upgrade_prelude(RRDHOST *host, struct sender_state *s) {
672
rbuf_push(buf, http, bytes);
673
674
http_parse_ctx ctx;
675
- http_parse_ctx_create(&ctx);
675
+ http_parse_ctx_create(&ctx, HTTP_PARSE_INITIAL);
676
ctx.flags |= HTTP_PARSE_FLAG_DONT_WAIT_FOR_CONTENT;
677
678
int rc;