miniroon

Simplistic macaroon-based authorization for Unix systems
git clone https://ccx.te2000.cz/git/miniroon
Log | Files | Refs

commit eec7d2a4e3e007a7f1276a76d16bac88a2eca93b
parent abfe7b684aa2e46ca308c2ccae3a4f8ea010f64c
Author: Jan Pobrislo <ccx@te2000.cz>
Date:   Wed,  9 Oct 2024 11:36:49 +0000

miniroon: refactor into reading and processing phases

Diffstat:
Msrc/miniroon.c | 131+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
1 file changed, 74 insertions(+), 57 deletions(-)

diff --git a/src/miniroon.c b/src/miniroon.c @@ -19,6 +19,8 @@ #define input_fd 0 #define payload_size_max 1024*1024 +#define MAX_CAVEATS 256 +#define MAX_ENV_ALLOW 256 typedef struct bytebuffer_s { char *data; @@ -44,12 +46,20 @@ typedef struct miniroon_header_s { } miniroon_header; +typedef struct miniroon_data_s { + miniroon_header hdr; + bytebuffer env_allow[MAX_ENV_ALLOW]; + bytebuffer caveats[MAX_CAVEATS]; + size_t env_count; + size_t caveat_count; +} miniroon_data; + /* declarations */ void dbg_print_bb(const bytebuffer bb); void dbg_print_bb1(const char *text, const bytebuffer bb); -void parse_payload(const bytebuffer payload); -void parse_header(miniroon_header *header, const bytebuffer source); -void parse_caveat(const bytebuffer source); // TODO +void process_payload(const bytebuffer payload); +void process_header(miniroon_header *header, const bytebuffer source); +void process_caveat(const bytebuffer source); // TODO void read_secret(const bytebuffer secret); // TODO void hmac_b2s_256(const bytebuffer key, const bytebuffer msg, const bytebuffer output); void hmac_sha2_256(const bytebuffer key, const bytebuffer msg, const bytebuffer output); @@ -104,6 +114,10 @@ void netstring_chunk_init (netstring_chunk *chunk, const bytebuffer source) { } bool netstring_chunk_next (netstring_chunk *c) { + // bytebuffer dbg_bb = {(void*)c, sizeof(netstring_chunk)}; + // dbg_print_bb1("netstring chunk", dbg_bb); + // dbg_print_bb1("netstring source", c->source); + if(!c->source.len) { return false; } @@ -112,18 +126,19 @@ bool netstring_chunk_next (netstring_chunk *c) { if (c->source.data[c->outer.len] != ':') { strerr_dief1x(111, "Malformed netstring (expected ':')"); } - if (c->outer.len + c->inner.len >= c->source.len) { + if (c->outer.len + c->inner.len + 2 > c->source.len) { strerr_dief1x(111, "Malformed netstring (truncated)"); } if (c->source.data[c->outer.len + c->inner.len + 1] != ',') { strerr_dief1x(111, "Malformed netstring (expected ',')"); } + assert(c->source.len >= c->outer.len); c->inner.data = &c->source.data[c->outer.len + 1]; c->outer.len += c->inner.len + 2; c->source.data += c->outer.len; c->source.len -= c->outer.len; - // dbg_print_bb1("Chunk > Outer", &c->outer); - // dbg_print_bb1("Chunk > Inner", &c->inner); + // dbg_print_bb1("Chunk > Outer", c->outer); + // dbg_print_bb1("Chunk > Inner", c->inner); return true; } @@ -162,7 +177,7 @@ void set_header_action(miniroon_header *header, const bytebuffer source) { } } -void parse_header(miniroon_header *header, const bytebuffer source) { +void process_header(miniroon_header *header, const bytebuffer source) { dbg_print_bb1("Got header", source); netstring_chunk c; netstring_chunk_init(&c, source); @@ -205,12 +220,11 @@ void parse_header(miniroon_header *header, const bytebuffer source) { } -void handle_payload(size_t payload_size) { - char payload[payload_size+1]; - char *read_next = payload; +void read_payload(const bytebuffer bb) { + char *read_next = bb.data; ssize_t read_size; - while(read_next - payload < payload_size + 1) { - read_size = read(input_fd, read_next, payload_size + 1 - (read_next - payload)); + while(read_next - bb.data < bb.len) { + read_size = read(input_fd, read_next, bb.len - (read_next - bb.data)); if(read_size == 0) { strerr_dief1x(111, "EOF before full netstring payload was read"); } @@ -222,22 +236,17 @@ void handle_payload(size_t payload_size) { } read_next += read_size; } - if(payload[payload_size] != ',') { + if(bb.data[bb.len - 1] != ',') { strerr_dief1x(111, "Invalid netstring terminator"); } - - bytebuffer payload_bb = {payload, payload_size}; - dbg_print_bb1("Got payload", payload_bb); - parse_payload(payload_bb); } -void parse_caveat(const bytebuffer source) { +void process_caveat(const bytebuffer source) { // TODO } void read_secret(const bytebuffer secret){ assert(secret.len == MINIROON_HMAC_SIZE); - // memset(secret.data, 0, secret.len); size_t bytes_read = 0; int secret_fd = open("secret", O_RDONLY); if (secret_fd < 0) { @@ -262,15 +271,15 @@ void read_secret(const bytebuffer secret){ } } -void parse_payload(const bytebuffer payload) { +void process_payload(const bytebuffer payload) { + miniroon_data m; netstring_chunk c; netstring_chunk_init(&c, payload); if(!netstring_chunk_next(&c)) { strerr_dief1x(111, "Mising miniroon header"); } - miniroon_header hdr; - parse_header(&hdr, c.inner); + process_header(&m.hdr, c.inner); // header should be verified by now, we can start hashing uint8_t hmac_data[MINIROON_HMAC_SIZE]; bytebuffer hmac_bb = {hmac_data, MINIROON_HMAC_SIZE}; @@ -287,7 +296,7 @@ void parse_payload(const bytebuffer payload) { while(netstring_chunk_next(&body)) { dbg_print_bb1("Got caveat", body.inner); - parse_caveat(body.inner); + process_caveat(body.inner); MINIROON_HMAC_FUNC(hmac_bb, body.inner, hmac_bb); // dbg_print_bb1("Signature update", hmac_bb); } @@ -403,49 +412,20 @@ void hmac_sha2_256(const bytebuffer key, const bytebuffer msg, bytebuffer output dbg_print_bb1("HMAC output", output); } -/* -capability ``` -container/bzr.ccx/123456 -login/tty1/7890 -``` -- secret -- execline command -- env allowlist (re?) -- max execution count/id (uuidv7?) - -``` -caphdr = [capv0;name;invoke-once] -c1 = [caphdr;;h1=hmac(secret, caphdr)] -c2 = [caphdr;[att1];h2=hmac(h1, att1)] -c3 = [caphdr;[att1;att2];h3=hmac(h2, att2)] -``` -*/ - -int main (int argc, char const *const *argv) -{ +size_t read_payload_size(int fd) { char read_char; size_t payload_size = 0; - if (argc != 2) { - strerr_dieusage(100, USAGE); - } - - if (chdir(argv[1]) != 0) { - strerr_dief1sys(111, "chdir()"); - } - - fd_block(input_fd); + fd_block(fd); while(payload_size < payload_size_max) { - switch(read(input_fd, &read_char, 1)) { + switch(read(fd, &read_char, 1)) { case 0: strerr_dief1x(111, "EOF before netstring size was read"); break; case 1: if(read_char == ':') { - handle_payload(payload_size); - strerr_dief1x(110, "Internal logic error, should not get here"); - return 1; + return payload_size; } else if(read_char >= '0' && read_char <= '9') { payload_size *= 10; payload_size += read_char - '0'; @@ -465,8 +445,45 @@ int main (int argc, char const *const *argv) } strerr_dief1x(111, "Input netstring too big"); - return 111; } +int main (int argc, char const *const *argv) +{ + + if (argc != 2) { + strerr_dieusage(100, USAGE); + } + + if (chdir(argv[1]) != 0) { + strerr_dief1sys(111, "chdir()"); + } + size_t payload_size = read_payload_size(input_fd); + char payload_data[payload_size + 1]; + bytebuffer payload = {payload_data, payload_size + 1}; + read_payload(payload); + payload.len -= 1; /* strip final netstring terminator */ + dbg_print_bb1("Got payload", payload); + process_payload(payload); + strerr_dief1x(110, "Internal logic error, should not get here"); + return 110; +} +/* +capability ``` +container/bzr.ccx/123456 +login/tty1/7890 +``` +- secret +- execline command +- env allowlist (re?) +- max execution count/id (uuidv7?) + +``` +caphdr = [capv0;name;invoke-once] +c1 = [caphdr;;h1=hmac(secret, caphdr)] +c2 = [caphdr;[att1];h2=hmac(h1, att1)] +c3 = [caphdr;[att1;att2];h3=hmac(h2, att2)] +``` +*/ + /* vim: sts=2 sw=2 et */