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-2013 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/gsignond-utils.h"
29 #include "gsignond/gsignond-error.h"
30 #include "gsignond-dbus-auth-session-adapter.h"
31 #include "gsignond-dbus.h"
42 static GParamSpec *properties[N_PROPERTIES];
44 struct _GSignondDbusAuthSessionAdapterPrivate
46 GDBusConnection *connection;
47 GSignondDbusAuthSession *dbus_auth_session;
48 GSignondAuthSession *session;
50 gboolean is_process_active;
51 GSignondSecurityContext *ctx;
54 G_DEFINE_TYPE (GSignondDbusAuthSessionAdapter, gsignond_dbus_auth_session_adapter, GSIGNOND_TYPE_DISPOSABLE)
57 #define GSIGNOND_DBUS_AUTH_SESSION_ADAPTER_GET_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_DBUS_AUTH_SESSION_ADAPTER, GSignondDbusAuthSessionAdapterPrivate)
59 #define PREPARE_SECURITY_CONTEXT(dbus_object, invocation) \
61 GSignondDbusAuthSessionAdapterPrivate *priv = dbus_object->priv; \
62 GSignondAccessControlManager *acm = gsignond_auth_session_get_acm (priv->session); \
63 const gchar *sender = NULL; \
65 sender = g_dbus_method_invocation_get_sender (invocation); \
67 GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation);\
68 fd = g_socket_get_fd(g_socket_connection_get_socket(G_SOCKET_CONNECTION(g_dbus_connection_get_stream (connection))));\
70 gsignond_access_control_manager_security_context_of_peer( \
78 static gboolean _handle_query_available_mechanisms (GSignondDbusAuthSessionAdapter *, GDBusMethodInvocation *, const gchar **, gpointer);
79 static gboolean _handle_process (GSignondDbusAuthSessionAdapter *, GDBusMethodInvocation *, const GVariant *, const gchar *, gpointer);
80 static gboolean _handle_cancel (GSignondDbusAuthSessionAdapter *, GDBusMethodInvocation *, gpointer);
83 gsignond_dbus_auth_session_adapter_set_property (GObject *object,
85 const GValue *value, GParamSpec *pspec)
87 GSignondDbusAuthSessionAdapter *self = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (object);
89 switch (property_id) {
91 gpointer object = g_value_get_object (value);
92 self->priv->session = GSIGNOND_AUTH_SESSION ((object));
95 case PROP_CONNECTION: {
96 if (self->priv->connection) g_object_unref (self->priv->connection);
97 self->priv->connection = G_DBUS_CONNECTION (g_value_dup_object (value));
100 case PROP_APP_CONTEXT: {
101 if (self->priv->app_context) g_free (self->priv->app_context);
102 self->priv->app_context = g_strdup (g_value_get_string (value));
106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
111 gsignond_dbus_auth_session_adapter_get_property (GObject *object,
116 GSignondDbusAuthSessionAdapter *self = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (object);
118 switch (property_id) {
120 g_value_set_object (value, self->priv->session);
123 case PROP_CONNECTION:
124 g_value_set_object (value, self->priv->connection);
126 case PROP_APP_CONTEXT:
127 g_value_set_string (value, self->priv->app_context);
130 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
135 gsignond_dbus_auth_session_adapter_dispose (GObject *object)
137 GSignondDbusAuthSessionAdapter *self = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (object);
139 if (self->priv->session) {
140 if (self->priv->is_process_active) {
141 gsignond_auth_session_abort_process (self->priv->session);
142 self->priv->is_process_active = FALSE;
145 g_object_unref (self->priv->session);
146 self->priv->session = NULL;
149 if (self->priv->dbus_auth_session) {
150 gsignond_dbus_auth_session_emit_unregistered (self->priv->dbus_auth_session);
151 DBG("(-)'%s' object unexported", g_dbus_interface_skeleton_get_object_path (
152 G_DBUS_INTERFACE_SKELETON(self->priv->dbus_auth_session)));
153 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON(self->priv->dbus_auth_session));
154 g_object_unref (self->priv->dbus_auth_session);
155 self->priv->dbus_auth_session = NULL;
158 if (self->priv->connection) {
159 g_object_unref (self->priv->connection);
160 self->priv->connection = NULL;
163 G_OBJECT_CLASS(gsignond_dbus_auth_session_adapter_parent_class)->dispose (object);
167 gsignond_dbus_auth_session_adapter_finalize (GObject *object)
169 GSignondDbusAuthSessionAdapter *self = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (object);
171 if (self->priv->ctx) {
172 gsignond_security_context_free (self->priv->ctx);
173 self->priv->ctx = NULL;
176 if (self->priv->app_context) {
177 g_free (self->priv->app_context);
178 self->priv->app_context = NULL;
181 G_OBJECT_CLASS (gsignond_dbus_auth_session_adapter_parent_class)->finalize (object);
185 gsignond_dbus_auth_session_adapter_class_init (GSignondDbusAuthSessionAdapterClass *klass)
187 GObjectClass* object_class = G_OBJECT_CLASS (klass);
189 g_type_class_add_private (object_class, sizeof (GSignondDbusAuthSessionAdapterPrivate));
191 object_class->get_property = gsignond_dbus_auth_session_adapter_get_property;
192 object_class->set_property = gsignond_dbus_auth_session_adapter_set_property;
193 object_class->dispose = gsignond_dbus_auth_session_adapter_dispose;
194 object_class->finalize = gsignond_dbus_auth_session_adapter_finalize;
196 properties[PROP_SESSION] = g_param_spec_object ("auth-session",
197 "Core auth session object",
198 "Core AuthSession Object",
199 GSIGNOND_TYPE_AUTH_SESSION,
201 G_PARAM_CONSTRUCT_ONLY |
202 G_PARAM_STATIC_STRINGS);
204 properties[PROP_CONNECTION] = g_param_spec_object ("connection",
205 "Dbus connection used",
206 "Dbus connection used",
207 G_TYPE_DBUS_CONNECTION,
209 G_PARAM_CONSTRUCT_ONLY |
210 G_PARAM_STATIC_STRINGS);
211 properties[PROP_APP_CONTEXT] = g_param_spec_string (
213 "application security context",
214 "Application security context of the identity object creater",
216 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
218 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
222 gsignond_dbus_auth_session_adapter_init (GSignondDbusAuthSessionAdapter *self)
224 self->priv = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER_GET_PRIV(self);
226 self->priv->connection = 0;
227 self->priv->session = 0;
228 self->priv->app_context = 0;
229 self->priv->is_process_active = FALSE;
230 self->priv->dbus_auth_session = gsignond_dbus_auth_session_skeleton_new ();
231 self->priv->ctx = gsignond_security_context_new ();
233 g_signal_connect_swapped (self->priv->dbus_auth_session,
234 "handle-query-available-mechanisms",
235 G_CALLBACK (_handle_query_available_mechanisms), self);
236 g_signal_connect_swapped (self->priv->dbus_auth_session, "handle-process", G_CALLBACK(_handle_process), self);
237 g_signal_connect_swapped (self->priv->dbus_auth_session, "handle-cancel", G_CALLBACK(_handle_cancel), self);
241 _handle_query_available_mechanisms (GSignondDbusAuthSessionAdapter *self,
242 GDBusMethodInvocation *invocation,
243 const gchar **wanted_mechanisms,
246 gchar **mechanisms = NULL;
247 GError *error = NULL;
249 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (self), FALSE);
251 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
253 PREPARE_SECURITY_CONTEXT (self, invocation);
255 mechanisms = gsignond_auth_session_query_available_mechanisms (
256 self->priv->session, wanted_mechanisms, self->priv->ctx, &error);
259 gsignond_dbus_auth_session_complete_query_available_mechanisms (
260 self->priv->dbus_auth_session, invocation, (const gchar * const *)mechanisms);
264 g_dbus_method_invocation_return_gerror (invocation, error);
265 g_error_free (error);
268 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
274 GSignondDbusAuthSessionAdapter *adapter;
275 GDBusMethodInvocation *invocation;
276 } _AuthSessionDbusInfo;
278 static _AuthSessionDbusInfo*
279 _auth_session_dbus_info_new (GSignondDbusAuthSessionAdapter *self, GDBusMethodInvocation *invocation)
281 _AuthSessionDbusInfo *info = g_slice_new0(_AuthSessionDbusInfo);
283 info->adapter = g_object_ref (self);
284 info->invocation = g_object_ref (invocation);
290 _auth_session_dbus_info_free (_AuthSessionDbusInfo *info)
294 g_object_unref (info->adapter);
295 g_object_unref (info->invocation);
297 g_slice_free (_AuthSessionDbusInfo, info);
301 _emit_state_changed (gint state, const gchar *message, gpointer user_data)
303 GSignondDbusAuthSessionAdapter *self = NULL;
304 _AuthSessionDbusInfo *info = (_AuthSessionDbusInfo*) user_data;
306 if (!info || !GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER(info->adapter)) return ;
308 self = info->adapter;
309 gsignond_dbus_auth_session_emit_state_changed (
310 self->priv->dbus_auth_session, state, message);
314 _on_process_done (GSignondSessionData *reply, const GError *error, gpointer user_data)
316 GSignondDbusAuthSessionAdapter *self = NULL;
317 _AuthSessionDbusInfo *info = (_AuthSessionDbusInfo*) user_data;
319 if (!info || !GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER(info->adapter)) return ;
321 self = info->adapter;
323 if (self->priv->is_process_active) {
324 self->priv->is_process_active = FALSE;
327 DBG("ERROR : %s(%d)", error->message, error->code);
328 GError *dbus_err = gsignond_get_gerror_for_id (error->code, error->message, NULL);
329 g_dbus_method_invocation_take_error (info->invocation, dbus_err);
332 GVariant *result = gsignond_dictionary_to_variant ((GSignondDictionary *)reply);
333 gsignond_dbus_auth_session_complete_process (
334 self->priv->dbus_auth_session, info->invocation, result);
337 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
339 _auth_session_dbus_info_free (info);
343 _handle_process (GSignondDbusAuthSessionAdapter *self,
344 GDBusMethodInvocation *invocation,
345 const GVariant *session_data,
346 const gchar *mechanisms,
349 _AuthSessionDbusInfo *info = 0;
350 GError *error = NULL;
351 GSignondSessionData *data = NULL;
353 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (self), FALSE);
355 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
357 PREPARE_SECURITY_CONTEXT (self, invocation);
359 data = (GSignondSessionData *)gsignond_dictionary_new_from_variant ((GVariant *)session_data);
360 info = _auth_session_dbus_info_new (self, invocation);
361 self->priv->is_process_active = TRUE;
362 if (!gsignond_auth_session_process (self->priv->session, data, mechanisms,
363 self->priv->ctx, _on_process_done,
364 _emit_state_changed, info, &error)) {
365 g_dbus_method_invocation_return_gerror (invocation, error);
366 g_error_free (error);
368 _auth_session_dbus_info_free (info);
370 self->priv->is_process_active = FALSE;
372 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
375 gsignond_dictionary_unref (data);
381 _handle_cancel (GSignondDbusAuthSessionAdapter *self,
382 GDBusMethodInvocation *invocation,
385 GError *error = NULL;
387 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (self), FALSE);
389 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
391 PREPARE_SECURITY_CONTEXT (self, invocation);
393 if (gsignond_auth_session_cancel (self->priv->session, self->priv->ctx, &error))
394 gsignond_dbus_auth_session_complete_cancel (self->priv->dbus_auth_session, invocation);
396 g_dbus_method_invocation_return_gerror (invocation, error);
397 g_error_free (error);
400 gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
406 gsignond_dbus_auth_session_adapter_get_object_path (GSignondDbusAuthSessionAdapter *self)
408 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER(self), NULL);
410 return g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON(self->priv->dbus_auth_session));
414 gsignond_dbus_auth_session_adapter_is_process_active (GSignondDbusAuthSessionAdapter *self)
416 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (self), FALSE);
418 return self->priv->is_process_active;
422 gsignond_dbus_auth_session_adapter_abort_process (GSignondDbusAuthSessionAdapter *self)
424 g_return_val_if_fail (self && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (self), FALSE);
426 if (self->priv->is_process_active) {
427 gsignond_auth_session_abort_process (self->priv->session);
428 self->priv->is_process_active = FALSE;
434 GSignondDbusAuthSessionAdapter *
435 gsignond_dbus_auth_session_adapter_new_with_connection (GDBusConnection *connection,
436 GSignondAuthSession *session,
437 const gchar *app_context,
440 static guint32 object_counter = 0;
442 gchar *object_path = NULL;
443 GSignondDbusAuthSessionAdapter *adapter = NULL;
444 GError *error = NULL;
446 adapter = GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (
447 g_object_new (GSIGNOND_TYPE_DBUS_AUTH_SESSION_ADAPTER,
448 "connection", connection, "auth-session", session, "app-context", app_context, NULL));
450 if (!adapter) return NULL;
452 nonce = gsignond_generate_nonce ();
453 object_path = g_strdup_printf ("%s/AuthSession_%s_%d",
454 GSIGNOND_DAEMON_OBJECTPATH,
458 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (adapter->priv->dbus_auth_session),
459 adapter->priv->connection,
462 ERR ("failed to register object: %s", error->message);
463 g_error_free (error);
464 g_free (object_path);
465 g_object_unref (adapter);
468 DBG("(+) '%s' object exported", object_path);
469 g_free (object_path);
471 gsignond_disposable_set_timeout (GSIGNOND_DISPOSABLE(adapter), timeout);
477 GSignondDbusAuthSessionAdapter *
478 gsignond_dbus_auth_session_adapter_new (GSignondAuthSession *session, const gchar *app_context, guint timeout)
480 GError *error = NULL;
481 GDBusConnection *connection = g_bus_get_sync (GSIGNOND_BUS_TYPE, NULL, &error);
483 ERR ("Error getting session bus :%s", error->message);
484 g_error_free (error);
488 return gsignond_dbus_auth_session_adapter_new_with_connection (connection, session, app_context, timeout);