1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2009 Red Hat, Inc.
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.
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.
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.
20 * Author: David Zeuthen <davidz@redhat.com>
25 #include <glib/gi18n.h>
27 #include "gdbusauthmechanismexternal.h"
28 #include "gcredentials.h"
29 #include "gdbuserror.h"
30 #include "gioenumtypes.h"
33 #include <sys/types.h>
37 struct _GDBusAuthMechanismExternalPrivate
41 GDBusAuthMechanismState state;
44 static gint mechanism_get_priority (void);
45 static const gchar *mechanism_get_name (void);
47 static gboolean mechanism_is_supported (GDBusAuthMechanism *mechanism);
48 static gchar *mechanism_encode_data (GDBusAuthMechanism *mechanism,
52 static gchar *mechanism_decode_data (GDBusAuthMechanism *mechanism,
56 static GDBusAuthMechanismState mechanism_server_get_state (GDBusAuthMechanism *mechanism);
57 static void mechanism_server_initiate (GDBusAuthMechanism *mechanism,
58 const gchar *initial_response,
59 gsize initial_response_len);
60 static void mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
63 static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
65 static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
66 static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
67 static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
68 static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
69 gsize *out_initial_response_len);
70 static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
73 static gchar *mechanism_client_data_send (GDBusAuthMechanism *mechanism,
75 static void mechanism_client_shutdown (GDBusAuthMechanism *mechanism);
77 /* ---------------------------------------------------------------------------------------------------- */
79 G_DEFINE_TYPE (GDBusAuthMechanismExternal, _g_dbus_auth_mechanism_external, G_TYPE_DBUS_AUTH_MECHANISM);
81 /* ---------------------------------------------------------------------------------------------------- */
84 _g_dbus_auth_mechanism_external_finalize (GObject *object)
86 //GDBusAuthMechanismExternal *mechanism = G_DBUS_AUTH_MECHANISM_EXTERNAL (object);
88 if (G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize != NULL)
89 G_OBJECT_CLASS (_g_dbus_auth_mechanism_external_parent_class)->finalize (object);
93 _g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *klass)
95 GObjectClass *gobject_class;
96 GDBusAuthMechanismClass *mechanism_class;
98 g_type_class_add_private (klass, sizeof (GDBusAuthMechanismExternalPrivate));
100 gobject_class = G_OBJECT_CLASS (klass);
101 gobject_class->finalize = _g_dbus_auth_mechanism_external_finalize;
103 mechanism_class = G_DBUS_AUTH_MECHANISM_CLASS (klass);
104 mechanism_class->get_name = mechanism_get_name;
105 mechanism_class->get_priority = mechanism_get_priority;
106 mechanism_class->is_supported = mechanism_is_supported;
107 mechanism_class->encode_data = mechanism_encode_data;
108 mechanism_class->decode_data = mechanism_decode_data;
109 mechanism_class->server_get_state = mechanism_server_get_state;
110 mechanism_class->server_initiate = mechanism_server_initiate;
111 mechanism_class->server_data_receive = mechanism_server_data_receive;
112 mechanism_class->server_data_send = mechanism_server_data_send;
113 mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
114 mechanism_class->server_shutdown = mechanism_server_shutdown;
115 mechanism_class->client_get_state = mechanism_client_get_state;
116 mechanism_class->client_initiate = mechanism_client_initiate;
117 mechanism_class->client_data_receive = mechanism_client_data_receive;
118 mechanism_class->client_data_send = mechanism_client_data_send;
119 mechanism_class->client_shutdown = mechanism_client_shutdown;
123 _g_dbus_auth_mechanism_external_init (GDBusAuthMechanismExternal *mechanism)
125 mechanism->priv = G_TYPE_INSTANCE_GET_PRIVATE (mechanism,
126 G_TYPE_DBUS_AUTH_MECHANISM_EXTERNAL,
127 GDBusAuthMechanismExternalPrivate);
130 /* ---------------------------------------------------------------------------------------------------- */
133 mechanism_is_supported (GDBusAuthMechanism *mechanism)
135 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), FALSE);
136 /* This mechanism is only available if credentials has been exchanged */
137 if (_g_dbus_auth_mechanism_get_credentials (mechanism) != NULL)
144 mechanism_get_priority (void)
146 /* We prefer EXTERNAL to most other mechanism (DBUS_COOKIE_SHA1 and ANONYMOUS) */
151 mechanism_get_name (void)
157 mechanism_encode_data (GDBusAuthMechanism *mechanism,
167 mechanism_decode_data (GDBusAuthMechanism *mechanism,
175 /* ---------------------------------------------------------------------------------------------------- */
177 static GDBusAuthMechanismState
178 mechanism_server_get_state (GDBusAuthMechanism *mechanism)
180 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
182 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
183 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
185 return m->priv->state;
189 data_matches_credentials (const gchar *data,
190 GCredentials *credentials)
196 if (credentials == NULL)
199 if (data == NULL || strlen (data) == 0)
202 #if defined(G_OS_UNIX)
207 /* on UNIX, this is the uid as a string in base 10 */
208 alleged_uid = g_ascii_strtoll (data, &endp, 10);
211 if (g_credentials_has_unix_user (credentials) &&
212 g_credentials_get_unix_user (credentials) == alleged_uid)
218 #elif defined(G_OS_WIN32)
220 const gchar *alleged_sid;
222 /* on Win32, this is the User SID */
224 if (g_credentials_has_windows_user (credentials) &&
225 g_strcmp0 (g_credentials_get_windows_user (credentials), alleged_sid) == 0)
231 #error Dont know how to read credentials on this OS. Please implement.
239 mechanism_server_initiate (GDBusAuthMechanism *mechanism,
240 const gchar *initial_response,
241 gsize initial_response_len)
243 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
245 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
246 g_return_if_fail (!m->priv->is_server && !m->priv->is_client);
248 m->priv->is_server = TRUE;
250 if (initial_response != NULL)
252 if (data_matches_credentials (initial_response, _g_dbus_auth_mechanism_get_credentials (mechanism)))
254 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
258 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
263 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
268 mechanism_server_data_receive (GDBusAuthMechanism *mechanism,
272 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
274 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
275 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
276 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
278 if (data_matches_credentials (data, _g_dbus_auth_mechanism_get_credentials (mechanism)))
280 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
284 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
289 mechanism_server_data_send (GDBusAuthMechanism *mechanism,
292 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
294 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
295 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
296 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
298 /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
299 g_assert_not_reached ();
305 mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
307 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
309 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
310 g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
311 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
313 /* can never end up here because we are never in the REJECTED state */
314 g_assert_not_reached ();
320 mechanism_server_shutdown (GDBusAuthMechanism *mechanism)
322 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
324 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
325 g_return_if_fail (m->priv->is_server && !m->priv->is_client);
327 m->priv->is_server = FALSE;
330 /* ---------------------------------------------------------------------------------------------------- */
332 static GDBusAuthMechanismState
333 mechanism_client_get_state (GDBusAuthMechanism *mechanism)
335 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
337 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), G_DBUS_AUTH_MECHANISM_STATE_INVALID);
338 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, G_DBUS_AUTH_MECHANISM_STATE_INVALID);
340 return m->priv->state;
344 mechanism_client_initiate (GDBusAuthMechanism *mechanism,
345 gsize *out_initial_response_len)
347 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
348 gchar *initial_response;
349 GCredentials *credentials;
351 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
352 g_return_val_if_fail (!m->priv->is_server && !m->priv->is_client, NULL);
354 m->priv->is_client = TRUE;
355 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
357 *out_initial_response_len = -1;
359 credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
360 g_assert (credentials != NULL);
363 #if defined(G_OS_UNIX)
364 initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, g_credentials_get_unix_user (credentials));
365 #elif defined(G_OS_WIN32)
366 initial_response = g_strdup_printf ("%s", g_credentials_get_windows_user ());
368 #warning Dont know how to send credentials on this OS. Please implement.
369 m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
371 return initial_response;
375 mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
379 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
381 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
382 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
383 g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
385 /* can never end up here because we are never in the WAITING_FOR_DATA state */
386 g_assert_not_reached ();
390 mechanism_client_data_send (GDBusAuthMechanism *mechanism,
393 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
395 g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
396 g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, NULL);
397 g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
399 /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
400 g_assert_not_reached ();
406 mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
408 GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
410 g_return_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism));
411 g_return_if_fail (m->priv->is_client && !m->priv->is_server);
413 m->priv->is_client = FALSE;
416 /* ---------------------------------------------------------------------------------------------------- */