Merge client library with moonshot-ui
authorSam Thursfield <samthursfield@codethink.co.uk>
Mon, 4 Jul 2011 18:44:14 +0000 (19:44 +0100)
committerSam Thursfield <samthursfield@codethink.co.uk>
Mon, 4 Jul 2011 18:44:14 +0000 (19:44 +0100)
(client library is currently in progress)

15 files changed:
.gitignore
Makefile.am
configure.ac
libmoonshot/libmoonshot-common.c [new file with mode: 0644]
libmoonshot/libmoonshot-common.h [new file with mode: 0644]
libmoonshot/libmoonshot-dbus.c [new file with mode: 0644]
libmoonshot/libmoonshot-msrpc.c [new file with mode: 0644]
libmoonshot/libmoonshot.h [new file with mode: 0644]
libmoonshot/moonshot-msrpc.acf [new file with mode: 0644]
libmoonshot/moonshot-msrpc.idl [new file with mode: 0644]
src/moonshot-msrpc.acf [deleted file]
src/moonshot-msrpc.idl [deleted file]
src/moonshot-msrpc.vapi
src/moonshot-server.vala
tests/basic.c [new file with mode: 0644]

index 66ee453..2de40f5 100755 (executable)
@@ -23,6 +23,10 @@ build-aux
 autom4te.cache
 aclocal.m4
 ABOUT-NLS
+.libs/
+*.la
+*.lo
+libtool
 src/moonshot-add-dialog.c
 src/moonshot-custom-vbox.c
 src/moonshot-id.c
@@ -56,8 +60,13 @@ m4/lcmessage.m4
 m4/lib-ld.m4
 m4/lib-link.m4
 m4/lib-prefix.m4
+m4/libtool.m4
 m4/lock.m4
 m4/longlong.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
 m4/nls.m4
 m4/po.m4
 m4/printf-posix.m4
index 475b2b7..f76fd31 100644 (file)
@@ -2,19 +2,33 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
 SUBDIRS = po
 
+
+lib_LTLIBRARIES = libmoonshot/libmoonshot.la
+
 bin_PROGRAMS = src/moonshot
 
+
 AM_CFLAGS =
 
 AM_CPPFLAGS = \
        -include config.h \
        -DLOCALEDIR=\""$(localedir)"\" \
-       $(moonshot_CFLAGS)
+       -I$(top_srcdir)/libmoonshot
 
 AM_VALAFLAGS = \
        config.vapi \
        --pkg gtk+-2.0
 
+
+libmoonshot_libmoonshot_la_CPPFLAGS = \
+        $(libmoonshot_CFLAGS) \
+        $(AM_CPPFLAGS)
+
+libmoonshot_libmoonshot_la_SOURCES = libmoonshot/libmoonshot-common.c
+
+libmoonshot_libmoonshot_la_LIBADD = $(libmoonshot_LIBS)
+
+
 src_moonshot_SOURCES = \
         src/moonshot-id.vala \
         src/moonshot-add-dialog.vala \
@@ -30,11 +44,23 @@ src_moonshot_SOURCES = \
 src_moonshot_LDADD = \
         $(moonshot_LIBS)
 
+src_moonshot_CPPFLAGS = \
+        $(moonshot_CFLAGS) \
+        $(AM_CPPFLAGS)
+
+
 if OS_WIN32
+
+libmoonshot_libmoonshot_la_LDFLAGS = -no-undefined
+
 src_moonshot_CFLAGS = -mwindows
+
+AM_CPPFLAGS += -DOS_WIN32
 AM_VALAFLAGS += --define=OS_WIN32
+
 endif
 
+
 if IPC_MSRPC
 
 AM_CPPFLAGS += -Isrc
@@ -43,30 +69,36 @@ AM_VALAFLAGS += \
        --pkg msrpc-1.0 \
        --define=IPC_MSRPC
 
+BUILT_SOURCES = libmoonshot/moonshot-msrpc.h \
+                libmoonshot/moonshot-msrpc_s.c \
+                libmoonshot/moonshot-msrpc_c.c
+
+DISTCLEANFILES = ${BUILT_SOURCES}
+
+libmoonshot/moonshot-msrpc.h: libmoonshot/moonshot-msrpc.idl libmoonshot/moonshot-msrpc.acf
+       ${AM_V_GEN} ${MIDL_WRAPPER} -o libmoonshot -m "${MIDL}" $^
+
+libmoonshot/moonshot-msrpc_s.c: libmoonshot/moonshot-msrpc.h
+libmoonshot/moonshot-msrpc_c.c: libmoonshot/moonshot-msrpc.h
+
+libmoonshot_libmoonshot_la_SOURCES += \
+        libmoonshot/libmoonshot-msrpc.c \
+        libmoonshot/moonshot-msrpc_c.c
+
 src_moonshot_SOURCES += \
         src/moonshot-msrpc.vapi
 
 nodist_src_moonshot_SOURCES = \
-        src/moonshot-msrpc_s.c
+        libmoonshot/moonshot-msrpc_s.c
 
 bin_PROGRAMS += src/msrpc-client
 
 nodist_src_msrpc_client_SOURCES = \
         src/msrpc-client.vala \
         src/moonshot-msrpc.vapi \
-        src/moonshot-msrpc_c.c
-
-src_msrpc_client_LDADD = \
-        $(moonshot_LIBS)
-
-BUILT_SOURCES = src/moonshot-msrpc.h src/moonshot-msrpc_s.c src/moonshot-msrpc_c.c
-
-DISTCLEANFILES = ${BUILT_SOURCES}
-
-src/moonshot-msrpc.h: src/moonshot-msrpc.idl src/moonshot-msrpc.acf
-       ${AM_V_GEN} ${MIDL_WRAPPER} -o src -m "${MIDL}" $^
+        libmoonshot/moonshot-msrpc_c.c
 
-src/moonshot-msrpc_s.c: src/moonshot-msrpc.h
+src_msrpc_client_LDADD = $(moonshot_LIBS)
 
 endif
 
@@ -85,6 +117,8 @@ AM_VALAFLAGS += \
        --pkg dbus-glib-1 \
        --define=IPC_DBUS
 
+libmoonshot_libmoonshot_la_SOURCES += libmoonshot/libmoonshot-dbus.c
+
 bin_PROGRAMS += src/dbus-client
 
 src_dbus_client_SOURCES = \
@@ -121,6 +155,14 @@ moonshot_webp_CFLAGS = -mwindows
 AM_VALAFLAGS += --define=OS_WIN32
 endif
 
+
+noinst_PROGRAMS = tests/basic
+
+
+tests_basic_LDADD = ${top_builddir}/libmoonshot/libmoonshot.la
+tests_basic_SOURCES = tests/basic.c
+
+
 if OS_WIN32
 
 ## A couple of Windows-specific targets:
index ec91abf..9afbc11 100644 (file)
@@ -13,6 +13,9 @@ AM_INIT_AUTOMAKE([1.11 -Wall foreign subdir-objects tar-pax no-dist-gzip dist-xz
 AM_SILENT_RULES([yes])
 AM_MAINTAINER_MODE([enable])
 
+LT_PREREQ([2.2])
+LT_INIT([win32-dll])
+
 PKG_PROG_PKG_CONFIG([0.24])
 
 # Platform checks
@@ -85,6 +88,10 @@ PKG_CHECK_MODULES(moonshot,[
         $IPC_MODULE
 ])
 
+PKG_CHECK_MODULES(libmoonshot,[
+        $IPC_MODULE
+])
+
 # i18n stuff
 AM_GNU_GETTEXT([external])
 AM_GNU_GETTEXT_VERSION([0.17])
diff --git a/libmoonshot/libmoonshot-common.c b/libmoonshot/libmoonshot-common.c
new file mode 100644 (file)
index 0000000..4161528
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * Author: Sam Thursfield <samthursfield@codethink.co.uk>
+ */
+
+#include "libmoonshot.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+MoonshotError *_moonshot_error_new (MoonshotErrorCode  code,
+                                    const char        *format,
+                                    ...)
+{
+    MoonshotError *error;
+    int            buffer_size;
+    va_list        args;
+
+    error = malloc (sizeof (MoonshotError));
+    error->code = code;
+
+    va_start (args, format);
+
+    #ifdef OS_WIN32
+    buffer_size = _vscprintf (format, args);
+    error->message = malloc (buffer_size + 1);
+    _vsnprintf (error->message, buffer_size, format, args);
+    #else
+    vasprintf (&error->message, format, args);
+    #endif
+
+    return error;
+}
+
+void moonshot_error_free (MoonshotError *error)
+{
+    if (error == NULL)
+        return;
+
+    if (error->message != NULL) 
+        free (error->message);
+
+    free (error);
+}
diff --git a/libmoonshot/libmoonshot-common.h b/libmoonshot/libmoonshot-common.h
new file mode 100644 (file)
index 0000000..0b4301e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * Author: Sam Thursfield <samthursfield@codethink.co.uk>
+ */
+
+#include "libmoonshot.h"
+
+MoonshotError *_moonshot_error_new (MoonshotErrorCode  code,
+                                    const char        *format,
+                                    ...);
diff --git a/libmoonshot/libmoonshot-dbus.c b/libmoonshot/libmoonshot-dbus.c
new file mode 100644 (file)
index 0000000..fcd19b4
--- /dev/null
@@ -0,0 +1,328 @@
+/* libmoonshot - Moonshot client library
+ * Copyright (c) 2011, 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.
+ *
+ * Author: Sam Thursfield <samthursfield@codethink.co.uk>
+ */
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+
+#include "libmoonshot.h"
+
+#define MOONSHOT_DBUS_NAME "org.janet.Moonshot"
+#define MOONSHOT_DBUS_PATH "/org/janet/moonshot"
+
+/* This library is overly complicated currently due to the requirement
+ * that it work on Debian Squeeze - this has GLib 2.24 which requires us
+ * to use dbus-glib instead of GDBus. If/when this requirement is
+ * dropped the DBus version of the library can be greatly simplified.
+ */
+
+typedef struct {
+    char *nai;
+    char *password;
+    char *server_certificate_hash;
+    char *ca_certificate;
+    char *subject_name_constraint;
+    char *subject_alt_name_constraint;
+} MoonshotIdentityData;
+
+static MoonshotIdentityData *moonshot_identity_data_new ()
+{
+    return g_slice_new (MoonshotIdentityData);
+}
+
+static void moonshot_identity_data_free (void *data)
+{
+    g_slice_free (MoonshotIdentityData, data);
+}
+
+static DBusGProxy *moonshot_dbus_proxy = NULL;
+
+GQuark moonshot_error_quark (void)
+{
+    return g_quark_from_static_string ("moonshot-error-quark");
+}
+
+static DBusGProxy *dbus_connect (GError **g_error)
+{
+    DBusConnection  *connection;
+    DBusError        dbus_error;
+    DBusGConnection *g_connection;
+    DBusGProxy      *g_proxy;
+    dbus_bool_t      name_has_owner;
+
+    g_return_val_if_fail (*g_error == NULL, NULL);
+
+    dbus_error_init (&dbus_error);
+
+    /* Check for moonshot server and start the service if possible. We use
+     * libdbus here because dbus-glib doesn't handle autostarting the service.
+     * If/when we move to GDBus this code can become a one-liner.
+     */
+
+    connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
+
+    if (dbus_error_is_set (&dbus_error)) {
+        *g_error = g_error_new (MOONSHOT_ERROR,
+                                MOONSHOT_ERROR_DBUS_ERROR,
+                                "DBus error: %s",
+                                dbus_error.message);
+        dbus_error_free (&dbus_error);
+        return NULL;
+    }
+
+    name_has_owner  = dbus_bus_name_has_owner (connection,
+                                               MOONSHOT_DBUS_NAME,
+                                               &dbus_error);
+
+    if (dbus_error_is_set (&dbus_error)) {
+        *g_error = g_error_new (MOONSHOT_ERROR,
+                                MOONSHOT_ERROR_DBUS_ERROR,
+                                "DBus error: %s",
+                                dbus_error.message);
+
+        dbus_error_free (&dbus_error);
+        return NULL;
+    }
+
+    if (! name_has_owner) {
+        dbus_bus_start_service_by_name (connection,
+                                        MOONSHOT_DBUS_NAME,
+                                        0,
+                                        NULL,
+                                        &dbus_error);
+
+        if (dbus_error_is_set (&dbus_error)) {
+            if (strcmp (dbus_error.name + 27, "ServiceUnknown") == 0) {
+                /* Missing .service file; the moonshot-ui install is broken */
+                *g_error = g_error_new (MOONSHOT_ERROR,
+                                        MOONSHOT_ERROR_SERVICE_NOT_FOUND,
+                                        "The Moonshot service was not found. "
+                                        "Please make sure that moonshot-ui is "
+                                        "correctly installed.");
+            } else {
+                *g_error = g_error_new (MOONSHOT_ERROR,
+                                        MOONSHOT_ERROR_DBUS_ERROR,
+                                        "DBus error: %s",
+                                        dbus_error.message);
+            }
+            dbus_error_free (&dbus_error);
+            return NULL;
+        }
+    }
+
+    /* Now the service should be running */
+
+    g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, g_error);
+
+    if (*g_error != NULL)
+        return NULL;
+
+    g_proxy = dbus_g_proxy_new_for_name_owner (g_connection,
+                                               MOONSHOT_DBUS_NAME,
+                                               MOONSHOT_DBUS_PATH,
+                                               MOONSHOT_DBUS_NAME,
+                                               g_error);
+
+    return g_proxy; 
+}
+
+static void dbus_call_complete_cb (DBusGProxy     *proxy,
+                                   DBusGProxyCall *call_id,
+                                   void           *user_data)
+{
+    GError *error = NULL;
+    GSimpleAsyncResult   *token;
+    MoonshotIdentityData *identity_data;
+    gboolean              success;
+
+    token = G_SIMPLE_ASYNC_RESULT (user_data);
+    identity_data = moonshot_identity_data_new ();
+
+    dbus_g_proxy_end_call (moonshot_dbus_proxy,
+                           call_id,
+                           &error,
+                           G_TYPE_STRING, &identity_data->nai,
+                           G_TYPE_STRING, &identity_data->password,
+                           G_TYPE_STRING, &identity_data->server_certificate_hash,
+                           G_TYPE_STRING, &identity_data->ca_certificate,
+                           G_TYPE_STRING, &identity_data->subject_name_constraint,
+                           G_TYPE_STRING, &identity_data->subject_alt_name_constraint,
+                           G_TYPE_BOOLEAN, &success,
+                           G_TYPE_INVALID);
+
+    if (error != NULL) {
+        g_simple_async_result_set_from_error (token, error);
+    }
+    else
+    if (success == FALSE) {
+        error = g_error_new (MOONSHOT_ERROR,
+                             MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
+                             "No matching identity was available");
+        g_simple_async_result_set_from_error (token, error);
+        g_error_free (error);
+    }
+    else {        
+        g_simple_async_result_set_op_res_gpointer (token,
+                                                   identity_data,
+                                                   moonshot_identity_data_free);
+    }
+
+    g_simple_async_result_complete (token);
+    g_object_unref (token);
+}
+
+/**
+ * moonshot_get_identity:
+ * @cancellable: A #GCancellable, or %NULL.
+ * @callback: A #GAsyncReadyCallback, which will be called when the
+ *            operation completes, fails or is cancelled.
+ * @user_data: Data to pass to @callback
+ * @nai: Name and issuer constraint for the required identity, or %NULL.
+ * @password: Password for the identity, or %NULL.
+ * @service: Service constraint for the required identity, or %NULL.
+ *
+ * This function initiates a call to the Moonshot server to request an ID card.
+ * The server will be activated if it is not already running. The user interface
+ * will be displayed if there is more than one matching identity and the user 
+ * will be asked to select one.
+ *
+ * When an identity has been selected, or the operation fails or is cancelled,
+ * @callback will be run.
+ *
+ * Note that the actual IPC call may not be made until control returns to the
+ * GLib main loop.
+ */
+void moonshot_get_identity (GCancellable        *cancellable,
+                            GAsyncReadyCallback  callback,
+                            gpointer             user_data,
+                            const char          *nai,
+                            const char          *password,
+                            const char          *service)
+{
+    DBusGProxyCall     *call_id;
+    GSimpleAsyncResult *result; 
+    GError *error = NULL;
+
+    if (moonshot_dbus_proxy == NULL)
+        moonshot_dbus_proxy = dbus_connect (&error);
+
+    if (moonshot_dbus_proxy == NULL) {
+        result = g_simple_async_result_new (NULL,
+                                            callback,
+                                            user_data,
+                                            moonshot_get_identity);
+        g_simple_async_result_set_from_error (result, error);
+        g_simple_async_result_complete_in_idle (result);
+        g_error_free (error);
+        return;
+    }
+
+    g_return_if_fail (DBUS_IS_G_PROXY (moonshot_dbus_proxy));
+
+    result = g_simple_async_result_new (NULL,
+                                        callback,
+                                        user_data,
+                                        moonshot_get_identity);
+
+    call_id = dbus_g_proxy_begin_call (moonshot_dbus_proxy,
+                                       "GetIdentity",
+                                       dbus_call_complete_cb,
+                                       result, NULL,
+                                       G_TYPE_STRING, nai,
+                                       G_TYPE_STRING, password,
+                                       G_TYPE_STRING, service);
+}
+
+/**
+ * moonshot_get_identity_finish:
+ * @result: The #GAsyncResult which was passed to your callback.
+ * @nai: A pointer to a string which receives the name and issuer of the
+ *       selected identity.
+ * @password: A pointer to a string which receives the password.
+ * @server_certificate_hash: Receives a hash of the identity server's
+ *                           certificate, or %NULL.
+ * @ca_certificate: The CA certificate, if @server_certificate_hash was %NULL.
+ * @subject_name_constraint: Set if @ca_certificate is set, otherwise %NULL.
+ * @subject_alt_name_constraint: Set if @ca_certificate is set, otherwise %NULL.
+ * @error: Return location for an error, or %NULL.
+ *
+ * Gets the details of the identity card that was selected, if any.
+ *
+ * There are two types of trust anchor that may be returned. If
+ * @server_certificate_hash is non-empty, the remaining parameters will be
+ * empty. Otherwise, the @ca_certificate parameter and the subject name
+ * constraints will be returned.
+ *
+ * Return value: %TRUE if an identity was successfully selected, %FALSE on
+ *               failure.
+ */
+gboolean moonshot_get_identity_finish (GAsyncResult  *result,
+                                       char         **nai,
+                                       char         **password,
+                                       char         **server_certificate_hash,
+                                       char         **ca_certificate,
+                                       char         **subject_name_constraint,
+                                       char         **subject_alt_name_constraint,
+                                       GError       **error)
+{
+    MoonshotIdentityData *identity;
+
+    g_return_val_if_fail (g_simple_async_result_is_valid (result,
+                                                          NULL,
+                                                          moonshot_get_identity),
+                          FALSE);
+
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+        return FALSE;
+
+    identity = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+    *nai = identity->nai;
+    *password = identity->password;
+    *server_certificate_hash = identity->server_certificate_hash;
+    *ca_certificate = identity->ca_certificate;
+    *subject_name_constraint = identity->subject_name_constraint;
+    *subject_alt_name_constraint = identity->subject_alt_name_constraint;
+
+    return TRUE;
+}
+
+
+    /**
+     * Returns the default identity - most recently used.
+     *
+     * @param nai_out NAI stored in the ID card
+     * @param password_out Password stored in the ID card
+     *
+     * @return true on success, false if no identities are stored
+     */
diff --git a/libmoonshot/libmoonshot-msrpc.c b/libmoonshot/libmoonshot-msrpc.c
new file mode 100644 (file)
index 0000000..b2f7f85
--- /dev/null
@@ -0,0 +1,243 @@
+/* libmoonshot - Moonshot client library
+ * Copyright (c) 2011, 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.
+ *
+ * Author: Sam Thursfield <samthursfield@codethink.co.uk>
+ */
+
+#include <windows.h>
+//#include <rpc.h>
+#include <msrpc-mingw.h>
+
+#include "libmoonshot.h"
+#include "libmoonshot-common.h"
+#include "moonshot-msrpc.h"
+
+#define MOONSHOT_ENDPOINT_NAME "/org/janet/Moonshot"
+#define MOONSHOT_INSTALL_PATH_KEY "Software\\Moonshot"
+
+
+static void launch_server (MoonshotError **error) {
+    HKEY key = NULL;
+    STARTUPINFO startup_info = { 0 };
+    PROCESS_INFORMATION process_info = { 0 };
+    LONG status;
+    DWORD value_type;
+    DWORD length;
+    char exe_path[1024];
+
+    status = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+                           MOONSHOT_INSTALL_PATH_KEY,
+                           0,
+                           KEY_READ,
+                           &key);
+
+    if (status != 0) {
+        *error = _moonshot_error_new (MOONSHOT_ERROR_OS_ERROR,
+                                      "Unable to read registry key HKLM\\%s",
+                                      MOONSHOT_INSTALL_PATH_KEY);
+        return;
+    }
+
+    length = 1023;
+    status = RegQueryValueEx (key, NULL, NULL, &value_type, exe_path, &length);
+
+    if (value_type != REG_SZ) {
+        *error = _moonshot_error_new (MOONSHOT_ERROR_OS_ERROR,
+                                      "Value of registry key HKLM\\%s is invalid. "
+                                      "Please set it to point to the location of "
+                                      "moonshot.exe",
+                                      MOONSHOT_INSTALL_PATH_KEY);
+        return;
+    }
+
+
+    if (status != 0) {
+        *error = _moonshot_error_new (MOONSHOT_ERROR_OS_ERROR,
+                                      "Unable to read value of registry key HKLM\\%s",
+                                      MOONSHOT_INSTALL_PATH_KEY);
+        return;
+    }
+
+    startup_info.cb = sizeof (startup_info);
+
+    status = CreateProcess (exe_path, NULL,
+                            NULL, NULL,
+                            FALSE, DETACHED_PROCESS,
+                            NULL, NULL,
+                            &startup_info, &process_info);
+
+    if (status != 0) {
+        *error = _moonshot_error_new (MOONSHOT_ERROR_UNABLE_TO_START_SERVICE,
+                                      "Unable to spawn the moonshot server at '%s'",
+                                      exe_path);
+        return;
+    }
+}
+
+/*static void dbus_call_complete_cb (DBusGProxy     *proxy,
+                                   DBusGProxyCall *call_id,
+                                   void           *user_data)
+{
+    GError *error = NULL;
+    GSimpleAsyncResult   *token;
+    MoonshotIdentityData *identity_data;
+    gboolean              success;
+
+    token = G_SIMPLE_ASYNC_RESULT (user_data);
+    identity_data = moonshot_identity_data_new ();
+
+    dbus_g_proxy_end_call (moonshot_dbus_proxy,
+                           call_id,
+                           &error,
+                           G_TYPE_STRING, &identity_data->nai,
+                           G_TYPE_STRING, &identity_data->password,
+                           G_TYPE_STRING, &identity_data->server_certificate_hash,
+                           G_TYPE_STRING, &identity_data->ca_certificate,
+                           G_TYPE_STRING, &identity_data->subject_name_constraint,
+                           G_TYPE_STRING, &identity_data->subject_alt_name_constraint,
+                           G_TYPE_BOOLEAN, &success,
+                           G_TYPE_INVALID);
+
+    if (error != NULL) {
+        g_simple_async_result_set_from_error (token, error);
+    }
+    else
+    if (success == FALSE) {
+        error = g_error_new (MOONSHOT_ERROR,
+                             MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
+                             "No matching identity was available");
+        g_simple_async_result_set_from_error (token, error);
+        g_error_free (error);
+    }
+    else {        
+        g_simple_async_result_set_op_res_gpointer (token,
+                                                   identity_data,
+                                                   moonshot_identity_data_free);
+    }
+
+    g_simple_async_result_complete (token);
+    g_object_unref (token);
+}
+*/
+
+int moonshot_get_identity (const char     *nai,
+                           const char     *password,
+                           const char     *service,
+                           char          **nai_out,
+                           char          **password_out,
+                           char          **server_certificate_hash_out,
+                           char          **ca_certificate_out,
+                           char          **subject_name_constraint_out,
+                           char          **subject_alt_name_constraint_out,
+                           MoonshotError **error)
+{
+    int status;
+
+    status = rpc_client_bind (&moonshot_binding_handle,
+                              MOONSHOT_ENDPOINT_NAME,
+                              RPC_PER_USER);
+
+    printf ("RPC status: %i\n", status);
+
+    /*DBusGProxyCall     *call_id;
+    GSimpleAsyncResult *result; 
+    GError *error = NULL;
+
+    if (moonshot_dbus_proxy == NULL)
+        moonshot_dbus_proxy = dbus_connect (&error);
+
+    if (moonshot_dbus_proxy == NULL) {
+        result = g_simple_async_result_new (NULL,
+                                            callback,
+                                            user_data,
+                                            moonshot_get_identity);
+        g_simple_async_result_set_from_error (result, error);
+        g_simple_async_result_complete_in_idle (result);
+        g_error_free (error);
+        return;
+    }
+
+    g_return_if_fail (DBUS_IS_G_PROXY (moonshot_dbus_proxy));
+
+    result = g_simple_async_result_new (NULL,
+                                        callback,
+                                        user_data,
+                                        moonshot_get_identity);
+
+    call_id = dbus_g_proxy_begin_call (moonshot_dbus_proxy,
+                                       "GetIdentity",
+                                       dbus_call_complete_cb,
+                                       result, NULL,
+                                       G_TYPE_STRING, nai,
+                                       G_TYPE_STRING, password,
+                                       G_TYPE_STRING, service);*/
+}
+
+/*gboolean moonshot_get_identity_finish (GAsyncResult  *result,
+                                       char         **nai,
+                                       char         **password,
+                                       char         **server_certificate_hash,
+                                       char         **ca_certificate,
+                                       char         **subject_name_constraint,
+                                       char         **subject_alt_name_constraint,
+                                       GError       **error)
+{
+    MoonshotIdentityData *identity;
+
+    g_return_val_if_fail (g_simple_async_result_is_valid (result,
+                                                          NULL,
+                                                          moonshot_get_identity),
+                          FALSE);
+
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+        return FALSE;
+
+    identity = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+    *nai = identity->nai;
+    *password = identity->password;
+    *server_certificate_hash = identity->server_certificate_hash;
+    *ca_certificate = identity->ca_certificate;
+    *subject_name_constraint = identity->subject_name_constraint;
+    *subject_alt_name_constraint = identity->subject_alt_name_constraint;
+
+    return TRUE;
+}*/
+
+
+    /**
+     * Returns the default identity - most recently used.
+     *
+     * @param nai_out NAI stored in the ID card
+     * @param password_out Password stored in the ID card
+     *
+     * @return true on success, false if no identities are stored
+     */
diff --git a/libmoonshot/libmoonshot.h b/libmoonshot/libmoonshot.h
new file mode 100644 (file)
index 0000000..39118db
--- /dev/null
@@ -0,0 +1,97 @@
+/* libmoonshot - Moonshot client library
+ * Copyright (c) 2011, 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.
+ *
+ * Author: Sam Thursfield <samthursfield@codethink.co.uk>
+ */
+
+#ifndef __LIBMOONSHOT_H
+#define __LIBMOONSHOT_H
+
+typedef enum {
+    MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
+    MOONSHOT_ERROR_DBUS_ERROR,
+    MOONSHOT_ERROR_UNABLE_TO_START_SERVICE,
+    MOONSHOT_ERROR_OS_ERROR
+} MoonshotErrorCode;
+
+typedef struct {
+    MoonshotErrorCode  code;
+    char              *message;
+} MoonshotError;
+
+void moonshot_error_free (MoonshotError *error);
+
+/**
+ * moonshot_get_identity:
+ * @nai: Name and issuer constraint for the required identity, or %NULL.
+ * @password: Password for the identity, or %NULL.
+ * @service: Service constraint for the required identity, or %NULL.
+ * @nai_out: A pointer to a string which receives the name and issuer of the
+ *       selected identity.
+ * @password_out: A pointer to a string which receives the password.
+ * @server_certificate_hash_out: Receives a hash of the identity server's
+ *                           certificate, or %NULL.
+ * @ca_certificate_out: The CA certificate, if @server_certificate_hash was
+ *                      %NULL.
+ * @subject_name_constraint_out: Set if @ca_certificate is set, otherwise %NULL.
+ * @subject_alt_name_constraint_out: Set if @ca_certificate is set, otherwise
+ *                                   %NULL.
+ * @error: Return location for a #MoonshotError, or %NULL.
+ *
+ * This function calls the Moonshot server to request an ID card. The server
+ * will be activated if it is not already running. The user interface will be
+ * displayed if there is more than one matching identity and the user will be
+ * asked to select one.
+ *
+ * There are two types of trust anchor that may be returned. If
+ * @server_certificate_hash is non-empty, the remaining parameters will be
+ * empty. Otherwise, the @ca_certificate parameter and the subject name
+ * constraints will be returned.
+ *
+ * Error reporting is handled by a simple mechanism similar to #GError. If
+ * an error occurs, a #MoonshotError object will be stored at *@error, with
+ * a code and message string. This must be freed using moonshot_error_free().
+ *
+ * Return value: %TRUE if an identity was successfully selected, %FALSE on
+ *               failure.
+ */
+int moonshot_get_identity (const char     *nai,
+                           const char     *password,
+                           const char     *service,
+                           char          **nai_out,
+                           char          **password_out,
+                           char          **server_certificate_hash_out,
+                           char          **ca_certificate_out,
+                           char          **subject_name_constraint_out,
+                           char          **subject_alt_name_constraint_out,
+                           MoonshotError **error);
+
+#endif
diff --git a/libmoonshot/moonshot-msrpc.acf b/libmoonshot/moonshot-msrpc.acf
new file mode 100644 (file)
index 0000000..c5a335e
--- /dev/null
@@ -0,0 +1,10 @@
+[
+  implicit_handle (handle_t moonshot_binding_handle)
+
+]
+interface moonshot
+{
+    [async] moonshot_get_identity_rpc();
+    [async] moonshot_get_default_identity_rpc();
+}
+
diff --git a/libmoonshot/moonshot-msrpc.idl b/libmoonshot/moonshot-msrpc.idl
new file mode 100644 (file)
index 0000000..8055713
--- /dev/null
@@ -0,0 +1,20 @@
+[
+    uuid(15aea4d8-222c-4b42-9225-63a7277811ae),
+    version(1.0)
+]
+interface moonshot
+{
+    int moonshot_get_identity_rpc ([in, string] const char *nai,
+                                   [in, string] const char *password,
+                                   [in, string] const char *certificate,
+                                   [out, string] char **nai_out,
+                                   [out, string] char **password_out,
+                                   [out, string] char **server_certificate_hash,
+                                   [out, string] char **ca_certificate,
+                                   [out, string] char **subject_name_constraint,
+                                   [out, string] char **subject_alt_name_constraint);
+
+    int moonshot_get_default_identity_rpc ([out, string] char **nai_out,
+                                           [out, string] char **password_out);
+}
+
diff --git a/src/moonshot-msrpc.acf b/src/moonshot-msrpc.acf
deleted file mode 100644 (file)
index cf5ed31..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[
-  implicit_handle (handle_t moonshot_binding_handle)
-
-]
-interface moonshot
-{
-    [async] moonshot_get_identity();
-    [async] moonshot_get_default_identity();
-}
-
diff --git a/src/moonshot-msrpc.idl b/src/moonshot-msrpc.idl
deleted file mode 100644 (file)
index 4189d79..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[
-    uuid(15aea4d8-222c-4b42-9225-63a7277811ae),
-    version(1.0)
-]
-interface moonshot
-{
-    int moonshot_get_identity ([in, string] const char *nai,
-                               [in, string] const char *password,
-                               [in, string] const char *certificate,
-                               [out, string] char **nai_out,
-                               [out, string] char **password_out,
-                               [out, string] char **server_certificate_hash,
-                               [out, string] char **ca_certificate,
-                               [out, string] char **subject_name_constraint,
-                               [out, string] char **subject_alt_name_constraint);
-
-    int moonshot_get_default_identity ([out, string] char **nai_out,
-                                       [out, string] char **password_out);
-}
-
index fd82a79..243f70a 100644 (file)
@@ -10,7 +10,7 @@ namespace MoonshotRpcInterface {
     [CCode (cname = "moonshot_binding_handle")]
     public BindingHandle binding_handle;
 
-    [CCode (cname = "moonshot_get_identity")]
+    [CCode (cname = "moonshot_get_identity_rpc")]
     public extern void get_identity (Rpc.AsyncCall call,
                                      string nai,
                                      string password,
@@ -22,7 +22,7 @@ namespace MoonshotRpcInterface {
                                      ref string subject_name_constraint,
                                      ref string subject_alt_name_constraint);
 
-    [CCode (cname = "moonshot_get_default_identity")]
+    [CCode (cname = "moonshot_get_default_identity_rpc")]
     public extern void get_default_identity (Rpc.AsyncCall call,
                                              ref string nai_out,
                                              ref string password_out);
index 7b35850..f83d5ea 100644 (file)
@@ -111,7 +111,7 @@ public class MoonshotServer : Object {
         return instance;
     }
 
-    [CCode (cname = "moonshot_get_identity")]
+    [CCode (cname = "moonshot_get_identity_rpc")]
     public static void get_identity (Rpc.AsyncCall call,
                                      string nai,
                                      string password,
@@ -172,7 +172,7 @@ public class MoonshotServer : Object {
         request.mutex.unlock ();
     }
 
-    [CCode (cname = "moonshot_get_default_identity")]
+    [CCode (cname = "moonshot_get_default_identity_rpc")]
     public static void get_default_identity (Rpc.AsyncCall call,
                                              ref string nai_out,
                                              ref string password_out)
diff --git a/tests/basic.c b/tests/basic.c
new file mode 100644 (file)
index 0000000..8bd09a0
--- /dev/null
@@ -0,0 +1,48 @@
+#include <glib.h>
+
+#include "libmoonshot.h"
+
+void test_connect ()
+{
+    char *nai,
+         *password,
+         *server_certificate_hash,
+         *ca_certificate,
+         *subject_name_constraint,
+         *subject_alt_name_constraint;
+    int success;
+    MoonshotError *error = NULL;
+
+    success = moonshot_get_identity ("test",
+                                     "test",
+                                     "test",
+                                     &nai,
+                                     &password,
+                                     &server_certificate_hash,
+                                     &ca_certificate,
+                                     &subject_name_constraint,
+                                     &subject_alt_name_constraint,
+                                     &error);
+
+    if (success == 0) {
+        g_print ("FAIL %s\n", error->message);
+    } else {
+        g_print ("PASS\n");
+    }
+}
+
+/* More stuff to test:
+ *   - server not available (dbus fail)
+ *   - no identities available (moonshot fail)
+ *   - valgrind
+ */
+
+int main (int argc, char *argv[])
+{
+    g_type_init ();
+    g_test_init (&argc, &argv, NULL);
+
+    g_test_add_func ("/basic/connect", test_connect);
+
+    g_test_run ();
+}