[geary/wip/713247-tls] Pin certificates when requested by user
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713247-tls] Pin certificates when requested by user
- Date: Thu, 28 Aug 2014 00:46:36 +0000 (UTC)
commit 4a3b8c27131b0406ca184c1efefba6cb1ac4d0cd
Author: Jim Nelson <jim yorba org>
Date: Wed Aug 27 17:44:55 2014 -0700
Pin certificates when requested by user
Also --revoke-certs will revoke (remove) pinned certificates to
allow the user to reset w/o using keyring/pkcs manager.
src/CMakeLists.txt | 1 +
src/client/application/geary-args.vala | 2 +
src/client/application/geary-controller.vala | 49 +++++++++++++++++++++++++-
3 files changed, 51 insertions(+), 1 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cc3a5d9..5a78661 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -561,6 +561,7 @@ set(CFLAGS
-D_GSETTINGS_DIR=\"${CMAKE_BINARY_DIR}/gsettings\"
-DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\"
-DLANGUAGE_SUPPORT_DIRECTORY=\"${LANGUAGE_SUPPORT_DIRECTORY}\"
+ -DGCR_API_SUBJECT_TO_CHANGE
-g
)
diff --git a/src/client/application/geary-args.vala b/src/client/application/geary-args.vala
index a26a9c8..70b9159 100644
--- a/src/client/application/geary-args.vala
+++ b/src/client/application/geary-args.vala
@@ -23,6 +23,7 @@ private const OptionEntry[] options = {
/// "Normalization" can also be called "synchronization"
{ "log-folder-normalization", 0, 0, OptionArg.NONE, ref log_folder_normalization, N_("Log folder
normalization"), null },
{ "inspector", 'i', 0, OptionArg.NONE, ref inspector, N_("Allow inspection of WebView"), null },
+ { "revoke-certs", 0, 0, OptionArg.NONE, ref revoke_certs, N_("Revoke all server certificates with TLS
warnings"), null },
{ "version", 'V', 0, OptionArg.NONE, ref version, N_("Display program version"), null },
{ null }
};
@@ -38,6 +39,7 @@ public bool log_periodic = false;
public bool log_sql = false;
public bool log_folder_normalization = false;
public bool inspector = false;
+public bool revoke_certs = false;
public bool version = false;
public bool parse(string[] args) {
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 43af7b6..f4d33f1 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -4,6 +4,15 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
+// Required because Gcr's VAPI is behind-the-times
+extern const string GCR_PURPOSE_SERVER_AUTH;
+extern bool gcr_trust_add_pinned_certificate(Gcr.Certificate cert, string purpose, string peer,
+ Cancellable? cancellable) throws Error;
+extern bool gcr_trust_is_certificate_pinned(Gcr.Certificate cert, string purpose, string peer,
+ Cancellable? cancellable) throws Error;
+extern bool gcr_trust_remove_pinned_certificate(Gcr.Certificate cert, string purpose, string peer,
+ Cancellable? cancellable) throws Error;
+
// Primary controller object for Geary.
public class GearyController : Geary.BaseObject {
// Named actions.
@@ -519,6 +528,33 @@ public class GearyController : Geary.BaseObject {
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);
+
+ // Geary allows for user to auto-revoke all questionable server certificates without
+ // digging around in a keyring/pk manager
+ if (Args.revoke_certs) {
+ debug("Auto-revoking certificate for %s...", peer);
+
+ try {
+ gcr_trust_remove_pinned_certificate(cert, GCR_PURPOSE_SERVER_AUTH, peer, null);
+ } catch (Error err) {
+ message("Unable to auto-revoke server certificate for %s: %s", peer, err.message);
+ }
+ }
+
+ // if pinned, the user has already made an exception for this server and its certificate,
+ // so go ahead w/o asking
+ if (gcr_trust_is_certificate_pinned(cert, GCR_PURPOSE_SERVER_AUTH, peer, null)) {
+ debug("Certificate for %s is pinned, accepting connection...", peer);
+
+ endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
+
+ return;
+ }
+
+ // question the user about this certificate
CertificateWarningDialog dialog = new CertificateWarningDialog(main_window, endpoint,
service, warnings);
switch (dialog.run()) {
@@ -528,12 +564,23 @@ public class GearyController : Geary.BaseObject {
case CertificateWarningDialog.Result.ALWAYS_TRUST:
endpoint.trust_untrusted_host = Geary.Trillian.TRUE;
- // TODO: Pin certificate
+
+ // pinning the certificate creates an exception for the next time a connection
+ // is attempted
+ debug("Pinning certificate for %s...", peer);
+ try {
+ gcr_trust_add_pinned_certificate(cert, GCR_PURPOSE_SERVER_AUTH, peer, null);
+ } catch (Error err) {
+ ErrorDialog error_dialog = new ErrorDialog(main_window,
+ _("Unable to store server trust exception"), err.message);
+ error_dialog.run();
+ }
break;
default:
endpoint.trust_untrusted_host = Geary.Trillian.FALSE;
+ // close the account; can't go any further w/o offline mode
try {
if (Geary.Engine.instance.get_accounts().has_key(account_information.email)) {
Geary.Account account =
Geary.Engine.instance.get_account_instance(account_information);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]