Add launch-hidden functionality to moonshot msrpc implementation
authorKevin Wasserman <krwasserman@painless-security.com>
Thu, 26 Feb 2015 19:44:15 +0000 (14:44 -0500)
committerKevin Wasserman <krwasserman@hotmail.com>
Wed, 4 Mar 2015 17:19:36 +0000 (12:19 -0500)
Also, when the identity manager cannot bind its rpc interface,
it now binds as a client and tells the existing server to show
itself, similar to the dbus implementation.

To link both client and server rpc code requires passing the
'prefix' argument to midl which is not exposed via the mingw
midl wrapper, so I created new moonshot-midl wrapper to pass to the mingw
midl wrapper.

Makefile.am
libmoonshot/libmoonshot-msrpc.c
libmoonshot/moonshot-msrpc.idl
moonshot-midl [new file with mode: 0644]
src/moonshot-server.vala
vapi/moonshot-msrpc.vapi
vapi/msrpc-1.0-extra.vapi [new file with mode: 0644]

index 290639d..21382e8 100644 (file)
@@ -123,7 +123,7 @@ if IPC_MSRPC
 AM_CPPFLAGS += -Isrc
 
 AM_VALAFLAGS += \
-       --pkg moonshot-msrpc --pkg msrpc-1.0 \
+       --pkg moonshot-msrpc --pkg msrpc-1.0 --pkg msrpc-1.0-extra \
        --define=IPC_MSRPC
 
 BUILT_SOURCES = libmoonshot/moonshot-msrpc.h \
@@ -132,8 +132,10 @@ BUILT_SOURCES = libmoonshot/moonshot-msrpc.h \
 
 DISTCLEANFILES = ${BUILT_SOURCES}
 
+export MIDL_NATIVE = ${MIDL}
+
 libmoonshot/moonshot-msrpc.h: libmoonshot/moonshot-msrpc.idl libmoonshot/moonshot-msrpc.acf
-       ${AM_V_GEN} ${MIDL_WRAPPER} -o libmoonshot -m "${MIDL}" $^
+       ${AM_V_GEN} ${MIDL_WRAPPER} -o libmoonshot -m ${top_builddir}/moonshot-midl $^
 
 libmoonshot/moonshot-msrpc_s.c: libmoonshot/moonshot-msrpc.h
 libmoonshot/moonshot-msrpc_c.c: libmoonshot/moonshot-msrpc.h
@@ -143,7 +145,9 @@ libmoonshot_libmoonshot_la_SOURCES += \
 
 
 nodist_src_moonshot_SOURCES = \
-        libmoonshot/moonshot-msrpc_s.c
+        libmoonshot/moonshot-msrpc_s.c \
+        libmoonshot/moonshot-msrpc_c.c
+
 
 nodist_libmoonshot_libmoonshot_la_SOURCES = \
         libmoonshot/moonshot-msrpc_c.c
index 0cf1e9c..1afbd59 100644 (file)
@@ -49,6 +49,7 @@
 
 #define MOONSHOT_ENDPOINT_NAME "/org/janet/Moonshot"
 #define MOONSHOT_INSTALL_PATH_KEY "Software\\Moonshot"
+#define MOONSHOT_STARTUP_ARGS "--dbus-launched"
 
 void *__RPC_USER MIDL_user_allocate (size_t size) {
     return malloc (size);
@@ -119,7 +120,9 @@ static void launch_server (MoonshotError **error) {
     LONG status;
     BOOL success;
     DWORD value_type;
+    DWORD commandline_length;
     DWORD length;
+    char* commandline=NULL;
     char* exe_path=NULL;
 
     status = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
@@ -179,8 +182,19 @@ static void launch_server (MoonshotError **error) {
 
     exe_path[length] = 0;
     startup_info.cb = sizeof (startup_info);
+    commandline_length = length + 1 + sizeof(MOONSHOT_STARTUP_ARGS);
+    commandline = malloc(commandline_length + 1);
+    if (commandline == NULL) {
+        *error = moonshot_error_new
+                    (MOONSHOT_ERROR_OS_ERROR,
+                        "Out of memory allocating %d bytes for moonshot commandline.",
+                        length);
+        goto cleanup;
+    }
+    snprintf(commandline, commandline_length, "%s %s", exe_path, MOONSHOT_STARTUP_ARGS);
+    commandline[commandline_length] = 0;
     success = CreateProcess (exe_path,
-                             NULL,
+                             commandline,
                              NULL,
                              NULL,
                              TRUE,
@@ -200,6 +214,8 @@ static void launch_server (MoonshotError **error) {
 cleanup:
     if (exe_path)
         free(exe_path);
+    if (commandline)
+        free(commandline);
 }
 
 static void bind_rpc (MoonshotError **error)
@@ -311,7 +327,7 @@ int moonshot_get_identity (const char     *nai,
     *subject_alt_name_constraint_out = NULL;
 
     RPC_TRY_EXCEPT {
-        moonshot_get_identity_rpc (&call,
+        c_moonshot_get_identity_rpc (&call,
                                    nai,
                                    password,
                                    service,
@@ -370,7 +386,7 @@ int moonshot_get_default_identity (char          **nai_out,
     *subject_alt_name_constraint_out = NULL;
 
     RPC_TRY_EXCEPT {
-        moonshot_get_default_identity_rpc (&call,
+        c_moonshot_get_default_identity_rpc (&call,
                                            nai_out,
                                            password_out,
                                            server_certificate_hash_out,
@@ -431,7 +447,7 @@ int moonshot_install_id_card (const char     *display_name,
     if (server_cert == NULL) server_cert = "";
 
     RPC_TRY_EXCEPT {
-        success = moonshot_install_id_card_rpc (display_name,
+        success = c_moonshot_install_id_card_rpc (display_name,
                                                 user_name,
                                                 password,
                                                 realm,
index ab64963..eb91110 100644 (file)
@@ -36,4 +36,6 @@ interface moonshot
                                       [in, string] const char *subject_alt,
                                       [in, string] const char *server_cert,
                                       int force_flat_file_store);
+
+    void moonshot_show_ui_rpc ();
 }
diff --git a/moonshot-midl b/moonshot-midl
new file mode 100644 (file)
index 0000000..df0f03f
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+"$MIDL_NATIVE" -prefix client "c_" "$@"
index 74288f7..4e30071 100644 (file)
@@ -265,10 +265,37 @@ public class MoonshotServer : Object {
 
     private static MoonshotServer instance = null;
 
+    private static void log_function(uint    status_code,
+                                     string  format,
+                                     va_list args)
+    {
+        stdout.printf("RPC Error %u:\n    ", status_code);
+        stdout.vprintf(format, args);
+        stdout.printf("\n");
+        stdout.flush();
+    }
+
     public static void start (IdentityManagerApp app)
     {
         parent_app = app;
-        Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
+        /* Rpc.server_start() would conveniently call Rpc.init() for us.
+         * Unfortunately, the default log function calls exit() on any
+         * error. We'd prefer to send a message to the existing server
+         * if there is one, so we need to use a custom log function.
+         */
+        Rpc.init();
+        Rpc.set_log_function(log_function);
+        if (Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER) != 0) {
+            /* Server failed to start; bind as client and send message to server to show ui */
+            uint status = Rpc.client_bind(ref MoonshotRpcInterface.binding_handle, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
+            if (status != 0) {
+                /* total failure; log error message and bail */
+                GLib.log("Moonshot UI", GLib.LogLevelFlags.LEVEL_INFO, "Could neither launch server nor bind as client. status code: %u", status);
+            } else {
+                MoonshotRpcInterface.show_ui();
+            }
+            GLib.Process.exit(0);
+        }
     }
 
     public static MoonshotServer get_instance ()
@@ -278,6 +305,16 @@ public class MoonshotServer : Object {
         return instance;
     }
 
+    [CCode (cname = "moonshot_show_ui_rpc")]
+    public static void show_ui ()
+    {
+        Idle.add( () => {
+            parent_app.show();
+            parent_app.explicitly_launched = true;
+            return false;
+        });
+    }
+
     [CCode (cname = "moonshot_get_identity_rpc")]
     public static void get_identity (Rpc.AsyncCall call,
                                      string nai,
index f940739..c464676 100644 (file)
@@ -16,7 +16,10 @@ namespace MoonshotRpcInterface {
         string always_confirm;
     }
 
-    [CCode (cname = "moonshot_get_identity_rpc")]
+    [CCode (cname = "c_moonshot_show_ui_rpc")]
+    public extern void show_ui();
+
+    [CCode (cname = "c_moonshot_get_identity_rpc")]
     public extern void get_identity (Rpc.AsyncCall call,
                                      string nai,
                                      string password,
@@ -28,7 +31,7 @@ namespace MoonshotRpcInterface {
                                      ref string subject_name_constraint,
                                      ref string subject_alt_name_constraint);
 
-    [CCode (cname = "moonshot_get_default_identity_rpc")]
+    [CCode (cname = "c_moonshot_get_default_identity_rpc")]
     public extern void get_default_identity (Rpc.AsyncCall call,
                                              ref string nai_out,
                                              ref string password_out);
diff --git a/vapi/msrpc-1.0-extra.vapi b/vapi/msrpc-1.0-extra.vapi
new file mode 100644 (file)
index 0000000..f4d0091
--- /dev/null
@@ -0,0 +1,6 @@
+[CCode (cprefix = "rpc_", cheader_filename = "msrpc-mingw.h")]
+
+namespace Rpc {
+       [CCode (cname = "rpc_init")]
+       public void init ();
+}