Commit Diff


commit - 58ba20cd5353626db13092dc3d817c7cb3da925f
commit + 3a227e9a01ae58219cafb85deca09d7efd78597a
blob - 52f9de718c26583b514690d60d90ce3205be586d
blob + 9150b2ae1134e4c1faa1fd8271d3f8432ed4f764
--- fs.c
+++ fs.c
@@ -16,6 +16,8 @@
 
 /*
  * Handles the data in ~/.telescope
+ *
+ * TODO: add some form of locking on the files
  */
 
 #include "telescope.h"
@@ -32,17 +34,20 @@ static void		 serve_bookmarks(uint32_t);
 static void		 handle_get(struct imsg*, size_t);
 static void		 handle_quit(struct imsg*, size_t);
 static void		 handle_bookmark_page(struct imsg*, size_t);
+static void		 handle_save_cert(struct imsg*, size_t);
 static void		 handle_dispatch_imsg(int, short, void*);
 
 static struct event		 imsgev;
 static struct imsgbuf		*ibuf;
 
 static char	bookmark_file[PATH_MAX];
+static char	known_hosts_file[PATH_MAX];
 
 static imsg_handlerfn *handlers[] = {
 	[IMSG_GET] = handle_get,
 	[IMSG_QUIT] = handle_quit,
 	[IMSG_BOOKMARK_PAGE] = handle_bookmark_page,
+	[IMSG_SAVE_CERT] = handle_save_cert,
 };
 
 static void __attribute__((__noreturn__))
@@ -138,6 +143,33 @@ end:
 }
 
 static void
+handle_save_cert(struct imsg *imsg, size_t datalen)
+{
+	struct tofu_entry	 e;
+	FILE			*f;
+	int			 res;
+
+	/* TODO: traverse the file to avoid duplications? */
+
+	if (datalen != sizeof(e))
+		die();
+	memcpy(&e, imsg->data, datalen);
+
+	if ((f = fopen(known_hosts_file, "a")) == NULL) {
+		res = errno;
+		goto end;
+	}
+	fprintf(f, "%s %s %d\n", e.domain, e.hash, e.verified);
+	fclose(f);
+
+	res = 0;
+end:
+	imsg_compose(ibuf, IMSG_SAVE_CERT_OK, imsg->hdr.peerid, 0, -1,
+	    &res, sizeof(res));
+	imsg_flush(ibuf);
+}
+
+static void
 handle_dispatch_imsg(int fd, short ev, void *d)
 {
 	struct imsgbuf	*ibuf = d;
@@ -145,13 +177,24 @@ handle_dispatch_imsg(int fd, short ev, void *d)
 }
 
 int
-fs_main(struct imsgbuf *b)
+fs_init(void)
 {
-	ibuf = b;
+	/* TODO: mkdir(~/.telescope) and touch bookmarks.gmi/known_hosts? */
 
 	strlcpy(bookmark_file, getenv("HOME"), sizeof(bookmark_file));
 	strlcat(bookmark_file, "/.telescope/bookmarks.gmi", sizeof(bookmark_file));
 
+	strlcpy(known_hosts_file, getenv("HOME"), sizeof(known_hosts_file));
+	strlcat(known_hosts_file, "/.telescope/known_hosts", sizeof(known_hosts_file));
+
+	return 1;
+}
+
+int
+fs_main(struct imsgbuf *b)
+{
+	ibuf = b;
+
 	event_init();
 
 	event_set(&imsgev, ibuf->fd, EV_READ | EV_PERSIST, handle_dispatch_imsg, ibuf);
@@ -162,3 +205,65 @@ fs_main(struct imsgbuf *b)
 	event_dispatch();
 	return 0;
 }
+
+
+
+int
+load_certs(struct ohash *h)
+{
+	char		*p, *last, *errstr, *el, *line = NULL;
+	int		 i;
+	size_t		 linesize = 0;
+	ssize_t		 linelen;
+	FILE		*f;
+	struct tofu_entry *e;
+
+	if ((f = fopen(known_hosts_file, "r")) == NULL)
+		return 0;
+
+	while ((linelen = getline(&line, &linesize, f)) != -1) {
+		if ((e = calloc(1, sizeof(*e))) == NULL)
+			abort();
+
+		i = 0;
+                for ((p = strtok_r(line, " ", &last)); p;
+		    (p = strtok_r(NULL, " ", &last))) {
+			if (*p == '\n') {
+				free(e);
+				break;
+			}
+
+			switch (i) {
+			case 0:
+				strlcpy(e->domain, p, sizeof(e->domain));
+				break;
+			case 1:
+				strlcpy(e->hash, p, sizeof(e->hash));
+				break;
+			case 2:
+				if ((el = strchr(p, '\n')) == NULL)
+					abort();
+				*el = '\0';
+
+				/* 0 <= verified <= 1 */
+				e->verified = strtonum(p, -1, 2, &errstr);
+				if (errstr != NULL)
+					errx(1, "verification for %s is %s: %s",
+					    e->domain, errstr, p);
+				break;
+			default:
+				abort();
+			}
+			i++;
+		}
+
+		if (i != 0 && i != 3)
+			abort();
+
+		if (i != 0)
+			telescope_ohash_insert(h, e);
+	}
+
+	free(line);
+	return ferror(f);
+}
blob - 0f0b79b109c3b7513a761b3e1f2ec9700233e4d3
blob + 7970f07dd792b041a6afdb00a5d4321e813f98f5
--- telescope.c
+++ telescope.c
@@ -31,6 +31,7 @@ static void		 handle_imsg_got_meta(struct imsg*, size_
 static void		 handle_imsg_buf(struct imsg*, size_t);
 static void		 handle_imsg_eof(struct imsg*, size_t);
 static void		 handle_imsg_bookmark_ok(struct imsg*, size_t);
+static void		 handle_imsg_save_cert_ok(struct imsg*, size_t);
 static void		 handle_dispatch_imsg(int, short, void*);
 static void		 load_page_from_str(struct tab*, const char*);
 static void		 do_load_url(struct tab*, const char*);
@@ -43,6 +44,7 @@ static imsg_handlerfn *handlers[] = {
 	[IMSG_BUF] = handle_imsg_buf,
 	[IMSG_EOF] = handle_imsg_eof,
 	[IMSG_BOOKMARK_OK] = handle_imsg_bookmark_ok,
+	[IMSG_SAVE_CERT_OK] = handle_imsg_save_cert_ok,
 };
 
 static struct ohash	certs;
@@ -111,6 +113,9 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal
 		strlcpy(e->domain, tab->url.host, sizeof(e->domain));
 		strlcpy(e->hash, hash, sizeof(e->hash));
 		telescope_ohash_insert(&certs, e);
+		imsg_compose(fsibuf, IMSG_SAVE_CERT, tab->id, 0, -1,
+		    e, sizeof(*e));
+		imsg_flush(fsibuf);
 	} else
 		tofu_res = !strcmp(hash, e->hash);
 
@@ -251,6 +256,19 @@ handle_imsg_bookmark_ok(struct imsg *imsg, size_t data
 }
 
 static void
+handle_imsg_save_cert_ok(struct imsg *imsg, size_t datalen)
+{
+	int res;
+
+	if (datalen != sizeof(res))
+		die();
+	memcpy(&res, imsg->data, datalen);
+	if (res != 0)
+		ui_notify("Failed to save the cert for: %s",
+		    strerror(res));
+}
+
+static void
 handle_dispatch_imsg(int fd, short ev, void *d)
 {
 	struct imsgbuf	*ibuf = d;
@@ -405,6 +423,10 @@ main(void)
 
 	signal(SIGCHLD, SIG_IGN);
 
+	/* initialize part of the fs layer.  Before starting the UI
+	 * and dropping the priviledges we need to read some stuff. */
+	fs_init();
+
 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fs_fds) == -1)
 		err(1, "socketpair");
 
@@ -445,6 +467,7 @@ main(void)
 	setproctitle("(%d) ui", pid);
 
 	telescope_ohash_init(&certs, 5, offsetof(struct tofu_entry, domain));
+	load_certs(&certs);
 
 	TAILQ_INIT(&tabshead);
 
blob - e73ac6d28bd4561c82014846568e4ff45d7efe62
blob + e2832ad89223268a6cf04b4c834b19187fb671e6
--- telescope.h
+++ telescope.h
@@ -45,6 +45,8 @@ enum imsg_type {
 	/* ui <-> fs */
 	IMSG_BOOKMARK_PAGE,
 	IMSG_BOOKMARK_OK,
+	IMSG_SAVE_CERT,
+	IMSG_SAVE_CERT_OK,
 };
 
 enum line_type {
@@ -186,7 +188,9 @@ struct keymap {
 };
 
 /* fs.c */
+int		 fs_init(void);
 int		 fs_main(struct imsgbuf*);
+int		 load_certs(struct ohash*);
 
 /* gemini.c */
 int		 client_main(struct imsgbuf*);
blob - c47a83b8c5a88d648f19103f2f6f69753bff09d4
blob + 88a155f7dac24ee2cba73a819c8ed0e2fd51ae35
--- util.c
+++ util.c
@@ -67,7 +67,7 @@ dispatch_imsg(struct imsgbuf *ibuf, imsg_handlerfn **h
 			return;
 		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
 		i = imsg.hdr.type;
-		if (i >= (size / sizeof(imsg_handlerfn*)) || handlers[i] == NULL)
+		if (i > (size / sizeof(imsg_handlerfn*)) || handlers[i] == NULL)
 			abort();
 		handlers[i](&imsg, datalen);
 		imsg_free(&imsg);