summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose M. Guisado <jguisado@soleta.eu>2023-06-05 18:15:58 +0200
committerJose M. Guisado <jguisado@soleta.eu>2023-06-13 14:04:54 +0200
commitd2c19ef13d73b92b94a29e2b226d76347d36374e (patch)
tree8b3a6fe6eb57c0f22f1a18f105b41ced35cfaef8
parent92f83c0385281c1d1e7996fc76c071e782ea6939 (diff)
core: add X-Sequence header supportv1.2.2
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.
-rw-r--r--src/core.c15
-rw-r--r--src/rest.c22
-rw-r--r--src/rest.h1
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;
};