[geary/wip/713247-tls] Refinements.
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713247-tls] Refinements.
- Date: Wed, 27 Aug 2014 23:01:22 +0000 (UTC)
commit 1bb55d48f2385ef57d18a2999b8c585eab2e7fdb
Author: Jim Nelson <jim yorba org>
Date: Wed Aug 27 12:28:47 2014 -0700
Refinements.
src/client/application/geary-controller.vala | 41 ++++++++++++++++---------
src/engine/api/geary-account-information.vala | 27 +++++++++++-----
src/engine/api/geary-endpoint.vala | 40 ++++++++++++++++++++----
src/engine/api/geary-engine.vala | 21 ++++++++----
ui/certificate_warning_dialog.glade | 32 ++++++++++++++-----
5 files changed, 115 insertions(+), 46 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 30d205c..cb19076 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -111,6 +111,7 @@ public class GearyController : Geary.BaseObject {
private LoginDialog? login_dialog = null;
private UpgradeDialog upgrade_dialog;
private Gee.List<string> pending_mailtos = new Gee.ArrayList<string>();
+ private Geary.Nonblocking.Mutex untrusted_host_prompt_mutex = new Geary.Nonblocking.Mutex();
// List of windows we're waiting to close before Geary closes.
private Gee.List<ComposerWidget> waiting_to_close = new Gee.ArrayList<ComposerWidget>();
@@ -177,7 +178,7 @@ public class GearyController : Geary.BaseObject {
Geary.Engine.instance.account_available.connect(on_account_available);
Geary.Engine.instance.account_unavailable.connect(on_account_unavailable);
- Geary.Engine.instance.tls_warnings_detected.connect(on_tls_warnings_detected);
+ Geary.Engine.instance.untrusted_host.connect(on_untrusted_host);
// Connect to various UI signals.
main_window.conversation_list_view.conversations_selected.connect(on_conversations_selected);
@@ -500,49 +501,59 @@ public class GearyController : Geary.BaseObject {
close_account(get_account_instance(account_information));
}
- private void on_tls_warnings_detected(Geary.AccountInformation account_information,
+ private void on_untrusted_host(Geary.AccountInformation account_information,
Geary.Endpoint endpoint, Geary.Endpoint.SecurityType security, TlsConnection cx,
Geary.Service service, TlsCertificateFlags warnings) {
- prompt_tls_warning_async.begin(account_information, endpoint, security, cx, service, warnings);
+ prompt_untrusted_host_async.begin(account_information, endpoint, security, cx, service, warnings);
}
- private Geary.Nonblocking.Mutex tls_prompt_mutex = new Geary.Nonblocking.Mutex();
-
- private async void prompt_tls_warning_async(Geary.AccountInformation account_information,
+ 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) {
+ int token = Geary.Nonblocking.Mutex.INVALID_TOKEN;
try {
- int token = yield tls_prompt_mutex.claim_async();
+ // use a mutex to prevent multiple dialogs popping up at the same time
+ token = yield untrusted_host_prompt_mutex.claim_async();
- // possible while waiting on mutex that this endpoint became trusted
- if (endpoint.trust_host)
+ // possible while waiting on mutex that this endpoint became trusted or untrusted
+ if (endpoint.trust_untrusted_host != Geary.Trillian.UNKNOWN)
return;
CertificateWarningDialog dialog = new CertificateWarningDialog(main_window, endpoint,
warnings);
switch (dialog.run()) {
case CertificateWarningDialog.Result.TRUST:
- endpoint.trust_host = true;
+ endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
break;
case CertificateWarningDialog.Result.ALWAYS_TRUST:
- endpoint.trust_host = true;
+ endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
// TODO: Pin certificate
break;
default:
+ endpoint.trust_untrusted_host = Geary.Trillian.FALSE;
+
try {
- Geary.Account account =
Geary.Engine.instance.get_account_instance(account_information);
- close_account(account);
+ if (Geary.Engine.instance.get_accounts().has_key(account_information.email)) {
+ Geary.Account account =
Geary.Engine.instance.get_account_instance(account_information);
+ close_account(account);
+ }
} catch (Error err) {
message("Unable to close account due to user trust issues: %s", err.message);
}
break;
}
-
- tls_prompt_mutex.release(ref token);
} catch (Error err) {
warning("Unable to prompt for certificate security warning: %s", err.message);
+ } finally {
+ if (token != Geary.Nonblocking.Mutex.INVALID_TOKEN) {
+ try {
+ untrusted_host_prompt_mutex.release(ref token);
+ } catch (Error err) {
+ debug("Unable to release mutex: %s", err.message);
+ }
+ }
}
}
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index 50bf1e7..9901f60 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -108,7 +108,16 @@ public class Geary.AccountInformation : BaseObject {
private Endpoint? imap_endpoint = null;
private Endpoint? smtp_endpoint = null;
- public signal void tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+ /**
+ * Indicates the supplied { link Endpoint} has reported TLS certificate warnings during
+ * connection.
+ *
+ * Since this { link Endpoint} persists for the lifetime of the { link AccountInformation},
+ * marking it as trusted once will survive the application session. It is up to the caller to
+ * pin the certificate appropriately if the user does not want to receive these warnings in
+ * the future.
+ */
+ public signal void untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
TlsConnection cx, Service service, TlsCertificateFlags warnings);
// Used to create temporary AccountInformation objects. (Note that these cannot be saved.)
@@ -186,10 +195,10 @@ public class Geary.AccountInformation : BaseObject {
~AccountInformation() {
if (imap_endpoint != null)
- imap_endpoint.tls_warnings_detected.disconnect(on_imap_tls_warnings_detected);
+ imap_endpoint.untrusted_host.disconnect(on_imap_untrusted_host);
if (smtp_endpoint != null)
- smtp_endpoint.tls_warnings_detected.disconnect(on_smtp_tls_warnings_detected);
+ smtp_endpoint.untrusted_host.disconnect(on_smtp_untrusted_host);
}
// Copies all data from the "from" object into this one.
@@ -485,14 +494,14 @@ public class Geary.AccountInformation : BaseObject {
assert_not_reached();
}
- imap_endpoint.tls_warnings_detected.connect(on_imap_tls_warnings_detected);
+ imap_endpoint.untrusted_host.connect(on_imap_untrusted_host);
return imap_endpoint;
}
- private void on_imap_tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+ private void on_imap_untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
TlsConnection cx, TlsCertificateFlags warnings) {
- tls_warnings_detected(endpoint, security, cx, Service.IMAP, warnings);
+ untrusted_host(endpoint, security, cx, Service.IMAP, warnings);
}
public Endpoint get_smtp_endpoint() {
@@ -527,14 +536,14 @@ public class Geary.AccountInformation : BaseObject {
assert_not_reached();
}
- smtp_endpoint.tls_warnings_detected.connect(on_smtp_tls_warnings_detected);
+ smtp_endpoint.untrusted_host.connect(on_smtp_untrusted_host);
return smtp_endpoint;
}
- private void on_smtp_tls_warnings_detected(Endpoint endpoint, Endpoint.SecurityType security,
+ private void on_smtp_untrusted_host(Endpoint endpoint, Endpoint.SecurityType security,
TlsConnection cx, TlsCertificateFlags warnings) {
- tls_warnings_detected(endpoint, security, cx, Service.SMTP, warnings);
+ untrusted_host(endpoint, security, cx, Service.SMTP, warnings);
}
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 876e1fd..1fc8ffa 100644
--- a/src/engine/api/geary-endpoint.vala
+++ b/src/engine/api/geary-endpoint.vala
@@ -42,9 +42,27 @@ public class Geary.Endpoint : BaseObject {
public Flags flags { get; private set; }
public uint timeout_sec { get; private set; }
public TlsCertificateFlags tls_validation_flags { get; set; default = TlsCertificateFlags.VALIDATE_ALL; }
- public TlsCertificateFlags tls_validation_warnings { get; private set; default = 0; }
public bool force_ssl3 { get; set; default = false; }
- public bool trust_host { get; set; default = false; }
+
+ /**
+ * When set, TLS has reported certificate issues.
+ *
+ * @see trust_untrusted_host
+ * @see untrusted_host
+ */
+ public TlsCertificateFlags tls_validation_warnings { get; private set; default = 0; }
+
+ /**
+ * When set, indicates the user has acceded to trusting the host even though TLS has reported
+ * certificate issues.
+ *
+ * Initialized to { link Trillian.UNKNOWN}, meaning the user must decide when warnings are
+ * detected.
+ *
+ * @see untrusted_host
+ * @see tls_validation_warnings
+ */
+ public Trillian trust_untrusted_host { get; set; default = Trillian.UNKNOWN; }
public bool is_ssl { get {
return flags.is_all_set(Flags.SSL);
@@ -56,7 +74,15 @@ public class Geary.Endpoint : BaseObject {
private SocketClient? socket_client = null;
- public signal void tls_warnings_detected(SecurityType security, TlsConnection cx,
+ /**
+ * Fired when TLS certificate warnings are detected and the caller has not marked this
+ * { link Endpoint} as trusted via { link trust_untrusted_host}.
+ *
+ * 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.
+ */
+ public signal void untrusted_host(SecurityType security, TlsConnection cx,
TlsCertificateFlags tls_warnings);
public Endpoint(string host_specifier, uint16 default_port, Flags flags, uint timeout_sec) {
@@ -118,8 +144,6 @@ public class Geary.Endpoint : BaseObject {
tls_cx.accept_certificate.connect(on_accept_starttls_certificate);
else
tls_cx.accept_certificate.connect(on_accept_ssl_certificate);
-
- tls_warnings_detected(SecurityType.SSL, tls_cx, TlsCertificateFlags.UNKNOWN_CA);
}
private bool on_accept_starttls_certificate(TlsConnection cx, TlsCertificate cert, TlsCertificateFlags
flags) {
@@ -138,10 +162,12 @@ public class Geary.Endpoint : BaseObject {
tls_validation_warnings = warnings;
- if (trust_host)
+ // if user has marked this untrusted host as trusted already, accept warnings and move on
+ if (trust_untrusted_host == Trillian.TRUE)
return true;
- tls_warnings_detected(security, cx, warnings);
+ // signal an issue has been detected and return false to deny the connection
+ untrusted_host(security, cx, warnings);
return false;
}
diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala
index 006c692..3fbe839 100644
--- a/src/engine/api/geary-engine.vala
+++ b/src/engine/api/geary-engine.vala
@@ -81,7 +81,14 @@ public class Geary.Engine : BaseObject {
*/
public signal void account_removed(AccountInformation account);
- public signal void tls_warnings_detected(Geary.AccountInformation account_information,
+ /**
+ * Fired when an { link Endpoint} associated with the { link AccountInformation} reports
+ * TLS certificate warnings during connection.
+ *
+ * This may be fired during normal operation or while validating the AccountInformation, in
+ * 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);
@@ -243,7 +250,7 @@ public class Geary.Engine : BaseObject {
if (!options.is_all_set(ValidationOption.CHECK_CONNECTIONS))
return error_code;
- account.tls_warnings_detected.connect(on_tls_warnings_detected);
+ account.untrusted_host.connect(on_untrusted_host);
// validate IMAP, which requires logging in and establishing an AUTHORIZED cx state
Geary.Imap.ClientSession? imap_session = new Imap.ClientSession(account.get_imap_endpoint());
@@ -299,7 +306,7 @@ public class Geary.Engine : BaseObject {
smtp_session = null;
}
- account.tls_warnings_detected.disconnect(on_tls_warnings_detected);
+ account.untrusted_host.disconnect(on_untrusted_host);
return error_code;
}
@@ -360,7 +367,7 @@ public class Geary.Engine : BaseObject {
accounts.set(account.email, account);
if (!already_added) {
- account.tls_warnings_detected.connect(on_tls_warnings_detected);
+ account.untrusted_host.connect(on_untrusted_host);
if (created)
account_added(account);
@@ -383,7 +390,7 @@ public class Geary.Engine : BaseObject {
}
if (accounts.unset(account.email)) {
- account.tls_warnings_detected.disconnect(on_tls_warnings_detected);
+ account.untrusted_host.disconnect(on_untrusted_host);
// Removal *MUST* be done in the following order:
// 1. Send the account-unavailable signal.
@@ -400,9 +407,9 @@ public class Geary.Engine : BaseObject {
}
}
- private void on_tls_warnings_detected(AccountInformation account_information, Endpoint endpoint,
+ private void on_untrusted_host(AccountInformation account_information, Endpoint endpoint,
Endpoint.SecurityType security, TlsConnection cx, Service service, TlsCertificateFlags warnings) {
- tls_warnings_detected(account_information, endpoint, security, cx, service, warnings);
+ untrusted_host(account_information, endpoint, security, cx, service, warnings);
}
}
diff --git a/ui/certificate_warning_dialog.glade b/ui/certificate_warning_dialog.glade
index 317b000..29e1bcf 100644
--- a/ui/certificate_warning_dialog.glade
+++ b/ui/certificate_warning_dialog.glade
@@ -4,7 +4,7 @@
<requires lib="gtk+" version="3.10"/>
<object class="GtkDialog" id="CertificateWarningDialog">
<property name="can_focus">False</property>
- <property name="title" translatable="yes">Certificate Security Warning</property>
+ <property name="title" translatable="yes">Untrusted Connection</property>
<property name="modal">True</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
@@ -12,10 +12,10 @@
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">8</property>
- <property name="margin_bottom">8</property>
+ <property name="margin_left">12</property>
+ <property name="margin_right">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
@@ -79,7 +79,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">4</property>
+ <property name="spacing">8</property>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
@@ -152,12 +152,13 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="label2">
+ <object class="GtkLabel" id="dont_trust_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">end</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">Selecting "Don't Trust This Host" will cause Geary
to exit.</property>
+ <property name="label" translatable="yes">Selecting "Don't Trust This Host" will cause Geary
to exit if you have no other registered email accounts.</property>
+ <property name="wrap">True</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@@ -169,6 +170,21 @@
<property name="position">3</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="bottom_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Contact your system administrator or email service
provider if you have any question about these issues.</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]