[epiphany/wip/google-safe-browsing: 12/27] web-view: Verify and inform user about URL safety



commit 9a35258cfd19dc8e96d736416cb2db596b368089
Author: Gabriel Ivascu <gabrielivascu gnome org>
Date:   Wed Sep 20 21:32:33 2017 +0300

    web-view: Verify and inform user about URL safety

 embed/ephy-embed-shell.c             |   34 +++++++
 embed/ephy-web-view.c                |  166 +++++++++++++++++++++++++++++++---
 embed/ephy-web-view.h                |    3 +-
 lib/safe-browsing/ephy-gsb-storage.c |    8 +-
 lib/safe-browsing/ephy-gsb-utils.h   |    4 +
 src/ephy-session.c                   |    2 +-
 6 files changed, 197 insertions(+), 20 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 9003701..3d913df 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -80,6 +80,7 @@ enum {
   WEB_VIEW_CREATED,
   PAGE_CREATED,
   ALLOW_TLS_CERTIFICATE,
+  ALLOW_UNSAFE_BROWSING,
   FORM_AUTH_DATA_SAVE_REQUESTED,
   SENSITIVE_FORM_FOCUSED,
 
@@ -337,6 +338,17 @@ web_extension_tls_error_page_message_received_cb (WebKitUserContentManager *mana
 }
 
 static void
+web_extension_unsafe_browsing_error_page_message_received_cb (WebKitUserContentManager *manager,
+                                                              WebKitJavascriptResult   *message,
+                                                              EphyEmbedShell           *shell)
+{
+  guint64 page_id;
+
+  page_id = ephy_embed_utils_get_js_result_as_number (message);
+  g_signal_emit (shell, signals[ALLOW_UNSAFE_BROWSING], 0, page_id);
+}
+
+static void
 web_extension_about_apps_message_received_cb (WebKitUserContentManager *manager,
                                               WebKitJavascriptResult   *message,
                                               EphyEmbedShell           *shell)
@@ -986,6 +998,12 @@ ephy_embed_shell_startup (GApplication *application)
                     shell);
 
   webkit_user_content_manager_register_script_message_handler (priv->user_content,
+                                                               "unsafeBrowsingErrorPage");
+  g_signal_connect (priv->user_content, "script-message-received::unsafeBrowsingErrorPage",
+                    G_CALLBACK (web_extension_unsafe_browsing_error_page_message_received_cb),
+                    shell);
+
+  webkit_user_content_manager_register_script_message_handler (priv->user_content,
                                                                "formAuthData");
   g_signal_connect (priv->user_content, "script-message-received::formAuthData",
                     G_CALLBACK (web_extension_form_auth_data_message_received_cb),
@@ -1261,6 +1279,22 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass)
                   G_TYPE_UINT64);
 
   /**
+   * EphyEmbedShell::allow-unsafe-browsing:
+   * @shell: the #EphyEmbedShell
+   * @page_id: the identifier of the web page
+   *
+   * Emitted when the web extension requests an exception be
+   * permitted for the unsafe browsing warning on the given page
+   */
+  signals[ALLOW_UNSAFE_BROWSING] =
+    g_signal_new ("allow-unsafe-browsing",
+                  EPHY_TYPE_EMBED_SHELL,
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_UINT64);
+
+  /**
    * EphyEmbedShell::form-auth-data-save-requested:
    * @shell: the #EphyEmbedShell
    * @request_id: the identifier of the request
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index cff23ec..4fe67d7 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -33,6 +33,7 @@
 #include "ephy-favicon-helpers.h"
 #include "ephy-file-helpers.h"
 #include "ephy-file-monitor.h"
+#include "ephy-gsb-utils.h"
 #include "ephy-history-service.h"
 #include "ephy-lib-type-builtins.h"
 #include "ephy-option-menu.h"
@@ -78,6 +79,7 @@ struct _EphyWebView {
   guint load_failed : 1;
   guint history_frozen : 1;
   guint ever_committed : 1;
+  guint bypass_gsb_verification : 1;
 
   char *address;
   char *display_address;
@@ -827,6 +829,18 @@ allow_tls_certificate_cb (EphyEmbedShell *shell,
 }
 
 static void
+allow_unsafe_browsing_cb (EphyEmbedShell *shell,
+                          guint64         page_id,
+                          EphyWebView    *view)
+{
+  if (webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)) != page_id)
+    return;
+
+  view->bypass_gsb_verification = TRUE;
+  ephy_web_view_load_url (view, ephy_web_view_get_address (view));
+}
+
+static void
 page_created_cb (EphyEmbedShell        *shell,
                  guint64                page_id,
                  EphyWebExtensionProxy *web_extension,
@@ -849,6 +863,10 @@ page_created_cb (EphyEmbedShell        *shell,
   g_signal_connect_object (shell, "allow-tls-certificate",
                            G_CALLBACK (allow_tls_certificate_cb),
                            view, 0);
+
+  g_signal_connect_object (shell, "allow-unsafe-browsing",
+                           G_CALLBACK (allow_unsafe_browsing_cb),
+                           view, 0);
 }
 
 static void
@@ -1008,7 +1026,7 @@ process_crashed_cb (EphyWebView *web_view, gpointer user_data)
     return;
 
   ephy_web_view_load_error_page (web_view, ephy_web_view_get_address (web_view),
-                                 EPHY_WEB_VIEW_ERROR_PROCESS_CRASH, NULL);
+                                 EPHY_WEB_VIEW_ERROR_PROCESS_CRASH, NULL, NULL);
 }
 
 static gboolean
@@ -1259,12 +1277,74 @@ new_window_cb (EphyWebView *view,
   popups_manager_add_window (view, container);
 }
 
+typedef struct {
+  EphyWebView          *web_view;
+  WebKitPolicyDecision *decision;
+  char                 *request_uri;
+} VerifyUrlData;
+
+static inline VerifyUrlData *
+verify_url_data_new (EphyWebView          *web_view,
+                     WebKitPolicyDecision *decision,
+                     const char           *request_uri)
+{
+  VerifyUrlData *data = g_slice_new (VerifyUrlData);
+
+  data->web_view = g_object_ref (web_view);
+  data->decision = g_object_ref (decision);
+  data->request_uri = g_strdup (request_uri);
+
+  return data;
+}
+
+static inline void
+verify_url_data_free (VerifyUrlData *data)
+{
+  g_object_unref (data->web_view);
+  g_object_unref (data->decision);
+  g_free (data->request_uri);
+  g_slice_free (VerifyUrlData, data);
+}
+
+static void
+verify_url_cb (GHashTable *threats,
+               gpointer    user_data)
+{
+  VerifyUrlData *data = (VerifyUrlData *)user_data;
+  EphyGSBThreatList *list;
+  GList *threat_lists;
+
+  if (g_hash_table_size (threats) == 0) {
+    webkit_policy_decision_use (data->decision);
+    goto out;
+  }
+
+  webkit_policy_decision_ignore (data->decision);
+
+  /* Very rarely there are URLs that pose multiple types of threats.
+   * However, inform the user only about the first threat type.
+   */
+  threat_lists = g_hash_table_get_keys (threats);
+  list = threat_lists->data;
+  ephy_web_view_load_error_page (data->web_view, data->request_uri,
+                                 EPHY_WEB_VIEW_ERROR_UNSAFE_BROWSING,
+                                 NULL, list->threat_type);
+
+  g_list_free (threat_lists);
+out:
+  g_hash_table_unref (threats);
+  verify_url_data_free (data);
+}
+
 static gboolean
 decide_policy_cb (WebKitWebView           *web_view,
                   WebKitPolicyDecision    *decision,
                   WebKitPolicyDecisionType decision_type,
                   gpointer                 user_data)
 {
+  EphyGSBService *service;
+  WebKitNavigationPolicyDecision *navigation_decision;
+  WebKitNavigationAction *action;
   WebKitResponsePolicyDecision *response_decision;
   WebKitURIResponse *response;
   WebKitURIRequest *request;
@@ -1273,6 +1353,30 @@ decide_policy_cb (WebKitWebView           *web_view,
   const char *mime_type;
   const char *request_uri;
 
+  if (decision_type == WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION) {
+    if (!g_settings_get_boolean (EPHY_SETTINGS_WEB,
+                                 EPHY_PREFS_WEB_ENABLE_SAFE_BROWSING))
+      return FALSE;
+
+    if (EPHY_WEB_VIEW (web_view)->bypass_gsb_verification) {
+      EPHY_WEB_VIEW (web_view)->bypass_gsb_verification = FALSE;
+      return FALSE;
+    }
+
+    navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
+    action = webkit_navigation_policy_decision_get_navigation_action (navigation_decision);
+    request = webkit_navigation_action_get_request (action);
+    request_uri = webkit_uri_request_get_uri (request);
+
+    service = ephy_embed_shell_get_global_gsb_service (ephy_embed_shell_get_default ());
+    ephy_gsb_service_verify_url (service, request_uri, verify_url_cb,
+                                 verify_url_data_new (EPHY_WEB_VIEW (web_view),
+                                                      decision, request_uri));
+
+    /* Delay decision until the safe browsing verification has completed. */
+    return TRUE;
+  }
+
   if (decision_type != WEBKIT_POLICY_DECISION_TYPE_RESPONSE)
     return FALSE;
 
@@ -2155,6 +2259,7 @@ format_tls_error_page (EphyWebView *view,
 static void
 format_unsafe_browsing_error_page (EphyWebView *view,
                                    const char  *origin,
+                                   const char  *threat_type,
                                    char       **page_title,
                                    char       **message_title,
                                    char       **message_body,
@@ -2178,17 +2283,47 @@ format_unsafe_browsing_error_page (EphyWebView *view,
   *message_title = g_strdup (_("Unsafe website detected!"));
 
   formatted_origin = g_strdup_printf ("<strong>%s</strong>", origin);
-  /* Error details on the unsafe browsing error page. */
-  first_paragraph = g_strdup_printf (_("%s is reported to be unsafe. It might "
-                                       "trick you by pretending to be a "
-                                       "different website to steal your "
-                                       "information, or it might harm "
-                                       "your computer by installing malicious "
-                                       "software."), /* FIXME: be more accurate */
-                                     formatted_origin);
+  /* Error details on the unsafe browsing error page.
+   * https://developers.google.com/safe-browsing/v4/usage-limits#UserWarnings
+   */
+  if (!g_strcmp0 (threat_type, GSB_THREAT_TYPE_MALWARE)) {
+    first_paragraph = g_strdup_printf (_("Visiting %s may harm your computer. This "
+                                         "page appears to contain malicious code that could "
+                                         "be downloaded to your computer without your consent."),
+                                       formatted_origin);
+    *message_details = g_strdup_printf (_("You can learn more about harmful web content "
+                                          "including viruses and other malicious code "
+                                          "and how to protect your computer at %s."),
+                                        "<a href=\"https://www.stopbadware.org/\";>"
+                                          "www.stopbadware.org"
+                                        "</a>");
+  } else if (!g_strcmp0 (threat_type, GSB_THREAT_TYPE_SOCIAL_ENGINEERING)) {
+    first_paragraph = g_strdup_printf (_("Attackers on %s may trick you into doing "
+                                         "something dangerous like installing software or "
+                                         "revealing your personal information (for example, "
+                                         "passwords, phone numbers, or credit cards)."),
+                                       formatted_origin);
+    *message_details = g_strdup_printf (_("You can find out more about social engineering "
+                                          "(phishing) at %s or from %s."),
+                                        "<a href=\"https://support.google.com/webmasters/answer/6350487\";>"
+                                          "Social Engineering (Phishing and Deceptive Sites)"
+                                        "</a>",
+                                        "<a href=\"https://www.antiphishing.org/\";>"
+                                          "www.antiphishing.org"
+                                        "</a>");
+  } else {
+    first_paragraph = g_strdup_printf (_("%s may contain harmful programs. Attackers might "
+                                         "attempt to trick you into installing programs that "
+                                         "harm your browsing experience (for example, by changing "
+                                         "your homepage or showing extra ads on sites you visit)."),
+                                       formatted_origin);
+    *message_details = g_strdup_printf (_("You can learn more about unwanted software at %s."),
+                                        "<a 
href=\"https://www.google.com/about/unwanted-software-policy.html\";>"
+                                          "Unwanted Software Policy"
+                                        "</a>");
+  }
 
   *message_body = g_strdup_printf ("<p>%s</p>", first_paragraph);
-  *message_details = g_strdup (""); /* FIXME */
 
   /* The button on unsafe browsing error page. DO NOT ADD MNEMONICS HERE. */
   *button_label = g_strdup (_("Go Back"));
@@ -2216,6 +2351,7 @@ format_unsafe_browsing_error_page (EphyWebView *view,
  * @uri: uri that caused the failure
  * @page: one of #EphyWebViewErrorPage
  * @error: a GError to inspect, or %NULL
+ * @user_data: a pointer to additional data
  *
  * Loads an error page appropiate for @page in @view.
  *
@@ -2224,7 +2360,8 @@ void
 ephy_web_view_load_error_page (EphyWebView         *view,
                                const char          *uri,
                                EphyWebViewErrorPage page,
-                               GError              *error)
+                               GError              *error,
+                               gpointer             user_data)
 {
   GBytes *html_file;
   GString *html = g_string_new ("");
@@ -2322,6 +2459,7 @@ ephy_web_view_load_error_page (EphyWebView         *view,
     case EPHY_WEB_VIEW_ERROR_UNSAFE_BROWSING:
       format_unsafe_browsing_error_page (view,
                                          origin,
+                                         user_data,
                                          &page_title,
                                          &msg_title,
                                          &msg_body,
@@ -2400,7 +2538,7 @@ load_failed_cb (WebKitWebView  *web_view,
   if (error->domain != WEBKIT_NETWORK_ERROR &&
       error->domain != WEBKIT_POLICY_ERROR &&
       error->domain != WEBKIT_PLUGIN_ERROR) {
-    ephy_web_view_load_error_page (view, uri, EPHY_WEB_VIEW_ERROR_PAGE_NETWORK_ERROR, error);
+    ephy_web_view_load_error_page (view, uri, EPHY_WEB_VIEW_ERROR_PAGE_NETWORK_ERROR, error, NULL);
     return TRUE;
   }
 
@@ -2418,7 +2556,7 @@ load_failed_cb (WebKitWebView  *web_view,
     case WEBKIT_PLUGIN_ERROR_CANNOT_LOAD_PLUGIN:
     case WEBKIT_PLUGIN_ERROR_JAVA_UNAVAILABLE:
     case WEBKIT_PLUGIN_ERROR_CONNECTION_CANCELLED:
-      ephy_web_view_load_error_page (view, uri, EPHY_WEB_VIEW_ERROR_PAGE_NETWORK_ERROR, error);
+      ephy_web_view_load_error_page (view, uri, EPHY_WEB_VIEW_ERROR_PAGE_NETWORK_ERROR, error, NULL);
       return TRUE;
     case WEBKIT_NETWORK_ERROR_CANCELLED:
     {
@@ -2462,7 +2600,7 @@ load_failed_with_tls_error_cb (WebKitWebView       *web_view,
   view->tls_errors = errors;
   view->tls_error_failing_uri = g_strdup (uri);
   ephy_web_view_load_error_page (EPHY_WEB_VIEW (web_view), uri,
-                                 EPHY_WEB_VIEW_ERROR_INVALID_TLS_CERTIFICATE, NULL);
+                                 EPHY_WEB_VIEW_ERROR_INVALID_TLS_CERTIFICATE, NULL, NULL);
 
   return TRUE;
 }
diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h
index f5bbdbe..49da569 100644
--- a/embed/ephy-web-view.h
+++ b/embed/ephy-web-view.h
@@ -114,7 +114,8 @@ EphyWebViewErrorPage       ephy_web_view_get_error_page           (EphyWebView
 void                       ephy_web_view_load_error_page          (EphyWebView               *view,
                                                                    const char                *uri,
                                                                    EphyWebViewErrorPage       page,
-                                                                   GError                    *error);
+                                                                   GError                    *error,
+                                                                   gpointer                   user_data);
 void                       ephy_web_view_get_best_web_app_icon    (EphyWebView               *view,
                                                                    GCancellable              *cancellable,
                                                                    GAsyncReadyCallback        callback,
diff --git a/lib/safe-browsing/ephy-gsb-storage.c b/lib/safe-browsing/ephy-gsb-storage.c
index 6f27610..0abb4ec 100644
--- a/lib/safe-browsing/ephy-gsb-storage.c
+++ b/lib/safe-browsing/ephy-gsb-storage.c
@@ -46,10 +46,10 @@
  * The format is {THREAT_TYPE, PLATFORM_TYPE, THREAT_ENTRY_TYPE}.
  */
 static const char * const gsb_linux_threat_lists[][3] = {
-  {"MALWARE",            "LINUX", "URL"},
-  {"SOCIAL_ENGINEERING", "LINUX", "URL"},
-  {"UNWANTED_SOFTWARE",  "LINUX", "URL"},
-  {"MALWARE",            "LINUX", "IP_RANGE"},
+  {GSB_THREAT_TYPE_MALWARE,            "LINUX", "URL"},
+  {GSB_THREAT_TYPE_SOCIAL_ENGINEERING, "LINUX", "URL"},
+  {GSB_THREAT_TYPE_UNWANTED_SOFTWARE,  "LINUX", "URL"},
+  {GSB_THREAT_TYPE_MALWARE,            "LINUX", "IP_RANGE"},
 };
 
 struct _EphyGSBStorage {
diff --git a/lib/safe-browsing/ephy-gsb-utils.h b/lib/safe-browsing/ephy-gsb-utils.h
index 4821c7c..341649a 100644
--- a/lib/safe-browsing/ephy-gsb-utils.h
+++ b/lib/safe-browsing/ephy-gsb-utils.h
@@ -28,6 +28,10 @@ G_BEGIN_DECLS
 #define GSB_HASH_TYPE G_CHECKSUM_SHA256
 #define GSB_HASH_SIZE (g_checksum_type_get_length (GSB_HASH_TYPE))
 
+#define GSB_THREAT_TYPE_MALWARE            "MALWARE"
+#define GSB_THREAT_TYPE_SOCIAL_ENGINEERING "SOCIAL_ENGINEERING"
+#define GSB_THREAT_TYPE_UNWANTED_SOFTWARE  "UNWANTED_SOFTWARE"
+
 typedef struct {
   char   *threat_type;
   char   *platform_type;
diff --git a/src/ephy-session.c b/src/ephy-session.c
index 76b220a..72a3620 100644
--- a/src/ephy-session.c
+++ b/src/ephy-session.c
@@ -1018,7 +1018,7 @@ confirm_before_recover (EphyWindow *window, const char *url, const char *title)
                                    0);
 
   ephy_web_view_load_error_page (ephy_embed_get_web_view (embed), url,
-                                 EPHY_WEB_VIEW_ERROR_PAGE_CRASH, NULL);
+                                 EPHY_WEB_VIEW_ERROR_PAGE_CRASH, NULL, NULL);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]