1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2012 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 #include "gsignond/gsignond-log.h"
28 #include "gsignond-dbus-auth-service-adapter.h"
29 #include "gsignond-dbus-identity-adapter.h"
30 #include "gsignond-dbus.h"
41 static GParamSpec *properties[N_PROPERTIES];
43 struct _GSignondDbusAuthServiceAdapterPrivate
45 GDBusConnection *connection;
46 GSignondDbusAuthService *dbus_auth_service;
47 GSignondDaemon *auth_service;
50 GHashTable *caller_watchers; //(dbus_caller:watcher_id)
54 G_DEFINE_TYPE (GSignondDbusAuthServiceAdapter, gsignond_dbus_auth_service_adapter, GSIGNOND_TYPE_DISPOSABLE)
56 #define GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER_GET_PRIV(obj) \
57 G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_AUTH_SERVICE_ADAPTER, GSignondDbusAuthServiceAdapterPrivate)
59 static gboolean _handle_register_new_identity (GSignondDbusAuthServiceAdapter *, GDBusMethodInvocation *,
60 const gchar *, gpointer);
61 static gboolean _handle_get_identity (GSignondDbusAuthServiceAdapter *, GDBusMethodInvocation *, guint32,
62 const gchar *, gpointer);
63 static gboolean _handle_query_methods (GSignondDbusAuthServiceAdapter *,
64 GDBusMethodInvocation *,
66 static gboolean _handle_query_mechanisms (GSignondDbusAuthServiceAdapter *,
67 GDBusMethodInvocation *,
68 const gchar *, gpointer);
69 static gboolean _handle_query_identities (GSignondDbusAuthServiceAdapter *,
70 GDBusMethodInvocation *,
74 static gboolean _handle_clear (GSignondDbusAuthServiceAdapter *, GDBusMethodInvocation *, gpointer);
75 static void _on_identity_disposed (gpointer data, GObject *object);
78 _set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
80 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (object);
82 switch (property_id) {
83 case PROP_AUTH_SERVICE: {
84 GObject *auth_service = g_value_get_object (value);
86 if (self->priv->auth_service) g_object_unref (self->priv->auth_service);
87 self->priv->auth_service = GSIGNOND_DAEMON (auth_service);
92 self->priv->connection = g_value_get_object(value);
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100 _get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
102 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (object);
104 switch (property_id) {
105 case PROP_AUTH_SERVICE: {
106 g_value_set_object (value, self->priv->auth_service);
109 case PROP_CONNECTION:
110 g_value_set_object (value, self->priv->connection);
113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
118 _identity_unref (gpointer data, gpointer user_data)
120 if (data && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER(data)) {
121 GObject *identity = G_OBJECT (data);
122 g_object_weak_unref (identity, _on_identity_disposed, user_data);
123 g_object_unref (identity);
128 _dispose (GObject *object)
130 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (object);
132 DBG("- unregistering dubs auth service. %d", G_OBJECT (self->priv->auth_service)->ref_count);
134 if (self->priv->identities) {
135 g_list_foreach (self->priv->identities, _identity_unref, self);
138 if (self->priv->auth_service) {
139 g_object_unref (self->priv->auth_service);
140 self->priv->auth_service = NULL;
143 if (self->priv->dbus_auth_service) {
144 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->priv->dbus_auth_service));
145 g_object_unref (self->priv->dbus_auth_service);
146 self->priv->dbus_auth_service = NULL;
149 if (self->priv->connection) {
150 g_object_unref (self->priv->connection);
151 self->priv->connection = NULL;
155 if (self->priv->caller_watchers) {
156 g_hash_table_unref (self->priv->caller_watchers);
157 self->priv->caller_watchers = NULL;
161 G_OBJECT_CLASS (gsignond_dbus_auth_service_adapter_parent_class)->dispose (object);
165 _finalize (GObject *object)
167 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (object);
169 if (self->priv->identities) {
170 g_list_free (self->priv->identities);
171 self->priv->identities = NULL;
174 G_OBJECT_CLASS (gsignond_dbus_auth_service_adapter_parent_class)->finalize (object);
178 gsignond_dbus_auth_service_adapter_class_init (GSignondDbusAuthServiceAdapterClass *klass)
180 GObjectClass* object_class = G_OBJECT_CLASS (klass);
182 g_type_class_add_private (object_class, sizeof (GSignondDbusAuthServiceAdapterPrivate));
184 object_class->get_property = _get_property;
185 object_class->set_property = _set_property;
186 object_class->dispose = _dispose;
187 object_class->finalize = _finalize;
189 properties[PROP_AUTH_SERVICE] = g_param_spec_object ("auth-service",
191 "AuthService core object",
192 GSIGNOND_TYPE_DAEMON,
193 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
195 properties[PROP_CONNECTION] = g_param_spec_object ("connection",
197 "DBus connection used",
198 G_TYPE_DBUS_CONNECTION,
199 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
201 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
205 gsignond_dbus_auth_service_adapter_init (GSignondDbusAuthServiceAdapter *self)
207 self->priv = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER_GET_PRIV(self);
209 self->priv->connection = 0;
210 self->priv->auth_service = 0;
211 self->priv->identities = NULL;
212 self->priv->dbus_auth_service = gsignond_dbus_auth_service_skeleton_new ();
214 self->priv->caller_watchers = g_hash_table_new_full (g_str_hash, g_str_equal,
215 g_free, (GDestroyNotify)g_bus_unwatch_name);
218 g_signal_connect_swapped (self->priv->dbus_auth_service,
219 "handle-register-new-identity", G_CALLBACK (_handle_register_new_identity), self);
220 g_signal_connect_swapped (self->priv->dbus_auth_service,
221 "handle-get-identity", G_CALLBACK(_handle_get_identity), self);
222 g_signal_connect_swapped (self->priv->dbus_auth_service,
223 "handle-query-methods", G_CALLBACK(_handle_query_methods), self);
224 g_signal_connect_swapped (self->priv->dbus_auth_service,
225 "handle-query-mechanisms", G_CALLBACK(_handle_query_mechanisms), self);
226 g_signal_connect_swapped (self->priv->dbus_auth_service,
227 "handle-query-identities", G_CALLBACK(_handle_query_identities), self);
228 g_signal_connect_swapped (self->priv->dbus_auth_service,
229 "handle-clear", G_CALLBACK(_handle_clear), self);
234 _clear_cache_for_name (gpointer data, gpointer user_data)
236 g_return_if_fail (user_data);
237 g_return_if_fail (data && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (data));
239 const gchar *caller = (const gchar *)user_data;
240 GSignondDbusIdentityAdapter *dbus_identity = GSIGNOND_DBUS_IDENTITY_ADAPTER (data);
241 const gchar *identity_owner = g_object_get_data (G_OBJECT (dbus_identity), "dbus-client-name");
243 if (g_strcmp0 (identity_owner, caller) == 0) {
244 DBG ("removing dbus identity '%p' from cache", dbus_identity);
245 g_object_unref (dbus_identity);
250 _on_connnection_lost (GDBusConnection *conn, const char *peer_name, gpointer user_data)
253 g_return_if_fail (peer_name);
254 g_return_if_fail (user_data && GSIGNOND_IS_DBUS_AUTH_SERVICE_ADAPTER(user_data));
256 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (user_data);
257 DBG ("(-)peer disappeared : %s", peer_name);
259 g_list_foreach (self->priv->identities, _clear_cache_for_name, (gpointer)peer_name);
261 if (g_hash_table_contains (self->priv->caller_watchers, peer_name)) {
262 g_hash_table_remove (self->priv->caller_watchers, (gpointer)peer_name);
268 _on_identity_disposed (gpointer data, GObject *object)
270 GSignondDbusAuthServiceAdapter *self = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (data);
272 DBG ("identity object %p disposed", object);
273 self->priv->identities = g_list_remove (self->priv->identities, object);
275 if (g_list_length (self->priv->identities) == 0) {
276 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
280 static GSignondDbusIdentityAdapter *
281 _create_and_cache_dbus_identity (GSignondDbusAuthServiceAdapter *self,
282 GSignondIdentity *identity,
283 const gchar *app_context,
284 GDBusConnection *connection,
287 GSignondDbusIdentityAdapter *dbus_identity = NULL;
288 guint identity_timeout = gsignond_daemon_get_identity_timeout (self->priv->auth_service);
290 dbus_identity = gsignond_dbus_identity_adapter_new_with_connection (
291 g_object_ref (connection), identity, app_context, identity_timeout);
293 /* keep alive till this identity object gets disposed */
294 if (g_list_length (self->priv->identities) == 0)
295 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
297 self->priv->identities = g_list_append (self->priv->identities, dbus_identity);
298 g_object_weak_ref (G_OBJECT (dbus_identity), _on_identity_disposed, self);
300 g_object_set_data_full (G_OBJECT(dbus_identity), "dbus-client-name", (gpointer)g_strdup(sender), g_free);
301 if (!g_hash_table_contains (self->priv->caller_watchers, sender)) {
302 guint watcher_id = g_bus_watch_name_on_connection (connection, sender, G_BUS_NAME_WATCHER_FLAGS_NONE,
303 NULL, _on_connnection_lost, self, NULL);
304 g_hash_table_insert (self->priv->caller_watchers,
305 (gpointer)g_strdup (sender),
306 GUINT_TO_POINTER(watcher_id));
310 return dbus_identity;
314 _handle_register_new_identity (GSignondDbusAuthServiceAdapter *self,
315 GDBusMethodInvocation *invocation,
316 const gchar *app_context,
319 GSignondIdentity *identity = NULL;
320 GError *error = NULL;
321 GDBusConnection *connection = NULL;
322 const gchar *sender = NULL;
324 GSignondSecurityContext *sec_context = gsignond_security_context_new ();
326 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SERVICE_ADAPTER(self), FALSE);
328 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
330 connection = g_dbus_method_invocation_get_connection (invocation);
332 fd = g_socket_get_fd (g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream(connection))));
334 sender = g_dbus_method_invocation_get_sender (invocation);
337 gsignond_access_control_manager_security_context_of_peer(
338 gsignond_daemon_get_access_control_manager (self->priv->auth_service),
344 identity = gsignond_daemon_register_new_identity (self->priv->auth_service, sec_context, &error);
347 GSignondDbusIdentityAdapter *dbus_identity = _create_and_cache_dbus_identity (self, identity, app_context, connection, sender);
349 gsignond_dbus_auth_service_complete_register_new_identity (self->priv->dbus_auth_service,
350 invocation, gsignond_dbus_identity_adapter_get_object_path (dbus_identity));
353 g_dbus_method_invocation_return_gerror (invocation, error);
354 g_error_free (error);
356 gsignond_security_context_free (sec_context);
358 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
364 _handle_get_identity (GSignondDbusAuthServiceAdapter *self,
365 GDBusMethodInvocation *invocation,
367 const gchar *app_context,
370 GSignondIdentity *identity = NULL;
371 GError *error = NULL;
372 GDBusConnection *connection = NULL;
373 const gchar *sender = NULL;
375 GSignondSecurityContext *sec_context = gsignond_security_context_new ();
377 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
379 connection = g_dbus_method_invocation_get_connection (invocation);
381 fd = g_socket_get_fd (g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream(connection))));
383 sender = g_dbus_method_invocation_get_sender (invocation);
385 gsignond_access_control_manager_security_context_of_peer(
386 gsignond_daemon_get_access_control_manager (self->priv->auth_service),
392 identity = gsignond_daemon_get_identity (self->priv->auth_service, id, sec_context, &error);
395 GSignondIdentityInfo *info = NULL;
396 GSignondDbusIdentityAdapter *dbus_identity = _create_and_cache_dbus_identity (self, identity, app_context, connection, sender);
398 info = gsignond_identity_get_identity_info (identity);
399 gsignond_dbus_auth_service_complete_get_identity (self->priv->dbus_auth_service,
400 invocation, gsignond_dbus_identity_adapter_get_object_path (dbus_identity),
401 gsignond_dictionary_to_variant (info));
404 g_dbus_method_invocation_return_gerror (invocation, error);
405 g_error_free (error);
407 gsignond_security_context_free (sec_context);
409 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
415 _handle_query_methods (GSignondDbusAuthServiceAdapter *self,
416 GDBusMethodInvocation *invocation,
419 const gchar **methods = NULL;
420 GError *error = NULL;
422 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
424 methods = gsignond_daemon_query_methods (self->priv->auth_service, &error);
427 g_dbus_method_invocation_return_gerror (invocation, error);
428 g_error_free (error);
430 const gchar *const empty_methods[] = { NULL };
431 gsignond_dbus_auth_service_complete_query_methods (
432 self->priv->dbus_auth_service, invocation,
433 methods ? (const gchar * const*)methods : empty_methods);
436 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
442 _handle_query_mechanisms (GSignondDbusAuthServiceAdapter *self,
443 GDBusMethodInvocation *invocation,
447 const gchar **mechanisms = 0;
448 GError *error = NULL;
450 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
452 mechanisms = gsignond_daemon_query_mechanisms (self->priv->auth_service, method, &error);
455 gsignond_dbus_auth_service_complete_query_mechanisms (
456 self->priv->dbus_auth_service, invocation, (const gchar* const*)mechanisms);
458 g_dbus_method_invocation_return_gerror (invocation, error);
459 g_error_free (error);
462 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
468 _append_identity_info (gpointer data, gpointer user_data)
470 GVariantBuilder *builder = (GVariantBuilder *)user_data;
472 g_variant_builder_add (builder, "@a{sv}", gsignond_dictionary_to_variant ((GSignondIdentityInfo*)data));
476 _handle_query_identities (GSignondDbusAuthServiceAdapter *self,
477 GDBusMethodInvocation *invocation,
479 const gchar *app_context,
482 GSignondIdentityInfoList *identities = NULL;
483 GError *error = NULL;
484 GSignondSecurityContext *sec_context;
485 const gchar *sender = NULL;
488 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
491 GDBusConnection *connection = NULL;
492 connection = g_dbus_method_invocation_get_connection (invocation);
493 fd = g_socket_get_fd (g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream(connection))));
495 sender = g_dbus_method_invocation_get_sender (invocation);
497 sec_context = gsignond_security_context_new ();
498 gsignond_access_control_manager_security_context_of_peer(
499 gsignond_daemon_get_access_control_manager (self->priv->auth_service),
502 sender, app_context);
504 identities = gsignond_daemon_query_identities (self->priv->auth_service,
509 gsignond_security_context_free (sec_context);
512 GVariantBuilder builder;
514 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
516 g_list_foreach(identities, _append_identity_info, &builder);
518 gsignond_identity_info_list_free (identities);
520 gsignond_dbus_auth_service_complete_query_identities (
521 self->priv->dbus_auth_service, invocation,
522 g_variant_builder_end(&builder));
524 g_variant_builder_clear (&builder);
527 g_dbus_method_invocation_return_gerror (invocation, error);
528 g_error_free (error);
531 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
537 _handle_clear (GSignondDbusAuthServiceAdapter *self,
538 GDBusMethodInvocation *invocation,
542 GError *error = NULL;
543 GSignondSecurityContext *sec_context;
544 const gchar *sender = NULL;
547 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
549 GDBusConnection *connection = NULL;
550 connection = g_dbus_method_invocation_get_connection (invocation);
551 fd = g_socket_get_fd (g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream(connection))));
553 sender = g_dbus_method_invocation_get_sender (invocation);
555 sec_context = gsignond_security_context_new ();
556 gsignond_access_control_manager_security_context_of_peer(
557 gsignond_daemon_get_access_control_manager (self->priv->auth_service),
562 res = gsignond_daemon_clear (self->priv->auth_service,
566 gsignond_security_context_free (sec_context);
569 gsignond_dbus_auth_service_complete_clear (self->priv->dbus_auth_service, invocation, res);
571 g_dbus_method_invocation_return_gerror (invocation, error);
572 g_error_free (error);
575 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
580 GSignondDbusAuthServiceAdapter *
581 gsignond_dbus_auth_service_adapter_new_with_connection (GDBusConnection *bus_connection, GSignondDaemon *daemon)
585 GSignondDbusAuthServiceAdapter *adapter = GSIGNOND_DBUS_AUTH_SERVICE_ADAPTER (
586 g_object_new (GSIGNOND_TYPE_AUTH_SERVICE_ADAPTER,
587 "auth-service", daemon,
588 "connection", bus_connection,
591 if (!g_dbus_interface_skeleton_export (
592 G_DBUS_INTERFACE_SKELETON(adapter->priv->dbus_auth_service),
593 adapter->priv->connection, GSIGNOND_DAEMON_OBJECTPATH, &err)) {
594 ERR ("failed to register object: %s", err->message);
596 g_object_unref (adapter);
599 DBG("(+) started auth service '%p' at path '%s' on connection '%p'", adapter, GSIGNOND_DAEMON_OBJECTPATH, bus_connection);
601 timeout = gsignond_daemon_get_timeout (adapter->priv->auth_service);
603 gsignond_disposable_set_timeout (GSIGNOND_DISPOSABLE (adapter), timeout);
608 GSignondDbusAuthServiceAdapter * gsignond_dbus_auth_service_adapter_new (GSignondDaemon *daemon)
610 GError *error = NULL;
611 GDBusConnection *connection = g_bus_get_sync (GSIGNOND_BUS_TYPE, NULL, &error);
614 ERR("failed to connect to session bus : %s", error->message);
615 g_error_free (error);
619 return gsignond_dbus_auth_service_adapter_new_with_connection (connection, daemon);