From 5d21e3a3954e947f889f024b8ba9db9e616aa28e Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Thu, 7 Jun 2012 12:54:25 -0400 Subject: Implement a warn_cert_changes setting to warn users when the remote ssl certificate is different from a previously cached certificate to help prevent against MITM attacks. Prompt the user with an action to take (show remote cert, allow for that session, or cache the new remote cert). --- about.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ settings.c | 16 ++++++ xombrero.1 | 25 ++++++++- xombrero.c | 161 +++++++++++++++++++++++++++++++++++++++++++--------------- xombrero.conf | 1 + xombrero.h | 27 ++++++++++ 6 files changed, 334 insertions(+), 42 deletions(-) diff --git a/about.c b/about.c index 012e52e..5c69a40 100644 --- a/about.c +++ b/about.c @@ -68,6 +68,7 @@ #define XT_XTP_FL (4) /* favorites */ #define XT_XTP_SL (5) /* search */ #define XT_XTP_AB (6) /* about */ +#define XT_XTP_SV (7) /* security violation */ /* XTP download actions */ #define XT_XTP_DL_LIST (1) @@ -96,6 +97,11 @@ /* XPT about actions */ #define XT_XTP_AB_EDIT_CONF (1) +/* XTP security violation actions */ +#define XT_XTP_SV_SHOW_CERT (1) +#define XT_XTP_SV_ALLOW_SESSION (2) +#define XT_XTP_SV_CACHE (3) + int js_show_wl(struct tab *, struct karg *); int pl_show_wl(struct tab *, struct karg *); int set(struct tab *, struct karg *); @@ -125,6 +131,7 @@ struct about_type about_list[] = { { XT_URI_ABOUT_PLUGINWL, pl_show_wl }, { XT_URI_ABOUT_WEBKIT, about_webkit }, { XT_URI_ABOUT_SEARCH, xtp_page_sl }, + { XT_URI_ABOUT_SECVIOLATION, NULL }, }; struct search_type { @@ -156,6 +163,7 @@ char *cl_session_key; /* cookie list */ char *fl_session_key; /* favorites list */ char *sl_session_key; /* search */ char *ab_session_key; /* about */ +char *sv_session_key; /* secviolation */ int updating_ab_tabs = 0; int updating_fl_tabs = 0; @@ -163,6 +171,7 @@ int updating_dl_tabs = 0; int updating_hl_tabs = 0; int updating_cl_tabs = 0; int updating_sl_tabs = 0; +int updating_sv_tabs = 0; struct download_list downloads; size_t @@ -879,6 +888,51 @@ xtp_handle_sl(struct tab *t, uint8_t cmd, int arg) g_free(uri); } +void +xtp_handle_sv(struct tab *t, uint8_t cmd, int id) +{ + SoupURI *soupuri = NULL; + struct karg args = {0}; + struct secviolation find, *sv; + struct sv_ignore *svi = NULL; + + find.xtp_arg = id; + if ((sv = RB_FIND(secviolation_list, &svl, &find)) == NULL) + return; + + args.ptr = (void *)sv->t; + args.s = sv->uri; + + switch (cmd) { + case XT_XTP_SV_SHOW_CERT: + args.i = XT_SHOW; + cert_cmd(t, &args); + break; + case XT_XTP_SV_ALLOW_SESSION: + soupuri = soup_uri_new(sv->uri); + svi = malloc(sizeof(struct sv_ignore)); + svi->domain = g_strdup(soupuri->host); + RB_INSERT(sv_ignore_list, &svil, svi); + load_uri(t, sv->uri); + focus_webview(t); + break; + case XT_XTP_SV_CACHE: + args.i = XT_CACHE; + cert_cmd(t, &args); + load_uri(t, sv->uri); + focus_webview(t); + break; + default: + show_oops(t, "%s: invalid secviolation command", __func__); + break; + }; + + g_free(sv->uri); + if (soupuri) + soup_uri_free(soupuri); + RB_REMOVE(secviolation_list, &svl, sv); +} + /* link an XTP class to it's session key and handler function */ struct xtp_despatch { uint8_t xtp_class; @@ -893,6 +947,7 @@ struct xtp_despatch xtp_despatches[] = { { XT_XTP_CL, &cl_session_key, xtp_handle_cl }, { XT_XTP_SL, &sl_session_key, xtp_handle_sl }, { XT_XTP_AB, &ab_session_key, xtp_handle_ab }, + { XT_XTP_SV, &sv_session_key, xtp_handle_sv }, { XT_XTP_INVALID, NULL, NULL } }; @@ -928,6 +983,7 @@ xtp_generate_keys(void) generate_xtp_session_key(&cl_session_key); generate_xtp_session_key(&fl_session_key); generate_xtp_session_key(&ab_session_key); + generate_xtp_session_key(&sv_session_key); } /* @@ -1126,6 +1182,25 @@ update_about_tabs(struct tab *apart_from) } } +/* + * update all secviolation tabs apart from one. Pass NULL if + * you want to update all. + */ +void +update_secviolation_tabs(struct tab *apart_from) +{ + struct tab *t; + + if (!updating_sv_tabs) { + updating_sv_tabs = 1; /* stop infinite recursion */ + TAILQ_FOREACH(t, &tabs, entry) + if ((t->xtp_meaning == XT_XTP_TAB_MEANING_SV) + && (t != apart_from)) + xtp_page_sv(t, NULL); + updating_sv_tabs = 0; + } +} + int xtp_page_ab(struct tab *t, struct karg *args) { @@ -1189,6 +1264,9 @@ xtp_page_ab(struct tab *t, struct karg *args) g_free(body); load_webkit_string(t, page, XT_URI_ABOUT_ABOUT); + + update_about_tabs(t); + g_free(page); return (0); @@ -1748,6 +1826,74 @@ xtp_page_sl(struct tab *t, struct karg *args) return (0); } +int +xtp_page_sv(struct tab *t, struct karg *args) +{ + SoupURI *soupuri; + static int arg = 0; + struct secviolation find, *sv; + char *page, *body; + + if (t == NULL) + show_oops(NULL, "secviolation invalid parameters"); + + /* Generate a new session key for next page instance. + * This only happens for the top level call to xtp_page_ab() + * in which case updating_sv_tabs = 0. + */ + if (!updating_sv_tabs) + generate_xtp_session_key(&sv_session_key); + + if (args == NULL) { + find.xtp_arg = t->xtp_arg; + sv = RB_FIND(secviolation_list, &svl, &find); + if (sv == NULL) + return (-1); + } else { + sv = g_malloc(sizeof(struct secviolation)); + sv->xtp_arg = ++arg; + t->xtp_arg = arg; + sv->t = t; + sv->uri = args->s; + RB_INSERT(secviolation_list, &svl, sv); + } + + if (sv->uri == NULL || (soupuri = soup_uri_new(sv->uri)) == NULL) + return (-1); + + body = g_strdup_printf( + "The domain of the page you have tried to access, %s, has a " + "different remote certificate then the local cached version from a " + "previous visit. As a security precaution to help prevent against " + "man-in-the-middle attacks, please choose one of the following " + "actions to continue, or disable the warn_cert_changes " + "setting in your xombrero configuration." + "

Choose an action:" + "
Show Certificate" + "
Allow for this Session" + "
Cache new certificate", + soupuri->host, + XT_XTP_STR, XT_XTP_SV, sv_session_key, XT_XTP_SV_SHOW_CERT, + sv->xtp_arg, + XT_XTP_STR, XT_XTP_SV, sv_session_key, XT_XTP_SV_ALLOW_SESSION, + sv->xtp_arg, + XT_XTP_STR, XT_XTP_SV, sv_session_key, XT_XTP_SV_CACHE, + sv->xtp_arg); + + page = get_html_page("Security Violation", body, "", 0); + g_free(body); + + update_secviolation_tabs(t); + + load_webkit_string(t, page, XT_URI_ABOUT_SECVIOLATION); + + g_free(page); + if (soupuri) + soup_uri_free(soupuri); + + return (0); +} + int startpage(struct tab *t, struct karg *args) { diff --git a/settings.c b/settings.c index 8a567b2..eabc2ce 100644 --- a/settings.c +++ b/settings.c @@ -105,6 +105,7 @@ char *external_editor = NULL; int referer_mode = XT_DS_REFERER_MODE; char *referer_custom = NULL; int download_notifications = XT_DS_DOWNLOAD_NOTIFICATIONS; +int warn_cert_changes = 0; char *cmd_font_name = NULL; /* these are all set at startup */ char *oops_font_name = NULL; @@ -186,6 +187,7 @@ int set_url_regex(char *); int set_userstyle_global(char *); int set_external_editor(char *); int set_xterm_workaround(char *); +int set_warn_cert_changes(char *); void walk_mime_type(struct settings *, void (*)(struct settings *, char *, void *), void *); @@ -420,6 +422,7 @@ struct settings rs[] = { { "referer", XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt }, { "download_notifications", XT_S_INT, 0, &download_notifications, NULL, NULL, NULL, set_download_notifications }, { "include_config", XT_S_STR, 0, NULL, &include_config, NULL, NULL, NULL }, + { "warn_cert_changes", XT_S_INT, 0, &warn_cert_changes, NULL, NULL, NULL, set_warn_cert_changes }, /* font settings */ { "cmd_font", XT_S_STR, 0, NULL, &cmd_font_name, NULL, NULL, set_cmd_font }, @@ -2142,6 +2145,19 @@ set_userstyle_global(char *value) return (0); } +int +set_warn_cert_changes(char *value) +{ + int tmp; + const char *errstr; + + tmp = strtonum(value, 0, 1, &errstr); + if (errstr) + return (-1); + warn_cert_changes = tmp; + return (0); +} + char * get_edit_mode(struct settings *s) { diff --git a/xombrero.1 b/xombrero.1 index 6bd548d..b25b1d3 100644 --- a/xombrero.1 +++ b/xombrero.1 @@ -1369,12 +1369,13 @@ en_US. .It Cm ssl_ca_file If set to a valid PEM file all server certificates will be validated against it. -The URL bar will be colored green (or blue when saved ) when the certificate is +The URL bar will be colored green (or blue when saved) when the certificate is trusted and yellow when untrusted. .Pp If .Cm ssl_ca_file -is not set then the URL bar will color all HTTPS connections red. +is not set, the URL bar will be colored red if the certificate has not +been saved, or blue if it has been saved. .Pp WebKit only supports a single PEM file. Many OS' or distributions have many PEM files. @@ -1428,6 +1429,26 @@ user-agent string. May be specified several times for switching between user-agents. .It Cm userstyle_global When enabled new tabs will automatically be displayed in low contrast mode. +.It Cm warn_cert_changes +When enabled all SSL certificates from HTTPS websites will be +cached in the +.Cm ~/.xombrero/certs_cache/ +directory. +On each page load, if the remote certificate differs from the cached +local version, a warning page with options of what to do next will be displayed +instead of the requested page. +This feature may be used in addition to the coloring of the URL bar and +can be used to help prevent against man-in-the-middle attacks, even if +the new remote certificate is signed by a trusted certificate +authority in +.Cm ssl_ca_file . +Default is 0. +.Pp +If a remote certificate has changed and you wish to cache the new one, +you must manually remove the old cached certificate from the +.Cm ~/.xombrero/certs_cache/ +directory and refresh the page. +The certificate will be named the same as the domain. .It Cm window_height Set the default height of the browser window. .It Cm window_width diff --git a/xombrero.c b/xombrero.c index 20894e8..cb4a4ac 100644 --- a/xombrero.c +++ b/xombrero.c @@ -85,6 +85,7 @@ TAILQ_HEAD(command_list, command_entry); #define XT_DIR (".xombrero") #define XT_CACHE_DIR ("cache") #define XT_CERT_DIR ("certs") +#define XT_CERT_CACHE_DIR ("certs_cache") #define XT_JS_DIR ("js") #define XT_SESSIONS_DIR ("sessions") #define XT_TEMP_DIR ("tmp") @@ -222,6 +223,8 @@ struct command_list chl; struct command_list shl; struct command_entry *history_at; struct command_entry *search_at; +struct secviolation_list svl; +struct sv_ignore_list svil; int undo_count; int cmd_history_count = 0; int search_history_count = 0; @@ -655,6 +658,7 @@ show_oops(struct tab *at, const char *fmt, ...) char work_dir[PATH_MAX]; char certs_dir[PATH_MAX]; +char certs_cache_dir[PATH_MAX]; char js_dir[PATH_MAX]; char cache_dir[PATH_MAX]; char sessions_dir[PATH_MAX]; @@ -697,6 +701,20 @@ download_rb_cmp(struct download *e1, struct download *e2) } RB_GENERATE(download_list, download, entry, download_rb_cmp); +int +secviolation_rb_cmp(struct secviolation *s1, struct secviolation *s2) +{ + return (s1->xtp_arg < s2->xtp_arg ? -1 : s1->xtp_arg > s2->xtp_arg); +} +RB_GENERATE(secviolation_list, secviolation, entry, secviolation_rb_cmp); + +int +sv_ignore_rb_cmp(struct sv_ignore *s1, struct sv_ignore *s2) +{ + return (strcmp(s1->domain, s2->domain)); +} +RB_GENERATE(sv_ignore_list, sv_ignore, entry, sv_ignore_rb_cmp); + struct valid_url_types { char *type; } vut[] = { @@ -704,6 +722,7 @@ struct valid_url_types { { "https://" }, { "ftp://" }, { "file://" }, + { XT_URI_ABOUT }, { XT_XTP_STR }, }; @@ -835,7 +854,8 @@ load_uri(struct tab *t, gchar *uri) if (!strncmp(uri, XT_URI_ABOUT, XT_URI_ABOUT_LEN)) { for (i = 0; i < about_list_size(); i++) - if (!strcmp(&uri[XT_URI_ABOUT_LEN], about_list[i].name)) { + if (!strcmp(&uri[XT_URI_ABOUT_LEN], about_list[i].name) && + about_list[i].func != NULL) { bzero(&args, sizeof args); about_list[i].func(t, &args); gtk_widget_set_sensitive(GTK_WIDGET(t->stop), @@ -1778,18 +1798,17 @@ statusbar_modify_attr(struct tab *t, const char *text, const char *base) void save_certs(struct tab *t, gnutls_x509_crt_t *certs, - size_t cert_count, char *domain) + size_t cert_count, const char *domain, const char *dir) { size_t cert_buf_sz; char cert_buf[64 * 1024], file[PATH_MAX]; int i; FILE *f; - GdkColor color; if (t == NULL || certs == NULL || cert_count <= 0 || domain == NULL) return; - snprintf(file, sizeof file, "%s" PS "%s", certs_dir, domain); + snprintf(file, sizeof file, "%s" PS "%s", dir, domain); if ((f = fopen(file, "w")) == NULL) { show_oops(t, "Can't create cert file %s %s", file, strerror(errno)); @@ -1809,10 +1828,6 @@ save_certs(struct tab *t, gnutls_x509_crt_t *certs, } } - /* not the best spot but oh well */ - gdk_color_parse(XT_COLOR_BLUE, &color); - gtk_widget_modify_base(t->uri_entry, GTK_STATE_NORMAL, &color); - statusbar_modify_attr(t, XT_COLOR_BLACK, XT_COLOR_BLUE); done: fclose(f); } @@ -1825,7 +1840,7 @@ enum cert_trust { }; enum cert_trust -load_compare_cert(const gchar *uri, const gchar **error_str) +load_compare_cert(const gchar *uri, const gchar **error_str, const char *dir) { char domain[8182], file[PATH_MAX]; char cert_buf[64 * 1024], r_cert_buf[64 * 1024]; @@ -1867,7 +1882,7 @@ load_compare_cert(const gchar *uri, const gchar **error_str) goto done; } - snprintf(file, sizeof file, "%s" PS "%s", certs_dir, domain); + snprintf(file, sizeof file, "%s" PS "%s", dir, domain); if ((f = fopen(file, "r")) == NULL) { if (!error) rv = CERT_TRUSTED; @@ -1880,7 +1895,7 @@ load_compare_cert(const gchar *uri, const gchar **error_str) cert_buf, &cert_buf_sz)) { goto freeit; } - if (fread(r_cert_buf, cert_buf_sz, 1, f) != 1) { + if (fread(r_cert_buf, cert_buf_sz, 1, f) != 1 && !feof(f)) { rv = CERT_BAD; /* critical */ goto freeit; } @@ -1901,7 +1916,7 @@ done: close(s); /* only complain if we didn't save it locally */ - if (error && rv != CERT_LOCAL) { + if (strlen(ssl_ca_file) != 0 && error && rv != CERT_LOCAL) { strlcpy(serr, "Certificate exception(s): ", sizeof serr); if (error & GNUTLS_CERT_INVALID) strlcat(serr, "invalid, ", sizeof serr); @@ -1935,7 +1950,6 @@ done: int cert_cmd(struct tab *t, struct karg *args) { - struct stat sb; const gchar *uri, *error_str = NULL; char domain[8182]; int s = -1; @@ -1943,16 +1957,14 @@ cert_cmd(struct tab *t, struct karg *args) gnutls_session_t gsession; gnutls_x509_crt_t *certs; gnutls_certificate_credentials_t xcred; + GdkColor color; if (t == NULL) return (1); - if (stat(ssl_ca_file, &sb)) { - show_oops(t, "Can't open CA file: %s", ssl_ca_file); - return (1); - } - - if ((uri = get_uri(t)) == NULL) { + if (args->s != NULL) + uri = args->s; + else if ((uri = get_uri(t)) == NULL) { show_oops(t, "Invalid URI"); return (1); } @@ -1975,8 +1987,13 @@ cert_cmd(struct tab *t, struct karg *args) if (args->i & XT_SHOW) show_certs(t, certs, cert_count, "Certificate Chain"); - else if (args->i & XT_SAVE) - save_certs(t, certs, cert_count, domain); + else if (args->i & XT_SAVE) { + save_certs(t, certs, cert_count, domain, certs_dir); + gdk_color_parse(XT_COLOR_BLUE, &color); + gtk_widget_modify_base(t->uri_entry, GTK_STATE_NORMAL, &color); + statusbar_modify_attr(t, XT_COLOR_BLACK, XT_COLOR_BLUE); + } else if (args->i & XT_CACHE) + save_certs(t, certs, cert_count, domain, certs_cache_dir); free_connection_certs(certs, cert_count); done: @@ -1989,6 +2006,65 @@ done: return (0); } +/* + * args must be allocated dynamically as the thread that added this function + * to the idle loop no longer exists + */ +gboolean +warn_cert_cache_differs_idle(struct karg *args) +{ + if (args == NULL) { + show_oops(NULL, "%s: invalid parameters", __func__); + /* return 0 to not re-add function to the idle loop */ + return (0); + } + xtp_page_sv((struct tab *)args->ptr, args); + free(args); + return (0); +} + +int +check_cert_changes(struct tab *t, const char *uri) +{ + SoupURI *soupuri = NULL; + struct karg args = {0}; + struct sv_ignore find; + const char *errstr = NULL; + struct karg *argsp; + + if (!(warn_cert_changes && g_str_has_prefix(uri, "https://"))) + return (0); + + switch (load_compare_cert(uri, &errstr, certs_cache_dir)) { + case CERT_LOCAL: + /* The cached certificate is identical */ + break; + case CERT_TRUSTED: /* FALLTHROUGH */ + case CERT_UNTRUSTED: + /* cache new certificate */ + args.i = XT_CACHE; + cert_cmd(t, &args); + break; + case CERT_BAD: + if ((soupuri = soup_uri_new(uri)) == NULL) + break; + find.domain = soupuri->host; + if (RB_FIND(sv_ignore_list, &svil, &find)) + break; + t->xtp_meaning = XT_XTP_TAB_MEANING_SV; + argsp = malloc(sizeof(struct karg)); + bzero(argsp, sizeof(struct karg)); + argsp->s = g_strdup((char *)uri); + argsp->ptr = (void *)t; + g_idle_add((GSourceFunc)warn_cert_cache_differs_idle, argsp); + break; + } + + if (soupuri) + soup_uri_free(soupuri); + return (0); +} + int remove_cookie(int index) { @@ -2704,7 +2780,7 @@ command(struct tab *t, struct karg *args) sp = NULL; } s = sl; - for (i = 0; i < sizeof subs / sizeof (struct prompt_sub); ++i) { + for (i = 0; i < LENGTH(subs); ++i) { sv = g_strsplit(sl, subs[i].s, -1); if (sl) g_free(sl); @@ -3537,15 +3613,17 @@ color_address_bar(gpointer p) #endif col_str = XT_COLOR_YELLOW; - switch (load_compare_cert(u, &error_str)) { + switch (load_compare_cert(u, &error_str, certs_dir)) { case CERT_LOCAL: col_str = XT_COLOR_BLUE; break; case CERT_TRUSTED: - col_str = XT_COLOR_GREEN; + col_str = (strlen(ssl_ca_file) == 0) ? XT_COLOR_RED + : XT_COLOR_GREEN; break; case CERT_UNTRUSTED: - col_str = XT_COLOR_YELLOW; + col_str = (strlen(ssl_ca_file) == 0) ? XT_COLOR_RED + : XT_COLOR_YELLOW; break; case CERT_BAD: col_str = XT_COLOR_RED; @@ -3609,11 +3687,17 @@ done: #endif } +void +check_certs(gpointer p) +{ + color_address_bar((struct tab *)p); + check_cert_changes((struct tab *)p, get_uri((struct tab *)p)); +} + void show_ca_status(struct tab *t, const char *uri) { GdkColor color; - struct stat sb; gchar *col_str = XT_COLOR_WHITE, *text, *base; DNPRINTF(XT_D_URL, "show_ca_status: %d %s %s\n", @@ -3622,20 +3706,10 @@ show_ca_status(struct tab *t, const char *uri) if (t == NULL) return; - if (uri == NULL) - goto done; - if (stat(ssl_ca_file, &sb)) { - if (g_str_has_prefix(uri, "http://")) - goto done; - if (g_str_has_prefix(uri, "https://")) { - col_str = XT_COLOR_RED; - goto done; - } - return; - } - if (g_str_has_prefix(uri, "http://") || + if (uri == NULL || g_str_has_prefix(uri, "http://") || !g_str_has_prefix(uri, "https://")) goto done; + #ifdef USE_THREADS /* * It is not necessary to see if the thread is already running. @@ -3644,9 +3718,9 @@ show_ca_status(struct tab *t, const char *uri) */ /* thread the coloring of the address bar */ - t->thread = g_thread_create((GThreadFunc)color_address_bar, t, TRUE, NULL); + t->thread = g_thread_create((GThreadFunc)check_certs, t, TRUE, NULL); #else - color_address_bar(t); + check_certs(t); #endif return; @@ -7834,6 +7908,8 @@ main(int argc, char **argv) RB_INIT(&pl_wl); RB_INIT(&downloads); RB_INIT(&st_tree); + RB_INIT(&svl); + RB_INIT(&svil); TAILQ_INIT(&sessions); TAILQ_INIT(&tabs); @@ -7981,6 +8057,11 @@ main(int argc, char **argv) snprintf(certs_dir, sizeof certs_dir, "%s" PS "%s", work_dir, XT_CERT_DIR); xxx_dir(certs_dir); + /* cert changes dir */ + snprintf(certs_cache_dir, sizeof certs_cache_dir, "%s" PS "%s", + work_dir, XT_CERT_CACHE_DIR); + xxx_dir(certs_cache_dir); + /* sessions dir */ snprintf(sessions_dir, sizeof sessions_dir, "%s" PS "%s", work_dir, XT_SESSIONS_DIR); diff --git a/xombrero.conf b/xombrero.conf index e732265..0c4dc14 100644 --- a/xombrero.conf +++ b/xombrero.conf @@ -60,6 +60,7 @@ # enable_favicon_entry = 0 # enable_favicon_tabs = 1 # referer = always +# warn_cert_changes = 1 # See http://www.xroxy.com/proxylist.php for a good list of open # proxies. diff --git a/xombrero.h b/xombrero.h index b204705..df0b0fe 100644 --- a/xombrero.h +++ b/xombrero.h @@ -246,6 +246,7 @@ struct tab { int ctrl_click; gchar *status; int xtp_meaning; /* identifies dls/favorites */ + int xtp_arg; gchar *tmp_uri; int popup; /* 1 if cmd_entry has popup visible */ #ifdef USE_THREADS @@ -284,6 +285,7 @@ struct karg { int i; char *s; int precount; + void *ptr; }; struct download { @@ -317,6 +319,22 @@ struct strict_transport { RB_HEAD(strict_transport_tree, strict_transport); RB_PROTOTYPE(strict_transport_tree, strict_transport, entry, strict_transport_rb_cmp); +struct secviolation { + RB_ENTRY(secviolation) entry; + int xtp_arg; + struct tab *t; + char *uri; +}; +RB_HEAD(secviolation_list, secviolation); +RB_PROTOTYPE(secviolation_list, secviolation, entry, secviolation_rb_cmp); + +struct sv_ignore { + RB_ENTRY(sv_ignore) entry; + char *domain; +}; +RB_HEAD(sv_ignore_list, sv_ignore); +RB_PROTOTYPE(sv_ignore_list, sv_ignore, entry, sv_ignore_rb_cmp); + /* utility */ #define XT_NAME ("xombrero") #define XT_CB_HANDLED (TRUE) @@ -405,6 +423,7 @@ char *tld_get_suffix(const char *); #define XT_URI_ABOUT_STARTPAGE ("startpage") #define XT_URI_ABOUT_WEBKIT ("webkit") #define XT_URI_ABOUT_SEARCH ("search") +#define XT_URI_ABOUT_SECVIOLATION ("secviolation") struct about_type { char *name; @@ -430,6 +449,7 @@ int xtp_page_dl(struct tab *, struct karg *); int xtp_page_fl(struct tab *, struct karg *); int xtp_page_hl(struct tab *, struct karg *); int xtp_page_sl(struct tab *, struct karg *); +int xtp_page_sv(struct tab *, struct karg *); int parse_xtp_url(struct tab *, const char *); int add_favorite(struct tab *, struct karg *); void update_favorite_tabs(struct tab *); @@ -454,6 +474,7 @@ void startpage_add(const char *, ...); #define XT_XTP_TAB_MEANING_HL (8) /* history manager in this tab */ #define XT_XTP_TAB_MEANING_SL (9) /* search engine chooser */ #define XT_XTP_TAB_MEANING_AB (10) /* about:about in this tab */ +#define XT_XTP_TAB_MEANING_SV (18) /* about:secviolation in tab */ /* whitelists */ #define XT_WL_TOGGLE (1<<0) @@ -468,6 +489,7 @@ void startpage_add(const char *, ...); #define XT_DELETE (1<<9) #define XT_SAVE (1<<10) #define XT_OPEN (1<<11) +#define XT_CACHE (1<<12) #define XT_WL_INVALID (0) #define XT_WL_JAVASCRIPT (1) @@ -686,6 +708,8 @@ int urlaction(struct tab *, struct karg *); int userstyle(struct tab *, struct karg *); struct tab *get_current_tab(void); int resizetab(struct tab *, struct karg *); +int cert_cmd(struct tab *, struct karg *); +void focus_webview(struct tab *); #define XT_DL_START (0) #define XT_DL_RESTART (1) @@ -765,6 +789,7 @@ extern int enable_favicon_tabs; extern int referer_mode; extern char *referer_custom; extern int download_notifications; +extern int warn_cert_changes; extern regex_t url_re; /* globals */ @@ -800,6 +825,8 @@ extern struct sp_list spl; extern struct user_agent_list ua_list; extern struct cmd_alias_list cal; extern struct custom_uri_list cul; +extern struct secviolation_list svl; +extern struct sv_ignore_list svil; extern int user_agent_count; extern PangoFontDescription *cmd_font; -- cgit 1.4.1-2-gfad0