miniroon

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

commit 04d3eebaceb4f0938023d15f2a7c77ad50076f1c
parent 4dcec9f36ce8974c08d79b5430bd3fdb9c31b0af
Author: Jan Pobrislo <ccx@te2000.cz>
Date:   Sun,  8 Dec 2024 06:12:20 +0000

Add error returncodes instead of dying outright

Diffstat:
Msrc/cmd_read.c | 20+++++---------------
Msrc/cmd_verify.c | 15++++++---------
Msrc/common.h | 2++
Msrc/decode.c | 22+++++++++++++---------
Msrc/decode.h | 3++-
Asrc/die_impl.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/errors.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/errors.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fd_util.c | 17+++++++++++++++++
Asrc/fd_util.h | 9+++++++++
Msrc/header.c | 27++++++++++++++++-----------
Msrc/header.h | 3++-
12 files changed, 288 insertions(+), 46 deletions(-)

diff --git a/src/cmd_read.c b/src/cmd_read.c @@ -12,27 +12,17 @@ #include <skalibs/stralloc.h> #include <skalibs/env.h> +#include "common.h" #include "netstring.h" #include "header.h" +#include "fd_util.h" #define USAGE "miniroon-read directory" #define PROG "miniroon-read" #define input_fd 0 -#define payload_size_max 1024*1024 -#define MAX_CAVEATS 256 -#define MAX_ENV_ALLOW 256 - -void fd_block(int fd) { - int flags = fcntl(fd, F_GETFL); - if(flags == -1) { - strerr_dief1sys(111, "fcntl() getfd"); - } - if(fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) { - strerr_dief1sys(111, "fcntl() setfd"); - } -} +#include "die_impl.h" size_t read_payload_size(int fd) { char read_char; @@ -40,7 +30,7 @@ size_t read_payload_size(int fd) { fd_block(fd); - while(payload_size < payload_size_max) { + while(payload_size < MAX_MINIROON_SIZE) { switch(read(fd, &read_char, 1)) { case 0: strerr_dief1x(111, "EOF before netstring size was read"); @@ -91,7 +81,7 @@ void read_payload(const bytebuffer bb) { } void process_header(miniroon_header *header, const bytebuffer source) { - parse_header(header, source); + die_on_error(parse_header(header, source)); char id[header->id.len + 1]; for(size_t i=0; i<header->id.len; i++) { diff --git a/src/cmd_verify.c b/src/cmd_verify.c @@ -16,6 +16,7 @@ #include <skalibs/stralloc.h> #include <skalibs/env.h> +#include "errors.h" #include "verify_common.h" #include "bytebuffer.h" #include "netstring.h" @@ -23,13 +24,15 @@ #include "caveats.h" #include "miniroon_data.h" #include "decode.h" +#include "fd_util.h" /* declarations */ void process_payload(const bytebuffer payload); void validate_and_exec(miniroon_data *data); +void die_on_error(miniroon_error e); /* definitions */ - +#include "die_impl.h" void validate_and_exec(miniroon_data *md) { miniroon_caveats_state state; @@ -54,19 +57,13 @@ void validate_and_exec(miniroon_data *md) { void process_payload(const bytebuffer payload) { miniroon_data md; - miniroon_decode(&md, payload); + die_on_error(miniroon_decode(&md, payload)); validate_and_exec(&md); strerr_dief1x(110, "Internal logic error, should not get here"); } void read_payload(int payload_fd, const bytebuffer bb) { - int flags = fcntl(payload_fd, F_GETFL); - if(flags == -1) { - strerr_dief1sys(111, "fcntl(payload_fd) getfd"); - } - if(fcntl(payload_fd, F_SETFL, flags & ~O_NONBLOCK) < 0) { - strerr_dief1sys(111, "fcntl(payload_fd) setfd"); - } + fd_block(payload_fd); ssize_t payload_read = fd_read(payload_fd, bb.data, bb.len); if(payload_read < 0 ) { diff --git a/src/common.h b/src/common.h @@ -1,6 +1,8 @@ #ifndef MINIROON_COMMON_H #define MINIROON_COMMON_H +#define MAX_MINIROON_SIZE 1024*1024 + #define MINIROON_HMAC_SIZE 32 //#define MINIROON_HMAC_FUNC(key, msg, out) hmac_b2s_256(key, msg, out) #define MINIROON_HMAC_FUNC(key, msg, out) hmac_sha2_256(key, msg, out) diff --git a/src/decode.c b/src/decode.c @@ -6,15 +6,17 @@ #include "secret.h" #include "hmac_sha2_256.h" -void miniroon_decode(miniroon_data *md, const bytebuffer encoded) { +miniroon_error miniroon_decode(miniroon_data *md, const bytebuffer encoded) { miniroon_data_init(md); netstring_chunk c; netstring_chunk_init(&c, encoded); if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising miniroon header"); + return miniroon_err1(MINIROON_EDEC_NO_HEADER, "Mising miniroon header"); + } + if(parse_header(&md->hdr, c.inner) != MINIROON_OK) { + return miniroon_current_error; } - parse_header(&md->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}; @@ -24,7 +26,7 @@ void miniroon_decode(miniroon_data *md, const bytebuffer encoded) { // dbg_print_bb1("Signature update", hmac_bb); if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising miniroon body"); + return miniroon_err1(MINIROON_EDEC_NO_BODY, "Mising miniroon body"); } netstring_chunk body; netstring_chunk_init(&body, c.inner); @@ -32,7 +34,7 @@ void miniroon_decode(miniroon_data *md, const bytebuffer encoded) { while(netstring_chunk_next(&body)) { dbg_print_bb1("Got caveat", body.inner); if(md->caveat_count >= MAX_CAVEATS) { - strerr_dief1x(111, "Too many caveats"); + return miniroon_err1(MINIROON_EDEC_MANY_CAVEATS, "Too many caveats"); } md->caveats[md->caveat_count++] = body.inner; MINIROON_HMAC_FUNC(hmac_bb, body.inner, hmac_bb); @@ -40,11 +42,11 @@ void miniroon_decode(miniroon_data *md, const bytebuffer encoded) { } if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising miniroon signature"); + return miniroon_err1(MINIROON_EDEC_NO_SIGNATURE, "Mising miniroon signature"); } dbg_print_bb1("Got signature", c.inner); if(c.inner.len != MINIROON_HMAC_SIZE) { - strerr_dief1x(111, "Invalid miniroon signature length"); + return miniroon_err1(MINIROON_EDEC_INV_SIGNATURE, "Invalid miniroon signature length"); } /* constant time hash compare */ uint8_t bitdiff = 0; @@ -52,9 +54,11 @@ void miniroon_decode(miniroon_data *md, const bytebuffer encoded) { bitdiff |= hmac_data[i] ^ c.inner.data[i]; } if(netstring_chunk_next(&c)) { - strerr_dief1x(111, "Extraneous data in miniroon"); + return miniroon_err1(MINIROON_EDEC_EXTRA, "Extraneous data in miniroon"); } if(bitdiff) { - strerr_dief1x(111, "Invalid miniroon signature"); + return miniroon_err1(MINIROON_EDEC_BAD_SIGNATURE, "Bad miniroon signature"); } + + return MINIROON_OK; } diff --git a/src/decode.h b/src/decode.h @@ -4,10 +4,11 @@ // implementation: // {IMP} decode.c +#include "errors.h" #include "bytebuffer.h" #include "netstring.h" #include "miniroon_data.h" -void miniroon_decode(miniroon_data *md, const bytebuffer encoded); +miniroon_error miniroon_decode(miniroon_data *md, const bytebuffer encoded); #endif diff --git a/src/die_impl.h b/src/die_impl.h @@ -0,0 +1,48 @@ +#ifndef MINIROON_DIE_IMPL_H +#define MINIROON_DIE_IMPL_H + +#include <assert.h> + +#include <skalibs/strerr.h> + +#include "errors.h" + +void die_on_error(miniroon_error e) { + assert(e == miniroon_current_error); + if(e == MINIROON_OK) { + return; + } + + assert(miniroon_errmsg_count <= 8 ); + switch(miniroon_errmsg_count) { + case 1: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0]); + break; + case 2: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1]); + break; + case 3: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2]); + break; + case 4: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2], miniroon_errmsg[3]); + break; + case 5: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2], miniroon_errmsg[3], miniroon_errmsg[4]); + break; + case 6: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2], miniroon_errmsg[3], miniroon_errmsg[4], miniroon_errmsg[5]); + break; + case 7: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2], miniroon_errmsg[3], miniroon_errmsg[4], miniroon_errmsg[5], miniroon_errmsg[6]); + break; + case 8: + strerr_diefn(111, miniroon_errmsg_count, miniroon_errmsg[0], miniroon_errmsg[1], miniroon_errmsg[2], miniroon_errmsg[3], miniroon_errmsg[4], miniroon_errmsg[5], miniroon_errmsg[6], miniroon_errmsg[7]); + break; + default: + strerr_diefn(111, 1, "[no error message provided]"); + break; + } +} + +#endif diff --git a/src/errors.c b/src/errors.c @@ -0,0 +1,120 @@ +#include <stddef.h> + +#include "errors.h" + +miniroon_error miniroon_current_error = 0; +char const *miniroon_errmsg[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +unsigned char miniroon_errmsg_count = 0; + +miniroon_error miniroon_err1(miniroon_error e, char const* const m1) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = NULL; + miniroon_errmsg[2] = NULL; + miniroon_errmsg[3] = NULL; + miniroon_errmsg[4] = NULL; + miniroon_errmsg[5] = NULL; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 1; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err2(miniroon_error e, char const* const m1, char const* const m2) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = NULL; + miniroon_errmsg[3] = NULL; + miniroon_errmsg[4] = NULL; + miniroon_errmsg[5] = NULL; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 2; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err3(miniroon_error e, char const* const m1, char const* const m2, char const* const m3) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = NULL; + miniroon_errmsg[4] = NULL; + miniroon_errmsg[5] = NULL; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 3; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err4(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = m4; + miniroon_errmsg[4] = NULL; + miniroon_errmsg[5] = NULL; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 4; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err5(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = m4; + miniroon_errmsg[4] = m5; + miniroon_errmsg[5] = NULL; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 5; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err6(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5, char const* const m6) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = m4; + miniroon_errmsg[4] = m5; + miniroon_errmsg[5] = m6; + miniroon_errmsg[6] = NULL; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 6; + miniroon_current_error = e; + return e; +} + +miniroon_error miniroon_err7(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5, char const* const m6, char const* const m7) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = m4; + miniroon_errmsg[4] = m5; + miniroon_errmsg[5] = m6; + miniroon_errmsg[6] = m7; + miniroon_errmsg[7] = NULL; + miniroon_errmsg_count = 7; + miniroon_current_error = e; + return e; +} + + +miniroon_error miniroon_err8(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5, char const* const m6, char const* const m7, char const* const m8) { + miniroon_errmsg[0] = m1; + miniroon_errmsg[1] = m2; + miniroon_errmsg[2] = m3; + miniroon_errmsg[3] = m4; + miniroon_errmsg[4] = m5; + miniroon_errmsg[5] = m6; + miniroon_errmsg[6] = m7; + miniroon_errmsg[7] = m8; + miniroon_errmsg_count = 8; + miniroon_current_error = e; + return e; +} diff --git a/src/errors.h b/src/errors.h @@ -0,0 +1,48 @@ +#ifndef MINIROON_ERRORS_H +#define MINIROON_ERRORS_H + +// implementation: +// {IMP} errors.c + +typedef enum miniroon_error_e { + MINIROON_OK = 0, + + MINIROON_ENST_NO_COLON, + MINIROON_ENST_NO_COMMA, + MINIROON_ENST_TRUNCATED, + + MINIROON_EENM_INV_VAR_NAME, + MINIROON_EENM_INV_VAR_VALUE, + MINIROON_EENM_EXEC, + + MINIROON_EHDR_INV_VERSION, + MINIROON_EHDR_INV_ACTION, + MINIROON_EHDR_NO_VERSION, + MINIROON_EHDR_NO_ID, + MINIROON_EHDR_NO_ACTION, + MINIROON_EHDR_EXTRA, + + MINIROON_EDEC_NO_HEADER, + MINIROON_EDEC_NO_BODY, + MINIROON_EDEC_MANY_CAVEATS, + MINIROON_EDEC_NO_SIGNATURE, + MINIROON_EDEC_INV_SIGNATURE, + MINIROON_EDEC_EXTRA, + MINIROON_EDEC_BAD_SIGNATURE, + + MINIROON_EMAX +} miniroon_error; + +extern miniroon_error miniroon_current_error; +extern char const *miniroon_errmsg[8]; +extern unsigned char miniroon_errmsg_count; + +miniroon_error miniroon_err1(miniroon_error e, char const* const m1); +miniroon_error miniroon_err2(miniroon_error e, char const* const m1, char const* const m2); +miniroon_error miniroon_err3(miniroon_error e, char const* const m1, char const* const m2, char const* const m3); +miniroon_error miniroon_err4(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4); +miniroon_error miniroon_err5(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5); +miniroon_error miniroon_err6(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5, char const* const m6); +miniroon_error miniroon_err7(miniroon_error e, char const* const m1, char const* const m2, char const* const m3, char const* const m4, char const* const m5, char const* const m6, char const* const m7); + +#endif diff --git a/src/fd_util.c b/src/fd_util.c @@ -0,0 +1,17 @@ +#include <fcntl.h> + +#include <skalibs/strerr.h> + +#include "fd_util.h" + +void fd_block(int fd) { + int flags = fcntl(fd, F_GETFL); + if(flags == -1) { + strerr_dief1sys(111, "fcntl() getfd"); + } + if(fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) { + strerr_dief1sys(111, "fcntl() setfd"); + } +} + + diff --git a/src/fd_util.h b/src/fd_util.h @@ -0,0 +1,9 @@ +#ifndef MINIROON_FD_UTIL_H +#define MINIROON_FD_UTIL_H + +// implementation: +// {IMP} fd_util.c + +void fd_block(int fd); + +#endif diff --git a/src/header.c b/src/header.c @@ -3,15 +3,15 @@ #include "netstring.h" #include "header.h" -void set_header_version(miniroon_header *header, const bytebuffer source) { +miniroon_error set_header_version(miniroon_header *header, const bytebuffer source) { if(strbbcmp(source, "capv0") == 0) { header->version = V0; } else { - strerr_dief1x(111, "Unhandled miniroon version"); + return miniroon_err1(MINIROON_EHDR_INV_VERSION, "Unhandled miniroon version"); } } -void set_header_action(miniroon_header *header, const bytebuffer source) { +miniroon_error set_header_action(miniroon_header *header, const bytebuffer source) { if(strbbcmp(source, "revoke") == 0) { header->action = REVOKE; } else if(strbbcmp(source, "invoke") == 0) { @@ -19,37 +19,42 @@ void set_header_action(miniroon_header *header, const bytebuffer source) { } else if(strbbcmp(source, "invoke-once") == 0) { header->action = INVOKE_ONCE; } else { - strerr_dief1x(111, "Unhandled miniroon action"); + return miniroon_err1(MINIROON_EHDR_INV_ACTION, "Unhandled miniroon action"); } } -void parse_header(miniroon_header *header, const bytebuffer source) { +miniroon_error parse_header(miniroon_header *header, const bytebuffer source) { dbg_print_bb1("Got header", source); netstring_chunk c; netstring_chunk_init(&c, source); if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising version in miniroon header"); + return miniroon_err1(MINIROON_EHDR_NO_VERSION, "Mising version in miniroon header"); } dbg_print_bb1("Header > Version", c.inner); - set_header_version(header, c.inner); + if(set_header_version(header, c.inner) != MINIROON_OK) { + return miniroon_current_error; + } if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising ID in miniroon header"); + return miniroon_err1(MINIROON_EHDR_NO_ID, "Mising ID in miniroon header"); } dbg_print_bb1("Header > ID", c.inner); header->id = c.inner; if(!netstring_chunk_next(&c)) { - strerr_dief1x(111, "Mising action in miniroon header"); + return miniroon_err1(MINIROON_EHDR_NO_ACTION, "Mising action in miniroon header"); } dbg_print_bb1("Header > Action", c.inner); - set_header_action(header, c.inner); + if(set_header_action(header, c.inner) != MINIROON_OK) { + return miniroon_current_error; + } if(netstring_chunk_next(&c)) { - strerr_dief1x(111, "Extraneous data in miniroon header"); + return miniroon_err1(MINIROON_EHDR_EXTRA, "Extraneous data in miniroon header"); } + return MINIROON_OK; } /* vim: sts=2 sw=2 et diff --git a/src/header.h b/src/header.h @@ -4,6 +4,7 @@ // implementation: // {IMP} header.c +#include "errors.h" #include "bytebuffer.h" typedef struct miniroon_header_s { @@ -19,6 +20,6 @@ typedef struct miniroon_header_s { } miniroon_header; -void parse_header(miniroon_header *header, const bytebuffer source); +miniroon_error parse_header(miniroon_header *header, const bytebuffer source); #endif