Update to upstream 1.0.1
[profile/ivi/gsignond.git] / src / daemon / gsignond-daemon.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: Jussi Laako <jussi.laako@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 <gmodule.h>
27
28 #include "config.h"
29
30 #include "gsignond-daemon.h"
31
32 #include "gsignond/gsignond-config.h"
33 #include "gsignond/gsignond-log.h"
34 #include "gsignond/gsignond-error.h"
35 #include "gsignond/gsignond-extension-interface.h"
36 #include "gsignond/gsignond-utils.h"
37 #include "daemon/gsignond-identity.h"
38 #include "daemon/db/gsignond-db-credentials-database.h"
39
40 struct _GSignondDaemonPrivate
41 {
42     GSignondConfig      *config;
43     GHashTable          *identities;
44     GModule             *extension_module;
45     GSignondExtension   *extension;
46     GSignondStorageManager *storage_manager;
47     GSignondSecretStorage *secret_storage;
48     GSignondDbCredentialsDatabase *db;
49     GSignondAccessControlManager *acm;
50     GSignondPluginProxyFactory *plugin_proxy_factory;
51     GSignondSignonuiProxy *ui;
52 };
53
54 G_DEFINE_TYPE (GSignondDaemon, gsignond_daemon, G_TYPE_OBJECT)
55
56
57 #define GSIGNOND_DAEMON_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_DAEMON, GSignondDaemonPrivate)
58
59 static GObject *self = 0;
60
61 static GObject*
62 _constructor (GType type,
63               guint n_construct_params,
64               GObjectConstructParam *construct_params)
65 {
66     /*
67      * Signleton daemon
68      */
69     if (!self) {
70         self = G_OBJECT_CLASS (gsignond_daemon_parent_class)->constructor (
71                   type, n_construct_params, construct_params);
72         g_object_add_weak_pointer (self, (gpointer) &self);
73     }
74     else {
75         g_object_ref (self);
76     }
77
78     return self;
79 }
80
81 void
82 _free_identity (gpointer data, gpointer user_data)
83 {
84     (void) user_data;
85     GObject *identity = G_OBJECT (data);
86
87     DBG ("free identity %p", identity);
88     g_object_unref (identity);
89 }
90
91 static void
92 _dispose (GObject *object)
93 {
94     GSignondDaemon *self = GSIGNOND_DAEMON(object);
95
96     if (self->priv->ui) {
97         g_object_unref (self->priv->ui);
98         self->priv->ui = NULL;
99     }
100
101     if (self->priv->plugin_proxy_factory) {
102         g_object_unref (self->priv->plugin_proxy_factory);
103         self->priv->plugin_proxy_factory = NULL;
104     }
105
106     if (self->priv->identities) {
107         g_hash_table_unref (self->priv->identities);
108         self->priv->identities = NULL;
109     }
110
111     if (self->priv->db) {
112  
113         if (!gsignond_db_credentials_database_close_secret_storage (
114                     self->priv->db)) {
115             WARN("gsignond_db_credentials_database_close_secret_storage() failed");
116         }   
117         g_object_unref (self->priv->db);
118         self->priv->db = NULL;
119     }
120
121     if (self->priv->extension) {
122         if (gsignond_storage_manager_filesystem_is_mounted (
123                     self->priv->storage_manager)) {
124             if (!gsignond_storage_manager_unmount_filesystem (
125                         self->priv->storage_manager)) {
126                 WARN("gsignond_storage_manager_unmount_filesystem() failed");
127             }
128         }
129
130         self->priv->storage_manager = NULL;
131         self->priv->secret_storage = NULL;
132         self->priv->acm = NULL;
133         g_object_unref (self->priv->extension);
134         self->priv->extension = NULL;
135     }
136
137     if (self->priv->extension_module) {
138         g_module_close (self->priv->extension_module);
139         self->priv->extension_module = NULL;
140     }
141
142     if (self->priv->config) {
143         g_object_unref (self->priv->config);
144         self->priv->config = NULL;
145     }
146
147     G_OBJECT_CLASS (gsignond_daemon_parent_class)->dispose (object);
148 }
149
150 static void
151 _finalize (GObject *object)
152 {
153     G_OBJECT_CLASS (gsignond_daemon_parent_class)->finalize (object);
154 }
155
156 static gboolean
157 _init_extension (GSignondDaemon *self)
158 {
159     guint32 ext_ver = gsignond_extension_get_version (self->priv->extension);
160
161     DBG ("Initializing extension '%s' %d.%d.%d.%d",
162          gsignond_extension_get_name (self->priv->extension),
163          (ext_ver >> 24),
164          (ext_ver >> 16) & 0xff,
165          (ext_ver >> 8) & 0xff,
166          ext_ver & 0xff);
167
168     self->priv->storage_manager =
169         gsignond_extension_get_storage_manager (self->priv->extension,
170                                                 self->priv->config);
171     self->priv->secret_storage =
172         gsignond_extension_get_secret_storage (self->priv->extension,
173                                                self->priv->config);
174     self->priv->acm =
175         gsignond_extension_get_access_control_manager (self->priv->extension,
176                                                        self->priv->config);
177
178     g_return_val_if_fail (self->priv->storage_manager &&
179                           self->priv->secret_storage &&
180                           self->priv->acm,
181                           FALSE);
182
183     return TRUE;
184 }
185
186 static void
187 _on_extension_dispose (gpointer data, GObject *object)
188 {
189     if (data) *(GSignondExtension **)data = NULL;
190 }
191
192 static GSignondExtension * _default_extension_init ()
193 {
194     static GSignondExtension *default_extension = NULL;
195
196     if (!default_extension) {
197         default_extension =
198             g_object_new (GSIGNOND_TYPE_EXTENSION, NULL);
199         
200         g_object_weak_ref (G_OBJECT (default_extension),
201                            _on_extension_dispose,
202                            &default_extension);
203     }
204
205     return default_extension;
206 }
207
208
209 static gboolean
210 _init_extensions (GSignondDaemon *self)
211 {
212     gboolean res = TRUE;
213     gboolean symfound;
214     const gchar *ext_path = GSIGNOND_EXTENSIONS_DIR;
215     const gchar *ext_name;
216     gchar *mod_name;
217     gchar *mod_filename;
218     gchar *initf_name;
219     GSignondExtension* (*ext_init) (void);
220
221 #   ifdef ENABLE_DEBUG
222     const gchar *env_val = g_getenv ("SSO_EXTENSIONS_DIR");
223     if (env_val)
224         ext_path = env_val;
225 #   endif
226     ext_name = gsignond_config_get_string (self->priv->config,
227         GSIGNOND_CONFIG_GENERAL_EXTENSION);
228     if (ext_name && !ext_path) return FALSE;
229
230     if (ext_name && g_strcmp0 (ext_name, "default") != 0) {
231         mod_name = g_strdup_printf ("extension-%s", ext_name);
232         mod_filename = g_module_build_path (ext_path, mod_name);
233         g_free (mod_name);
234         if (!mod_filename) return FALSE;
235         DBG ("Loading extension '%s'", mod_filename);
236         self->priv->extension_module =
237             g_module_open (mod_filename, G_MODULE_BIND_LOCAL);
238         g_free (mod_filename);
239         if (!self->priv->extension_module) {
240             DBG("failed to load module : %s", g_module_error());
241             return FALSE;
242         }
243         initf_name = g_strdup_printf ("%s_extension_init", ext_name);
244         symfound = g_module_symbol (self->priv->extension_module,
245                                     initf_name,
246                                     (gpointer *) &ext_init);
247         g_free(initf_name);
248         if (!symfound) {
249             g_module_close (self->priv->extension_module);
250             self->priv->extension_module = NULL;
251             return FALSE;
252         }
253     } else {
254         ext_init = _default_extension_init;
255     }
256     self->priv->extension = ext_init ();
257     g_return_val_if_fail (self->priv->extension &&
258                           GSIGNOND_IS_EXTENSION (self->priv->extension),
259                           FALSE);
260
261     res = _init_extension (self);
262
263     return res;
264 }
265
266 static gboolean
267 _init_storage (GSignondDaemon *self)
268 {
269     const gchar *storage_location;
270
271     DBG("Initializing storage");
272
273     if (!gsignond_storage_manager_storage_is_initialized (
274                                                  self->priv->storage_manager)) {
275         if (!gsignond_storage_manager_initialize_storage (
276                                                    self->priv->storage_manager))
277             return FALSE;
278     }
279
280     storage_location = gsignond_storage_manager_mount_filesystem (
281                                                    self->priv->storage_manager);
282     if (storage_location == NULL)
283         return FALSE;
284     gsignond_config_set_string (self->priv->config, 
285         GSIGNOND_CONFIG_GENERAL_SECURE_DIR, storage_location);                                                 
286
287     return (storage_location != NULL);
288 }
289
290 static gboolean
291 _open_database (GSignondDaemon *self)
292 {
293     DBG("Open databases");
294
295     self->priv->db = gsignond_db_credentials_database_new (self->priv->config,
296                                                     self->priv->secret_storage);
297     if (!self->priv->db)
298         return FALSE;
299
300     return gsignond_db_credentials_database_open_secret_storage (
301                                                                 self->priv->db);
302 }
303
304 static gboolean
305 _clear_identity (gpointer idp, gpointer identityp, gpointer user_data)
306 {
307     (void) user_data;
308
309     return gsignond_identity_clear (GSIGNOND_IDENTITY (identityp));
310 }
311
312 static void
313 gsignond_daemon_init (GSignondDaemon *self)
314 {
315     self->priv = GSIGNOND_DAEMON_PRIV(self);
316
317     self->priv->config = gsignond_config_new ();
318     self->priv->identities = g_hash_table_new_full (
319             g_direct_hash, g_direct_equal, NULL, NULL);
320     self->priv->plugin_proxy_factory = gsignond_plugin_proxy_factory_new(
321         self->priv->config);
322     
323     if (!_init_extensions (self))
324         ERR("gsignond_daemon_init_extensions() failed");
325
326     if (!_init_storage (self))
327         ERR("gsignond_daemon_init_storage() failed");
328     if (!_open_database (self))
329         ERR("gisgnond_daemon_open_database() failed");
330
331     self->priv->ui = gsignond_signonui_proxy_new ();
332 }
333
334 static void
335 gsignond_daemon_class_init (GSignondDaemonClass *klass)
336 {
337     GObjectClass* object_class = G_OBJECT_CLASS (klass);
338
339     g_type_class_add_private (object_class, sizeof (GSignondDaemonPrivate));
340
341     object_class->constructor = _constructor;
342     object_class->dispose = _dispose;
343     object_class->finalize = _finalize;
344 }
345
346 static gboolean
347 _compare_identity_by_pointer (gpointer key, gpointer value, gpointer dead_object)
348 {
349     return value == dead_object;
350 }
351
352 static void
353 _on_identity_disposed (gpointer data, GObject *object)
354 {
355     GSignondDaemon *daemon = GSIGNOND_DAEMON (data);
356
357     DBG ("daemon %p identity %p disposed", daemon, object);
358     g_hash_table_foreach_remove (daemon->priv->identities,
359                 _compare_identity_by_pointer, object);
360 }
361
362 guint32
363 gsignond_daemon_store_identity (GSignondDaemon *daemon, GSignondIdentity *identity)
364 {
365     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), 0);
366     g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), 0);
367
368     GSignondIdentityInfo *info = NULL;
369     guint32 id = 0;
370     gboolean was_new_identity = FALSE;
371     
372     info = gsignond_identity_get_identity_info(identity);
373     if (!info) return 0;
374     
375     was_new_identity = gsignond_identity_info_get_is_identity_new (info);
376
377     id = gsignond_db_credentials_database_update_identity (daemon->priv->db, info);
378
379     if (was_new_identity && id) {
380         g_hash_table_insert (daemon->priv->identities, GUINT_TO_POINTER(id), identity);
381         g_object_weak_ref (G_OBJECT (identity), _on_identity_disposed, daemon);
382     }
383
384     return id;
385 }
386
387 gboolean
388 gsignond_daemon_remove_identity (GSignondDaemon *daemon, guint32 id)
389 {
390     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
391
392     return gsignond_db_credentials_database_remove_identity(daemon->priv->db, id);
393 }
394
395 guint32
396 gsignond_daemon_add_identity_reference (GSignondDaemon *daemon, guint32 identity_id, const GSignondSecurityContext *owner, const gchar *reference)
397 {
398     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), 0);
399
400     return gsignond_db_credentials_database_insert_reference (daemon->priv->db, identity_id, owner, reference);
401 }
402
403 gboolean
404 gsignond_daemon_remove_identity_reference (GSignondDaemon *daemon, guint32 identity_id, const GSignondSecurityContext *owner, const gchar *reference)
405 {
406     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
407
408     return gsignond_db_credentials_database_remove_reference (daemon->priv->db, identity_id, owner, reference);
409 }
410
411 gboolean
412 gsignond_daemon_store_identity_data (GSignondDaemon *daemon, guint32 identity_id, const gchar *method, GSignondDictionary *data)
413 {
414     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
415
416     return gsignond_db_credentials_database_update_data (daemon->priv->db, identity_id, method, data);
417 }
418
419 gboolean
420 gsignond_daemon_clear_identity_data (GSignondDaemon *daemon, guint32 identity_id)
421 {
422     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
423
424     return gsignond_db_credentials_database_remove_data (daemon->priv->db, identity_id, NULL);
425 }
426
427 GSignondDictionary *
428 gsignond_daemon_load_identity_data (GSignondDaemon *daemon, guint32 identity_id, const gchar *method)
429 {
430     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), NULL);
431     g_return_val_if_fail (identity_id, NULL);
432     g_return_val_if_fail (method, NULL);
433
434     return gsignond_db_credentials_database_load_data (daemon->priv->db, identity_id, method);
435 }
436
437 GSignondIdentity *
438 gsignond_daemon_register_new_identity (GSignondDaemon *daemon,
439                                        const GSignondSecurityContext *ctx,
440                                        GError **error) 
441 {
442     if (!daemon || !GSIGNOND_IS_DAEMON (daemon) || !ctx) {
443         WARN ("assertion failed (daemon && GSIGNOND_IS_DAEMON (daemon)) failed");
444         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
445         return NULL;
446     }
447
448     GSignondIdentityInfo *info = gsignond_identity_info_new ();
449     GSignondIdentity *identity = NULL;
450     GSignondSecurityContext *owner = NULL;
451     GSignondSecurityContextList *acl = NULL;
452
453     owner = gsignond_security_context_copy (ctx);
454
455     gsignond_identity_info_set_owner (info, owner);
456
457     acl = (GSignondSecurityContextList *)g_list_append (NULL, owner);
458     gsignond_identity_info_set_access_control_list (info, acl);
459     gsignond_security_context_free (owner);
460     g_list_free (acl);
461
462     DBG("register_new_identity: cache size : %d", g_hash_table_size(daemon->priv->identities));
463     identity = gsignond_identity_new (daemon, info);
464     if (identity == NULL) {
465         gsignond_identity_info_unref (info);
466         ERR("Unable to register new identity");
467         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, "Internal server error");
468         return NULL;
469     }
470     DBG(" --- registered new identity : %p", identity);
471     return identity;
472 }
473
474 GSignondIdentity *
475 gsignond_daemon_get_identity (GSignondDaemon *daemon,
476                               const guint32 id,
477                               const GSignondSecurityContext *ctx,
478                               GError **error)
479 {
480     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
481         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON (daemon)) failed");
482         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
483         return NULL;
484     }
485     if (id <= 0) {
486         WARN ("client provided invalid identity id");
487         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Invalid identity id");
488         return NULL;
489     }
490
491     GSignondIdentity *identity = NULL;
492     GSignondIdentityInfo *identity_info = NULL;
493
494 #define VALIDATE_IDENTITY_READ_ACCESS(info, ctx, ret) \
495 { \
496     GSignondAccessControlManager *acm = daemon->priv->acm; \
497     GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (info); \
498     GSignondSecurityContext *owner = gsignond_identity_info_get_owner (info); \
499     gboolean valid = gsignond_access_control_manager_peer_is_allowed_to_use_identity (acm, ctx, owner, acl); \
500     gsignond_security_context_free (owner); \
501     gsignond_security_context_list_free (acl); \
502     if (!valid) { \
503         WARN ("identity access check failed"); \
504         gsignond_identity_info_unref (info); \
505         if (error) { \
506             *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "Can not read identity"); \
507         } \
508         return ret; \
509     } \
510 }
511     DBG("Get identity for id '%d'\n cache size : %d", id, g_hash_table_size(daemon->priv->identities));
512     identity = GSIGNOND_IDENTITY(g_hash_table_lookup (daemon->priv->identities, GUINT_TO_POINTER(id)));
513     if (identity) {
514         identity_info = gsignond_identity_get_identity_info (identity);
515         gsignond_identity_info_ref (identity_info);
516         VALIDATE_IDENTITY_READ_ACCESS (identity_info, ctx, NULL);
517         DBG ("using cased Identity '%p' for id %d", identity, id);
518         gsignond_identity_info_unref (identity_info);
519
520         return GSIGNOND_IDENTITY (g_object_ref (identity));
521     }
522
523     /* identity not found in cache, so try to load form db */
524     identity_info = gsignond_db_credentials_database_load_identity (
525                             daemon->priv->db, id, TRUE);
526     if (!identity_info) {
527         if (error)  {
528             const GError *err = gsignond_db_credentials_database_get_last_error (daemon->priv->db);
529             *error = err ? g_error_copy (err) : gsignond_get_gerror_for_id (
530                         GSIGNOND_ERROR_IDENTITY_NOT_FOUND, "identity not found with id '%d'", id);
531         }
532         return NULL;
533     }
534
535     VALIDATE_IDENTITY_READ_ACCESS (identity_info, ctx, NULL);
536
537     identity = gsignond_identity_new (daemon, identity_info);
538     if (!identity) {
539         gsignond_identity_info_unref (identity_info);
540         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, "Internal server error");
541         return NULL;
542     }
543
544     g_hash_table_insert (daemon->priv->identities, GUINT_TO_POINTER(id), identity);
545     g_object_weak_ref (G_OBJECT (identity), _on_identity_disposed, daemon);
546
547     DBG("created new identity '%p' for id '%d'", identity, id);
548
549     return identity;
550
551 #undef VALIDATE_IDENTITY_READ_ACCESS
552 }
553
554 const gchar ** 
555 gsignond_daemon_query_methods (GSignondDaemon *daemon, GError **error)
556 {
557     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
558         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON(daemon)) failed");
559         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
560         return NULL;
561     }
562
563     return gsignond_plugin_proxy_factory_get_plugin_types (
564             daemon->priv->plugin_proxy_factory);
565 }
566
567 const gchar ** 
568 gsignond_daemon_query_mechanisms (GSignondDaemon *daemon, const gchar *method, GError **error) 
569 {
570     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
571         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON(daemon)) failed");
572         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
573         return NULL;
574     }
575
576     const gchar **mechanisms = gsignond_plugin_proxy_factory_get_plugin_mechanisms (
577             daemon->priv->plugin_proxy_factory, method);
578
579     if (!mechanisms || mechanisms[0] == NULL) {
580         DBG("no mechanisms found for method '%s'", method);
581         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN, "method '%s' not found", method);
582     }
583
584     return mechanisms;
585 }
586
587 static gboolean
588 _check_keychain_access (GSignondDaemon *self,
589                         const GSignondSecurityContext *ctx,
590                         GError **error)
591 {
592     GSignondAccessControlManager *acm = self->priv->acm;
593     GSignondSecurityContext *keychain =
594         gsignond_access_control_manager_security_context_of_keychain (acm);
595     gboolean has_access =
596         (gsignond_security_context_compare (keychain, ctx) == 0);
597     DBG ("keychain access compare [%s:%s] vs [%s:%s] = %d",
598          gsignond_security_context_get_system_context (keychain),
599          gsignond_security_context_get_application_context (keychain),
600          gsignond_security_context_get_system_context (ctx),
601          gsignond_security_context_get_application_context (ctx),
602          has_access);
603     gsignond_security_context_free (keychain);
604     if (!has_access) {
605         WARN ("keychain access check failed");
606         if (error) {
607             *error = gsignond_get_gerror_for_id (
608                                     GSIGNOND_ERROR_PERMISSION_DENIED,
609                                     "Can not access keychain functionality");
610         }
611     }
612     return has_access;
613 }
614
615 GSignondIdentityInfoList *
616 gsignond_daemon_query_identities (GSignondDaemon *self,
617                                   GVariant *filter,
618                                   const GSignondSecurityContext *ctx,
619                                   GError **error)
620 {
621     if (!self || !GSIGNOND_IS_DAEMON (self)) {
622         WARN ("assertion (self && GSIGNOND_IS_DAEMON(self)) failed");
623         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN,
624                                                                 "Unknown error");
625         return NULL;
626     }
627
628     GSignondIdentityInfoList *identities  = NULL;
629     GSignondDictionary *filter_map =
630                 gsignond_dictionary_new_from_variant (filter);
631
632     if (!_check_keychain_access (self, ctx, NULL)) {
633         /* Other than 'keychain' app, can only get identities owned by it. */
634         gsignond_dictionary_set (filter_map, "Owner",
635                         gsignond_security_context_to_variant (ctx));
636     }
637
638     identities = gsignond_db_credentials_database_load_identities (
639                       self->priv->db, filter_map);
640
641     gsignond_dictionary_unref (filter_map);
642
643     if (!identities) {
644         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN,
645                                                                 "Not found");
646     }
647
648     return identities;
649 }
650
651 gboolean 
652 gsignond_daemon_clear (GSignondDaemon *self,
653                        const GSignondSecurityContext *ctx,
654                        GError **error)
655 {
656     if (!self || !GSIGNOND_IS_DAEMON (self)) {
657         WARN ("assertion (self && GSIGNOND_IS_DAEMON(self)) failed");
658         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
659         return FALSE;
660     }
661
662     if (!_check_keychain_access (self, ctx, error))
663         return FALSE;
664
665     gboolean retval = TRUE;
666     GSignondDaemonPrivate *priv = self->priv;
667
668     DBG ("destroy all identities");
669     g_hash_table_foreach_remove (priv->identities, _clear_identity, self);
670     if (g_hash_table_size (priv->identities) > 0) {
671         WARN ("g_hash_table_foreach_remove(identities) failed for some items");
672         retval = FALSE;
673     }
674     DBG ("perform internal clear");
675     if (!gsignond_db_credentials_database_clear (priv->db)) {
676         WARN ("gsignond_db_credentials_database_clear() failed");
677         retval = FALSE;
678     }
679
680     DBG ("close databases");
681     if (!gsignond_db_credentials_database_close_secret_storage (priv->db)) {
682         WARN ("gsignond_db_credentials_database_close_secret_storage() failed");
683         retval = FALSE;
684     }   
685     g_object_unref (priv->db);
686     priv->db = NULL;
687
688     DBG ("clear data");
689     if (!gsignond_storage_manager_delete_storage (priv->storage_manager)) {
690         WARN ("gsignond_storage_manager_delete_storage() failed");
691         retval = FALSE;
692     }
693
694     DBG ("re-create storage");
695     if (!_init_storage (self)) {
696         WARN ("_init_storage() failed");
697         retval = FALSE;
698     }
699
700     if (!_open_database (self)) {
701         WARN ("_open_database() failed");
702         retval = FALSE;
703     }
704
705     return retval;
706 }
707
708 /**
709  * gsignond_daemon_new:
710  *
711  * Returns: (transfer full): newly created object of type #GSignondDaemon
712  */
713 GSignondDaemon *
714 gsignond_daemon_new ()
715 {
716     return  GSIGNOND_DAEMON(g_object_new (GSIGNOND_TYPE_DAEMON, NULL));
717 }
718
719 guint
720 gsignond_daemon_get_timeout (GSignondDaemon *self)
721 {
722     return gsignond_config_get_integer (self->priv->config,
723         GSIGNOND_CONFIG_DBUS_DAEMON_TIMEOUT);
724 }
725
726 guint
727 gsignond_daemon_get_identity_timeout (GSignondDaemon *self)
728 {
729     return gsignond_config_get_integer (self->priv->config,
730         GSIGNOND_CONFIG_DBUS_IDENTITY_TIMEOUT);
731 }
732
733 guint
734 gsignond_daemon_get_auth_session_timeout (GSignondDaemon *self)
735 {
736     return gsignond_config_get_integer (self->priv->config,
737         GSIGNOND_CONFIG_DBUS_AUTH_SESSION_TIMEOUT);
738 }
739
740 GSignondAccessControlManager *
741 gsignond_daemon_get_access_control_manager (GSignondDaemon *self)
742 {
743     g_assert (self != NULL);
744     g_assert (self->priv != NULL);
745
746     return self->priv->acm;
747 }
748
749 GSignondPluginProxyFactory *
750 gsignond_daemon_get_plugin_proxy_factory (GSignondDaemon *self)
751 {
752     g_assert (self != NULL);
753     g_assert (self->priv != NULL);
754
755     return self->priv->plugin_proxy_factory;
756 }
757
758 GSignondConfig *
759 gsignond_daemon_get_config (GSignondDaemon *self)
760 {
761     g_assert (self != NULL);
762     g_assert (self->priv != NULL);
763
764     return self->priv->config;
765 }
766
767 gboolean
768 gsignond_daemon_show_dialog (GSignondDaemon *self,
769                              GObject *caller,
770                              GSignondSignonuiData *ui_data,
771                              GSignondSignonuiProxyQueryDialogCb handler,
772                              GSignondSignonuiProxyRefreshCb refresh_handler,
773                              gpointer userdata)
774 {
775     g_return_val_if_fail (self && GSIGNOND_IS_DAEMON(self), FALSE);
776
777     return gsignond_signonui_proxy_query_dialog (self->priv->ui, caller, ui_data, handler, refresh_handler, userdata);
778 }
779
780 gboolean
781 gsignond_daemon_refresh_dialog (GSignondDaemon *self,
782                                 GObject *caller,
783                                 GSignondSignonuiData *ui_data,
784                                 GSignondSignonuiProxyRefreshDialogCb handler,
785                                 gpointer userdata)
786 {
787     g_return_val_if_fail (self && GSIGNOND_IS_DAEMON(self), FALSE);
788
789     return gsignond_signonui_proxy_refresh_dialog (self->priv->ui, caller, ui_data, handler, userdata);
790 }
791
792 gboolean
793 gsignond_daemon_cancel_dialog (GSignondDaemon *self,
794                                GObject *caller,
795                                GSignondSignonuiProxyCancelRequestCb handler,
796                                gpointer userdata)
797 {
798     g_return_val_if_fail (self && GSIGNOND_IS_DAEMON(self), FALSE);
799
800     return gsignond_signonui_proxy_cancel_request (self->priv->ui, caller, handler, userdata);
801 }
802
803 GSignondAccessControlManager *
804 gsignond_get_access_control_manager ()
805 {
806     return gsignond_daemon_get_access_control_manager(GSIGNOND_DAEMON(self));
807 }
808
809 GSignondPluginProxyFactory *
810 gsignond_get_plugin_proxy_factory ()
811 {
812     return gsignond_daemon_get_plugin_proxy_factory(GSIGNOND_DAEMON(self));
813 }
814
815 GSignondConfig *
816 gsignond_get_config ()
817 {
818     return gsignond_daemon_get_config(GSIGNOND_DAEMON(self));
819 }