about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--freebsd/Makefile1
-rw-r--r--hsts-preload108
-rw-r--r--linux/Makefile3
-rw-r--r--settings.c35
-rw-r--r--unix.c2
-rw-r--r--whitelist.c6
-rw-r--r--xombrero.120
-rw-r--r--xombrero.c44
-rw-r--r--xombrero.conf10
-rw-r--r--xombrero.h9
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;