commit 3a227e9a01ae58219cafb85deca09d7efd78597a from: Omar Polo date: Thu Mar 18 09:28:02 2021 UTC persist certificate hashes to the known_hosts file 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);