Implement DBUS call for ConfirmCACertificate
authorDan Breslau <dbreslau@painless-security.com>
Wed, 28 Sep 2016 22:31:16 +0000 (18:31 -0400)
committerDan Breslau <dbreslau@painless-security.com>
Wed, 28 Sep 2016 22:31:16 +0000 (18:31 -0400)
libmoonshot/libmoonshot-dbus.c
libmoonshot/libmoonshot.def
libmoonshot/libmoonshot.h
libmoonshot/libmoonshot.vapi
src/moonshot-identity-dialog.vala
src/moonshot-identity-management-view.vala
src/moonshot-server-linux.vala
src/moonshot-server-win32.vala [deleted file]
src/moonshot-trust-anchor-dialog.vala
src/moonshot-utils.vala

index e7c4b51..e5ac3f1 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <dbus/dbus-glib.h>
@@ -447,3 +448,58 @@ int moonshot_install_id_card (const char     *display_name,
 
     return success;
 }
+
+int moonshot_confirm_ca_certificate (const char           *identity_name,
+                                     const char           *realm,
+                                     const unsigned char  *ca_hash,
+                                     int                   hash_len,
+                                     MoonshotError       **error)
+{
+    GError     *g_error = NULL;
+    int         success = 99;
+    int         confirmed = 99;
+    char        hash_str[65];
+    DBusGProxy *dbus_proxy = get_dbus_proxy (error);
+    int         out = 0;
+    int         i;
+
+    if (*error != NULL) {
+        return FALSE;
+    }
+
+    g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
+
+    /* Convert hash byte array to string */
+    out = 0;
+    for (i = 0; i < hash_len; i++) {
+        sprintf(&(hash_str[out]), "%02X", ca_hash[i]);
+        out += 2;
+    }
+
+    printf("moonshot_confirm_ca_certificate: calling ConfirmCaCertificate; hash='%s'\n", hash_str);
+
+    int call_ok = dbus_g_proxy_call_with_timeout (dbus_proxy,
+                                                  "ConfirmCaCertificate",
+                                                  INFINITE_TIMEOUT,
+                                                  &g_error,
+                                                  G_TYPE_STRING, identity_name,
+                                                  G_TYPE_STRING, realm,
+                                                  G_TYPE_STRING, hash_str,
+                                                  G_TYPE_INVALID,
+                                                  G_TYPE_INT,   &confirmed,
+                                                  G_TYPE_BOOLEAN, &success,
+                                                  G_TYPE_INVALID);
+
+    printf("moonshot_confirm_ca_certificate: back from ConfirmCaCertificate. call_ok=%d; confirmed=%d; success=%d\n", 
+           (call_ok? 1 : 0), confirmed, success);
+
+    g_object_unref (dbus_proxy);
+
+    if (g_error != NULL) {
+        *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
+                                     g_error->message);
+        return FALSE;
+    }
+
+    return (int) confirmed;
+}
index 0819d1b..98f4393 100644 (file)
@@ -4,3 +4,4 @@ EXPORTS
     moonshot_error_new
     moonshot_get_default_identity
     moonshot_get_identity
+    moonshot_confirm_ca_certificate
index d7830c2..5b2524d 100644 (file)
@@ -187,4 +187,19 @@ int moonshot_install_id_card (const char     *display_name,
                               int             force_flat_file_store,
                               MoonshotError **error);
 
+
+
+/**
+ * moonshot_confirm_ca_certificate
+ * @
+ * Return value: %TRUE if the certificate is approved; %FALSE otherwise
+ */
+
+int moonshot_confirm_ca_certificate (const char           *identity_name,
+                                     const char           *realm,
+                                     const unsigned char  *sha256,
+                                     int                   sha256_length,
+                                     MoonshotError       **error);
+
+
 #endif
index 8662596..840e19f 100644 (file)
@@ -51,4 +51,11 @@ namespace Moonshot {
                                  string? server_cert,
                                  int force_flat_file_store,
                                  out Moonshot.Error error);
+
+    [CCode (cname = "moonshot_confirm_ca_certificate")]
+    public bool moonshot_confirm_ca_certificate (string identity_name,
+                                                 string realm,
+                                                 string ca_hash,
+                                                 out uint32 confirmed,
+                                                 out Moonshot.Error error);
 }
index 3eb8c2b..0c467a3 100644 (file)
@@ -235,7 +235,7 @@ class IdentityDialog : Dialog
         row++;
 
         if (id.trust_anchor.get_anchor_type() == TrustAnchor.TrustAnchorType.SERVER_CERT) {
-            Widget fingerprint = make_ta_fingerprint_widget(id.trust_anchor);
+            Widget fingerprint = make_ta_fingerprint_widget(id.trust_anchor.server_cert);
             ta_table.attach(fingerprint, 0, 1, row, row + 2, fill_and_expand, fill_and_expand, 5, 5);
 
             // To make the fingerprint box wider, try:
index 55932f7..32313cf 100644 (file)
@@ -547,11 +547,6 @@ public class IdentityManagerView : Window {
     {
         return_if_fail(this.selection_in_progress());
 
-        if (!check_and_confirm_trust_anchor(id)) {
-            // Allow user to pick again
-            return;
-        }
-
         var request = this.request_queue.pop_head();
         var identity = check_add_password(id, request, identities_manager);
         send_button.set_sensitive(false);
@@ -586,33 +581,6 @@ 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.TrustAnchorType.SERVER_CERT) {
-            if (!id.trust_anchor.user_verified) {
-
-                bool ret = false;
-                int result = ResponseType.CANCEL;
-                var dialog = new TrustAnchorDialog(id, this);
-                while (!dialog.complete)
-                    result = dialog.run();
-
-                switch (result) {
-                case ResponseType.OK:
-                    id.trust_anchor.user_verified = true;
-                    ret = true;
-                    break;
-                default:
-                    break;
-                }
-
-                dialog.destroy();
-                return ret;
-            }
-        }
-        return true;
-    }
-
     private void on_about_action()
     {
         string copyright = "Copyright (c) 2011, %d JANET".printf(LATEST_EDIT_YEAR);
index a7692d7..8657c86 100644 (file)
@@ -32,8 +32,6 @@
 
 using Gee;
 
-#if IPC_DBUS
-
 [DBus (name = "org.janet.Moonshot")]
 public class MoonshotServer : Object {
 
@@ -300,251 +298,20 @@ public class MoonshotServer : Object {
         return installed_cards;
     }
 
-    public async bool confim_ca_certificate(string nai,
-                                            string realm,
-                                            string ca_hash)
+    public async bool confirm_ca_certificate(string nai,
+                                             string realm,
+                                             string ca_hash,
+                                             out int confirmed)
     {
         logger.trace(@"MoonshotServer.confirm_ca_certificate: nai='$nai'; realm='$realm'; ca_hash='$ca_hash'");
 
-        return true;
-    }
-}
-
-
-
-#elif IPC_MSRPC
-
-using Rpc;
-using MoonshotRpcInterface;
-
-/* This class must be a singleton, because we use a global RPC
- * binding handle. I cannot picture a situation where more than
- * one instance of the same interface would be needed so this
- * shouldn't be a problem.
- *
- * Shutdown is automatically done by the RPC runtime when the
- * process ends
- */
-public class MoonshotServer : Object {
-    private static IdentityManagerApp parent_app;
-
-    private static MoonshotServer instance = null;
-
-    public static void start(IdentityManagerApp app)
-    {
-        parent_app = app;
-        Rpc.server_start(MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
-    }
-
-    public static MoonshotServer get_instance()
-    {
-        if (instance == null)
-            instance = new MoonshotServer();
-        return instance;
-    }
-
-    [CCode (cname = "moonshot_get_identity_rpc")]
-    public static void get_identity(Rpc.AsyncCall call,
-                                    string nai,
-                                    string password,
-                                    string service,
-                                    ref string nai_out,
-                                    ref string password_out,
-                                    ref string server_certificate_hash,
-                                    ref string ca_certificate,
-                                    ref string subject_name_constraint,
-                                    ref string subject_alt_name_constraint)
-    {
-        logger.trace("(static) get_identity");
-
-        bool result = false;
-
-        var request = new IdentityRequest(parent_app,
-                                          nai,
-                                          password,
-                                          service);
-
-        // Pass execution to the main loop and block the RPC thread
-        request.mutex = new Mutex();
-        request.cond = new Cond();
-        request.set_callback(return_identity_cb);
-
-        request.mutex.lock();
-        Idle.add(request.execute);
-
-        while (request.complete == false)
-            request.cond.wait(request.mutex);
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        var id_card = request.id_card;
-
-        if (id_card != null) {
-            // The strings are freed by the RPC runtime
-            nai_out = id_card.nai;
-            password_out = id_card.password;
-            server_certificate_hash = id_card.trust_anchor.server_cert;
-            ca_certificate = id_card.trust_anchor.ca_cert;
-            subject_name_constraint = id_card.trust_anchor.subject;
-            subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
-
-            return_if_fail(nai_out != null);
-            return_if_fail(password_out != null);
-            return_if_fail(server_certificate_hash != null);
-            return_if_fail(ca_certificate != null);
-            return_if_fail(subject_name_constraint != null);
-            return_if_fail(subject_alt_name_constraint != null);
-
-            result = true;
-        }
-
-        // The outputs must be set before this function is called. For this
-        // reason they are 'ref' not 'out' parameters - Vala assigns to the
-        // 'out' parameters only at the end of the function, which is too
-        // late.
-        call.return(&result);
-
-        request.cond.signal();
-        request.mutex.unlock();
-    }
-
-    [CCode (cname = "moonshot_get_default_identity_rpc")]
-    public static void get_default_identity(Rpc.AsyncCall call,
-                                            ref string nai_out,
-                                            ref string password_out,
-                                            ref string server_certificate_hash,
-                                            ref string ca_certificate,
-                                            ref string subject_name_constraint,
-                                            ref string subject_alt_name_constraint)
-    {
-        logger.trace("(static) get_default_identity");
-
-        bool result;
-
-        var request = new IdentityRequest.default(parent_app);
-        request.mutex = new Mutex();
-        request.cond = new Cond();
-        request.set_callback(return_identity_cb);
-
-        request.mutex.lock();
-        Idle.add(request.execute);
-
-        while (request.complete == false)
-            request.cond.wait(request.mutex);
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        if (request.id_card != null)
-        {
-            nai_out = request.id_card.nai;
-            password_out = request.id_card.password;
-            server_certificate_hash = "certificate";
-
-            return_if_fail(nai_out != null);
-            return_if_fail(password_out != null);
-            return_if_fail(server_certificate_hash != null);
-            return_if_fail(ca_certificate != null);
-            return_if_fail(subject_name_constraint != null);
-            return_if_fail(subject_alt_name_constraint != null);
-
-            result = true;
-        }
-        else
-        {
-            result = false;
-        }
-
-        call.return(&result);
-
-        request.cond.signal();
-        request.mutex.unlock();
-    }
-
-    // Called from the main loop thread when an identity has
-    // been selected
-    static void return_identity_cb(IdentityRequest request) {
-        // Notify the RPC thread that the request is complete
-        request.mutex.lock();
-        request.cond.signal();
-
-        // Block the main loop until the RPC call has returned
-        // to avoid any races
-        request.cond.wait(request.mutex);
-        request.mutex.unlock();
-    }
-
-    [CCode (cname = "moonshot_install_id_card_rpc")]
-    public static bool install_id_card(string     display_name,
-                                       string     user_name,
-                                       string     password,
-                                       string     realm,
-                                       string[]   rules_patterns,
-                                       string[]   rules_always_confirm,
-                                       string[]   services,
-                                       string     ca_cert,
-                                       string     subject,
-                                       string     subject_alt,
-                                       string     server_cert,
-                                       bool       force_flat_file_store)
-    {
-        logger.trace("(static) install_id_card");
-        IdCard idcard = new IdCard();
-
-        bool success = false;
-        Mutex mutex = new Mutex();
-        Cond cond = new Cond();
-
-        idcard.display_name = display_name;
-        idcard.username = user_name;
-        idcard.password = password;
-        idcard.issuer = realm;
-        idcard.services = services;
-        idcard.trust_anchor.ca_cert = ca_cert;
-        idcard.trust_anchor.subject = subject;
-        idcard.trust_anchor.subject_alt = subject_alt;
-        idcard.trust_anchor.server_cert = server_cert;
-
-        if (rules_patterns.length == rules_always_confirm.length)
-        {
-            idcard.rules = new Rule[rules_patterns.length];
-         
-            for (int i = 0; i < idcard.rules.length; i++)
-            { 
-                idcard.rules[i].pattern = rules_patterns[i];
-                idcard.rules[i].always_confirm = rules_always_confirm[i];
-            }
-        }
-
-        mutex.lock();
-
-        ArrayList<IdCard>? old_duplicates = null;
-        // Defer addition to the main loop thread.
-        Idle.add(() => {
-                mutex.lock();
-                success = parent_app.add_identity(idcard, force_flat_file_store, out old_duplicates);
-                foreach (IdCard id_card in old_duplicates) {
-                    stdout.printf("removing duplicate id for '%s'\n", new_card.nai);
-                }
-                cond.signal();
-                mutex.unlock();
-                return false;
-            });
-
-        cond.wait(mutex);
-        mutex.unlock();
+        var request = new TrustAnchorConfirmationRequest(nai, realm, ca_hash);
+        request.set_callback((TrustAnchorConfirmationRequest) => confirm_ca_certificate.callback());
+        request.execute();
+        yield;
 
-        return success;
+        confirmed = (request.confirmed ? 1 : 0);
+        logger.trace(@"MoonshotServer.confirm_ca_certificate: confirmed=$confirmed");
+        return true;
     }
 }
-
-#endif
diff --git a/src/moonshot-server-win32.vala b/src/moonshot-server-win32.vala
deleted file mode 100644 (file)
index a7692d7..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * 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 Gee;
-
-#if IPC_DBUS
-
-[DBus (name = "org.janet.Moonshot")]
-public class MoonshotServer : Object {
-
-    static MoonshotLogger logger = get_logger("MoonshotServer");
-
-    private string app_name = "Moonshot";
-
-    private IdentityManagerApp parent_app;
-
-    public MoonshotServer(IdentityManagerApp app)
-    {
-        logger.trace("MoonshotServer.<constructor>; app=" + (app == null ? "null" : "non-null"));
-        this.parent_app = app;
-    }
-
-    public bool show_ui()
-    {
-        logger.trace("MoonshotServer.show_ui");
-
-        if (parent_app.view == null) {
-            stderr.printf(app_name, "show_ui: parent_app.view is null!\n");
-            logger.warn("show_ui: parent_app.view is null!");
-            return false;
-        }
-        parent_app.show();
-        parent_app.explicitly_launched = true;
-        logger.trace("MoonshotServer.show_ui: returning true");
-        return true;
-    }
-
-    public async bool get_identity(string nai,
-                                   string password,
-                                   string service,
-                                   out string nai_out,
-                                   out string password_out,
-                                   out string server_certificate_hash,
-                                   out string ca_certificate,
-                                   out string subject_name_constraint,
-                                   out string subject_alt_name_constraint)
-    {
-        logger.trace(@"MoonshotServer.get_identity: nai='$nai'; service='$service'");
-        var request = new IdentityRequest(parent_app,
-                                          nai,
-                                          password,
-                                          service);
-        logger.trace(@"MoonshotServer.get_identity: Calling request.execute()");
-        request.set_callback((IdentityRequest) => get_identity.callback());
-        request.execute();
-        logger.trace(@"MoonshotServer.get_identity: Back from request.execute()");
-        yield;
-        logger.trace(@"MoonshotServer.get_identity: back from yield");
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        var id_card = request.id_card;
-
-        if ((id_card != null) && (!id_card.is_no_identity())) {
-            nai_out = id_card.nai;
-            if ((request.password != null) && (request.password != ""))
-                password_out = request.password;
-            else
-                password_out = id_card.password;
-
-            server_certificate_hash = id_card.trust_anchor.server_cert;
-            ca_certificate = id_card.trust_anchor.ca_cert;
-            subject_name_constraint = id_card.trust_anchor.subject;
-            subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
-
-            if (nai_out == null)
-                nai_out = "";
-            if (password_out == null)
-                password_out = "";
-            if (server_certificate_hash == null)
-                server_certificate_hash = "";
-            if (ca_certificate == null)
-                ca_certificate = "";
-            if (subject_name_constraint == null)
-                subject_name_constraint = "";
-            if (subject_alt_name_constraint == null)
-                subject_alt_name_constraint = "";
-
-            logger.trace(@"MoonshotServer.get_identity: returning with nai_out=$nai_out");
-
-            return true;
-        }
-
-        logger.trace("MoonshotServer.get_identity: returning false");
-        return false;
-    }
-
-    public async bool get_default_identity(out string nai_out,
-                                           out string password_out,
-                                           out string server_certificate_hash,
-                                           out string ca_certificate,
-                                           out string subject_name_constraint,
-                                           out string subject_alt_name_constraint)
-    {
-        logger.trace("MoonshotServer.get_default_identity");
-        var request = new IdentityRequest.default(parent_app);
-        request.set_callback((IdentityRequest) => get_default_identity.callback());
-        request.execute();
-        yield;
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        if (request.id_card != null)
-        {
-            nai_out = request.id_card.nai;
-            password_out = request.id_card.password;
-
-            server_certificate_hash = request.id_card.trust_anchor.server_cert;
-            ca_certificate = request.id_card.trust_anchor.ca_cert;
-            subject_name_constraint = request.id_card.trust_anchor.subject;
-            subject_alt_name_constraint = request.id_card.trust_anchor.subject_alt;
-
-            if (nai_out == null)
-                nai_out = "";
-            if (password_out == null)
-                password_out = "";
-            if (server_certificate_hash == null)
-                server_certificate_hash = "";
-            if (ca_certificate == null)
-                ca_certificate = "";
-            if (subject_name_constraint == null)
-                subject_name_constraint = "";
-            if (subject_alt_name_constraint == null)
-                subject_alt_name_constraint = "";
-
-            logger.trace("MoonshotServer.get_default_identity: returning true");
-            return true;
-        }
-
-        return false;
-    }
-
-    public bool install_id_card(string   display_name,
-                                string   user_name,
-                                string   ?password,
-                                string   ?realm,
-                                string[] ?rules_patterns,
-                                string[] ?rules_always_confirm,
-                                string[] ?services,
-                                string   ?ca_cert,
-                                string   ?subject,
-                                string   ?subject_alt,
-                                string   ?server_cert,
-                                int      force_flat_file_store)
-    {
-        IdCard idcard = new IdCard();
-
-        idcard.display_name = display_name;
-        idcard.username = user_name;
-        idcard.password = password;
-        if ((password != null) && (password != ""))
-            idcard.store_password = true;
-        idcard.issuer = realm;
-        idcard.update_services(services);
-        var ta = new TrustAnchor(ca_cert, server_cert, subject, subject_alt, false);
-
-        if (!ta.is_empty()) {
-            // We have to set the datetime_added here, because it isn't delivered via IPC.
-            string ta_datetime_added = TrustAnchor.format_datetime_now();
-            ta.set_datetime_added(ta_datetime_added);
-            logger.trace("install_id_card : Set ta_datetime_added for '%s' to '%s'; ca_cert='%s'; server_cert='%s'".printf(idcard.display_name, ta.datetime_added, ta.ca_cert, ta.server_cert));
-        }
-        idcard.set_trust_anchor_from_store(ta);
-
-        logger.trace("install_id_card: Card '%s' has services: '%s'"
-                     .printf(idcard.display_name, idcard.get_services_string("; ")));
-
-        logger.trace(@"Installing IdCard named '$(idcard.display_name)'; ca_cert='$(idcard.trust_anchor.ca_cert)'; server_cert='$(idcard.trust_anchor.server_cert)'");
-
-
-        if (rules_patterns.length == rules_always_confirm.length)
-        {
-            /* workaround Centos vala array property bug: use temp array */
-            Rule[] rules = new Rule[rules_patterns.length];
-         
-            for (int i = 0; i < rules.length; i++)
-            { 
-                rules[i].pattern = rules_patterns[i];
-                rules[i].always_confirm = rules_always_confirm[i];
-            }
-            idcard.rules = rules;
-        }
-
-        ArrayList<IdCard>? old_duplicates = null;
-        var ret = parent_app.add_identity(idcard, (force_flat_file_store != 0), out old_duplicates);
-
-        if (old_duplicates != null) {
-            // Printing to stdout here is ugly behavior; but it's old behavior that
-            // may be expected. (TODO: Do we need to keep this?)
-            foreach (IdCard id_card in old_duplicates) {
-                stdout.printf("removed duplicate id for '%s'\n", id_card.nai);
-            }
-        }
-        return ret;
-    }
-
-
-    public int install_from_file(string file_name)
-    {
-        var webp = new WebProvisioning.Parser(file_name);
-
-        webp.parse();
-        bool result = false;
-        int installed_cards = 0;
-        foreach (IdCard card in webp.cards)
-        {
-            string[] rules_patterns = {};
-            string[] rules_always_confirm = {};
-        
-            if (card.rules.length > 0)
-            {
-                int i = 0;
-                rules_patterns = new string[card.rules.length];
-                rules_always_confirm = new string[card.rules.length];
-                foreach (Rule r in card.rules)
-                {
-                    rules_patterns[i] = r.pattern;
-                    rules_always_confirm[i] = r.always_confirm;
-                    i++;
-                }
-            } 
-
-
-            // prevent a crash by holding the reference to otherwise
-            // unowned array(?)
-
-            // string[] svcs = card.services.to_array();
-            // string[] svcs = card.services.to_array()[:];
-            string[] svcs = new string[card.services.size];
-            for (int i = 0; i < card.services.size; i++) {
-                svcs[i] = card.services[i];
-            }
-
-            logger.trace(@"install_from_file: Adding card with display name '$(card.display_name)'");
-            result = install_id_card(card.display_name,
-                                     card.username,
-                                     card.password,
-                                     card.issuer,
-                                     rules_patterns,
-                                     rules_always_confirm,
-                                     svcs,
-                                     card.trust_anchor.ca_cert,
-                                     card.trust_anchor.subject,
-                                     card.trust_anchor.subject_alt,
-                                     card.trust_anchor.server_cert,
-                                     0);
-            if (result) {
-                installed_cards++;
-            }
-        }
-        return installed_cards;
-    }
-
-    public async bool confim_ca_certificate(string nai,
-                                            string realm,
-                                            string ca_hash)
-    {
-        logger.trace(@"MoonshotServer.confirm_ca_certificate: nai='$nai'; realm='$realm'; ca_hash='$ca_hash'");
-
-        return true;
-    }
-}
-
-
-
-#elif IPC_MSRPC
-
-using Rpc;
-using MoonshotRpcInterface;
-
-/* This class must be a singleton, because we use a global RPC
- * binding handle. I cannot picture a situation where more than
- * one instance of the same interface would be needed so this
- * shouldn't be a problem.
- *
- * Shutdown is automatically done by the RPC runtime when the
- * process ends
- */
-public class MoonshotServer : Object {
-    private static IdentityManagerApp parent_app;
-
-    private static MoonshotServer instance = null;
-
-    public static void start(IdentityManagerApp app)
-    {
-        parent_app = app;
-        Rpc.server_start(MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
-    }
-
-    public static MoonshotServer get_instance()
-    {
-        if (instance == null)
-            instance = new MoonshotServer();
-        return instance;
-    }
-
-    [CCode (cname = "moonshot_get_identity_rpc")]
-    public static void get_identity(Rpc.AsyncCall call,
-                                    string nai,
-                                    string password,
-                                    string service,
-                                    ref string nai_out,
-                                    ref string password_out,
-                                    ref string server_certificate_hash,
-                                    ref string ca_certificate,
-                                    ref string subject_name_constraint,
-                                    ref string subject_alt_name_constraint)
-    {
-        logger.trace("(static) get_identity");
-
-        bool result = false;
-
-        var request = new IdentityRequest(parent_app,
-                                          nai,
-                                          password,
-                                          service);
-
-        // Pass execution to the main loop and block the RPC thread
-        request.mutex = new Mutex();
-        request.cond = new Cond();
-        request.set_callback(return_identity_cb);
-
-        request.mutex.lock();
-        Idle.add(request.execute);
-
-        while (request.complete == false)
-            request.cond.wait(request.mutex);
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        var id_card = request.id_card;
-
-        if (id_card != null) {
-            // The strings are freed by the RPC runtime
-            nai_out = id_card.nai;
-            password_out = id_card.password;
-            server_certificate_hash = id_card.trust_anchor.server_cert;
-            ca_certificate = id_card.trust_anchor.ca_cert;
-            subject_name_constraint = id_card.trust_anchor.subject;
-            subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
-
-            return_if_fail(nai_out != null);
-            return_if_fail(password_out != null);
-            return_if_fail(server_certificate_hash != null);
-            return_if_fail(ca_certificate != null);
-            return_if_fail(subject_name_constraint != null);
-            return_if_fail(subject_alt_name_constraint != null);
-
-            result = true;
-        }
-
-        // The outputs must be set before this function is called. For this
-        // reason they are 'ref' not 'out' parameters - Vala assigns to the
-        // 'out' parameters only at the end of the function, which is too
-        // late.
-        call.return(&result);
-
-        request.cond.signal();
-        request.mutex.unlock();
-    }
-
-    [CCode (cname = "moonshot_get_default_identity_rpc")]
-    public static void get_default_identity(Rpc.AsyncCall call,
-                                            ref string nai_out,
-                                            ref string password_out,
-                                            ref string server_certificate_hash,
-                                            ref string ca_certificate,
-                                            ref string subject_name_constraint,
-                                            ref string subject_alt_name_constraint)
-    {
-        logger.trace("(static) get_default_identity");
-
-        bool result;
-
-        var request = new IdentityRequest.default(parent_app);
-        request.mutex = new Mutex();
-        request.cond = new Cond();
-        request.set_callback(return_identity_cb);
-
-        request.mutex.lock();
-        Idle.add(request.execute);
-
-        while (request.complete == false)
-            request.cond.wait(request.mutex);
-
-        nai_out = "";
-        password_out = "";
-        server_certificate_hash = "";
-        ca_certificate = "";
-        subject_name_constraint = "";
-        subject_alt_name_constraint = "";
-
-        if (request.id_card != null)
-        {
-            nai_out = request.id_card.nai;
-            password_out = request.id_card.password;
-            server_certificate_hash = "certificate";
-
-            return_if_fail(nai_out != null);
-            return_if_fail(password_out != null);
-            return_if_fail(server_certificate_hash != null);
-            return_if_fail(ca_certificate != null);
-            return_if_fail(subject_name_constraint != null);
-            return_if_fail(subject_alt_name_constraint != null);
-
-            result = true;
-        }
-        else
-        {
-            result = false;
-        }
-
-        call.return(&result);
-
-        request.cond.signal();
-        request.mutex.unlock();
-    }
-
-    // Called from the main loop thread when an identity has
-    // been selected
-    static void return_identity_cb(IdentityRequest request) {
-        // Notify the RPC thread that the request is complete
-        request.mutex.lock();
-        request.cond.signal();
-
-        // Block the main loop until the RPC call has returned
-        // to avoid any races
-        request.cond.wait(request.mutex);
-        request.mutex.unlock();
-    }
-
-    [CCode (cname = "moonshot_install_id_card_rpc")]
-    public static bool install_id_card(string     display_name,
-                                       string     user_name,
-                                       string     password,
-                                       string     realm,
-                                       string[]   rules_patterns,
-                                       string[]   rules_always_confirm,
-                                       string[]   services,
-                                       string     ca_cert,
-                                       string     subject,
-                                       string     subject_alt,
-                                       string     server_cert,
-                                       bool       force_flat_file_store)
-    {
-        logger.trace("(static) install_id_card");
-        IdCard idcard = new IdCard();
-
-        bool success = false;
-        Mutex mutex = new Mutex();
-        Cond cond = new Cond();
-
-        idcard.display_name = display_name;
-        idcard.username = user_name;
-        idcard.password = password;
-        idcard.issuer = realm;
-        idcard.services = services;
-        idcard.trust_anchor.ca_cert = ca_cert;
-        idcard.trust_anchor.subject = subject;
-        idcard.trust_anchor.subject_alt = subject_alt;
-        idcard.trust_anchor.server_cert = server_cert;
-
-        if (rules_patterns.length == rules_always_confirm.length)
-        {
-            idcard.rules = new Rule[rules_patterns.length];
-         
-            for (int i = 0; i < idcard.rules.length; i++)
-            { 
-                idcard.rules[i].pattern = rules_patterns[i];
-                idcard.rules[i].always_confirm = rules_always_confirm[i];
-            }
-        }
-
-        mutex.lock();
-
-        ArrayList<IdCard>? old_duplicates = null;
-        // Defer addition to the main loop thread.
-        Idle.add(() => {
-                mutex.lock();
-                success = parent_app.add_identity(idcard, force_flat_file_store, out old_duplicates);
-                foreach (IdCard id_card in old_duplicates) {
-                    stdout.printf("removing duplicate id for '%s'\n", new_card.nai);
-                }
-                cond.signal();
-                mutex.unlock();
-                return false;
-            });
-
-        cond.wait(mutex);
-        mutex.unlock();
-
-        return success;
-    }
-}
-
-#endif
index 0537494..dcc8d67 100644 (file)
 */
 using Gtk;
 
+public delegate void TrustAnchorConfirmationCallback(TrustAnchorConfirmationRequest request);
+
+public class TrustAnchorConfirmationRequest : GLib.Object {
+    static MoonshotLogger logger = get_logger("TrustAnchorConfirmationRequest");
+
+    string nai;
+    string realm;
+    string ca_hash;
+    public bool confirmed = false;
+
+    TrustAnchorConfirmationCallback callback = null;
+
+    public TrustAnchorConfirmationRequest(string nai,
+                                          string realm,
+                                          string ca_hash)
+    {
+        this.nai = nai;
+        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() {
+
+        var dialog = new TrustAnchorDialog(nai, realm, ca_hash);
+        var response = dialog.run();
+        this.confirmed = (response == ResponseType.OK);
+        dialog.destroy();
+
+        // Send back the confirmation (we can't directly run the
+        // callback because we may be being called from a 'yield')
+        GLib.Idle.add(
+            () => {
+                return_confirmation(confirmed);
+                return false;
+            }
+            );
+
+
+//        return_confirmation(confirmed);
+
+        /* This function works as a GSourceFunc, so it can be passed to
+         * the main loop from other threads
+         */
+        return false;
+    }
+
+    public void return_confirmation(bool confirmed) {
+        this.confirmed = confirmed;
+        logger.trace(@"return_confirmation: confirmed=$confirmed");
+
+        return_if_fail(callback != null);
+        logger.trace("return_confirmation: invoking callback");
+        callback(this);
+    }
+}
+
+
+
 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(string nai,
+                             string realm,
+                             string ca_hash)
     {
         this.set_title(_("Trust Anchor"));
         this.set_modal(true);
-        this.set_transient_for(parent);
+//        this.set_transient_for(parent);
         this.modify_bg(StateType.NORMAL, white);
 
         this.add_buttons(_("Cancel"), ResponseType.CANCEL,
@@ -62,16 +131,16 @@ class TrustAnchorDialog : Dialog
         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: ") + nai);
         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."));
         confirm_label.set_alignment(0, 0.5f);
 
-        var trust_anchor_display = make_ta_fingerprint_widget(idcard.trust_anchor);
+        var trust_anchor_display = make_ta_fingerprint_widget(ca_hash);
 
         var vbox = new VBox(false, 0);
         vbox.set_border_width(6);
index 3567a0e..9182388 100644 (file)
@@ -124,7 +124,7 @@ internal void set_atk_relation(Widget widget, Widget target_widget, Atk.Relation
 }
 
 
-internal Widget make_ta_fingerprint_widget(TrustAnchor trust_anchor)
+internal Widget make_ta_fingerprint_widget(string server_cert)
 {
         var fingerprint_label = new Label(_("SHA-256 fingerprint:"));
         fingerprint_label.set_alignment(0, 0.5f);
@@ -135,7 +135,7 @@ internal Widget make_ta_fingerprint_widget(TrustAnchor trust_anchor)
         fingerprint.set_editable(false);
         fingerprint.set_left_margin(3);
         var buffer = fingerprint.get_buffer();
-        buffer.set_text(colonize(trust_anchor.server_cert, 16), -1);
+        buffer.set_text(colonize(server_cert, 16), -1);
         fingerprint.wrap_mode = Gtk.WrapMode.WORD_CHAR;
 
         set_atk_relation(fingerprint_label, fingerprint, Atk.RelationType.LABEL_FOR);