~rbdr/tiny-command-pal

Remotely request command execution
ef51091a — Ruben Beltran del Rio 3 months ago
Constraint max payload length to 3 bytes
511d8518 — Ruben Beltran del Rio 3 months ago
Add tables of the commands
22d0966e — Ruben Beltran del Rio 3 months ago
Add license

refs

main
browse  log 

clone

read-only
https://git.sr.ht/~rbdr/tiny-command-pal
read/write
git@git.sr.ht:~rbdr/tiny-command-pal

You can also use your local clone with git send-email.

#tiny-command-pal (tcpal)

A server that listens for a signed command and payload, and executes a local command based on it. It's intended to be used on very low bandwidth networks.

#Configuration

tcpal is configured using a TOML located in XDG_CONFIG_HOME called tcpal.toml

A typical tcpal config looks like this

[publish_blog]
command = 'echo {{payload}} > ~/posts/incoming.gmi && blog --add ~/posts/incoming.gmi'
authorized_keys = [
    ssh-ed25519 AAAA...ZZZ ruben
]
authorized_hosts = [
    192.168.1.10,
    192.168.0.0/24
]
  • command is the command to execute. {{payload}} will be replaced with the contents of the signed payload. Can't be longer than 255 bytes.
  • authorized_keys is an array of public ed25519 keys that are allowed to run this command.
  • authorized_hosts is an array of hosts that are authorized to run this command. 0.0.0.0 is not allowed.

At least one entry is required in both of the authorized arrays, otherwise the command won't be executed.

#The Process

TBD

#The Messages

  • Message IDs 00-79 are reserved for clients.
  • Message IDs 80-FF are reserved for servers.

#The Authorization Check Message (0x00)

This command is used to confirm whether the current host is authorized to send the given command. While not necessary, it is recommended that clients do this to avoid sending the payload without confirming the identity of the server, and whether the command is allowed.

## Header, 4 bytes
1. Magic Byte (0x7C), 1 byte
2. Authorization Check Message Flag (0x00), 1 byte
3. Length of command in bytes (0x00-0xFF), 1 byte
4. Start of Text Byte (0x02), 1 byte
## The Command (Variable)
1. The command, Up to 255 bytes in length, must correspond to the value in header field 3
2. Unit Separator Byte (0x1F), 1 byte
3. The signature of the command, signed by a private ed25519 key, 64 bytes
4. End of Text Byte (0x03), 1 byte
## Footer, 1 byte
1. End of Transmission Byte (0x04), 1 byte
All numbers in hexadecimal.
┌───────────────────┬──────────────────────────────────┬────┐
│      HEADER       │               BODY               │FOOT│
├────┬────┬────┬────┼────┬─────────┬────┬────┬────┬────┼────┤
│ 00 │ 01 │ 02 │ 03 │ 04 ┊ A+CLEN  │B+01│B+02┊B+41│B+42│B+43│
├────┼────┼────┼────┼────┴─────────┼────┼────┴────┼────┼────┤
│ 7C │ 00 │CLEN│ 02 │   COMMAND    │ 1F │SIGNATURE│ 03 │ 04 │
└────┴────┴────┴────┼──────────────┼────┴─────────┴────┴────┘
                   A              B

#The Authorization Response Message (0x80)

Sent as a response of the 0x00 message. It includes the authorization status of the client for the given command, as well as the signature of the command signed by the server.

This signature should be used to confirm whether the client is talking to the right server. This is left up to the client and can be strict (eg. only accept responses from servers whose public key we have authorized before), flexible (eg. accept the first signature and ensure a server keeps the same signature), or it may choose to ignore this value completely.

## Header, 3 bytes
1. Magic Byte (0x7C), 1 byte
2. Authorization Response Message Flag (0x80), 1 byte
3. Start of Text Byte (0x02), 1 byte
## The Command, 67 bytes
1. Authorization Response Code (0x00-0xFF), 1 byte
2. Record Separator Byte (0x1E), 1 byte
3. The signature of the command, signed by the server's private ed25519 key, 64 bytes
4. End of Text Byte (0x03), 1 byte
## Footer, 1 byte
4. End of Transmission Byte (0x04), 1 byte
All numbers in hexadecimal.
┌──────────────┬────────────────────────┬────┐
│    HEADER    │          BODY          │FOOT│
├────┬────┬────┼────┬────┬────┬────┬────┼────┤
│ 00 │ 01 │ 02 │ 03 ┊ 04 │ 05 ┊ 44 │ 45 ┊ 41 │
├────┼────┼────┼────┼────┼────┴────┼────┼────┤
│ 7C │ 80 │ 02 │AUTH│ 1E │SIGNATURE│ 03 │ 04 │
└────┴────┴────┴────┴────┴─────────┴────┴────┘

The codes are as follows:

  • 00 Authorized
  • 40 Unrecognized Command
  • 41 Unauthorized Host
  • 42 Unauthorized Key
  • 50 Unknown Error

#The Command Message (0x01)

This is an actual command.

## Header, 7 bytes
1. Magic Byte (0x7C), 1 byte
2. Command Message Flag (0x01), 1 byte
3. Length of command in bytes (0x00-0xFF), 1 byte
4. Length of payload (0x000000-0xFFFFFF), 3 bytes
5. Start of Text Byte (0x02), 1 byte
## The Command (Variable)
1. The command, Up to 255 bytes in length, must correspond to the value in header field 3
2. Unit Separator Byte (0x1F), 1 byte
3. The signature of the command, signed by a private ed25519 key, 64 bytes
4. Record Separator Byte (0x1E), 1 byte
## The Payload (Variable)
1. The payload, up to 16,777,215 bytes in length, must correspond to the value in header field 4.
2. Unit Separator Byte (0x1F)
3. The signature of the payload, signed by the same private ed25519 key as the command, 64 bytes
4. End of Text Byte (0x03), 1 byte
## Footer, 1 byte
2. End of Transmission Byte (0x04), 1 byte
All numbers in hexadecimal.
┌─────────────────────────────┬─────────────────────────────────────────────────────────────────────┬────┐
│           HEADER            │               BODY                               BODY               │FOOT│
├────┬────┬────┬────┬────┬────┼────┬─────────┬────┬────┬────┬────┬────┬─────────┬────┬────┬────┬────┼────┤
│ 00 │ 01 │ 02 │ 03 ┊ 05 │ 06 │ 07 ┊ A+CLEN  │B+01│B+02┊B+41│B+42│B+43┊B+42+PLEN│C+01│C+02┊C+41│C+42│C+43│
├────┼────┼────┼────┴────┼────┼────┴─────────┼────┼────┴────┼────┼────┴─────────┼────┼────┴────┼────┼────┤
│ 7C │ 01 │CLEN│   PLEN  │ 02 │   COMMAND    │ 1F │SIGNATURE│ 1E │   PAYLOAD    │ 1F │SIGNATURE│ 03 │ 04 │
└────┴────┴────┴─────────┴────┼──────────────┼────┴─────────┴────┴──────────────┼────┴─────────┴────┴────┘
                             A              B                                  C

#The Command Result Message (0x81)

Sent as a response to an 0x01 command, it includes the authorization code, the exit status of the command, and the signature of the command sent.

If authorization is anything other than 0x00, then exit status will always be 0x00.

## Header, 3 bytes
1. Magic Byte (0x7C), 1 byte
2. Command Result Message Flag (0x81), 1 byte
3. Start of Text Byte (0x02), 1 byte
## Body, 69 Bytes
1. Authorization Response Code (0x00-0xFF), 1 byte
2. Record Separator Byte (0x1E), 1 byte
3. Command Exit Status Code (0x00-0xFF), 1 byte
4. Record Separator Byte (0x1E), 1 byte
5. The signature of the command, signed by the server's private ed25519 key, 64 bytes
6. End of Text Byte (0x03), 1 byte
## Footer, 1 byte
1. End of Transmission Byte (0x04), 1 byte
All numbers in hexadecimal.
┌──────────────┬──────────────────────────────────┬────┐
│    HEADER    │          BODY                    │FOOT│
├────┬────┬────┼────┬────┬────┬────┬────┬────┬────┼────┤
│ 00 │ 01 │ 02 │ 03 ┊ 04 │ 05 ┊ 06 │ 07 ┊ 46 │ 47 ┊ 48 │
├────┼────┼────┼────┼────┼────┼────┼────┴────┼────┼────┤
│ 7C │ 81 │ 02 │AUTH│ 1E │CODE│ 1E │SIGNATURE│ 03 │ 04 │
└────┴────┴────┴────┴────┴────┴────┴─────────┴────┴────┘

The authorization codes are the same as for the authorization response message.