7de4ef6260e1d41e2ee03587d07b721451c63fa4
[profile/ivi/gsignond.git] / src / daemon / dbus / gsignond-dbus-identity-adapter.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012-2013 Intel Corporation.
7  *
8  * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
9  *
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.
14  *
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.
19  *
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
23  * 02110-1301 USA
24  */
25
26 #include "config.h"
27 #include "gsignond/gsignond-log.h"
28 #include "gsignond/gsignond-utils.h"
29 #include "gsignond-dbus-identity-adapter.h"
30 #include "gsignond-dbus-auth-session-adapter.h"
31 #include "gsignond-dbus.h"
32
33 enum
34 {
35     PROP_0,
36
37     PROP_CONNECTION,
38     PROP_IDENTITY,
39     PROP_APP_CONTEXT,
40     N_PROPERTIES
41 };
42
43 static GParamSpec *properties[N_PROPERTIES];
44
45 typedef struct {
46     GSignondDbusIdentityAdapter *adapter;
47     GDBusMethodInvocation *invocation;
48     gpointer user_data;
49 } _IdentityDbusInfo;
50
51 static _IdentityDbusInfo*
52 _identity_dbus_info_new (GSignondDbusIdentityAdapter *self, GDBusMethodInvocation *invocation, gpointer userdata)
53 {
54     _IdentityDbusInfo *info = g_new0(_IdentityDbusInfo, 1);
55
56     info->adapter = g_object_ref (self);
57     info->invocation = g_object_ref (invocation);
58     info->user_data = userdata;
59
60     return info;
61 }
62
63 static void
64 _identity_dbus_info_free (_IdentityDbusInfo *info)
65 {
66     if (!info) return ;
67
68     if (info->adapter) g_object_unref (info->adapter);
69     if (info->invocation) g_object_unref (info->invocation);
70
71     g_free (info);
72 }
73
74 struct _GSignondDbusIdentityAdapterPrivate
75 {
76     GDBusConnection   *connection;
77     GSignondDbusIdentity *dbus_identity;
78     GSignondIdentity  *identity;
79     gchar *app_context;
80     GSignondSecurityContext *sec_context;
81     GList *sessions;
82     /* signal handler ids */
83     gulong info_updated_handler_id;
84     gulong verify_user_handler_id;
85     gulong verify_secret_handler_id;
86     gulong credentials_update_handler_id;
87 };
88
89 G_DEFINE_TYPE (GSignondDbusIdentityAdapter, gsignond_dbus_identity_adapter, GSIGNOND_TYPE_DISPOSABLE)
90
91 #define GSIGNOND_DBUS_IDENTITY_ADAPTER_GET_PRIV(obj) \
92         G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_DBUS_IDENTITY_ADAPTER, GSignondDbusIdentityAdapterPrivate)
93
94 #define PREPARE_SECURITY_CONTEXT(dbus_object, invocation) \
95 { \
96     GSignondDbusIdentityAdapterPrivate *priv = dbus_object->priv;\
97     GSignondAccessControlManager *acm = gsignond_identity_get_acm (priv->identity);\
98     if (acm) { \
99         const gchar *sender = NULL; \
100         int fd = -1; \
101         sender = g_dbus_method_invocation_get_sender (invocation);\
102         if (!sender) {\
103             GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation);\
104             fd = g_socket_get_fd (g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream(connection))));\
105         }\
106         gsignond_access_control_manager_security_context_of_peer( \
107             acm, \
108             priv->sec_context, \
109             fd, \
110             sender, \
111             priv->app_context); \
112     }\
113 }
114
115 static gboolean _handle_request_credentials_update (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, const gchar*, gpointer);
116 static gboolean _handle_get_info (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, gpointer);
117 static gboolean _handle_get_auth_session (GSignondDbusIdentityAdapter *self, GDBusMethodInvocation *invocation, const gchar *method, gpointer user_data);
118 static gboolean _handle_verify_user (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, GVariant *, gpointer);
119 static gboolean _handle_verify_secret (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, const gchar *, gpointer);
120 static gboolean _handle_remove (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, gpointer);
121 static gboolean _handle_sign_out (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, gpointer);
122 static gboolean _handle_store (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, const GVariant *, gpointer);
123 static gboolean _handle_add_reference (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, const gchar *, gpointer);
124 static gboolean _handle_remove_reference (GSignondDbusIdentityAdapter *, GDBusMethodInvocation *, const gchar *, gpointer);
125 static void _emit_info_updated (GSignondIdentity *identity, GSignondIdentityChangeType change, gpointer userdata);
126 static void _on_session_disposed (gpointer data, GObject *session);
127
128 static void
129 gsignond_dbus_identity_adapter_set_property (GObject *object,
130         guint property_id,
131         const GValue *value, GParamSpec *pspec)
132 {
133     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (object);
134
135     switch (property_id) {
136         case PROP_CONNECTION: {
137             self->priv->connection = g_value_get_object (value);
138             break;
139         }
140         case PROP_IDENTITY: {
141             gpointer identity = g_value_get_object (value);
142             if (identity) {
143                 if (self->priv->identity) {
144                     if (self->priv->info_updated_handler_id) {
145                         g_signal_handler_disconnect (self->priv->identity, self->priv->info_updated_handler_id);
146                         self->priv->info_updated_handler_id = 0;
147                     }
148                     if (self->priv->verify_user_handler_id) {
149                         g_signal_handler_disconnect (self->priv->identity, self->priv->verify_user_handler_id);
150                         self->priv->verify_user_handler_id = 0;
151                     }
152                     if (self->priv->verify_secret_handler_id) {
153                         g_signal_handler_disconnect (self->priv->identity, self->priv->verify_secret_handler_id);
154                         self->priv->verify_secret_handler_id = 0;
155                     }
156                     if (self->priv->credentials_update_handler_id) {
157                         g_signal_handler_disconnect (self->priv->identity, self->priv->credentials_update_handler_id);
158                         self->priv->credentials_update_handler_id = 0;
159                     }
160                     g_object_unref (self->priv->identity);
161                     self->priv->identity = NULL;
162                 }
163                 self->priv->identity = GSIGNOND_IDENTITY(identity);
164                 self->priv->info_updated_handler_id = g_signal_connect (
165                         self->priv->identity, "info-updated", G_CALLBACK (_emit_info_updated), self);
166             }
167             break;
168         }
169         case PROP_APP_CONTEXT: {
170             if (self->priv->app_context) g_free (self->priv->app_context);
171             self->priv->app_context = g_strdup (g_value_get_string (value));
172             break;
173         }
174         default:
175             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
176     }
177 }
178
179 static void
180 gsignond_dbus_identity_adapter_get_property (GObject *object,
181         guint property_id,
182         GValue *value, 
183         GParamSpec *pspec)
184 {
185     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (object);
186
187     switch (property_id) {
188         case PROP_IDENTITY:{
189             g_value_set_object (value, self->priv->identity);
190             break;
191         }
192         case PROP_CONNECTION: {
193             g_value_set_object (value, self->priv->connection);
194             break;
195         }
196         case PROP_APP_CONTEXT:{
197             g_value_set_string (value, self->priv->app_context);
198             break;
199         }
200         default:
201             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
202     }
203 }
204
205 static void
206 _destroy_session (gpointer data, gpointer user_data)
207 {
208     if (data && GSIGNOND_IS_DBUS_AUTH_SESSION_ADAPTER (data)) {
209         GObject *dbus_session = G_OBJECT (data);
210         g_object_weak_unref (dbus_session, _on_session_disposed, user_data);
211         gsignond_dbus_auth_session_adapter_abort_process (
212             GSIGNOND_DBUS_AUTH_SESSION_ADAPTER (dbus_session));
213         g_object_unref (dbus_session);
214     }
215 }
216
217 static void
218 gsignond_dbus_identity_adapter_dispose (GObject *object)
219 {
220     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (object);
221
222     if (self->priv->sessions) {
223         g_list_foreach (self->priv->sessions, _destroy_session, self);
224     }
225
226     if (self->priv->identity) {
227         if (self->priv->info_updated_handler_id) {
228             g_signal_handler_disconnect (self->priv->identity, self->priv->info_updated_handler_id);
229             self->priv->info_updated_handler_id = 0;
230         }
231         if (self->priv->verify_user_handler_id) {
232             g_signal_handler_disconnect (self->priv->identity, self->priv->verify_user_handler_id);
233             self->priv->verify_user_handler_id = 0;
234         }
235         if (self->priv->verify_secret_handler_id) {
236             g_signal_handler_disconnect (self->priv->identity, self->priv->verify_secret_handler_id);
237             self->priv->verify_secret_handler_id = 0;
238         }
239
240         if (self->priv->credentials_update_handler_id) {
241             g_signal_handler_disconnect (self->priv->identity, self->priv->credentials_update_handler_id);
242             self->priv->credentials_update_handler_id = 0;
243         }
244
245         g_object_unref (self->priv->identity);
246         self->priv->identity = NULL;
247     }
248
249     if (self->priv->dbus_identity) {
250         GDBusInterfaceSkeleton *iface = G_DBUS_INTERFACE_SKELETON(self->priv->dbus_identity);
251         gsignond_dbus_identity_emit_unregistered (self->priv->dbus_identity);
252         DBG("(-)'%s' object unexported", g_dbus_interface_skeleton_get_object_path (iface));
253         g_dbus_interface_skeleton_unexport (iface);
254         g_object_unref (self->priv->dbus_identity);
255         self->priv->dbus_identity = NULL;
256     }
257
258     if (self->priv->connection) {
259         g_object_unref (self->priv->connection);
260         self->priv->connection = NULL;
261     }
262
263     G_OBJECT_CLASS (gsignond_dbus_identity_adapter_parent_class)->dispose (object);
264 }
265
266 static void
267 gsignond_dbus_identity_adapter_finalize (GObject *object)
268 {
269     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (object);
270
271     if (self->priv->sec_context) {
272         gsignond_security_context_free (self->priv->sec_context);
273         self->priv->sec_context = NULL;
274     }
275
276     if (self->priv->sessions) {
277         g_list_free (self->priv->sessions);
278         self->priv->sessions = NULL;
279     }
280
281     if (self->priv->app_context) {
282         g_free (self->priv->app_context);
283         self->priv->app_context = NULL;
284     }
285
286     G_OBJECT_CLASS (gsignond_dbus_identity_adapter_parent_class)->finalize (object);
287 }
288
289 static void
290 gsignond_dbus_identity_adapter_class_init (GSignondDbusIdentityAdapterClass *klass)
291 {
292     GObjectClass* object_class = G_OBJECT_CLASS (klass);
293
294     g_type_class_add_private (object_class, sizeof (GSignondDbusIdentityAdapterPrivate));
295
296     object_class->get_property = gsignond_dbus_identity_adapter_get_property;
297     object_class->set_property = gsignond_dbus_identity_adapter_set_property;
298     object_class->dispose = gsignond_dbus_identity_adapter_dispose;
299     object_class->finalize = gsignond_dbus_identity_adapter_finalize;
300
301     properties[PROP_IDENTITY] = g_param_spec_object ("identity",
302                                                      "Core identity object",
303                                                      "Core Identity Object",
304                                                      GSIGNOND_TYPE_IDENTITY,
305                                                      G_PARAM_READWRITE |
306                                                      G_PARAM_CONSTRUCT_ONLY | 
307                                                      G_PARAM_STATIC_STRINGS);
308     properties[PROP_CONNECTION] = g_param_spec_object ("connection",
309                                                        "bus connection used",
310                                                        "Bus connection",
311                                                        G_TYPE_DBUS_CONNECTION,
312                                                        G_PARAM_READWRITE |
313                                                        G_PARAM_CONSTRUCT_ONLY |
314                                                        G_PARAM_STATIC_STRINGS);
315     properties[PROP_APP_CONTEXT] = g_param_spec_string (
316                 "app-context",
317                 "application security context",
318                 "Application security context of the identity object creater",
319                 NULL,
320                 G_PARAM_READWRITE |G_PARAM_STATIC_STRINGS);
321
322     g_object_class_install_properties (object_class, N_PROPERTIES, properties);
323 }
324
325 static void
326 gsignond_dbus_identity_adapter_init (GSignondDbusIdentityAdapter *self)
327 {
328     self->priv = GSIGNOND_DBUS_IDENTITY_ADAPTER_GET_PRIV(self);
329
330     self->priv->connection = 0;
331     self->priv->identity = 0;
332     self->priv->app_context = 0;
333     self->priv->dbus_identity = gsignond_dbus_identity_skeleton_new();
334     self->priv->sec_context = gsignond_security_context_new ();
335
336     g_signal_connect_swapped (self->priv->dbus_identity,
337             "handle-request-credentials-update", G_CALLBACK (_handle_request_credentials_update), self);
338     g_signal_connect_swapped (self->priv->dbus_identity,
339             "handle-get-info", G_CALLBACK(_handle_get_info), self);
340     g_signal_connect_swapped (self->priv->dbus_identity,
341             "handle-get-auth-session", G_CALLBACK(_handle_get_auth_session), self);
342     g_signal_connect_swapped (self->priv->dbus_identity,
343             "handle-verify-user", G_CALLBACK(_handle_verify_user), self);
344     g_signal_connect_swapped (self->priv->dbus_identity,
345             "handle-verify-secret", G_CALLBACK(_handle_verify_secret), self);
346     g_signal_connect_swapped (self->priv->dbus_identity,
347             "handle-remove", G_CALLBACK(_handle_remove), self);
348     g_signal_connect_swapped (self->priv->dbus_identity,
349             "handle-sign-out", G_CALLBACK(_handle_sign_out), self);
350     g_signal_connect_swapped (self->priv->dbus_identity,
351             "handle-store", G_CALLBACK(_handle_store), self);
352     g_signal_connect_swapped (self->priv->dbus_identity,
353             "handle-add-reference", G_CALLBACK(_handle_add_reference), self);
354     g_signal_connect_swapped (self->priv->dbus_identity,
355             "handle-remove-reference", G_CALLBACK(_handle_remove_reference), self);
356 }
357
358 static void
359 _on_credentials_updated (_IdentityDbusInfo *info, guint32 updated_id, GError *error, gpointer userdata)
360 {
361     g_assert (info);
362     
363     GSignondDbusIdentityAdapter *self = info->adapter;
364     GDBusMethodInvocation *invocation = info->invocation;
365
366     g_signal_handler_disconnect (userdata, self->priv->credentials_update_handler_id);
367     self->priv->credentials_update_handler_id = 0;
368     if (error) {
369         g_dbus_method_invocation_return_gerror (invocation, error);
370         g_error_free (error);
371     }
372     else
373     {
374         gsignond_dbus_identity_complete_request_credentials_update (
375                 self->priv->dbus_identity, invocation, updated_id);
376     }
377
378     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
379
380     _identity_dbus_info_free (info);
381 }
382
383 static gboolean
384 _handle_request_credentials_update (GSignondDbusIdentityAdapter *self,
385                                     GDBusMethodInvocation *invocation,
386                                     const gchar *message,
387                                     gpointer user_data)
388 {
389     GError *error = NULL;
390
391     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
392
393     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
394
395     PREPARE_SECURITY_CONTEXT (self, invocation);
396
397     gsignond_identity_request_credentials_update (self->priv->identity, message, self->priv->sec_context, &error);
398     if (error) {
399         g_dbus_method_invocation_return_gerror (invocation, error);
400         g_error_free (error);
401  
402         gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
403     }
404     else {
405         self->priv->credentials_update_handler_id = g_signal_connect_swapped (self->priv->identity,
406             "credentials-updated", G_CALLBACK (_on_credentials_updated), self);
407     }
408
409     return TRUE;
410 }
411
412 static gboolean
413 _handle_get_info (GSignondDbusIdentityAdapter *self,
414                   GDBusMethodInvocation *invocation,
415                   gpointer user_data)
416 {
417     GVariant *identity_data = 0;
418     GError *error = NULL;
419
420     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
421
422     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
423
424     PREPARE_SECURITY_CONTEXT (self, invocation);
425     
426     identity_data = gsignond_identity_get_info (self->priv->identity, 
427         self->priv->sec_context, &error);
428
429     if (identity_data) {
430         gsignond_dbus_identity_complete_get_info (
431             self->priv->dbus_identity, invocation, identity_data);
432     }
433     else {
434         g_dbus_method_invocation_return_gerror (invocation, error);
435         g_error_free (error);
436     }
437
438     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
439
440     return TRUE;
441 }
442
443 static void
444 _on_session_disposed (gpointer data, GObject *session)
445 {
446     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (data);
447
448     if (!self) return;
449
450     self->priv->sessions = g_list_remove (self->priv->sessions, session);
451
452     if (g_list_length (self->priv->sessions) == 0){
453         gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE(self), TRUE);
454     }
455 }
456
457 static gboolean
458 _handle_get_auth_session (GSignondDbusIdentityAdapter *self,
459                           GDBusMethodInvocation *invocation,
460                           const gchar *method,
461                           gpointer user_data)
462 {
463     GSignondAuthSession *session = NULL;
464     GError *error = NULL;
465
466     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
467
468     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
469
470     PREPARE_SECURITY_CONTEXT (self, invocation);
471
472     session = gsignond_identity_get_auth_session (self->priv->identity, method, self->priv->sec_context, &error);
473
474     if (session) {
475         guint timeout =gsignond_identity_get_auth_session_timeout (self->priv->identity);
476         GSignondDbusAuthSessionAdapter *dbus_session = gsignond_dbus_auth_session_adapter_new_with_connection (
477             g_object_ref (self->priv->connection), session, self->priv->app_context, timeout);
478
479         if (g_list_length (self->priv->sessions) == 0)
480             gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
481
482         self->priv->sessions = g_list_append (self->priv->sessions, dbus_session);
483
484         g_object_weak_ref (G_OBJECT (dbus_session), _on_session_disposed, self);
485
486         gsignond_dbus_identity_complete_get_auth_session (
487             self->priv->dbus_identity, invocation, 
488             gsignond_dbus_auth_session_adapter_get_object_path (dbus_session));
489     }
490     else {
491         g_dbus_method_invocation_return_gerror (invocation, error);
492         g_error_free (error);
493     }
494
495     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE(self), TRUE);
496
497     return TRUE;
498 }
499
500 static void
501 _on_user_verfied (_IdentityDbusInfo *info, gboolean res, const GError *error, gpointer user_data)
502 {
503     if (!info) {
504         WARN ("assertion G_UNLIKELY (info) failed");
505         return ;
506     }
507
508     GSignondDbusIdentityAdapter *self = info->adapter;
509     GDBusMethodInvocation *invocation = info->invocation;
510
511     g_signal_handler_disconnect (user_data, self->priv->verify_user_handler_id);
512     self->priv->verify_user_handler_id = 0;
513
514     if (error) {
515         g_dbus_method_invocation_return_gerror (invocation, error);
516     }
517     else {
518         gsignond_dbus_identity_complete_verify_user (
519             self->priv->dbus_identity, invocation, res);
520     }
521
522     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
523
524     _identity_dbus_info_free (info);
525 }
526
527 static gboolean
528 _handle_verify_user (GSignondDbusIdentityAdapter *self,
529                      GDBusMethodInvocation *invocation,
530                      GVariant *params,
531                      gpointer user_data)
532 {
533     GError *error = NULL;
534
535     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
536
537     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
538
539     PREPARE_SECURITY_CONTEXT (self, invocation);
540
541     gsignond_identity_verify_user (self->priv->identity, params, self->priv->sec_context, &error);
542
543     if (error) {
544         g_dbus_method_invocation_return_gerror (invocation, error);
545         g_error_free (error);
546
547         gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
548     }
549     else {
550         _IdentityDbusInfo *info = _identity_dbus_info_new (self, invocation, NULL);
551
552         /* FIXME: Do we allow multiple calls at a given point of time */
553         self->priv->verify_user_handler_id = g_signal_connect_swapped (self->priv->identity, 
554                     "user-verified", G_CALLBACK (_on_user_verfied), (gpointer)info);
555     }
556
557     return TRUE;
558 }
559
560 static void
561 _on_secret_verfied (_IdentityDbusInfo *info, gboolean res, const GError *error, gpointer user_data)
562 {
563     g_assert (info);
564
565     GSignondDbusIdentityAdapter *self = info->adapter;
566     GDBusMethodInvocation *invocation = info->invocation;
567
568     g_signal_handler_disconnect (user_data, self->priv->verify_secret_handler_id);
569     self->priv->verify_secret_handler_id = 0;
570
571     if (error) {
572         g_dbus_method_invocation_return_gerror (info->invocation, error);
573     }
574     else {
575         gsignond_dbus_identity_complete_verify_secret (
576             self->priv->dbus_identity, invocation, res);
577     }
578
579     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE(self), TRUE);
580
581     _identity_dbus_info_free (info);
582 }
583
584 static gboolean
585 _handle_verify_secret (GSignondDbusIdentityAdapter *self,
586                       GDBusMethodInvocation *invocation,
587                       const gchar *secret,
588                       gpointer user_data)
589 {
590     GError *error = NULL;
591
592     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
593
594     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
595
596     PREPARE_SECURITY_CONTEXT (self, invocation);
597     
598     gsignond_identity_verify_secret (self->priv->identity, secret, self->priv->sec_context, &error);
599
600     if (error) {
601         g_dbus_method_invocation_return_gerror (invocation, error);
602         g_error_free (error);
603         gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
604     }
605     else {
606         _IdentityDbusInfo *info = _identity_dbus_info_new (self, invocation, NULL);
607
608         self->priv->verify_secret_handler_id = g_signal_connect_swapped (self->priv->identity, 
609                 "secret-verified", G_CALLBACK (_on_secret_verfied), (gpointer)info);
610     }
611
612     return TRUE;
613 }
614
615 static gboolean 
616 _handle_remove (GSignondDbusIdentityAdapter   *self,
617                 GDBusMethodInvocation *invocation,
618                 gpointer               user_data)
619 {
620     GError *error = NULL;
621  
622     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
623
624     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
625
626     PREPARE_SECURITY_CONTEXT (self, invocation);
627
628     if (!gsignond_identity_remove (self->priv->identity, self->priv->sec_context, &error)) {
629         g_dbus_method_invocation_return_gerror (invocation, error);
630         g_error_free (error);
631     }
632     else {
633         gsignond_dbus_identity_complete_remove (self->priv->dbus_identity, invocation);
634     }
635
636     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
637
638     return TRUE;
639 }
640
641 static gboolean
642 _handle_sign_out (GSignondDbusIdentityAdapter *self,
643                   GDBusMethodInvocation *invocation,
644                   gpointer user_data)
645 {
646     GError *error = NULL;
647     gboolean res;
648  
649     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
650
651     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
652
653     PREPARE_SECURITY_CONTEXT (self, invocation);
654
655     res = gsignond_identity_sign_out (self->priv->identity, self->priv->sec_context, &error);
656
657     if (!error) {
658         gsignond_dbus_identity_complete_sign_out (self->priv->dbus_identity, invocation, res);
659     }
660     else {
661         g_dbus_method_invocation_return_gerror (invocation, error);
662         g_error_free (error);
663     }
664
665     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
666
667     return TRUE;
668 }
669
670 static gboolean
671 _handle_store (GSignondDbusIdentityAdapter *self,
672                GDBusMethodInvocation *invocation,
673                const GVariant *info,
674                gpointer user_data)
675 {
676     guint id = 0;
677     GError *error = NULL;
678
679     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
680
681     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
682
683     PREPARE_SECURITY_CONTEXT (self, invocation);
684
685     id = gsignond_identity_store (self->priv->identity, info, self->priv->sec_context, &error);
686
687     if (id) {
688         gsignond_dbus_identity_complete_store (self->priv->dbus_identity, invocation, id);
689     } else {
690         g_dbus_method_invocation_return_gerror (invocation, error);
691         g_error_free (error);
692     }
693
694     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
695
696     return TRUE;
697 }
698
699 static gboolean
700 _handle_add_reference (GSignondDbusIdentityAdapter *self,
701                        GDBusMethodInvocation *invocation,
702                        const gchar *reference,
703                        gpointer user_data)
704 {
705     guint32 id = 0;
706     GError *error = NULL;
707
708     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
709
710     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
711
712     PREPARE_SECURITY_CONTEXT (self, invocation);
713
714     id = gsignond_identity_add_reference (self->priv->identity, reference, self->priv->sec_context, &error);
715
716     if (id) {
717         gsignond_dbus_identity_complete_add_reference (self->priv->dbus_identity, invocation, id);
718     }
719     else {
720         g_dbus_method_invocation_return_gerror (invocation, error);
721         g_error_free (error);
722     }
723
724     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
725
726     return TRUE;
727 }
728
729 static gboolean
730 _handle_remove_reference (GSignondDbusIdentityAdapter *self,
731                           GDBusMethodInvocation *invocation,
732                           const gchar *reference,
733                           gpointer user_data)
734 {
735     guint32 id = 0;
736     GError *error = NULL;
737
738     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), FALSE);
739
740     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), FALSE);
741
742     PREPARE_SECURITY_CONTEXT (self, invocation);
743
744     id = gsignond_identity_remove_reference (self->priv->identity, reference, self->priv->sec_context, &error);
745
746     if (id) {
747         gsignond_dbus_identity_complete_remove_reference (self->priv->dbus_identity, invocation, id);
748     } else {
749         g_dbus_method_invocation_return_gerror (invocation, error);
750         g_error_free (error);
751     }
752
753     gsignond_disposable_set_auto_dispose (GSIGNOND_DISPOSABLE (self), TRUE);
754
755     return TRUE;
756 }
757
758 static void
759 _emit_info_updated (GSignondIdentity *identity,
760                    GSignondIdentityChangeType change,
761                    gpointer userdata)
762 {
763     GSignondDbusIdentityAdapter *self = GSIGNOND_DBUS_IDENTITY_ADAPTER (userdata);
764
765     gsignond_dbus_identity_emit_info_updated (self->priv->dbus_identity, change);
766
767     if (change == GSIGNOND_IDENTITY_REMOVED)
768         gsignond_disposable_delete_later (GSIGNOND_DISPOSABLE (self));
769     else if (change == GSIGNOND_IDENTITY_SIGNED_OUT && self->priv->sessions) {
770         /* destroy all sessions on this identity as it's signed out */
771         g_list_foreach (self->priv->sessions, _destroy_session, NULL);
772         g_list_free (self->priv->sessions);
773         self->priv->sessions = NULL;
774     }
775 }
776
777 const gchar *
778 gsignond_dbus_identity_adapter_get_object_path(GSignondDbusIdentityAdapter *self)
779 {
780     g_return_val_if_fail (self && GSIGNOND_IS_DBUS_IDENTITY_ADAPTER (self), NULL);
781
782     return g_dbus_interface_skeleton_get_object_path (
783                 G_DBUS_INTERFACE_SKELETON (self->priv->dbus_identity));
784 }
785
786 GSignondDbusIdentityAdapter *
787 gsignond_dbus_identity_adapter_new_with_connection (GDBusConnection *connection,
788                                                     GSignondIdentity *identity,
789                                                     const gchar *app_context,
790                                                     guint timeout)
791 {
792     static guint32 object_counter = 0;
793     gchar *nonce;
794     gchar *object_path = NULL;
795     GError *err = NULL;
796     GSignondDbusIdentityAdapter *adapter = GSIGNOND_DBUS_IDENTITY_ADAPTER (
797         g_object_new (GSIGNOND_TYPE_DBUS_IDENTITY_ADAPTER, 
798             "identity", identity, "connection", connection, "app-context", app_context, NULL));
799
800     if (!adapter) return NULL;
801
802     nonce = gsignond_generate_nonce ();
803     object_path = g_strdup_printf ("%s/Identity_%s_%d",
804                                    GSIGNOND_DAEMON_OBJECTPATH,
805                                    nonce,
806                                    object_counter++);
807     g_free (nonce);
808
809     if (!g_dbus_interface_skeleton_export (
810             G_DBUS_INTERFACE_SKELETON (adapter->priv->dbus_identity),
811             adapter->priv->connection, object_path, &err)) {
812         ERR ("failed to register object: %s", err->message);
813         g_error_free (err);
814         g_free (object_path);
815         g_object_unref (adapter);
816
817         return NULL;
818     }
819     DBG("(+)'%s' object exported(%p)", object_path, adapter);
820     g_free (object_path);
821
822     gsignond_disposable_set_timeout (GSIGNOND_DISPOSABLE (adapter), timeout);
823
824     return adapter;
825 }
826
827 #ifndef USE_P2P
828 /**
829  * gsignond_dbus_identity_adapter_new:
830  * @impl: Instance of #GSignondDbusIdentityAdapter
831  *
832  * Creates new instance of #GSignondDbusIdentityAdapter 
833  *
834  * Retrurns: (transfer full) new instance of #GSignondDbusIdentityAdapter
835  */
836 GSignondDbusIdentityAdapter * 
837 gsignond_dbus_identity_adapter_new (GSignondIdentity *identity, const gchar *app_context, guint timeout)
838 {
839     GError *error = NULL;
840     GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
841
842     if (error) {
843         ERR("failed to connect to session bus : %s", error->message);
844         g_error_free (error);
845         return NULL;
846     }
847
848     return gsignond_dbus_identity_adapter_new_with_connection (connection, identity, app_context, timeout);
849 }
850
851 #endif
852 #undef PREPARE_SECURITY_CONTEXT