[geary/wip/713247-tls] Now fixing w/ LoginDialog and initial registration



commit 1625872d4267696f60b1b6bd4d8d0bad6ca48528
Author: Jim Nelson <jim yorba org>
Date:   Wed Aug 27 19:46:52 2014 -0700

    Now fixing w/ LoginDialog and initial registration

 src/client/application/geary-controller.vala  |   74 +++++++++++++++++++++----
 src/engine/api/geary-account-information.vala |   10 ++--
 src/engine/api/geary-endpoint.vala            |   20 +++++--
 src/engine/api/geary-engine.vala              |    7 +-
 4 files changed, 85 insertions(+), 26 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 9f3c90a..17dc6ca 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -513,13 +513,13 @@ public class GearyController : Geary.BaseObject {
     
     private void on_untrusted_host(Geary.AccountInformation account_information,
         Geary.Endpoint endpoint, Geary.Endpoint.SecurityType security, TlsConnection cx,
-        Geary.Service service, TlsCertificateFlags warnings) {
-        prompt_untrusted_host_async.begin(account_information, endpoint, security, cx, service, warnings);
+        Geary.Service service) {
+        prompt_untrusted_host_async.begin(account_information, endpoint, security, cx, service);
     }
     
     private async void prompt_untrusted_host_async(Geary.AccountInformation account_information,
         Geary.Endpoint endpoint, Geary.Endpoint.SecurityType security, TlsConnection cx,
-        Geary.Service service, TlsCertificateFlags warnings) {
+        Geary.Service service) {
         // use a mutex to prevent multiple dialogs popping up at the same time
         int token = Geary.Nonblocking.Mutex.INVALID_TOKEN;
         try {
@@ -531,7 +531,7 @@ public class GearyController : Geary.BaseObject {
         }
         
         yield locked_prompt_untrusted_host_async(account_information, endpoint, security, cx,
-            service, warnings);
+            service);
         
         try {
             untrusted_host_prompt_mutex.release(ref token);
@@ -541,16 +541,23 @@ public class GearyController : Geary.BaseObject {
         }
     }
     
+    private static void get_gcr_params(Geary.Endpoint endpoint, out Gcr.Certificate cert,
+        out string peer) {
+        cert = new Gcr.SimpleCertificate(endpoint.untrusted_certificate.certificate.data);
+        peer = "%s:%u".printf(endpoint.remote_address.hostname, endpoint.remote_address.port);
+    }
+    
     private async void locked_prompt_untrusted_host_async(Geary.AccountInformation account_information,
         Geary.Endpoint endpoint, Geary.Endpoint.SecurityType security, TlsConnection cx,
-        Geary.Service service, TlsCertificateFlags warnings) {
+        Geary.Service service) {
         // possible while waiting on mutex that this endpoint became trusted or untrusted
         if (endpoint.trust_untrusted_host != Geary.Trillian.UNKNOWN)
             return;
         
-        // Convert into a GCR certificate
-        Gcr.Certificate cert = new Gcr.SimpleCertificate(cx.peer_certificate.certificate.data);
-        string peer = "%s:%u".printf(endpoint.remote_address.hostname, endpoint.remote_address.port);
+        // get GCR parameters
+        Gcr.Certificate cert;
+        string peer;
+        get_gcr_params(endpoint, out cert, out peer);
         
         // Geary allows for user to auto-revoke all questionable server certificates without
         // digging around in a keyring/pk manager
@@ -582,9 +589,18 @@ public class GearyController : Geary.BaseObject {
                 peer, err.message);
         }
         
-        // question the user about this certificate
-        CertificateWarningDialog dialog = new CertificateWarningDialog(main_window, endpoint,
-            service, warnings);
+        // if the login dialog is in play, can't prompt from within its run() loop, so exit here
+        // and let it deal with this after the dialog is finished; see validate_or_retry_async()
+        if (login_dialog != null && login_dialog.visible)
+            return;
+        
+        prompt_for_untrusted_host(main_window, account_information, endpoint, service);
+    }
+    
+    private void prompt_for_untrusted_host(Gtk.Window? parent, Geary.AccountInformation account_information,
+        Geary.Endpoint endpoint, Geary.Service service) {
+        CertificateWarningDialog dialog = new CertificateWarningDialog(parent, endpoint, service,
+            endpoint.tls_validation_warnings);
         switch (dialog.run()) {
             case CertificateWarningDialog.Result.TRUST:
                 endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
@@ -593,6 +609,11 @@ public class GearyController : Geary.BaseObject {
             case CertificateWarningDialog.Result.ALWAYS_TRUST:
                 endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
                 
+                // get GCR parameters for pinning
+                Gcr.Certificate cert;
+                string peer;
+                get_gcr_params(endpoint, out cert, out peer);
+                
                 // pinning the certificate creates an exception for the next time a connection
                 // is attempted
                 debug("Pinning certificate for %s...", peer);
@@ -646,6 +667,37 @@ public class GearyController : Geary.BaseObject {
         if (result == Geary.Engine.ValidationResult.OK)
             return null;
         
+        // check Endpoints for trust issues
+        
+        // use LoginDialog for parent only if available and visible
+        Gtk.Window? parent;
+        if (login_dialog != null && login_dialog.visible)
+            parent = login_dialog;
+        else
+            parent = main_window;
+        
+        bool prompted = false;
+        
+        Geary.Endpoint endpoint = account_information.get_imap_endpoint();
+        if (endpoint.tls_validation_warnings != 0 && endpoint.trust_untrusted_host != Geary.Trillian.TRUE) {
+            prompt_for_untrusted_host(parent, account_information, endpoint, Geary.Service.IMAP);
+            prompted = true;
+        }
+        
+        endpoint = account_information.get_smtp_endpoint();
+        if (endpoint.tls_validation_warnings != 0 && endpoint.trust_untrusted_host != Geary.Trillian.TRUE) {
+            prompt_for_untrusted_host(parent, account_information, endpoint, Geary.Service.SMTP);
+            prompted = true;
+        }
+        
+        // if prompted for user acceptance of bad certificates and they agreed to both, try again;
+        // this will loop back and re-validate, making connections this time and skipping this
+        // entirely
+        if (prompted && account_information.get_imap_endpoint().is_trusted_or_never_connected
+            && account_information.get_smtp_endpoint().is_trusted_or_never_connected) {
+            return account_information;
+        }
+        
         debug("Validation failed. Prompting user for revised account information");
         Geary.AccountInformation? new_account_information =
             request_account_information(account_information, result);
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index bf49023..ee9c76a 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -118,7 +118,7 @@ public class Geary.AccountInformation : BaseObject {
      * the future.
      */
     public signal void untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
-        TlsConnection cx, Service service, TlsCertificateFlags warnings);
+        TlsConnection cx, Service service);
     
     // Used to create temporary AccountInformation objects.  (Note that these cannot be saved.)
     public AccountInformation.temp_copy(AccountInformation copy) {
@@ -507,8 +507,8 @@ public class Geary.AccountInformation : BaseObject {
     }
     
     private void on_imap_untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
-        TlsConnection cx, TlsCertificateFlags warnings) {
-        untrusted_host(endpoint, security, cx, Service.IMAP, warnings);
+        TlsConnection cx) {
+        untrusted_host(endpoint, security, cx, Service.IMAP);
     }
     
     /**
@@ -556,8 +556,8 @@ public class Geary.AccountInformation : BaseObject {
     }
     
     private void on_smtp_untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
-        TlsConnection cx, TlsCertificateFlags warnings) {
-        untrusted_host(endpoint, security, cx, Service.SMTP, warnings);
+        TlsConnection cx) {
+        untrusted_host(endpoint, security, cx, Service.SMTP);
     }
     
     private Geary.FolderPath? build_folder_path(Gee.List<string>? parts) {
diff --git a/src/engine/api/geary-endpoint.vala b/src/engine/api/geary-endpoint.vala
index 049e87f..adbd98a 100644
--- a/src/engine/api/geary-endpoint.vala
+++ b/src/engine/api/geary-endpoint.vala
@@ -55,6 +55,11 @@ public class Geary.Endpoint : BaseObject {
     public TlsCertificateFlags tls_validation_warnings { get; private set; default = 0; }
     
     /**
+     * The TLS certificate for an invalid or untrusted connection.
+     */
+    public TlsCertificate? untrusted_certificate { get; private set; default = null; }
+    
+    /**
      * When set, indicates the user has acceded to trusting the host even though TLS has reported
      * certificate issues.
      *
@@ -104,9 +109,10 @@ public class Geary.Endpoint : BaseObject {
      * The connection will be closed when this is fired.  The caller should query the user about
      * how to deal with the situation.  If user wants to proceed, set { link trust_untrusted_host}
      * to { link Trillian.TRUE} and retry connection.
+     *
+     * @see tls_validation_warnings
      */
-    public signal void untrusted_host(SecurityType security, TlsConnection cx,
-        TlsCertificateFlags tls_warnings);
+    public signal void untrusted_host(SecurityType security, TlsConnection cx);
     
     public Endpoint(string host_specifier, uint16 default_port, Flags flags, uint timeout_sec) {
         this.remote_address = new NetworkAddress(host_specifier, default_port);
@@ -170,27 +176,29 @@ public class Geary.Endpoint : BaseObject {
     }
     
     private bool on_accept_starttls_certificate(TlsConnection cx, TlsCertificate cert, TlsCertificateFlags 
flags) {
-        return report_tls_warnings(SecurityType.STARTTLS, cx, flags);
+        return report_tls_warnings(SecurityType.STARTTLS, cx, cert, flags);
     }
     
     private bool on_accept_ssl_certificate(TlsConnection cx, TlsCertificate cert, TlsCertificateFlags flags) 
{
-        return report_tls_warnings(SecurityType.SSL, cx, flags);
+        return report_tls_warnings(SecurityType.SSL, cx, cert, flags);
     }
     
-    private bool report_tls_warnings(SecurityType security, TlsConnection cx, TlsCertificateFlags warnings) {
+    private bool report_tls_warnings(SecurityType security, TlsConnection cx, TlsCertificate cert,
+        TlsCertificateFlags warnings) {
         // TODO: Report or verify flags with user, but for now merely log for informational/debugging
         // reasons and accede
         message("%s TLS warnings connecting to %s: %Xh (%s)", security.to_string(), to_string(), warnings,
             tls_flags_to_string(warnings));
         
         tls_validation_warnings = warnings;
+        untrusted_certificate = cert;
         
         // if user has marked this untrusted host as trusted already, accept warnings and move on
         if (trust_untrusted_host == Trillian.TRUE)
             return true;
         
         // signal an issue has been detected and return false to deny the connection
-        untrusted_host(security, cx, warnings);
+        untrusted_host(security, cx);
         
         return false;
     }
diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala
index 3fbe839..7415253 100644
--- a/src/engine/api/geary-engine.vala
+++ b/src/engine/api/geary-engine.vala
@@ -89,8 +89,7 @@ public class Geary.Engine : BaseObject {
      * which case there is no { link Account} associated with it.
      */
     public signal void untrusted_host(Geary.AccountInformation account_information,
-        Endpoint endpoint, Endpoint.SecurityType security, TlsConnection cx, Service service,
-        TlsCertificateFlags warnings);
+        Endpoint endpoint, Endpoint.SecurityType security, TlsConnection cx, Service service);
     
     private Engine() {
     }
@@ -408,8 +407,8 @@ public class Geary.Engine : BaseObject {
     }
     
     private void on_untrusted_host(AccountInformation account_information, Endpoint endpoint,
-        Endpoint.SecurityType security, TlsConnection cx, Service service, TlsCertificateFlags warnings) {
-        untrusted_host(account_information, endpoint, security, cx, service, warnings);
+        Endpoint.SecurityType security, TlsConnection cx, Service service) {
+        untrusted_host(account_information, endpoint, security, cx, service);
     }
 }
 


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