commit f29b59ae633b2fec66409f9cc2f6fcb753ecd14b
parent c56608039b134849dbb2f332e0b5d76621ea73a2
Author: William Casarin <jb55@jb55.com>
Date: Sun, 6 Dec 2020 08:53:02 -0800
json/sig progress
Diffstat:
M | Makefile | | | 10 | +++++++--- |
M | src/http.c | | | 14 | ++++++++++++++ |
M | src/http.h | | | 2 | ++ |
A | src/inbox.c | | | 109 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/inbox.h | | | 17 | +++++++++++++++++ |
A | src/json.c | | | 117 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/parse.h | | | 22 | ++++++++++++++++++++++ |
A | src/util.h | | | 24 | ++++++++++++++++++++++++ |
M | src/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[])