diff options
author | Josh Rickmar <jrick@devio.us> | 2012-07-31 09:55:26 -0400 |
---|---|---|
committer | Josh Rickmar <jrick@devio.us> | 2012-07-31 09:55:26 -0400 |
commit | 0c240f728d489408cda135786cf29244c1cd4d83 (patch) | |
tree | e063f765a1c73d301ec3ad5e8a5904165337a63e | |
parent | 02e03fcb67ee3ee37ff7bd5f287a7c53ca55f97e (diff) | |
download | xombrero-0c240f728d489408cda135786cf29244c1cd4d83.tar.gz |
Add a force_https setting (using the same domain syntax as the
whitelist settings) to make all requests to that domain use the HTTPS scheme, similar to HSTS. Install a new file, hsts-preload, into the resource dir. This is a regular config file with a bunch of force_https = ... lines, which is used to implement a preloaded HSTS list. Right now all the domains in this file, except for conformal.com and cyphertite.com, are taken directly from chromium's preloaded HSTS list (and should be synced with this file every so often). Also implement a new setting, preload_strict_transport (enabled by default), to enable or disable the loading of this preloaded HSTS list. Document force_https and preload_strict_transport in the manpage.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | freebsd/Makefile | 1 | ||||
-rw-r--r-- | hsts-preload | 108 | ||||
-rw-r--r-- | linux/Makefile | 3 | ||||
-rw-r--r-- | settings.c | 35 | ||||
-rw-r--r-- | unix.c | 2 | ||||
-rw-r--r-- | whitelist.c | 6 | ||||
-rw-r--r-- | xombrero.1 | 20 | ||||
-rw-r--r-- | xombrero.c | 44 | ||||
-rw-r--r-- | xombrero.conf | 10 | ||||
-rw-r--r-- | xombrero.h | 9 |
11 files changed, 228 insertions, 11 deletions
diff --git a/Makefile b/Makefile index 5867dcb..e9ada1a 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,7 @@ beforeinstall: install -m 644 ${.CURDIR}/xombreroicon128.png ${PREFIX}/share/xombrero install -m 644 ${.CURDIR}/tld-rules ${PREFIX}/share/xombrero install -m 644 ${.CURDIR}/style.css ${PREFIX}/share/xombrero + install -m 644 ${.CURDIR}/hsts-preload ${PREFIX}/share/xombrero ${PROG} ${OBJS} beforedepend: javascript.h diff --git a/freebsd/Makefile b/freebsd/Makefile index a6be6af..9ed119b 100644 --- a/freebsd/Makefile +++ b/freebsd/Makefile @@ -72,6 +72,7 @@ install: all install -m 644 ../xombreroicon128.png $(DESTDIR)$(RESDIR) install -m 644 ../tld-rules $(DESTDIR)$(RESDIR) install -m 644 ../style.css $(DESTDIR)$(RESDIR) + install -m 644 ../hsts-preload $(DESTDIR)$(RESDIR) clean: rm -f xombrero *.o diff --git a/hsts-preload b/hsts-preload new file mode 100644 index 0000000..5bff60d --- /dev/null +++ b/hsts-preload @@ -0,0 +1,108 @@ +force_https = bitbucket.org +force_https = .bitrig.org +force_https = .conformal.com +force_https = .conformalsys.org +force_https = .cyphertite.com +force_https = .defcon.org +force_https = duck.co +force_https = .eff.org +force_https = github.com +force_https = gist.github.com +force_https = bugzilla.gnome.org +force_https = lobste.rs +force_https = .bugzilla.mozilla.org +force_https = mtgox.com +force_https = gitweb.torproject.org +force_https = twitter.com + +# sites from chromium's preloaded HSTS list +# http://src.chromium.org/viewvc/chrome/trunk/src/net/base/transport_security_state_static.json?view=markup +force_https = .market.android.com +force_https = .ssl.google-analytics.com +force_https = .googleplex.com +force_https = www.paypal.com +force_https = www.elanex.biz +force_https = .jottit.com +force_https = .sunshinepress.org +force_https = www.noisebridge.net +force_https = .neg9.org +force_https = .riseup.net +force_https = factor.cc +force_https = members.mayfirst.org +force_https = support.mayfirst.org +force_https = id.mayfirst.org +force_https = lists.mayfirst.org +force_https = aladdinschools.appspot.com +force_https = .ottospora.nl +force_https = www.paycheckrecords.com +force_https = lastpass.com +force_https = www.lastpass.com +force_https = .keyerror.com +force_https = entropia.de +force_https = www.entropia.de +force_https = .romab.com +force_https = logentries.com +force_https = www.logentries.com +force_https = .stripe.com +force_https = .cloudsecurityalliance.org +force_https = .login.sapo.pt +force_https = .mattmccutchen.net +force_https = .betnet.fr +force_https = .uprotect.it +force_https = squareup.com +force_https = .cert.se +force_https = .crypto.is +force_https = .simon.butcher.name +force_https = .linx.net +force_https = dropcam.com +force_https = www.dropcam.com +force_https = .ebanking.indovinabank.com.vn +force_https = epoxate.com +force_https = torproject.org +force_https = .blog.torproject.org +force_https = .check.torproject.org +force_https = .www.torproject.org +force_https = .www.moneybookers.com +force_https = ledgerscope.net +force_https = www.ledgerscope.net +force_https = kyps.net +force_https = www.kyps.net +force_https = .app.recurly.com +force_https = .api.recurly.com +force_https = greplin.com +force_https = www.greplin.com +force_https = .luneta.nearbuysystems.com +force_https = .ubertt.org +force_https = .pixi.me +force_https = .grepular.com +force_https = mydigipass.com +force_https = www.mydigipass.com +force_https = developer.mydigipass.com +force_https = www.developer.mydigipass.com +force_https = sandbox.mydigipass.com +force_https = www.sandbox.mydigipass.com +force_https = .crypto.cat +force_https = .bigshinylock.minazo.net +force_https = .crate.io +force_https = .braintreegateway.com +force_https = braintreepayments.com +force_https = www.braintreepayments.com +force_https = emailprivacytester.com +force_https = .business.medbank.com.mt +force_https = .arivo.com.br +force_https = .www.apollo-auto.com +force_https = .www.cueup.com +force_https = jitsi.org +force_https = www.jitsi.org +force_https = download.jitsi.org +force_https = .sol.io +force_https = irccloud.com +force_https = www.irccloud.com +force_https = alpha.irccloud.com +force_https = .passwd.io +force_https = .browserid.org +force_https = .login.persona.org +force_https = gmail.com +force_https = googlemail.com +force_https = www.gmail.com +force_https = www.googlemail.com diff --git a/linux/Makefile b/linux/Makefile index c0c2455..8d4e3cf 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -61,6 +61,7 @@ install: all install -m 644 ../xombreroicon128.png $(DESTDIR)$(RESDIR) install -m 644 ../tld-rules $(DESTDIR)$(RESDIR) install -m 644 ../style.css $(DESTDIR)$(RESDIR) + install -m 644 ../hsts-preload $(DESTDIR)$(RESDIR) uninstall: rm -f $(DESTDIR)$(BINDIR)/xombrero @@ -71,7 +72,9 @@ uninstall: rm -f $(DESTDIR)$(RESDIR)/xombreroicon48.png rm -f $(DESTDIR)$(RESDIR)/xombreroicon64.png rm -f $(DESTDIR)$(RESDIR)/xombreroicon128.png + rm -f $(DESTDIR)$(RESDIR)/tld-rules rm -f $(DESTDIR)$(RESDIR)/style.css + rm -f $(DESTDIR)$(RESDIR)/hsts-preload if [ -d $(DESTDIR)$(RESDIR) ]; then rmdir $(DESTDIR)$(RESDIR); fi clean: rm -f xombrero $(OBJS) $(DEPS) diff --git a/settings.c b/settings.c index 053d145..0850b4e 100644 --- a/settings.c +++ b/settings.c @@ -112,6 +112,7 @@ int warn_cert_changes = 0; int allow_insecure_content = XT_DS_ALLOW_INSECURE_CONTENT; int allow_insecure_scripts = XT_DS_ALLOW_INSECURE_SCRIPTS; int do_not_track = XT_DS_DO_NOT_TRACK; +int preload_strict_transport = XT_DS_PRELOAD_STRICT_TRANSPORT; char *cmd_font_name = NULL; /* these are all set at startup */ char *oops_font_name = NULL; @@ -140,6 +141,7 @@ int add_ua(struct settings *, char *); int add_http_accept(struct settings *, char *); int add_cmd_alias(struct settings *, char *); int add_custom_uri(struct settings *, char *); +int add_force_https(struct settings *, char *); int set_append_next(char *); int set_autofocus_onload(char *); @@ -226,6 +228,8 @@ void walk_cmd_alias(struct settings *, void (*)(struct settings *, char *, void *), void *); void walk_custom_uri(struct settings *, void (*)(struct settings *, char *, void *), void *); +void walk_force_https(struct settings *, void (*)(struct settings *, + char *, void *), void *); int set_http_proxy(char *proxy) @@ -395,6 +399,12 @@ struct special s_userstyle = { NULL }; +struct special s_force_https = { + add_force_https, + NULL, + walk_force_https +}; + struct settings rs[] = { { "allow_insecure_content", XT_S_INT, 0, &allow_insecure_content, NULL, NULL, NULL, set_allow_insecure_content }, { "allow_insecure_scripts", XT_S_INT, 0, &allow_insecure_scripts, NULL, NULL, NULL, set_allow_insecure_scripts }, @@ -442,6 +452,7 @@ struct settings rs[] = { { "max_connections", XT_S_INT, XT_SF_RESTART,&max_connections, NULL, NULL, NULL, NULL }, { "max_host_connections", XT_S_INT, XT_SF_RESTART,&max_host_connections, NULL, NULL, NULL, NULL }, { "oops_font", XT_S_STR, 0, NULL, &oops_font_name, NULL, NULL, set_oops_font }, + { "preload_strict_transport", XT_S_INT, 0, &preload_strict_transport, NULL, NULL, NULL, NULL }, { "read_only_cookies", XT_S_INT, 0, &read_only_cookies, NULL, NULL, NULL, set_read_only_cookies }, { "referer", XT_S_STR, 0, NULL, NULL,&s_referer, NULL, set_referer_rt }, { "refresh_interval", XT_S_INT, 0, &refresh_interval, NULL, NULL, NULL, set_refresh_interval }, @@ -478,6 +489,7 @@ struct settings rs[] = { { "cmd_alias", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_cmd_alias, NULL, NULL }, { "cookie_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_cookie_wl, NULL, NULL }, { "custom_uri", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_uri, NULL, NULL }, + { "force_https", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_force_https, NULL, NULL }, { "http_accept", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_http_accept, NULL, NULL }, { "js_wl", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_js, NULL, NULL }, { "keybinding", XT_S_STR, XT_SF_RUNTIME, NULL, NULL, &s_kb, NULL, NULL }, @@ -1476,6 +1488,14 @@ walk_ua(struct settings *s, } int +add_force_https(struct settings *s, char *value) +{ + wl_add(value, &force_https, + XT_WL_FLAG_HANDY | XT_WL_FLAG_EXCLUDE_SUBDOMAINS); + return (0); +} + +int add_http_accept(struct settings *s, char *value) { struct http_accept *ha; @@ -2582,6 +2602,21 @@ walk_pl_wl(struct settings *s, cb(s, d->d, cb_args); } +void +walk_force_https(struct settings *s, + void (*cb)(struct settings *, char *, void *), void *cb_args) +{ + struct domain *d; + + if (s == NULL || cb == NULL) { + show_oops(NULL, "walk_force_https invalid parameters"); + return; + } + + RB_FOREACH_REVERSE(d, domain_list, &force_https) + cb(s, d->d, cb_args); +} + int settings_add(char *var, char *val) { diff --git a/unix.c b/unix.c index e7a883e..93d0b1c 100644 --- a/unix.c +++ b/unix.c @@ -19,7 +19,7 @@ void init_unix(void) { - resource_dir = g_strdup("/usr/local/share/xombrero/"); + resource_dir = g_strdup("/usr/local/share/xombrero"); } void (*os_init)(void) = init_unix; diff --git a/whitelist.c b/whitelist.c index 9719dac..2c3ee01 100644 --- a/whitelist.c +++ b/whitelist.c @@ -266,7 +266,7 @@ wl_show(struct tab *t, struct karg *args, char *title, struct domain_list *wl) } void -wl_add(char *str, struct domain_list *wl, int handy) +wl_add(const char *str, struct domain_list *wl, int flags) { struct domain *d; int add_dot = 0; @@ -282,7 +282,7 @@ wl_add(char *str, struct domain_list *wl, int handy) str = &str[1]; else if (str[0] == '.') str = &str[0]; - else + else if (!(flags & XT_WL_FLAG_EXCLUDE_SUBDOMAINS)) add_dot = 1; /* slice off port number */ @@ -295,7 +295,7 @@ wl_add(char *str, struct domain_list *wl, int handy) d->d = g_strdup_printf(".%s", str); else d->d = g_strdup(str); - d->handy = handy; + d->handy = flags & XT_WL_FLAG_HANDY; if (RB_INSERT(domain_list, wl, d)) goto unwind; diff --git a/xombrero.1 b/xombrero.1 index 6cf5c27..a896599 100644 --- a/xombrero.1 +++ b/xombrero.1 @@ -1232,6 +1232,14 @@ Enables a backward, forward, and stop button to the toolbar. Additionally if .Cm search_string is set it'll enable an entry box for searches. +.It Cm force_https +This setting is used to define the domains of sites that should be +only accessed over the HTTPS scheme. +Any requests to these domains over HTTP will be rewritten to use HTTPS +instead. +See +.Cm cookie_wl +for semantics. .It Cm guess_search When enabled .Nm @@ -1365,6 +1373,18 @@ This is a plugin whitelist item. See .Cm cookie_wl for semantics and more details. +.It Cm preload_strict_transport +If enabled, a preloaded list of sites which set the HTTP Strict +Transport Security header will be used to automatically set the +.Cm force_https +setting for these sites. +This is used to prevent SSL stripping attacks when first visiting +these sites, before they have been added to the strict-transport file. +This list is comprised of domains chosen by the +.Nm +authors, as well as domains included in Chromium's preloaded HSTS +list. +Default is 1. .It Cm read_only_cookies Mark cookies file read-only and discard all cookies once the session is terminated. diff --git a/xombrero.c b/xombrero.c index 439b367..b215e32 100644 --- a/xombrero.c +++ b/xombrero.c @@ -216,6 +216,7 @@ struct session_list sessions; struct domain_list c_wl; struct domain_list js_wl; struct domain_list pl_wl; +struct domain_list force_https; struct strict_transport_tree st_tree; struct undo_tailq undos; struct keybinding_list kbl; @@ -4722,6 +4723,20 @@ corrupt_file: return (1); } +int +force_https_check(const char *uri) +{ + struct domain *d = NULL; + + if (uri == NULL) + return (0); + + if ((d = wl_find_uri(uri, &force_https)) == NULL) + return (0); + else + return (1); +} + void strict_transport_security_cb(SoupMessage *msg, gpointer data) { @@ -4918,19 +4933,23 @@ webview_rrs_cb(WebKitWebView *wv, WebKitWebFrame *wf, WebKitWebResource *res, WebKitNetworkRequest *request, WebKitNetworkResponse *response, struct tab *t) { - SoupMessage *msg; - SoupURI *uri; - struct http_accept ha_find, *ha; - const char *accept; + SoupMessage *msg = NULL; + SoupURI *uri = NULL; + struct http_accept ha_find, *ha = NULL; + const char *accept = NULL; + char *uri_s = NULL; msg = webkit_network_request_get_message(request); if (!msg) return; uri = soup_message_get_uri(msg); - if (!uri) return; + if (!uri) + return; + uri_s = soup_uri_to_string(uri, FALSE); if (strcmp(uri->scheme, SOUP_URI_SCHEME_HTTP) == 0) { - if (strict_transport_check(uri->host)) { + if (strict_transport_check(uri->host) || + force_https_check(uri_s)) { DNPRINTF(XT_D_NAV, "webview_rrs_cb: force https for %s\n", uri->host); soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTPS); @@ -4946,7 +4965,7 @@ webview_rrs_cb(WebKitWebView *wv, WebKitWebFrame *wf, WebKitWebResource *res, "Accept"); if (accept == NULL || strncmp(accept, "text/html", strlen("text/html"))) - return; + goto done; ha_find.id = t->http_accept_id; ha = RB_FIND(http_accept_list, &ha_list, &ha_find); @@ -4963,6 +4982,9 @@ webview_rrs_cb(WebKitWebView *wv, WebKitWebFrame *wf, WebKitWebResource *res, soup_message_headers_replace(msg->request_headers, "Accept", http_accept->value); } +done: + if (uri_s) + g_free(uri_s); } WebKitWebView * @@ -8365,6 +8387,7 @@ main(int argc, char **argv) RB_INIT(&hl); RB_INIT(&js_wl); RB_INIT(&pl_wl); + RB_INIT(&force_https); RB_INIT(&downloads); RB_INIT(&st_tree); RB_INIT(&svl); @@ -8494,6 +8517,13 @@ main(int argc, char **argv) pwd->pw_dir, XT_CONF_FILE); config_parse(conf, 0); + /* read preloaded HSTS list */ + if (preload_strict_transport) { + snprintf(conf, sizeof conf, "%s" PS "%s", + resource_dir, XT_HSTS_PRELOAD_FILE); + config_parse(conf, 0); + } + /* init fonts */ cmd_font = pango_font_description_from_string(cmd_font_name); oops_font = pango_font_description_from_string(oops_font_name); diff --git a/xombrero.conf b/xombrero.conf index b3643c4..f04eddb 100644 --- a/xombrero.conf +++ b/xombrero.conf @@ -59,6 +59,7 @@ # userstyle_global = 1 # enable_favicon_entry = 0 # enable_favicon_tabs = 1 +# preload_strict_transport = 1 # referer = always # warn_cert_changes = 1 @@ -146,6 +147,15 @@ ## +## FORCE HTTPS FOR SITES +## + +# Add the domains of sites that should be only accesed over HTTPS. + +# force_https = .conformal.com + + +## ## MIME TYPES ## diff --git a/xombrero.h b/xombrero.h index 218d712..cd8f4c7 100644 --- a/xombrero.h +++ b/xombrero.h @@ -370,6 +370,7 @@ RB_PROTOTYPE(http_accept_list, http_accept, entry, http_accept_rb_cmp); #define XT_CSS_FILE ("xombrero.css") #define XT_FAVS_FILE ("favorites") #define XT_SOD_FILE ("startofday") +#define XT_HSTS_PRELOAD_FILE ("hsts-preload") #define XT_RESERVED_CHARS "$&+,/:;=?@ \"<>#%%{}|^~[]`" int run_script(struct tab *, char *); @@ -525,6 +526,9 @@ void startpage_add(const char *, ...); #define XT_WL_COOKIE (2) #define XT_WL_PLUGIN (3) +#define XT_WL_FLAG_HANDY (1<<0) +#define XT_WL_FLAG_EXCLUDE_SUBDOMAINS (1<<1) + struct domain { RB_ENTRY(domain) entry; gchar *d; @@ -648,6 +652,7 @@ int command_mode(struct tab *, struct karg *); #define XT_DS_ALLOW_INSECURE_CONTENT (TRUE) #define XT_DS_ALLOW_INSECURE_SCRIPTS (TRUE) #define XT_DS_DO_NOT_TRACK (0) +#define XT_DS_PRELOAD_STRICT_TRANSPORT (1) /* actions */ @@ -739,6 +744,8 @@ int cert_cmd(struct tab *, struct karg *); void focus_webview(struct tab *); int is_g_object_setting(GObject *, char *); int set_scrollbar_visibility(struct tab *, int); +void wl_add(const char *, struct domain_list *, int); +void preload_hsts(void); #define XT_DL_START (0) #define XT_DL_RESTART (1) @@ -828,6 +835,7 @@ extern regex_t url_re; extern int allow_insecure_content; extern int allow_insecure_scripts; extern int do_not_track; +extern int preload_strict_transport; /* globals */ extern void (*os_init)(void); @@ -854,6 +862,7 @@ extern struct about_type about_list[]; extern struct domain_list c_wl; extern struct domain_list js_wl; extern struct domain_list pl_wl; +extern struct domain_list force_https; extern struct strict_transport_tree st_tree; extern struct alias_list aliases; extern struct mime_type_list mtl; |