Commit Diff


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 <op@omarpolo.com>
+ *
+ * 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 <stdlib.h>
+
+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*);