GDBus: Add new symbols to gio.symbols
[platform/upstream/glib.git] / gio / gdbusauthmechanismexternal.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2009 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <string.h>
26
27 #include "gdbusauthmechanismexternal.h"
28 #include "gcredentials.h"
29 #include "gdbuserror.h"
30 #include "gioenumtypes.h"
31
32 #ifdef G_OS_UNIX
33 #include <sys/types.h>
34 #include <unistd.h>
35 #endif
36
37 #include "glibintl.h"
38 #include "gioalias.h"
39
40 struct _GDBusAuthMechanismExternalPrivate
41 {
42   gboolean is_client;
43   gboolean is_server;
44   GDBusAuthMechanismState state;
45 };
46
47 static gint                     mechanism_get_priority              (void);
48 static const gchar             *mechanism_get_name                  (void);
49
50 static gboolean                 mechanism_is_supported              (GDBusAuthMechanism   *mechanism);
51 static gchar                   *mechanism_encode_data               (GDBusAuthMechanism   *mechanism,
52                                                                      const gchar          *data,
53                                                                      gsize                 data_len,
54                                                                      gsize                *out_data_len);
55 static gchar                   *mechanism_decode_data               (GDBusAuthMechanism   *mechanism,
56                                                                      const gchar          *data,
57                                                                      gsize                 data_len,
58                                                                      gsize                *out_data_len);
59 static GDBusAuthMechanismState  mechanism_server_get_state          (GDBusAuthMechanism   *mechanism);
60 static void                     mechanism_server_initiate           (GDBusAuthMechanism   *mechanism,
61                                                                      const gchar          *initial_response,
62                                                                      gsize                 initial_response_len);
63 static void                     mechanism_server_data_receive       (GDBusAuthMechanism   *mechanism,
64                                                                      const gchar          *data,
65                                                                      gsize                 data_len);
66 static gchar                   *mechanism_server_data_send          (GDBusAuthMechanism   *mechanism,
67                                                                      gsize                *out_data_len);
68 static gchar                   *mechanism_server_get_reject_reason  (GDBusAuthMechanism   *mechanism);
69 static void                     mechanism_server_shutdown           (GDBusAuthMechanism   *mechanism);
70 static GDBusAuthMechanismState  mechanism_client_get_state          (GDBusAuthMechanism   *mechanism);
71 static gchar                   *mechanism_client_initiate           (GDBusAuthMechanism   *mechanism,
72                                                                      gsize                *out_initial_response_len);
73 static void                     mechanism_client_data_receive       (GDBusAuthMechanism   *mechanism,
74                                                                      const gchar          *data,
75                                                                      gsize                 data_len);
76 static gchar                   *mechanism_client_data_send          (GDBusAuthMechanism   *mechanism,
77                                                                      gsize                *out_data_len);
78 static void                     mechanism_client_shutdown           (GDBusAuthMechanism   *mechanism);
79
80 /* ---------------------------------------------------------------------------------------------------- */
81
82 G_DEFINE_TYPE (GDBusAuthMechanismExternal, _g_dbus_auth_mechanism_external, G_TYPE_DBUS_AUTH_MECHANISM);
83
84 /* ---------------------------------------------------------------------------------------------------- */
85
86 static void
87 _g_dbus_auth_mechanism_external_finalize (GObject *object)
88 {
89   //GDBusAuthMechanismExternal *mechanism = G_DBUS_AUTH_MECHANISM_EXTERNAL (object);
90
91   if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize != NULL)
92     G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize (object);
93 }
94
95 static void
96 _g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *klass)
97 {
98   GObjectClass *gobject_class;
99   GDBusAuthMechanismClass *mechanism_class;
100
101   g_type_class_add_private (klass, sizeof (GDBusAuthMechanismExternalPrivate));
102
103   gobject_class = G_OBJECT_CLASS (klass);
104   gobject_class->finalize = _g_dbus_auth_mechanism_external_finalize;
105
106   mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
107   mechanism_class->get_name                  = mechanism_get_name;
108   mechanism_class->get_priority              = mechanism_get_priority;
109   mechanism_class->is_supported              = mechanism_is_supported;
110   mechanism_class->encode_data               = mechanism_encode_data;
111   mechanism_class->decode_data               = mechanism_decode_data;
112   mechanism_class->server_get_state          = mechanism_server_get_state;
113   mechanism_class->server_initiate           = mechanism_server_initiate;
114   mechanism_class->server_data_receive       = mechanism_server_data_receive;
115   mechanism_class->server_data_send          = mechanism_server_data_send;
116   mechanism_class->server_get_reject_reason  = mechanism_server_get_reject_reason;
117   mechanism_class->server_shutdown           = mechanism_server_shutdown;
118   mechanism_class->client_get_state          = mechanism_client_get_state;
119   mechanism_class->client_initiate           = mechanism_client_initiate;
120   mechanism_class->client_data_receive       = mechanism_client_data_receive;
121   mechanism_class->client_data_send          = mechanism_client_data_send;
122   mechanism_class->client_shutdown           = mechanism_client_shutdown;
123 }
124
125 static void
126 _g_dbus_auth_mechanism_external_init (GDBusAuthMechanismExternal *mechanism)
127 {
128   mechanism->priv = G_TYPE_INSTANCE_GET_PRIVATE (mechanism,
129                                                  G_TYPE_DBUS_AUTH_MECHANISM_EXTERNAL,
130                                                  GDBusAuthMechanismExternalPrivate);
131 }
132
133 /* ---------------------------------------------------------------------------------------------------- */
134
135 static gboolean
136 mechanism_is_supported (GDBusAuthMechanism *mechanism)
137 {
138   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), FALSE);
139   /* This mechanism is only available if credentials has been exchanged */
140   if (_g_dbus_auth_mechanism_get_credentials (mechanism) != NULL)
141     return TRUE;
142   else
143     return FALSE;
144 }
145
146 static gint
147 mechanism_get_priority (void)
148 {
149   /* We prefer EXTERNAL to most other mechanism (DBUS_COOKIE_SHA1 and ANONYMOUS) */
150   return 100;
151 }
152
153 static const gchar *
154 mechanism_get_name (void)
155 {
156   return "EXTERNAL";
157 }
158
159 static gchar *
160 mechanism_encode_data (GDBusAuthMechanism   *mechanism,
161                        const gchar          *data,
162                        gsize                 data_len,
163                        gsize                *out_data_len)
164 {
165   return NULL;
166 }
167
168
169 static gchar *
170 mechanism_decode_data (GDBusAuthMechanism   *mechanism,
171                        const gchar          *data,
172                        gsize                 data_len,
173                        gsize                *out_data_len)
174 {
175   return NULL;
176 }
177
178 /* ---------------------------------------------------------------------------------------------------- */
179
180 static GDBusAuthMechanismState
181 mechanism_server_get_state (GDBusAuthMechanism   *mechanism)
182 {
183   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
184
185   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
186   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
187
188   return m->priv->state;
189 }
190
191 static gboolean
192 data_matches_credentials (const gchar *data,
193                           GCredentials *credentials)
194 {
195   gboolean match;
196
197   match = FALSE;
198
199   if (credentials == NULL)
200     goto out;
201
202   if (data == NULL || strlen (data) == 0)
203     goto out;
204
205 #if defined(G_OS_UNIX)
206   {
207     gint64 alleged_uid;
208     gchar *endp;
209
210     /* on UNIX, this is the uid as a string in base 10 */
211     alleged_uid = g_ascii_strtoll (data, &endp, 10);
212     if (*endp == '\0')
213       {
214         if (g_credentials_has_unix_user (credentials) &&
215             g_credentials_get_unix_user (credentials) == alleged_uid)
216           {
217             match = TRUE;
218           }
219       }
220   }
221 #elif defined(G_OS_WIN32)
222   {
223     const gchar *alleged_sid;
224
225     /* on Win32, this is the User SID */
226     alleged_sid = data;
227     if (g_credentials_has_windows_user (credentials) &&
228         g_strcmp0 (g_credentials_get_windows_user (credentials), alleged_sid) == 0)
229       {
230         match = TRUE;
231       }
232   }
233 #else
234 #error Dont know how to read credentials on this OS. Please implement.
235 #endif
236
237  out:
238   return match;
239 }
240
241 static void
242 mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
243                            const gchar          *initial_response,
244                            gsize                 initial_response_len)
245 {
246   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
247
248   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
249   g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
250
251   m->priv->is_server = TRUE;
252
253   if (initial_response != NULL)
254     {
255       if (data_matches_credentials (initial_response, _g_dbus_auth_mechanism_get_credentials (mechanism)))
256         {
257           m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
258         }
259       else
260         {
261           m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
262         }
263     }
264   else
265     {
266       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
267     }
268 }
269
270 static void
271 mechanism_server_data_receive (GDBusAuthMechanism   *mechanism,
272                                const gchar          *data,
273                                gsize                 data_len)
274 {
275   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
276
277   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
278   g_return_if_fail (m->priv->is_server && !m->priv->is_client);
279   g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
280
281   if (data_matches_credentials (data, _g_dbus_auth_mechanism_get_credentials (mechanism)))
282     {
283       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
284     }
285   else
286     {
287       m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
288     }
289 }
290
291 static gchar *
292 mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
293                             gsize                *out_data_len)
294 {
295   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
296
297   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
298   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
299   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
300
301   /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
302   g_assert_not_reached ();
303
304   return NULL;
305 }
306
307 static gchar *
308 mechanism_server_get_reject_reason (GDBusAuthMechanism   *mechanism)
309 {
310   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
311
312   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
313   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
314   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
315
316   /* can never end up here because we are never in the REJECTED state */
317   g_assert_not_reached ();
318
319   return NULL;
320 }
321
322 static void
323 mechanism_server_shutdown (GDBusAuthMechanism   *mechanism)
324 {
325   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
326
327   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
328   g_return_if_fail (m->priv->is_server && !m->priv->is_client);
329
330   m->priv->is_server = FALSE;
331 }
332
333 /* ---------------------------------------------------------------------------------------------------- */
334
335 static GDBusAuthMechanismState
336 mechanism_client_get_state (GDBusAuthMechanism   *mechanism)
337 {
338   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
339
340   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
341   g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
342
343   return m->priv->state;
344 }
345
346 static gchar *
347 mechanism_client_initiate (GDBusAuthMechanism   *mechanism,
348                            gsize                *out_initial_response_len)
349 {
350   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
351   gchar *initial_response;
352   GCredentials *credentials;
353
354   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
355   g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
356
357   m->priv->is_client = TRUE;
358   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
359
360   *out_initial_response_len = -1;
361
362   credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
363   g_assert (credentials != NULL);
364
365   /* return the uid */
366 #if defined(G_OS_UNIX)
367   initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, g_credentials_get_unix_user (credentials));
368 #elif defined(G_OS_WIN32)
369   initial_response = g_strdup_printf ("%s", g_credentials_get_windows_user ());
370 #else
371 #warning Dont know how to send credentials on this OS. Please implement.
372   m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
373 #endif
374   return initial_response;
375 }
376
377 static void
378 mechanism_client_data_receive (GDBusAuthMechanism   *mechanism,
379                                const gchar          *data,
380                                gsize                 data_len)
381 {
382   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
383
384   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
385   g_return_if_fail (m->priv->is_client && !m->priv->is_server);
386   g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
387
388   /* can never end up here because we are never in the WAITING_FOR_DATA state */
389   g_assert_not_reached ();
390 }
391
392 static gchar *
393 mechanism_client_data_send (GDBusAuthMechanism   *mechanism,
394                             gsize                *out_data_len)
395 {
396   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
397
398   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
399   g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
400   g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
401
402   /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
403   g_assert_not_reached ();
404
405   return NULL;
406 }
407
408 static void
409 mechanism_client_shutdown (GDBusAuthMechanism   *mechanism)
410 {
411   GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
412
413   g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
414   g_return_if_fail (m->priv->is_client && !m->priv->is_server);
415
416   m->priv->is_client = FALSE;
417 }
418
419 /* ---------------------------------------------------------------------------------------------------- */
420
421 #define __G_DBUS_AUTH_MECHANISM_EXTERNAL_C__
422 #include "gioaliasdef.c"