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.
master v1.2.2
Jose M. Guisado 2023-06-05 18:15:58 +02:00
parent 92f83c0385
commit d2c19ef13d
3 changed files with 35 additions and 3 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
};