1 /* libmoonshot - Moonshot client library
2 * Copyright (c) 2011, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * Author: Sam Thursfield <samthursfield@codethink.co.uk>
35 #include <dbus/dbus-glib.h>
36 #include <dbus/dbus.h>
38 #include "libmoonshot.h"
39 #include "libmoonshot-common.h"
42 #define INFINITE_TIMEOUT 10*24*60*60*1000
44 #define MOONSHOT_DBUS_NAME "org.janet.Moonshot"
45 #define MOONSHOT_DBUS_PATH "/org/janet/moonshot"
47 /* This library is overly complicated currently due to the requirement
48 * that it work on Debian Squeeze - this has GLib 2.24 which requires us
49 * to use dbus-glib instead of GDBus. If/when this requirement is
50 * dropped the DBus version of the library can be greatly simplified.
53 /* Note that ideally this library would not depend on GLib. This would be
54 * possible using libdbus directly and running our own message loop while
58 void moonshot_free (void *data)
63 static DBusGProxy *dbus_connect (MoonshotError **error)
65 DBusConnection *connection;
67 DBusGConnection *g_connection;
70 dbus_bool_t name_has_owner;
72 g_return_val_if_fail (*error == NULL, NULL);
74 dbus_error_init (&dbus_error);
76 /* Check for moonshot server and start the service if possible. We use
77 * libdbus here because dbus-glib doesn't handle autostarting the service.
78 * If/when we move to GDBus this code can become a one-liner.
81 connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
83 if (dbus_error_is_set (&dbus_error)) {
84 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
87 dbus_error_free (&dbus_error);
91 name_has_owner = dbus_bus_name_has_owner (connection,
95 if (dbus_error_is_set (&dbus_error)) {
96 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
99 dbus_error_free (&dbus_error);
103 if (! name_has_owner) {
104 dbus_bus_start_service_by_name (connection,
110 if (dbus_error_is_set (&dbus_error)) {
111 if (strcmp (dbus_error.name + 27, "ServiceUnknown") == 0) {
112 /* Missing .service file; the moonshot-ui install is broken */
113 *error = moonshot_error_new (MOONSHOT_ERROR_UNABLE_TO_START_SERVICE,
114 "The Moonshot service was not found. "
115 "Please make sure that moonshot-ui is "
116 "correctly installed.");
118 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
122 dbus_error_free (&dbus_error);
127 /* Now the service should be running */
130 g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &g_error);
132 if (g_error != NULL) {
133 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
136 g_error_free (g_error);
140 g_proxy = dbus_g_proxy_new_for_name_owner (g_connection,
146 if (g_error != NULL) {
147 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
150 g_error_free (g_error);
157 static DBusGProxy *get_dbus_proxy (MoonshotError **error)
159 static DBusGProxy *dbus_proxy = NULL;
160 static GStaticMutex init_lock = G_STATIC_MUTEX_INIT;
162 g_static_mutex_lock (&init_lock);
164 if (dbus_proxy == NULL) {
165 /* Make sure GObject is initialised, in case we are the only user
166 * of GObject in the process
169 dbus_proxy = dbus_connect (error);
172 if (dbus_proxy != NULL)
173 g_object_ref (dbus_proxy);
175 g_static_mutex_unlock (&init_lock);
180 int moonshot_get_identity (const char *nai,
181 const char *password,
185 char **server_certificate_hash_out,
186 char **ca_certificate_out,
187 char **subject_name_constraint_out,
188 char **subject_alt_name_constraint_out,
189 MoonshotError **error)
191 GError *g_error = NULL;
192 DBusGProxy *dbus_proxy;
195 dbus_proxy = get_dbus_proxy (error);
200 g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
202 dbus_g_proxy_call_with_timeout (dbus_proxy,
207 G_TYPE_STRING, password,
208 G_TYPE_STRING, service,
210 G_TYPE_STRING, nai_out,
211 G_TYPE_STRING, password_out,
212 G_TYPE_STRING, server_certificate_hash_out,
213 G_TYPE_STRING, ca_certificate_out,
214 G_TYPE_STRING, subject_name_constraint_out,
215 G_TYPE_STRING, subject_alt_name_constraint_out,
216 G_TYPE_BOOLEAN, &success,
219 g_object_unref (dbus_proxy);
221 if (g_error != NULL) {
222 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
227 if (success == FALSE) {
228 *error = moonshot_error_new (MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
229 "No identity was returned by the Moonshot "
237 int moonshot_get_default_identity (char **nai_out,
239 char **server_certificate_hash_out,
240 char **ca_certificate_out,
241 char **subject_name_constraint_out,
242 char **subject_alt_name_constraint_out,
243 MoonshotError **error)
245 GError *g_error = NULL;
246 DBusGProxy *dbus_proxy;
249 dbus_proxy = get_dbus_proxy (error);
254 g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
256 dbus_g_proxy_call_with_timeout (dbus_proxy,
257 "GetDefaultIdentity",
261 G_TYPE_STRING, nai_out,
262 G_TYPE_STRING, password_out,
263 G_TYPE_STRING, server_certificate_hash_out,
264 G_TYPE_STRING, ca_certificate_out,
265 G_TYPE_STRING, subject_name_constraint_out,
266 G_TYPE_STRING, subject_alt_name_constraint_out,
267 G_TYPE_BOOLEAN, &success,
270 g_object_unref (dbus_proxy);
272 if (g_error != NULL) {
273 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
278 if (success == FALSE) {
279 *error = moonshot_error_new (MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
280 "No identity was returned by the Moonshot "
288 int moonshot_install_id_card (const char *display_name,
289 const char *user_name,
290 const char *password,
292 char *rules_patterns[],
293 int rules_patterns_length,
294 char *rules_always_confirm[],
295 int rules_always_confirm_length,
300 const char *subject_alt,
301 const char *server_cert,
302 MoonshotError **error)
304 GError *g_error = NULL;
305 DBusGProxy *dbus_proxy;
308 const char **rules_patterns_strv,
309 **rules_always_confirm_strv,
312 dbus_proxy = get_dbus_proxy (error);
317 g_return_val_if_fail (DBUS_IS_G_PROXY (dbus_proxy), FALSE);
318 g_return_val_if_fail (rules_patterns_length == rules_always_confirm_length, FALSE);
320 /* Marshall array and struct parameters for DBus */
321 rules_patterns_strv = g_malloc ((rules_patterns_length + 1) * sizeof (const char *));
322 rules_always_confirm_strv = g_malloc ((rules_patterns_length + 1) * sizeof (const char *));
323 services_strv = g_malloc ((services_length + 1) * sizeof (const char *));
325 for (i = 0; i < rules_patterns_length; i ++) {
326 rules_patterns_strv[i] = rules_patterns[i];
327 rules_always_confirm_strv[i] = rules_always_confirm[i];
330 for (i = 0; i < services_length; i ++)
331 services_strv[i] = services[i];
333 rules_patterns_strv[rules_patterns_length] = NULL;
334 rules_always_confirm_strv[rules_patterns_length] = NULL;
335 services_strv[services_length] = NULL;
337 dbus_g_proxy_call (dbus_proxy,
340 G_TYPE_STRING, display_name,
341 G_TYPE_STRING, user_name,
342 G_TYPE_STRING, password,
343 G_TYPE_STRING, realm,
344 G_TYPE_STRV, rules_patterns_strv,
345 G_TYPE_STRV, rules_always_confirm_strv,
346 G_TYPE_STRV, services_strv,
347 G_TYPE_STRING, ca_cert,
348 G_TYPE_STRING, subject,
349 G_TYPE_STRING, subject_alt,
350 G_TYPE_STRING, server_cert,
352 G_TYPE_BOOLEAN, &success,
355 g_object_unref (dbus_proxy);
357 if (g_error != NULL) {
358 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,