From d2c19ef13d73b92b94a29e2b226d76347d36374e Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado" Date: Mon, 5 Jun 2023 18:15:58 +0200 Subject: core: add X-Sequence header support Add non-standard HTTP header "X-Sequence" to the header section of requests (og_send_request) sent to a connected client. Define a starting sequence number when creating a new instance of struct og_client inside og_server_accept_cb. This sequence number is incremented by one for each outgoing request from ogServer. This sequence number is checked when receiving a response from a connected client, if they do not match the connection is dropped. Use sequence 0 for out-of-band commands (reboot, poweroff, stop). Any client response with header "X-Sequence: 0" bypasses sequence check. --- src/core.c | 15 +++++++++++++++ src/rest.c | 22 +++++++++++++++++++--- src/rest.h | 1 + 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/core.c b/src/core.c index 8b2832a..bb76df0 100644 --- a/src/core.c +++ b/src/core.c @@ -160,6 +160,7 @@ enum og_agent_state { static int og_agent_state_recv_hdr_rest(struct og_client *cli) { + uint32_t seq; char *ptr; ptr = strstr(cli->buf, "\r\n\r\n"); @@ -176,6 +177,20 @@ static int og_agent_state_recv_hdr_rest(struct og_client *cli) cli->msg_len += cli->content_length; } + ptr = strstr(cli->buf, "X-Sequence: "); + if (ptr) { + if (sscanf(ptr, "X-Sequence: %i[^\r\n]", &seq) != 1) { + syslog(LOG_ERR, "Invalid sequence value from client %s. Payload:\n%s", + inet_ntoa(cli->addr.sin_addr), cli->buf); + return -1; + } + if (cli->seq != 0 && cli->seq != seq) { + syslog(LOG_ERR, "Unexpected sequence %u from client %s, expecting %u.", + seq, inet_ntoa(cli->addr.sin_addr), cli->seq); + return -1; + } + } + return 1; } diff --git a/src/rest.c b/src/rest.c index 1f35174..ff51332 100644 --- a/src/rest.c +++ b/src/rest.c @@ -296,6 +296,7 @@ int og_send_request(enum og_rest_method method, enum og_cmd_type type, const char *uri; unsigned int i; int client_sd; + bool has_seq; if (method == OG_METHOD_GET) snprintf(method_str, 5, "GET"); @@ -312,9 +313,17 @@ int og_send_request(enum og_rest_method method, enum og_cmd_type type, JSON_COMPACT); uri = og_cmd_to_uri[type]; - snprintf(buf, OG_MSG_REQUEST_MAXLEN, - "%s /%s HTTP/1.1\r\nContent-Length: %d\r\n%s\r\n\r\n%s", - method_str, uri, content_length, content_type, content); + + switch (type) { + case OG_CMD_POWEROFF: + case OG_CMD_REBOOT: + case OG_CMD_STOP: + has_seq = false; + break; + default: + has_seq = true; + break; + } for (i = 0; i < params->ips_array_len; i++) { cli = og_client_find(params->ips_array[i]); @@ -331,6 +340,13 @@ int og_send_request(enum og_rest_method method, enum og_cmd_type type, continue; } + if (++cli->seq == 0) + cli->seq++; + + snprintf(buf, OG_MSG_REQUEST_MAXLEN, + "%s /%s HTTP/1.1\r\nContent-Length: %d\r\nX-Sequence: %u\r\n%s\r\n\r\n%s", + method_str, uri, content_length, has_seq ? cli->seq : 0, content_type, content); + if (send(client_sd, buf, strlen(buf), 0) < 0) continue; diff --git a/src/rest.h b/src/rest.h index df6b225..d146868 100644 --- a/src/rest.h +++ b/src/rest.h @@ -68,6 +68,7 @@ struct og_client { enum og_cmd_result last_cmd_result; bool autorun; uint32_t speed; + uint32_t seq; const char *shell_output; }; -- cgit v1.2.3-18-g5258