X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmoonshot-trust-anchor-dialog.vala;h=b22c874db5fb3f4a01edf22c7fed718d9f08ecde;hb=ac29bce25074b99a585dcdd74c90b261be026461;hp=0537494dedd8bfa76aab1f99309db7a786664ff7;hpb=1d7bb0f8787ac31c1660d7f755ae88ebb21e25c2;p=moonshot-ui.git diff --git a/src/moonshot-trust-anchor-dialog.vala b/src/moonshot-trust-anchor-dialog.vala index 0537494..b22c874 100644 --- a/src/moonshot-trust-anchor-dialog.vala +++ b/src/moonshot-trust-anchor-dialog.vala @@ -31,47 +31,165 @@ */ using Gtk; +public delegate void TrustAnchorConfirmationCallback(TrustAnchorConfirmationRequest request); + +public class TrustAnchorConfirmationRequest : GLib.Object { + static MoonshotLogger logger = get_logger("TrustAnchorConfirmationRequest"); + + IdentityManagerApp parent_app; + string userid; + string realm; + string ca_hash; + public bool confirmed = false; + + TrustAnchorConfirmationCallback callback = null; + + public TrustAnchorConfirmationRequest(IdentityManagerApp parent_app, + string userid, + string realm, + string ca_hash) + { + this.parent_app = parent_app; + this.userid = userid; + this.realm = realm; + this.ca_hash = ca_hash; + } + + public void set_callback(owned TrustAnchorConfirmationCallback cb) + { +// #if VALA_0_12 + this.callback = ((owned) cb); +// #else +// this.callback = ((IdCard) => cb(IdCard)); +// #endif + } + + public bool execute() { + + string nai = userid + "@" + realm; + IdCard? card = parent_app.model.find_id_card(nai, parent_app.use_flat_file_store); + if (card == null) { + logger.warn(@"execute: Could not find ID card for NAI $nai; returning false."); + return_confirmation(false); + return false; + } + + if (!(card.trust_anchor.is_empty() || card.trust_anchor.get_anchor_type() == TrustAnchor.TrustAnchorType.SERVER_CERT)) { + logger.warn(@"execute: Trust anchor type for NAI $nai is not empty or SERVER_CERT; returning true."); + return_confirmation(true); + return false; + } + + if (card.trust_anchor.server_cert == ca_hash) { + logger.trace(@"execute: Fingerprint for $nai matches stored value; returning true."); + return_confirmation(true); + return false; + } + + var dialog = new TrustAnchorDialog(card, userid, realm, ca_hash); + var response = dialog.run(); + dialog.destroy(); + bool is_confirmed = (response == ResponseType.OK); + + if (is_confirmed) { + logger.trace(@"execute: Fingerprint confirmed; updating stored value."); + + card.trust_anchor.update_server_fingerprint(ca_hash); + parent_app.model.update_card(card); + } + + return_confirmation(is_confirmed); + + /* This function works as a GSourceFunc, so it can be passed to + * the main loop from other threads + */ + return false; + } + + private void return_confirmation(bool confirmed) { + return_if_fail(callback != null); + + this.confirmed = confirmed; + logger.trace(@"return_confirmation: confirmed=$confirmed"); + + // Send back the confirmation (we can't directly run the + // callback because we may be being called from a 'yield') + GLib.Idle.add( + () => { + logger.trace("return_confirmation[Idle handler]: invoking callback"); + callback(this); + return false; + } + ); + } +} + + + class TrustAnchorDialog : Dialog { private static Gdk.Color white = make_color(65535, 65535, 65535); public bool complete = false; - public TrustAnchorDialog(IdCard idcard, Window parent) + public TrustAnchorDialog(IdCard card, + string userid, + string realm, + string ca_hash) { + string server_ta_label_text = _("Server’s trust anchor certificate (SHA-256 fingerprint):"); + this.set_title(_("Trust Anchor")); this.set_modal(true); - this.set_transient_for(parent); - this.modify_bg(StateType.NORMAL, white); +// this.set_transient_for(parent); + set_bg_color(this); this.add_buttons(_("Cancel"), ResponseType.CANCEL, _("Confirm"), ResponseType.OK); - this.set_default_response(ResponseType.OK); + this.set_default_response(ResponseType.CANCEL); var content_area = this.get_content_area(); ((Box) content_area).set_spacing(12); - content_area.modify_bg(StateType.NORMAL, white); + set_bg_color(content_area); 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:") + ""; + string label_markup; + if (card.trust_anchor.server_cert == "") { + label_markup = "" + + _("You are using this identity for the first time with the following trust anchor:") + ""; + } + else { + // The server's fingerprint isn't what we're expecting this server to provide. + label_markup = "" + + _("WARNING: The certificate we received for the authentication server for %s").printf(card.issuer) + + _(" is different than expected. Either the server certificate has changed, or an") + + _(" attack may be underway. If you proceed to the wrong server, your login credentials may be compromised.") + + ""; + } 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); + var user_label = new Label(_("Username: ") + userid); user_label.set_alignment(0, 0.5f); - var realm_label = new Label(_("Realm: ") + idcard.issuer); + var realm_label = new Label(_("Realm: ") + realm); realm_label.set_alignment(0, 0.5f); - Label confirm_label = new Label(_("Please confirm that this is the correct trust anchor.")); + string confirm_text = _("\nPlease check with your realm administrator for the correct fingerprint") + + _(" for your authentication server. If it matches the above fingerprint,") + + _(" confirm the change. If not, then cancel."); + + Label confirm_label = new Label(confirm_text); confirm_label.set_alignment(0, 0.5f); + confirm_label.set_line_wrap(true); + confirm_label.set_width_chars(60); - var trust_anchor_display = make_ta_fingerprint_widget(idcard.trust_anchor); + var trust_anchor_display = make_ta_fingerprint_widget(ca_hash, server_ta_label_text); var vbox = new VBox(false, 0); vbox.set_border_width(6);