commit cbcc75fb9de09c1187e40a3b185e029fb5b1bbfc from: Omar Polo date: Wed Mar 17 16:22:20 2021 UTC starting to implement TOFU popuplate an hash table with the certs and keep it in memory. Later, store the table in ~/.telescope/known_hosts and re-read back during startup. commit - 8255077602558143997f8768875a6f2efdce3d26 commit + cbcc75fb9de09c1187e40a3b185e029fb5b1bbfc blob - e16501d2dcee4bd502a2a607fd995a5c7310903f blob + 895d05682bc4f894fe4911bee0909e6718614c07 --- Makefile.am +++ Makefile.am @@ -5,6 +5,7 @@ telescope_SOURCES = compat.h \ fs.c \ gemini.c \ gemtext.c \ + hash.c \ hist.c \ keymap.c \ mime.c \ blob - /dev/null blob + 85da37ed241f9e889a3c21f4f5ed5f1a1d884755 (mode 644) --- /dev/null +++ hash.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Omar Polo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "telescope.h" + +#include + +static void *hash_alloc(size_t, void*); +static void *hash_calloc(size_t, size_t, void*); +static void hash_free(void*, void*); + +static void * +hash_alloc(size_t len, void *d) +{ + if ((d = malloc(len)) == NULL) + abort(); + return d; +} + +static void * +hash_calloc(size_t nmemb, size_t size, void *d) +{ + if ((d = calloc(nmemb, size)) == NULL) + abort(); + return d; +} + +static void +hash_free(void *ptr, void *d) +{ + free(ptr); +} + +void +telescope_ohash_init(struct ohash *h, unsigned int sz, ptrdiff_t ko) +{ + struct ohash_info info = { + .key_offset = ko, + .calloc = hash_calloc, + .free = hash_free, + .alloc = hash_alloc, + }; + + ohash_init(h, sz, &info); +} + +struct tofu_entry * +telescope_lookup_tofu(struct ohash *h, const char *domain) +{ + unsigned int slot; + + slot = ohash_qlookup(h, domain); + return ohash_find(h, slot); +} + +void +telescope_ohash_insert(struct ohash *h, struct tofu_entry *e) +{ + unsigned int slot; + + slot = ohash_qlookup(h, e->domain); + ohash_insert(h, slot, e); +} blob - 3f13eb4d75c4c1fa2d714003700e0c6dfbb576ae blob + 0f0b79b109c3b7513a761b3e1f2ec9700233e4d3 --- telescope.c +++ telescope.c @@ -45,6 +45,8 @@ static imsg_handlerfn *handlers[] = { [IMSG_BOOKMARK_OK] = handle_imsg_bookmark_ok, }; +static struct ohash certs; + static void __attribute__((__noreturn__)) die(void) { @@ -85,11 +87,39 @@ handle_imsg_err(struct imsg *imsg, size_t datalen) static void handle_imsg_check_cert(struct imsg *imsg, size_t datalen) { - int tofu_res = 1; - struct tab *tab; + const char *hash; + int tofu_res; + struct tofu_entry *e; + struct tab *tab; + hash = imsg->data; + if (hash[datalen-1] != '\0') + abort(); + tab = tab_by_id(imsg->hdr.peerid); - tab->trust = TS_TRUSTED; + + if ((e = telescope_lookup_tofu(&certs, tab->url.host)) == NULL) { + /* TODO: an update in libressl/libretls changed + * significantly. Find a better approach at storing + * the certs! */ + if (datalen > sizeof(e->hash)) + abort(); + + tofu_res = 1; /* trust on first use */ + if ((e = calloc(1, sizeof(*e))) == NULL) + abort(); + strlcpy(e->domain, tab->url.host, sizeof(e->domain)); + strlcpy(e->hash, hash, sizeof(e->hash)); + telescope_ohash_insert(&certs, e); + } else + tofu_res = !strcmp(hash, e->hash); + + if (tofu_res) + tab->trust = e->verified ? TS_VERIFIED : TS_TRUSTED; + else { + tab->trust = TS_UNTRUSTED; + load_page_from_str(tab, "# Certificate mismatch\n"); + } imsg_compose(netibuf, IMSG_CERT_STATUS, imsg->hdr.peerid, 0, -1, &tofu_res, sizeof(tofu_res)); imsg_flush(netibuf); @@ -414,6 +444,8 @@ main(void) setproctitle("(%d) ui", pid); + telescope_ohash_init(&certs, 5, offsetof(struct tofu_entry, domain)); + TAILQ_INIT(&tabshead); event_init(); blob - e991b7169dcb7b2a768358237f4345eb50cc0ef7 blob + e73ac6d28bd4561c82014846568e4ff45d7efe62 --- telescope.h +++ telescope.h @@ -133,6 +133,14 @@ enum trust_state { TS_VERIFIED, }; +struct tofu_entry { + char domain[GEMINI_URL_LEN]; + /* enough space for ``PROTO:HASH''. probably isn't a good + * idea thou. */ + char hash[128+1]; + int verified; +}; + extern TAILQ_HEAD(tabshead, tab) tabshead; struct tab { struct parser page; @@ -186,6 +194,11 @@ int client_main(struct imsgbuf*); /* gemtext.c */ void gemtext_initparser(struct parser*); +/* hash.c */ +void telescope_ohash_init(struct ohash*, unsigned int, ptrdiff_t); +struct tofu_entry *telescope_lookup_tofu(struct ohash*, const char*); +void telescope_ohash_insert(struct ohash*, struct tofu_entry*); + /* hist.c */ void hist_clear_forward(struct histhead*, struct hist*); void hist_push(struct histhead*, struct hist*);