commit - 9fedd923db07f03084a4efadf960020480d0db80
commit + a2fd3805b0807d0e85411613df26bd6dcaed01ce
blob - e1e2f6100e6e2893f2f672f01835563a2a24528f
blob + 38c23eb99a604a05c94508b2afdc5c1baf64681b
--- ChangeLog
+++ ChangeLog
2021-07-06 Omar Polo <op@omarpolo.com>
+ * telescope.c (handle_check_cert_user_choice): fix two bug: don't crash when there's a certificate mismatch and after saving the cert, before choosing to persist it, the page gets redirected. Now when the user accept a certificate, is treated as temporary saved for the whole session.
+
* defaults.c (load_default_keys): bind M-prior/next (M-pageup/pagedown) to tab-previous and tab-next
2021-07-05 Omar Polo <op@omarpolo.com>
blob - 0242dd56c8199241ef26e40d82bcb0729755dd80
blob + 7c7f77a1f4e1fbe7110be914331bfaf7aea92664
--- telescope.c
+++ telescope.c
static struct tab *tab_by_id(uint32_t);
static void handle_imsg_err(struct imsg*, size_t);
static void handle_imsg_check_cert(struct imsg*, size_t);
-static void handle_check_cert_user_choice(int, unsigned int);
-static void handle_maybe_save_new_cert(int, unsigned int);
+static void handle_check_cert_user_choice(int, struct tab *);
+static void handle_maybe_save_new_cert(int, struct tab *);
static void handle_imsg_got_code(struct imsg*, size_t);
static void handle_imsg_got_meta(struct imsg*, size_t);
-static void handle_maybe_save_page(int, unsigned int);
+static void handle_maybe_save_page(int, struct tab *);
static void handle_save_page_path(const char *, unsigned int);
static void handle_imsg_file_opened(struct imsg*, size_t);
static void handle_imsg_buf(struct imsg*, size_t);
tofu_res = !strcmp(hash, e->hash);
if (tofu_res) {
- tab->trust = e->verified ? TS_VERIFIED : TS_TRUSTED;
+ if (e->verified == -1)
+ tab->trust = TS_TEMP_TRUSTED;
+ else if (e->verified == 1)
+ tab->trust = TS_VERIFIED;
+ else
+ tab->trust = TS_TRUSTED;
+
imsg_compose(netibuf, IMSG_CERT_STATUS, imsg->hdr.peerid, 0, -1,
&tofu_res, sizeof(tofu_res));
imsg_flush(netibuf);
if ((tab->cert = strdup(hash)) == NULL)
die();
ui_yornp("Certificate mismatch. Proceed?",
- handle_check_cert_user_choice, tab->id);
+ handle_check_cert_user_choice, tab);
}
}
static void
-handle_check_cert_user_choice(int accept, unsigned int tabid)
+handle_check_cert_user_choice(int accept, struct tab *tab)
{
- struct tab *tab;
-
- tab = tab_by_id(tabid);
-
- imsg_compose(netibuf, IMSG_CERT_STATUS, tabid, 0, -1,
+ imsg_compose(netibuf, IMSG_CERT_STATUS, tab->id, 0, -1,
&accept, sizeof(accept));
imsg_flush(netibuf);
- if (accept)
+ if (accept) {
+ /*
+ * trust the certificate for this session only. If
+ * the page results in a redirect while we're asking
+ * the user to save, we'll end up with an invalid
+ * tabid (one request == one tab id) and crash. It
+ * also makes sense to save it for the current session
+ * if the user accepted it.
+ */
+ tofu_temp_trust(&certs, tab->uri.host, tab->uri.port, tab->cert);
+
ui_yornp("Save the new certificate?",
- handle_maybe_save_new_cert, tabid);
- else {
+ handle_maybe_save_new_cert, tab);
+ } else {
free(tab->cert);
tab->cert = NULL;
}
}
static void
-handle_maybe_save_new_cert(int accept, unsigned int tabid)
+handle_maybe_save_new_cert(int accept, struct tab *tab)
{
- struct tab *tab;
struct tofu_entry *e;
const char *host, *port;
- tab = tab_by_id(tabid);
-
if (tab->proxy != NULL) {
host = tab->proxy->host;
port = tab->proxy->port;
} else {
load_page_from_str(tab, err_pages[UNKNOWN_TYPE_OR_CSET]);
ui_yornp("Can't display page, wanna save?",
- handle_maybe_save_page, tab->id);
+ handle_maybe_save_page, tab);
}
} else if (tab->code < 40) { /* 3x */
tab->redirect_count++;
}
static void
-handle_maybe_save_page(int dosave, unsigned int tabid)
+handle_maybe_save_page(int dosave, struct tab *tab)
{
if (dosave)
- ui_read("Save to path", handle_save_page_path, tabid);
+ ui_read("Save to path", handle_save_page_path, tab->id);
else
- stop_tab(tab_by_id(tabid));
+ stop_tab(tab);
}
static void
blob - 0fa19093d9bea18e148c18178e4e1df77a2d3600
blob + 54c23576691a715aa722570bb81528d86e78b7ec
--- telescope.h
+++ telescope.h
enum trust_state {
TS_UNKNOWN,
TS_UNTRUSTED,
+ TS_TEMP_TRUSTED,
TS_TRUSTED,
TS_VERIFIED,
};
struct tofu_entry *tofu_lookup(struct ohash*, const char*, const char*);
void tofu_add(struct ohash*, struct tofu_entry*);
void tofu_update(struct ohash*, struct tofu_entry*);
+void tofu_temp_trust(struct ohash *, const char *, const char *, const char *);
/* ui.c */
extern int body_lines;
void ui_schedule_redraw(void);
void ui_require_input(struct tab*, int);
void ui_read(const char*, void(*)(const char*, unsigned int), unsigned int);
-void ui_yornp(const char*, void (*)(int, unsigned int), unsigned int);
+void ui_yornp(const char*, void (*)(int, struct tab *), struct tab *);
void ui_end(void);
/* utf.8 */
blob - b474a99d2639bb8390a3b0ec64e782783a93d344
blob + 6be7ec6fe0393108c660c9508e739cfe58beba2d
--- tofu.c
+++ tofu.c
free(e);
}
}
+
+void
+tofu_temp_trust(struct ohash *h, const char *host, const char *port,
+ const char *hash)
+{
+ struct tofu_entry *e;
+
+ if ((e = calloc(1, sizeof(*e))) == NULL)
+ abort();
+
+ strlcpy(e->domain, host, sizeof(e->domain));
+ if (*port != '\0' && strcmp(port, "1965")) {
+ strlcat(e->domain, ":", sizeof(e->domain));
+ strlcat(e->domain, port, sizeof(e->domain));
+ }
+ strlcpy(e->hash, hash, sizeof(e->hash));
+ e->verified = -1;
+
+ tofu_update(h, e);
+}
blob - e8aa4f0a5a8bb9205f2f9116ec2fb1d8059df8f6
blob + c7b26c92c942ee917b5c9aa274f41084d0862f82
--- ui.c
+++ ui.c
static char keybuf[64];
-static void (*yornp_cb)(int, unsigned int);
-static unsigned int yornp_data;
+static void (*yornp_cb)(int, struct tab *);
+static struct tab *yornp_data;
static void (*read_cb)(const char*, unsigned int);
static unsigned int read_data;
switch (ts) {
case TS_UNKNOWN: return 'u';
case TS_UNTRUSTED: return '!';
+ case TS_TEMP_TRUSTED: return '!';
case TS_TRUSTED: return 'v';
case TS_VERIFIED: return 'V';
default: return 'X';
}
void
-ui_yornp(const char *prompt, void (*fn)(int, unsigned int),
- unsigned int data)
+ui_yornp(const char *prompt, void (*fn)(int, struct tab *),
+ struct tab *data)
{
size_t len;