From e32b9690270bbb4c4152ce9672db5d11a81f98e1 Mon Sep 17 00:00:00 2001 From: Dan Breslau Date: Tue, 9 Aug 2016 19:14:50 -0400 Subject: [PATCH] First cut at supporting trust anchors --- .gitignore | 1 + Makefile.am | 1 + src/moonshot-id.vala | 60 +++++++++++- src/moonshot-idcard-widget.vala | 6 +- src/moonshot-identity-management-view.vala | 43 ++++++++- src/moonshot-settings.vala | 37 ++++++++ src/moonshot-trust-anchor-dialog.vala | 142 +++++++++++++++++++++++++++++ webprovisioning/complex-test.msht | 94 ++++++++++++++----- 8 files changed, 347 insertions(+), 37 deletions(-) create mode 100644 src/moonshot-trust-anchor-dialog.vala diff --git a/.gitignore b/.gitignore index a39248a..b2b436a 100755 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ src/moonshot-provisioning-common-new.vala src/moonshot-provisioning-common.c src/moonshot-server.c src/moonshot-settings.c +src/moonshot-trust-anchor-dialog.c src/moonshot-utils.c src/moonshot-warning-dialog.c src/moonshot-webp-parser.c diff --git a/Makefile.am b/Makefile.am index 0470762..4f40dd4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,6 +68,7 @@ src_moonshot_SOURCES = \ src/moonshot-settings.vala \ src/moonshot-password-dialog.vala \ src/moonshot-provisioning-common.vala \ + src/moonshot-trust-anchor-dialog.vala \ src/moonshot-utils.vala \ src/moonshot-futils.c \ src/moonshot-logger.vala \ diff --git a/src/moonshot-id.vala b/src/moonshot-id.vala index ec0866c..77afd4e 100644 --- a/src/moonshot-id.vala +++ b/src/moonshot-id.vala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, JANET(UK) + * Copyright (c) 2011-2016, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,10 +34,60 @@ using Gee; public class TrustAnchor : Object { - public string ca_cert {get; set; default = "";} - public string subject {get; set; default = "";} - public string subject_alt {get; set; default = "";} - public string server_cert {get; set; default = "";} + public static const string TYPE_CA_CERT = _("CA Certificate"); + public static const string TYPE_ENTERPRISE = _("Enterprise provisioned"); + + + private string _ca_cert = ""; + private string _subject = ""; + private string _subject_alt = ""; + private string _server_cert = ""; + + public string ca_cert { + get { + return _ca_cert; + } + set { + _ca_cert = (value ?? ""); + } + } + + public string subject { + get { + return _subject; + } + set { + _subject = (value ?? ""); + } + } + + public string subject_alt { + get { + return _subject_alt; + } + set { + _subject_alt = (value ?? ""); + } + } + + + public string server_cert { + get { + return _server_cert; + } + set { + _server_cert = (value ?? ""); + } + } + + public bool is_empty() { + return ca_cert == "" && subject == "" && subject_alt == "" && server_cert == ""; + } + + public string get_anchor_type() { + return server_cert == "" ? TYPE_CA_CERT : TYPE_ENTERPRISE; + } + public int Compare(TrustAnchor other) { if (this.ca_cert != other.ca_cert) diff --git a/src/moonshot-idcard-widget.vala b/src/moonshot-idcard-widget.vala index 7a34cf2..6cd2b37 100644 --- a/src/moonshot-idcard-widget.vala +++ b/src/moonshot-idcard-widget.vala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, JANET(UK) + * Copyright (c) 2011-2016, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -131,7 +131,9 @@ class IdCardWidget : Box { label_text += "\nUsername: " + id_card.username; label_text += "\nRealm: " + id_card.issuer; - + if (!id_card.trust_anchor.is_empty()) { + label_text += "\nTrust anchor: " + id_card.trust_anchor.get_anchor_type(); + } services_text += this.id_card.get_services_string(service_spacer); label_text += "\n" + services_text; } diff --git a/src/moonshot-identity-management-view.vala b/src/moonshot-identity-management-view.vala index cea963b..6620ac0 100644 --- a/src/moonshot-identity-management-view.vala +++ b/src/moonshot-identity-management-view.vala @@ -542,14 +542,19 @@ public class IdentityManagerView : Window { private void send_identity_cb(IdCard id) { - send_button.set_sensitive(false); - - IdCard identity = id; return_if_fail(request_queue.length > 0); - candidates = null; + if (!check_and_confirm_trust_anchor(id)) { + // Allow user to pick again + return; + } + var request = this.request_queue.pop_head(); - identity = check_add_password(identity, request, identities_manager); + var identity = check_add_password(id, request, identities_manager); + send_button.set_sensitive(false); + + candidates = null; + if (this.request_queue.is_empty()) { candidates = null; @@ -578,6 +583,34 @@ public class IdentityManagerView : Window { remember_identity_binding.hide(); } + private bool check_and_confirm_trust_anchor(IdCard id) + { + if (!id.trust_anchor.is_empty() && id.trust_anchor.get_anchor_type() == TrustAnchor.TYPE_ENTERPRISE) { + if (get_string_setting("TrustAnchors", id.nai) != id.trust_anchor.server_cert) { + + bool ret = false; + int result = ResponseType.CANCEL; + var dialog = new TrustAnchorDialog(id, this); + while (!dialog.complete) + result = dialog.run(); + + switch (result) { + case ResponseType.OK: + set_string_setting("TrustAnchors", id.nai, id.trust_anchor.server_cert); + ret = true; + break; + default: + break; + } + + dialog.destroy(); + return ret; + } + } + return true; + } + + // private void label_make_bold(Label label) // { // var font_desc = new Pango.FontDescription(); diff --git a/src/moonshot-settings.vala b/src/moonshot-settings.vala index 1549213..8107c05 100644 --- a/src/moonshot-settings.vala +++ b/src/moonshot-settings.vala @@ -135,3 +135,40 @@ internal bool get_bool_setting(string group_name, string key_name, bool default= } return default; } + + +internal void set_string_setting(string group_name, string key_name, string value) +{ + KeyFile key_file = get_keyfile(); + + key_file.set_string(group_name, key_name, value); + save_keyfile(key_file); +} + +internal string get_string_setting(string group_name, string key_name, string default="") +{ + KeyFile key_file = get_keyfile(); + + if (key_file == null) + return default; + + try { + if (!key_file.has_key(group_name, key_name)) + { + logger().info(@"get_string_setting : key file doesn't contain key '$key_name' in group '$group_name'"); + return default; + } + } + catch(KeyFileError e) { + logger().info(@"get_string_setting : KeyFileError checking if key '$key_name' exists in group '$group_name' (maybe ignorable?) : " + e.message); + } + + try { + // throws KeyFileError if key is not found + return key_file.get_string(group_name, key_name); + } + catch (KeyFileError e) { + logger().info("get_string_setting got KeyFileError (may be ignorable) : " + e.message); + } + return default; +} diff --git a/src/moonshot-trust-anchor-dialog.vala b/src/moonshot-trust-anchor-dialog.vala new file mode 100644 index 0000000..9fc2213 --- /dev/null +++ b/src/moonshot-trust-anchor-dialog.vala @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2011-2016, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. +*/ +using Gtk; + +class TrustAnchorDialog : Dialog +{ + private static Gdk.Color white = make_color(65535, 65535, 65535); + + private Entry trust_anchor_entry; + + public bool complete = false; + + public TrustAnchorDialog(IdCard idcard, Window parent) + { + this.set_title(_("Trust Anchor")); + this.set_modal(true); + this.set_transient_for(parent); + this.modify_bg(StateType.NORMAL, white); + + this.add_buttons(_("Connect"), ResponseType.OK, + _("Cancel"), ResponseType.CANCEL); + + this.set_default_response(ResponseType.OK); + + var content_area = this.get_content_area(); + ((Box) content_area).set_spacing(12); + content_area.modify_bg(StateType.NORMAL, white); + + Label dialog_label = new Label(""); + dialog_label.set_alignment(0, 0); + + string label_markup = _("You are using this identity for the first time with the following trust anchor:"); + + dialog_label.set_markup(label_markup); + dialog_label.set_line_wrap(true); + dialog_label.set_width_chars(60); + + var user_label = new Label(_("Username: ") + idcard.username); + user_label.set_alignment(0, 0.5f); + + var realm_label = new Label(_("Realm: ") + idcard.issuer); + realm_label.set_alignment(0, 0.5f); + + var fingerprint_label = new Label(_("SHA-256 fingerprint:")); + fingerprint_label.set_alignment(0, 0.5f); + + var footprint = new TextView(); + //footprint.activates_default = false; + // footprint.set_sensitive(false); + footprint.set_editable(false); + // footprint.set_text(idcard.trust_anchor.server_cert); + var buffer = footprint.get_buffer(); + buffer.set_text(colonize(idcard.trust_anchor.server_cert), -1); + footprint.wrap_mode = WrapMode.WORD_CHAR; + + set_atk_relation(fingerprint_label, footprint, Atk.RelationType.LABEL_FOR); + + var footprint_width_constraint = new ScrolledWindow(null, null); + footprint_width_constraint.set_policy(PolicyType.NEVER, PolicyType.NEVER); + footprint_width_constraint.set_shadow_type(ShadowType.IN); + footprint_width_constraint.set_size_request(400, 60); + footprint_width_constraint.add_with_viewport(footprint); + + Label confirm_label = new Label(_("Please confirm that this is the correct trust anchor.")); + confirm_label.set_alignment(0, 0.5f); + + var vbox = new VBox(false, 0); + vbox.set_border_width(6); + vbox.pack_start(dialog_label, true, true, 12); + vbox.pack_start(user_label, true, true, 2); + vbox.pack_start(realm_label, true, true, 2); + vbox.pack_start(fingerprint_label, true, true, 2); + vbox.pack_start(footprint_width_constraint, true, true, 2); + vbox.pack_start(confirm_label, true, true, 12); + + ((Container) content_area).add(vbox); + + this.set_border_width(6); + this.set_resizable(false); + + this.response.connect(on_response); + + this.show_all(); + } + + private void on_response(Dialog source, int response_id) + { + switch (response_id) { + case ResponseType.OK: + complete = true; + break; + case ResponseType.CANCEL: + complete = true; + break; + } + } + + // Yeah, it doesn't mean "colonize" the way you might think... :-) + private static string colonize(string input) { + return_if_fail(input.length % 2 == 0); + + string result = ""; + int i = 0; + while (i < input.length) { + if (i > 0) { + result += ":"; + } + result += input[i : i + 2]; + i += 2; + } + return result; + } +} diff --git a/webprovisioning/complex-test.msht b/webprovisioning/complex-test.msht index 2c11172..b09b1d0 100644 --- a/webprovisioning/complex-test.msht +++ b/webprovisioning/complex-test.msht @@ -3,10 +3,10 @@ Unique Name user1 - foo.baz + painless-security.com - irc@jabber.project-moonshot.org - xmpp@jabber.project-moonshot.org + irc/painless-security.com + xmpp/painless-security.com @@ -14,56 +14,100 @@ true - imap@*moonshot.org + imap/*moonshot.org false - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 - Foo - Bar + MIIE9jCCA96gAwIBAgIJAJ6SVDCP6o2nMA0GCSqGSIb3DQEBBQUAMIGaMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBk1hbGRlbjEaMBgGA1UEChMR +UGFpbmxlc3MgU2VjdXJpdHkxLzAtBgkqhkiG9w0BCQEWIHBvc3RtYXN0ZXJAcGFp +bmxlc3Mtc2VjdXJpdHkuY29tMSAwHgYDVQQDExdQYWlubGVzcyBTZWN1cml0eSwg +SW5jLjAeFw0xNjA4MDExNjIxMDVaFw0xOTExMTQxNjIxMDVaMIGaMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBk1hbGRlbjEaMBgGA1UEChMRUGFp +bmxlc3MgU2VjdXJpdHkxLzAtBgkqhkiG9w0BCQEWIHBvc3RtYXN0ZXJAcGFpbmxl +c3Mtc2VjdXJpdHkuY29tMSAwHgYDVQQDExdQYWlubGVzcyBTZWN1cml0eSwgSW5j +LjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKPiSkw1y6zMJFjnoPjd +5Bh9EA1NhQcoNxJAtgYEJtpH9a2tfjnXXncXpbIMIfMgv2VKRAxvKb+knCfSCRtU +PM9i998+ZhJY9o6SSFomlMvdaClauPvBhQvQMmJmp1WINgMUHPpzsGlj04kkl7jw +iK/oDxp1becikKc10Gr9W03aEJtOaiSqC45zeIgnz9GoQ2tJvz2DDBcddaaT1mSV +n/lk4ahPC4XaJ08Jn1L6XkVVyDGD38Rwg7r1SFI7ByBFvvQh93Fa48Z7ik0I8s48 +U1euHak2gSJ4zfzLndvGy05qMjhRTlxQu+Rt1g7CS3CLcJqqYzWNrEJWpD8Wn7iA +MIUCAwEAAaOCATswggE3MB0GA1UdDgQWBBR1qlvY7r2DqhHu5s+sCUPeqBcQuzCB +zwYDVR0jBIHHMIHEgBR1qlvY7r2DqhHu5s+sCUPeqBcQu6GBoKSBnTCBmjELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAk1BMQ8wDQYDVQQHEwZNYWxkZW4xGjAYBgNVBAoT +EVBhaW5sZXNzIFNlY3VyaXR5MS8wLQYJKoZIhvcNAQkBFiBwb3N0bWFzdGVyQHBh +aW5sZXNzLXNlY3VyaXR5LmNvbTEgMB4GA1UEAxMXUGFpbmxlc3MgU2VjdXJpdHks +IEluYy6CCQCeklQwj+qNpzAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeG +JWh0dHA6Ly93d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcN +AQEFBQADggEBAB6J5Zxvq96SdIsfEajqU+pANBiA2VTZCpxfIMAKz8KfyzWzFvCM +8epvYDliyOjw1zR9cYxhQqOcbPHrjLXheVvCePd3jCUOv+tt1Nw2gS2DiMuq37DO +BZOTlPJ3m2NnvJVO3NjB2I+Pk9v3YlG6mkiVc9dNWgO20SqT2Y+KvHqA5Of8Cb/s +uIBftctvGpIyEnqSmU7KB0nhIWe65Bsu60hjHHfX1qhJE7qGKbqNaHujssQ/SBXJ +g7HUhtywv8z3TFoYW0MoBpKGM2Ojc9kQ8f0rYvUKTiD1UfjQoll/Io5xwKy7FXtn +musuCxXeWkqDtw0clWg6vkf5Tb9v/JQ2PW0= + Painless Security Server Certificate - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 + Another Unique Name user2 - foo.bar + painless-security.com - irc@jabber.project-moonshot.org - email@project-moonshot.org + irc/painless-security.com + email/painless-security.com - *@project-moonshot.org + */painless-security.com true - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 - Foo - Bar - - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 + MIIE9jCCA96gAwIBAgIJAJ6SVDCP6o2nMA0GCSqGSIb3DQEBBQUAMIGaMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBk1hbGRlbjEaMBgGA1UEChMR +UGFpbmxlc3MgU2VjdXJpdHkxLzAtBgkqhkiG9w0BCQEWIHBvc3RtYXN0ZXJAcGFp +bmxlc3Mtc2VjdXJpdHkuY29tMSAwHgYDVQQDExdQYWlubGVzcyBTZWN1cml0eSwg +SW5jLjAeFw0xNjA4MDExNjIxMDVaFw0xOTExMTQxNjIxMDVaMIGaMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcTBk1hbGRlbjEaMBgGA1UEChMRUGFp +bmxlc3MgU2VjdXJpdHkxLzAtBgkqhkiG9w0BCQEWIHBvc3RtYXN0ZXJAcGFpbmxl +c3Mtc2VjdXJpdHkuY29tMSAwHgYDVQQDExdQYWlubGVzcyBTZWN1cml0eSwgSW5j +LjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKPiSkw1y6zMJFjnoPjd +5Bh9EA1NhQcoNxJAtgYEJtpH9a2tfjnXXncXpbIMIfMgv2VKRAxvKb+knCfSCRtU +PM9i998+ZhJY9o6SSFomlMvdaClauPvBhQvQMmJmp1WINgMUHPpzsGlj04kkl7jw +iK/oDxp1becikKc10Gr9W03aEJtOaiSqC45zeIgnz9GoQ2tJvz2DDBcddaaT1mSV +n/lk4ahPC4XaJ08Jn1L6XkVVyDGD38Rwg7r1SFI7ByBFvvQh93Fa48Z7ik0I8s48 +U1euHak2gSJ4zfzLndvGy05qMjhRTlxQu+Rt1g7CS3CLcJqqYzWNrEJWpD8Wn7iA +MIUCAwEAAaOCATswggE3MB0GA1UdDgQWBBR1qlvY7r2DqhHu5s+sCUPeqBcQuzCB +zwYDVR0jBIHHMIHEgBR1qlvY7r2DqhHu5s+sCUPeqBcQu6GBoKSBnTCBmjELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAk1BMQ8wDQYDVQQHEwZNYWxkZW4xGjAYBgNVBAoT +EVBhaW5sZXNzIFNlY3VyaXR5MS8wLQYJKoZIhvcNAQkBFiBwb3N0bWFzdGVyQHBh +aW5sZXNzLXNlY3VyaXR5LmNvbTEgMB4GA1UEAxMXUGFpbmxlc3MgU2VjdXJpdHks +IEluYy6CCQCeklQwj+qNpzAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeG +JWh0dHA6Ly93d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcN +AQEFBQADggEBAB6J5Zxvq96SdIsfEajqU+pANBiA2VTZCpxfIMAKz8KfyzWzFvCM +8epvYDliyOjw1zR9cYxhQqOcbPHrjLXheVvCePd3jCUOv+tt1Nw2gS2DiMuq37DO +BZOTlPJ3m2NnvJVO3NjB2I+Pk9v3YlG6mkiVc9dNWgO20SqT2Y+KvHqA5Of8Cb/s +uIBftctvGpIyEnqSmU7KB0nhIWe65Bsu60hjHHfX1qhJE7qGKbqNaHujssQ/SBXJ +g7HUhtywv8z3TFoYW0MoBpKGM2Ojc9kQ8f0rYvUKTiD1UfjQoll/Io5xwKy7FXtn +musuCxXeWkqDtw0clWg6vkf5Tb9v/JQ2PW0= + Painless Security Server Certificate Yet Another Unique Name user3 - foo.com + painless-security.com - irc@jabber.project-moonshot.org - email@project-moonshot.org + irc/painless-security.com + email/painless-security.com - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 - Foo - Bar - - ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910 + 3838E17EC9A2A06D7B6030E3C5727E3466EAB4BB4159DCE7CF6297ADAFC8A56F -- 2.1.4