chibipub

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f29b59ae633b2fec66409f9cc2f6fcb753ecd14b
parent c56608039b134849dbb2f332e0b5d76621ea73a2
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  6 Dec 2020 08:53:02 -0800

json/sig progress

Diffstat:
MMakefile | 10+++++++---
Msrc/http.c | 14++++++++++++++
Msrc/http.h | 2++
Asrc/inbox.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/inbox.h | 17+++++++++++++++++
Asrc/json.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/parse.h | 22++++++++++++++++++++++
Asrc/util.h | 24++++++++++++++++++++++++
Msrc/wolfsocks.c | 150++++---------------------------------------------------------------------------
9 files changed, 319 insertions(+), 146 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,10 +1,14 @@ CFLAGS = -Wall -Werror -std=c99 -Isrc -OBJS = src/http.o src/base64.o +OBJS = src/http.o src/base64.o src/inbox.o src/json.o -wolfsocks: src/wolfsocks.c $(OBJS) - $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ +HEADERS = $(wildcard src/*.h) + +DEPS = src/wolfsocks.c $(OBJS) + +wolfsocks: $(DEPS) $(HEADERS) + $(CC) $(CFLAGS) $(DEPS) $(LDFLAGS) -o $@ clean: fake rm -f $(OBJS) wolfsocks diff --git a/src/http.c b/src/http.c @@ -1,4 +1,5 @@ #include "http.h" +#include "util.h" #include <stdio.h> #include <assert.h> @@ -130,3 +131,16 @@ void print_http_request(struct http_req *req) printf("%s: %s\n", header->name, header->value); } } + +int get_header(struct http_header *header, const char *match, + const char **result) +{ + for (; header; header = header->next) { + if (stricmp(header->name, match)) { + *result = header->value; + return 1; + } + } + + return 0; +} diff --git a/src/http.h b/src/http.h @@ -21,6 +21,8 @@ struct http_req { struct http_header *headers; }; + +int get_header(struct http_header *header, const char *match, const char **result); int parse_http_request(struct http_req *req, struct parser *p); void print_http_request(struct http_req *req); diff --git a/src/inbox.c b/src/inbox.c @@ -0,0 +1,109 @@ + +#include "inbox.h" +#include "http.h" +#include "util.h" +#include "base64.h" + +#include <assert.h> +#include <stdio.h> + +static int parse_until(struct cursor *cur, struct cursor *arena, char match, + const char **out) +{ + unsigned char *start; + + start = cur->p; + + for (; cur->p < cur->end; cur->p++) { + if (*cur->p == match) { + *out = (char*)arena->p; + if (!push_data(arena, start, cur->p - start)) { + return 0; + } + if (!push_byte(arena, 0)) { + return 0; + } + cur->p++; + return 1; + } + } + + cur->p = start; + + return 0; +} + +static int parse_kv(struct cursor *cur, struct cursor *arena, + const char **key, const char **val) +{ + if (!parse_until(cur, arena, '=', key)) { + note_error(cur, "= not found"); + return 0; + } + + if (!parse_until(cur, arena, ',', val)) { + *val = (char*)cur->p; + assert(*cur->end == 0); + } + + return 1; +} + +int parse_signature_header(struct cursor *arena, const char *value, struct sig_header *out) +{ + const char *key; + const char *val; + struct cursor cur; + size_t out_len; + make_cursor((unsigned char*)value, (unsigned char*)value + strlen(value), &cur); + + while (1) { + if (!parse_kv(&cur, arena, &key, &val)) { + break; + } + + if (stricmp(key, "keyid")) { + out->key_id = val; + } else if (stricmp(key, "headers")) { + out->headers = val; + } else if (stricmp(key, "signature")) { + out->signature = arena->p; + + if (!base64_decode((const unsigned char*)val, strlen(val), + arena->p, arena->end - arena->p, + &out_len)) { + note_error(arena, "base64 decode signature"); + return 0; + } + + out->signature_len = out_len; + + arena->p += out_len; + if (!push_byte(arena, 0)) { + note_error(arena, "oom"); + return 0; + } + } + } + + if (out->key_id == NULL || out->headers == NULL || out->signature == NULL) { + return 0; + } + + return 1; +} + +int verify_signature_header(struct sig_header *sig) +{ + int i; + + printf("verifying\nkeyid %s\nheaders %s\nsignature ", + sig->key_id, sig->headers); + + for (i = 0; i < sig->signature_len; i++) { + printf("%02x", sig->signature[i]); + } + printf("\n"); + + return 1; +} diff --git a/src/inbox.h b/src/inbox.h @@ -0,0 +1,17 @@ +#ifndef WOLFSOCKS_INBOX +#define WOLFSOCKS_INBOX + +#include "cursor.h" + +struct sig_header { + const char *key_id; + const char *headers; + unsigned char *signature; + int signature_len; +}; + + +int parse_signature_header(struct cursor *arena, const char *value, struct sig_header *out); +int verify_signature_header(struct sig_header *sig); + +#endif diff --git a/src/json.c b/src/json.c @@ -0,0 +1,117 @@ + +#include "cursor.h" +#include <ctype.h> + + +struct json_parser { + struct cursor cur; + struct cursor ubjson; +}; + +static void consume_whitespace(struct cursor *cur) +{ + for (; cur->p < cur->end; cur->p++) { + if (!isspace(*cur->p)) + return; + } +} + +static int parse_string(struct json_parser *p) +{ + if (!parse_char(&p->cur, &c, '"')) { + note_error(p, "expected '\"', got '%c'", c); + return 0; + } +} + +static int parse_kv(struct json_parser *p) +{ +} + +static int parse_object(struct json_parser *p) +{ + char c; + c = 0; + + if (!parse_char(&p->cur, &c, '{')) { + note_error(p, "expected '{' got '%c'", c); + return 0; + } + + while(1) { + consume_whitespace(&p->cur); + + if (!peek_char(&p->cur, &c)) { + note_error(p, "oob"); + return 0; + } + + if (c == '}') { + /* TODO (generalize): finalize_object */ + return push_byte(&p->ubjson, '}'); + } + + if (c != '"') { + note_error(p, "expected '\"' or '}', got '%c'", c); + return 0; + } + + if (!parse_kv(p)) { + note_error(p, "expected key value pair"); + return 0; + } + + if (!peek_char(&p->cur, &c)) { + note_error(p, "oob"); + return 0; + } + + if (c == ',') { + p->cur.p++; + continue; + } + + if (c == '}') { + /* TODO (generalize): finalize_object */ + return push_byte(&p->ubjson, '}'); + } + + note_error(p, "expected ',' or '}', got '%c'", c); + return 0; + } + + note_error(p, "impossibru"); + return 0; +} + +static int parse_array_or_object(struct json_parser *p) +{ + char c; + consume_whitespace(p); + + if (!peek_char(&p->cur, &c)) { + note_error(p, "oob"); + return 0; + } + + if (c == '{') + return parse_object(p); + + if (c == '[') + return parse_array(p); + + note_error(p, "expected '{' or '[', got '%c'", c); + return 0; +} + +int parse_json(unsigned char *buf, size_t buf_size, unsigned char *mem, + size_t mem_size) +{ + struct json_parser p; + memset(&p, 0, sizeof(p)); + + make_cursor(buf, buf + buf_size, &p->cur); + make_cursor(buf, mem + mem_size, &p->mem); + + return parse_array_or_object(&p); +} diff --git a/src/parse.h b/src/parse.h @@ -0,0 +1,22 @@ + +#ifndef WOLFSOCKS_PARSE +#define WOLFSOCKS_PARSE + +#include "cursor.h" + +static inline int peek_char(struct cursor *cur, char *out) +{ + return cursor_peek_byte(cur, (unsigned char*)out, 0); +} + +static inline int parse_char(struct cursor *cur, char *out, char match) +{ + if (peek_char(cur, out) && *out == match) { + cur->p++; + return 1; + } + + return 0; +} + +#endif /* WOLFSOCKS_PARSE */ diff --git a/src/util.h b/src/util.h @@ -0,0 +1,24 @@ + +#ifndef WOLFSOCKS_UTIL +#define WOLFSOCKS_UTIL + +#include <ctype.h> +#include <string.h> + +#define note_error(a, msg) fprintf(stderr, "%s: %s\n", __FUNCTION__, msg) + +static inline int stricmp(const char *a, const char *b) { + int len, i; + + if ((len = strlen(a)) != strlen(b)) + return 0; + + for (i = 0; i < len; i++) { + if (tolower(a[i]) != tolower(b[i])) + return 0; + } + + return 1; +} + +#endif diff --git a/src/wolfsocks.c b/src/wolfsocks.c @@ -13,159 +13,19 @@ #include <base64.h> #include "http.h" +#include "inbox.h" #define BUF_SIZE 4096 -#define ARENA_SIZE 8192 +#define ARENA_SIZE 134217728 /* 128 MB virtual mem arena */ #define note_error(a, msg) fprintf(stderr, "%s: %s\n", __FUNCTION__, msg) -struct request { - struct http_req http_req; - int client; -}; - -struct sig_header { - const char *key_id; - const char *headers; - unsigned char *signature; - int signature_len; -}; - static void error(char *msg) { perror(msg); exit(1); } -static int stricmp(const char *a, const char *b) { - int len, i; - - if ((len = strlen(a)) != strlen(b)) - return 0; - - for (i = 0; i < len; i++) { - if (tolower(a[i]) != tolower(b[i])) - return 0; - } - - return 1; -} - -static int parse_until(struct cursor *cur, struct cursor *arena, char match, - const char **out) -{ - unsigned char *start; - - start = cur->p; - - for (; cur->p < cur->end; cur->p++) { - if (*cur->p == match) { - *out = (char*)arena->p; - if (!push_data(arena, start, cur->p - start)) { - return 0; - } - if (!push_byte(arena, 0)) { - return 0; - } - cur->p++; - return 1; - } - } - - cur->p = start; - - return 0; -} - -static int parse_kv(struct cursor *cur, struct cursor *arena, - const char **key, const char **val) -{ - if (!parse_until(cur, arena, '=', key)) { - note_error(cur, "= not found"); - return 0; - } - - if (!parse_until(cur, arena, ',', val)) { - *val = (char*)cur->p; - assert(*cur->end == 0); - } - - return 1; -} - -static int parse_signature_header(struct cursor *arena, const char *value, - struct sig_header *out) -{ - const char *key; - const char *val; - struct cursor cur; - size_t out_len; - make_cursor((unsigned char*)value, (unsigned char*)value + strlen(value), &cur); - - while (1) { - if (!parse_kv(&cur, arena, &key, &val)) { - break; - } - - if (stricmp(key, "keyid")) { - out->key_id = val; - } else if (stricmp(key, "headers")) { - out->headers = val; - } else if (stricmp(key, "signature")) { - out->signature = arena->p; - - if (!base64_decode((const unsigned char*)val, strlen(val), - arena->p, arena->end - arena->p, - &out_len)) { - note_error(arena, "base64 decode signature"); - return 0; - } - - out->signature_len = out_len; - - arena->p += out_len; - if (!push_byte(arena, 0)) { - note_error(arena, "oom"); - return 0; - } - } - } - - if (out->key_id == NULL || out->headers == NULL || out->signature == NULL) { - return 0; - } - - return 1; -} - -static int verify_signature_header(struct sig_header *sig) -{ - int i; - - printf("verifying\nkeyid %s\nheaders %s\nsignature ", - sig->key_id, sig->headers); - - for (i = 0; i < sig->signature_len; i++) { - printf("%02x", sig->signature[i]); - } - printf("\n"); - - return 1; -} - -static int get_header(struct http_header *header, const char *match, - const char **result) -{ - for (; header; header = header->next) { - if (stricmp(header->name, match)) { - *result = header->value; - return 1; - } - } - - return 0; -} - static int handle_request(struct http_req *req, struct cursor *arena) { struct sig_header sig; @@ -199,8 +59,8 @@ static int handle_request(struct http_req *req, struct cursor *arena) void run_http_server() { - static unsigned char arena[ARENA_SIZE]; static unsigned char buffer[BUF_SIZE]; + unsigned char *arena; ssize_t len; socklen_t client_len; @@ -216,6 +76,8 @@ void run_http_server() struct parser parser; const int port = 5188; + arena = malloc(ARENA_SIZE); + assert(arena); if ((parent = socket(AF_INET, SOCK_STREAM, 0)) < 0) { error("socket"); @@ -287,6 +149,8 @@ void run_http_server() close(client); } + + free(arena); } int main(int argc, char *argv[])