From 2507f971caa0d556164e09a6e5bbbaa1248119a0 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Tue, 13 Apr 2010 23:44:21 +0200 Subject: [PATCH] Validate SSL against root certificates If one of two known root certificate files is available, we enable certificate validation, otherwise a warning is emitted. Not using validation means that we trust any certificate. We should consider doing the opposite. The new property MidoriView:security is set during load and indicates the security status. midori_view_get_security can be used to determine the status later on. midori_location_action_set_security_hint is implemented to present security status visually. For now, this only changes the icon, we need to find a more visible solution. MidoriBrowser updates the security hint for the current view in _midori_browser_update_interface. --- midori/main.c | 20 +++++++++ midori/midori-browser.c | 2 + midori/midori-locationaction.c | 41 +++++++++++++++++- midori/midori-locationaction.h | 5 +++ midori/midori-view.c | 79 +++++++++++++++++++++++++++++++++- midori/midori-view.h | 17 ++++++++ 6 files changed, 162 insertions(+), 2 deletions(-) diff --git a/midori/main.c b/midori/main.c index e79d78fd..d8b73f70 100644 --- a/midori/main.c +++ b/midori/main.c @@ -849,9 +849,29 @@ midori_soup_session_prepare (SoupSession* session, SoupCookieJar* cookie_jar, MidoriWebSettings* settings) { + const gchar* certificate_files[] = + { + "/etc/pki/tls/certs/ca-bundle.crt", + "/etc/ssl/certs/ca-certificates.crt", + NULL + }; + guint i; SoupSessionFeature* feature; gchar* config_file; + for (i = 0; i < G_N_ELEMENTS (certificate_files); i++) + if (g_access (certificate_files[i], F_OK) == 0) + { + g_object_set (session, + "ssl-ca-file", certificate_files[i], + "ssl-strict", FALSE, + NULL); + break; + } + if (i == G_N_ELEMENTS (certificate_files)) + g_warning (_("No root certificate file is available. " + "SSL certificates cannot be verified.")); + soup_session_settings_notify_http_proxy_cb (settings, NULL, session); g_signal_connect (settings, "notify::http-proxy", G_CALLBACK (soup_session_settings_notify_http_proxy_cb), session); diff --git a/midori/midori-browser.c b/midori/midori-browser.c index 30ab381c..1b2f883d 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -363,6 +363,8 @@ _midori_browser_update_interface (MidoriBrowser* browser) #endif action = _action_by_name (browser, "Location"); + midori_location_action_set_security_hint ( + MIDORI_LOCATION_ACTION (action), midori_view_get_security (view)); if (g_object_get_data (G_OBJECT (view), "news-feeds")) { midori_location_action_set_secondary_icon ( diff --git a/midori/midori-locationaction.c b/midori/midori-locationaction.c index 9bbd710b..b4b1dafe 100644 --- a/midori/midori-locationaction.c +++ b/midori/midori-locationaction.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2008-2009 Christian Dywan + Copyright (C) 2008-2010 Christian Dywan Copyright (C) 2008-2010 Dale Whittaker This library is free software; you can redistribute it and/or @@ -1685,3 +1685,42 @@ midori_location_action_clear (MidoriLocationAction* location_action) midori_location_action_toggle_arrow (location_action); } + +/** + * midori_location_action_set_security_hint: + * @location_action: a #MidoriLocationAction + * @hint: a security hint + * + * Sets a security hint on the action, so that the security status + * can be reflected visually. + * + * Since: 0.2.5 + **/ +void +midori_location_action_set_security_hint (MidoriLocationAction* location_action, + MidoriSecurity hint) +{ + #if !HAVE_HILDON + GSList* proxies; + GtkWidget* entry; + GtkWidget* child; + #endif + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + + #if !HAVE_HILDON + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); + + for (; proxies != NULL; proxies = g_slist_next (proxies)) + if (GTK_IS_TOOL_ITEM (proxies->data)) + { + entry = midori_location_action_entry_for_proxy (proxies->data); + child = gtk_bin_get_child (GTK_BIN (entry)); + + if (hint == MIDORI_SECURITY_UNKNOWN) + gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (child), GTK_ICON_ENTRY_PRIMARY, GTK_STOCK_INFO); + else if (hint == MIDORI_SECURITY_TRUSTED) + gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (child), GTK_ICON_ENTRY_PRIMARY, "lock"); + } + #endif +} diff --git a/midori/midori-locationaction.h b/midori/midori-locationaction.h index 2dc56314..3decc542 100644 --- a/midori/midori-locationaction.h +++ b/midori/midori-locationaction.h @@ -13,6 +13,7 @@ #define __MIDORI_LOCATION_ACTION_H__ #include +#include "midori-view.h" G_BEGIN_DECLS @@ -101,6 +102,10 @@ midori_location_action_delete_item_from_uri (MidoriLocationAction* location_acti void midori_location_action_clear (MidoriLocationAction* location_action); +void +midori_location_action_set_security_hint (MidoriLocationAction* location_action, + MidoriSecurity hint); + G_END_DECLS #endif /* __MIDORI_LOCATION_ACTION_H__ */ diff --git a/midori/midori-view.c b/midori/midori-view.c index 2bffc890..7a31e3f4 100644 --- a/midori/midori-view.c +++ b/midori/midori-view.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2009 Christian Dywan + Copyright (C) 2007-2010 Christian Dywan Copyright (C) 2009 Jean-François Guchens This library is free software; you can redistribute it and/or @@ -66,6 +66,7 @@ struct _MidoriView gchar* uri; gboolean special; gchar* title; + MidoriSecurity security; gchar* mime_type; GdkPixbuf* icon; gchar* icon_uri; @@ -154,12 +155,30 @@ midori_new_view_get_type (void) return type; } +GType +midori_security_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_SECURITY_NONE, "MIDORI_SECURITY_NONE", "No security" }, + { MIDORI_SECURITY_UNKNOWN, "MIDORI_SECURITY_UNKNOWN", "Security unknown" }, + { MIDORI_SECURITY_TRUSTED, "MIDORI_SECURITY_TRUSTED", "Trusted security" }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriSecurity", values); + } + return type; +} + enum { PROP_0, PROP_URI, PROP_TITLE, + PROP_SECURITY, PROP_MIME_TYPE, PROP_ICON, PROP_LOAD_STATUS, @@ -445,6 +464,23 @@ midori_view_class_init (MidoriViewClass* class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * MidoriView:security: + * + * The security status of the loaded page. + * + * Since: 0.2.5 + */ + g_object_class_install_property (gobject_class, + PROP_SECURITY, + g_param_spec_enum ( + "security", + "Security", + "The security of the currently loaded page", + MIDORI_TYPE_SECURITY, + MIDORI_SECURITY_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** * MidoriView:mime-type: * @@ -1012,9 +1048,30 @@ webkit_web_view_load_committed_cb (WebKitWebView* web_view, midori_view_update_icon (view, NULL); + if (!strncmp (uri, "https", 5)) + { + WebKitWebDataSource *source; + WebKitNetworkRequest *request; + SoupMessage *message; + + source = webkit_web_frame_get_data_source (web_frame); + request = webkit_web_data_source_get_request (source); + message = webkit_network_request_get_message (request); + + if (message + && soup_message_get_flags (message) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) + view->security = MIDORI_SECURITY_TRUSTED; + else + view->security = MIDORI_SECURITY_UNKNOWN; + } + else + view->security = MIDORI_SECURITY_NONE; + g_object_notify (G_OBJECT (view), "security"); + midori_view_update_load_status (view, MIDORI_LOAD_COMMITTED); g_object_thaw_notify (G_OBJECT (view)); + } static void @@ -2723,6 +2780,7 @@ midori_view_init (MidoriView* view) { view->uri = NULL; view->title = NULL; + view->security = MIDORI_SECURITY_NONE; view->mime_type = g_strdup (""); view->icon = NULL; view->icon_uri = NULL; @@ -2862,6 +2920,9 @@ midori_view_get_property (GObject* object, case PROP_TITLE: g_value_set_string (value, view->title); break; + case PROP_SECURITY: + g_value_set_enum (value, view->security); + break; case PROP_MIME_TYPE: g_value_set_string (value, view->mime_type); break; @@ -4862,6 +4923,22 @@ midori_view_get_web_view (MidoriView* view) return view->web_view; } +/** + * midori_view_get_security + * @view: a #MidoriView + * + * Returns: The #MidoriSecurity for this view + * + * Since: 0.2.5 + **/ +MidoriSecurity +midori_view_get_security (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), MIDORI_SECURITY_NONE); + + return view->security; +} + static void thumb_view_load_status_cb (MidoriView* thumb_view, GParamSpec* pspec, diff --git a/midori/midori-view.h b/midori/midori-view.h index 3bbc7d97..73af4d75 100644 --- a/midori/midori-view.h +++ b/midori/midori-view.h @@ -46,6 +46,20 @@ midori_new_view_get_type (void) G_GNUC_CONST; #define MIDORI_TYPE_VIEW \ (midori_view_get_type ()) + +typedef enum +{ + MIDORI_SECURITY_NONE, /* The connection is neither encrypted nor verified. */ + MIDORI_SECURITY_UNKNOWN, /* The security is unknown, due to lack of validation. */ + MIDORI_SECURITY_TRUSTED /* The security is validated and trusted. */ +} MidoriSecurity; + +GType +midori_security_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_SECURITY \ + (midori_security_get_type ()) + #define MIDORI_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEW, MidoriView)) #define MIDORI_VIEW_CLASS(klass) \ @@ -212,6 +226,9 @@ midori_view_get_snapshot (MidoriView* view, GtkWidget* midori_view_get_web_view (MidoriView* view); +MidoriSecurity +midori_view_get_security (MidoriView* view); + G_END_DECLS #endif /* __MIDORI_VIEW_H__ */