miniroon

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

commit 570ad8dc58ee32d83fc1108a08ad23cf6876ef38
parent f29bb200c1fb86697c4bbda34fbd96c21c169767
Author: Jan Pobrislo <ccx@te2000.cz>
Date:   Tue, 30 Jul 2024 18:18:15 +0000

Add WIP miniroon implementation.

Diffstat:
Asrc/miniroon.c | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+), 0 deletions(-)

diff --git a/src/miniroon.c b/src/miniroon.c @@ -0,0 +1,134 @@ +#include <errno.h> +#include <unistd.h> +#include <sys/select.h> + +#include <skalibs/types.h> +#include <skalibs/strerr.h> +#include <skalibs/djbunix.h> +#include <skalibs/exec.h> +#include <skalibs/netstring.h> +#include <skalibs/uint64.h> + +#define USAGE "macrun directory" +#define PROG "macrun" + +#define input_fd 0 +#define payload_size_max 1024*1024 + +typedef struct { + char *data; + size_t len; +} bytebuffer_t; + +int netstring_get_chunk (const bytebuffer_t *input, bytebuffer_t *chunk, bytebuffer_t *rest) +{ + uint64_t nlen; /* size of payload */ + size_t pos; /* size of numerical prefix */ + if (!input->len) { + return 0; + } + pos = uint64_scan(input->start, &nlen) ; + if (pos >= input->len) { + return 0; + } + if (input->start[pos] != ':') { + return 0; + } + char const *s = input->start + pos + 1; /* start of payload */ + if (len <= nlen + pos + 1) { + return 0; + } + if (s[nlen] != ',') { + return 0; + } + if (chunk != NULL) { + chunk->data = s; + chunk->len = nlen; + } + if (rest != NULL) { + chunk->data = s + 1; + chunk->len = input->len - nlen - pos - 2; + } + return 1; +} + +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"); + } +} + +int handle_payload(size_t payload_size) { + char payload[payload_size+1]; + char *read_next = payload; + ssize_t read_size; + while(read_next - payload < payload_size + 1) { + read_size = read(input_fd, read_next, payload_size + 1 - (read_next - payload)); + if(read_size == 0) { + strerr_dief1x(111, "EOF before full netstring payload was read"); + } + if(read_size == -1) { + if(errno != EINTR) { + strerr_dief1sys(111, "read()"); + } + continue; + } + read_next += read_size; + } + if(payload[payload_size] != ',') { + strerr_dief1x(111, "Invalid netstring terminator"); + } + + bytebuffer_t input, chunk, next; + next.data = payload; + next.len = payload_size; + + while(next.len) { + input = next; + if(!netstring_get_chunk(&input, &chunk, &next)) { + strerr_dief1x(111, "Malformed netstring"); + } + + } +} + +int main (int argc, char const *const *argv) +{ + char read_char; + size_t payload_size = 0; + + fd_block(input_fd); + + while(payload_size < payload_size_max) { + switch(read(input_fd, &read_char, 1)) { + case 0: + strerr_dief1x(111, "EOF before netstring size was read"); + break; + case 1: + if(read_char == ':') { + return handle_payload(payload_size); + } else if(size_next >= '0' && size_next <= '9') { + payload_size *= 10; + payload_size += read_char - '0'; + } else { + strerr_dief1x(111, "Malformed netstring on input"); + } + break; + } + case -1: + if(errno != EINTR) { + strerr_dief1sys(111, "read()"); + } + break; + default: + strerr_dief1x(110, "Unexpected return value from read()"); + break; + } + + strerr_dief1x(111, "Input netstring too big"); + return 111; +}