04d6da66fab15e3d82391b12f17634f8f4a6e51e
[moonshot-ui.git] / libmoonshot / libmoonshot-dbus.c
1 /* libmoonshot - Moonshot client library
2  * Copyright (c) 2011, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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
30  * SUCH DAMAGE.
31  *
32  * Author: Sam Thursfield <samthursfield@codethink.co.uk>
33  */
34
35 #include <dbus/dbus-glib.h>
36 #include <dbus/dbus.h>
37
38 #include "libmoonshot.h"
39 #include "libmoonshot-common.h"
40
41 #define MOONSHOT_DBUS_NAME "org.janet.Moonshot"
42 #define MOONSHOT_DBUS_PATH "/org/janet/moonshot"
43
44 /* This library is overly complicated currently due to the requirement
45  * that it work on Debian Squeeze - this has GLib 2.24 which requires us
46  * to use dbus-glib instead of GDBus. If/when this requirement is
47  * dropped the DBus version of the library can be greatly simplified.
48  */
49
50 /* Note that ideally this library would not depend on GLib. This would be
51  * possible using libdbus directly and running our own message loop while
52  * waiting for calls.
53  */
54
55 static DBusGProxy *moonshot_dbus_proxy = NULL;
56
57 static DBusGProxy *dbus_connect (MoonshotError **error)
58 {
59     DBusConnection  *connection;
60     DBusError        dbus_error;
61     DBusGConnection *g_connection;
62     DBusGProxy      *g_proxy;
63     GError          *g_error;
64     dbus_bool_t      name_has_owner;
65
66     g_return_val_if_fail (*error == NULL, NULL);
67
68     dbus_error_init (&dbus_error);
69
70     /* Check for moonshot server and start the service if possible. We use
71      * libdbus here because dbus-glib doesn't handle autostarting the service.
72      * If/when we move to GDBus this code can become a one-liner.
73      */
74
75     connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
76
77     if (dbus_error_is_set (&dbus_error)) {
78         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
79                                      "DBus error: %s",
80                                      dbus_error.message);
81         dbus_error_free (&dbus_error);
82         return NULL;
83     }
84
85     name_has_owner  = dbus_bus_name_has_owner (connection,
86                                                MOONSHOT_DBUS_NAME,
87                                                &dbus_error);
88
89     if (dbus_error_is_set (&dbus_error)) {
90         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
91                                      "DBus error: %s",
92                                      dbus_error.message);
93         dbus_error_free (&dbus_error);
94         return NULL;
95     }
96
97     if (! name_has_owner) {
98         dbus_bus_start_service_by_name (connection,
99                                         MOONSHOT_DBUS_NAME,
100                                         0,
101                                         NULL,
102                                         &dbus_error);
103
104         if (dbus_error_is_set (&dbus_error)) {
105             if (strcmp (dbus_error.name + 27, "ServiceUnknown") == 0) {
106                 /* Missing .service file; the moonshot-ui install is broken */
107                 *error = moonshot_error_new (MOONSHOT_ERROR_UNABLE_TO_START_SERVICE,
108                                              "The Moonshot service was not found. "
109                                              "Please make sure that moonshot-ui is "
110                                              "correctly installed.");
111             } else {
112                 *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
113                                              "DBus error: %s",
114                                              dbus_error.message);
115             }
116             dbus_error_free (&dbus_error);
117             return NULL;
118         }
119     }
120
121     /* Now the service should be running */
122     g_error = NULL;
123
124     g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &g_error);
125
126     if (g_error != NULL) {
127         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
128                                      "DBus error: %s",
129                                      g_error->message);
130         g_error_free (g_error);
131         return NULL;
132     }
133
134     g_proxy = dbus_g_proxy_new_for_name_owner (g_connection,
135                                                MOONSHOT_DBUS_NAME,
136                                                MOONSHOT_DBUS_PATH,
137                                                MOONSHOT_DBUS_NAME,
138                                                &g_error);
139
140     if (g_error != NULL) {
141         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
142                                      "DBus error: %s",
143                                      g_error->message);
144         g_error_free (g_error);
145         return NULL;
146     }
147
148     return g_proxy; 
149 }
150
151 int moonshot_get_identity (const char     *nai,
152                            const char     *password,
153                            const char     *service,
154                            char          **nai_out,
155                            char          **password_out,
156                            char          **server_certificate_hash_out,
157                            char          **ca_certificate_out,
158                            char          **subject_name_constraint_out,
159                            char          **subject_alt_name_constraint_out,
160                            MoonshotError **error)
161 {
162     GError   *g_error = NULL;
163     int success;
164
165     if (moonshot_dbus_proxy == NULL)
166         moonshot_dbus_proxy = dbus_connect (error);
167
168     if (*error != NULL)
169         return;
170
171     g_return_if_fail (DBUS_IS_G_PROXY (moonshot_dbus_proxy));
172
173     dbus_g_proxy_call (moonshot_dbus_proxy,
174                        "GetIdentity",
175                        &g_error,
176                        G_TYPE_STRING, nai,
177                        G_TYPE_STRING, password,
178                        G_TYPE_STRING, service,
179                        G_TYPE_INVALID,
180                        G_TYPE_STRING, nai_out,
181                        G_TYPE_STRING, password_out,
182                        G_TYPE_STRING, server_certificate_hash_out,
183                        G_TYPE_STRING, ca_certificate_out,
184                        G_TYPE_STRING, subject_name_constraint_out,
185                        G_TYPE_STRING, subject_alt_name_constraint_out,
186                        G_TYPE_BOOLEAN, &success,
187                        G_TYPE_INVALID);
188
189     if (g_error != NULL) {
190         *error = moonshot_error_new (MOONSHOT_ERROR_IPC_ERROR,
191                                      g_error->message);
192         return FALSE;
193     }
194
195     if (success == FALSE) {
196         *error = moonshot_error_new (MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
197                                      "No identity was returned by the Moonshot "
198                                      "user interface.");
199         return FALSE;
200     }
201
202     return TRUE;
203 }
204
205
206
207     /**
208      * Returns the default identity - most recently used.
209      *
210      * @param nai_out NAI stored in the ID card
211      * @param password_out Password stored in the ID card
212      *
213      * @return true on success, false if no identities are stored
214      */