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