Release 1.0.3
[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 - 2014 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     DBG ("Initializing extension '%s' %d.%d.%d.%d",
160          gsignond_extension_get_name (self->priv->extension),
161          (gsignond_extension_get_version (self->priv->extension) >> 24),
162          (gsignond_extension_get_version (self->priv->extension) >> 16) & 0xff,
163          (gsignond_extension_get_version (self->priv->extension) >> 8) & 0xff,
164          gsignond_extension_get_version (self->priv->extension) & 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 = GSIGNOND_EXTENSIONS_DIR;
213     const gchar *ext_name;
214     gchar *mod_name;
215     gchar *mod_filename;
216     gchar *initf_name;
217     GSignondExtension* (*ext_init) (void);
218
219 #   ifdef ENABLE_DEBUG
220     const gchar *env_val = g_getenv ("SSO_EXTENSIONS_DIR");
221     if (env_val)
222         ext_path = env_val;
223 #   endif
224     ext_name = gsignond_config_get_string (self->priv->config,
225         GSIGNOND_CONFIG_GENERAL_EXTENSION);
226     if (ext_name && !ext_path) return FALSE;
227
228     if (ext_name && g_strcmp0 (ext_name, "default") != 0) {
229         mod_name = g_strdup_printf ("extension-%s", ext_name);
230         mod_filename = g_module_build_path (ext_path, mod_name);
231         g_free (mod_name);
232         if (!mod_filename) return FALSE;
233         DBG ("Loading extension '%s'", mod_filename);
234         self->priv->extension_module =
235             g_module_open (mod_filename, G_MODULE_BIND_LOCAL);
236         g_free (mod_filename);
237         if (!self->priv->extension_module) {
238             DBG("failed to load module : %s", g_module_error());
239             return FALSE;
240         }
241         initf_name = g_strdup_printf ("%s_extension_init", ext_name);
242         symfound = g_module_symbol (self->priv->extension_module,
243                                     initf_name,
244                                     (gpointer *) &ext_init);
245         g_free(initf_name);
246         if (!symfound) {
247             g_module_close (self->priv->extension_module);
248             self->priv->extension_module = NULL;
249             return FALSE;
250         }
251     } else {
252         ext_init = _default_extension_init;
253     }
254     self->priv->extension = ext_init ();
255     g_return_val_if_fail (self->priv->extension &&
256                           GSIGNOND_IS_EXTENSION (self->priv->extension),
257                           FALSE);
258
259     res = _init_extension (self);
260
261     return res;
262 }
263
264 static gboolean
265 _init_storage (GSignondDaemon *self)
266 {
267     const gchar *storage_location;
268
269     DBG("Initializing storage");
270
271     if (!gsignond_storage_manager_storage_is_initialized (
272                                                  self->priv->storage_manager)) {
273         if (!gsignond_storage_manager_initialize_storage (
274                                                    self->priv->storage_manager))
275             return FALSE;
276     }
277
278     storage_location = gsignond_storage_manager_mount_filesystem (
279                                                    self->priv->storage_manager);
280     if (storage_location == NULL)
281         return FALSE;
282     gsignond_config_set_string (self->priv->config, 
283         GSIGNOND_CONFIG_GENERAL_SECURE_DIR, storage_location);                                                 
284
285     return (storage_location != NULL);
286 }
287
288 static gboolean
289 _open_database (GSignondDaemon *self)
290 {
291     DBG("Open databases");
292
293     self->priv->db = gsignond_db_credentials_database_new (self->priv->config,
294                                                     self->priv->secret_storage);
295     if (!self->priv->db)
296         return FALSE;
297
298     return gsignond_db_credentials_database_open_secret_storage (
299                                                                 self->priv->db);
300 }
301
302 static gboolean
303 _clear_identity (gpointer idp, gpointer identityp, gpointer user_data)
304 {
305     (void) user_data;
306
307     return gsignond_identity_clear (GSIGNOND_IDENTITY (identityp));
308 }
309
310 static void
311 gsignond_daemon_init (GSignondDaemon *self)
312 {
313     self->priv = GSIGNOND_DAEMON_PRIV(self);
314
315     self->priv->config = gsignond_config_new ();
316     self->priv->identities = g_hash_table_new_full (
317             g_direct_hash, g_direct_equal, NULL, NULL);
318     self->priv->plugin_proxy_factory = gsignond_plugin_proxy_factory_new(
319         self->priv->config);
320     
321     if (!_init_extensions (self))
322         ERR("gsignond_daemon_init_extensions() failed");
323
324     if (!_init_storage (self))
325         ERR("gsignond_daemon_init_storage() failed");
326     if (!_open_database (self))
327         ERR("gisgnond_daemon_open_database() failed");
328
329     self->priv->ui = gsignond_signonui_proxy_new ();
330 }
331
332 static void
333 gsignond_daemon_class_init (GSignondDaemonClass *klass)
334 {
335     GObjectClass* object_class = G_OBJECT_CLASS (klass);
336
337     g_type_class_add_private (object_class, sizeof (GSignondDaemonPrivate));
338
339     object_class->constructor = _constructor;
340     object_class->dispose = _dispose;
341     object_class->finalize = _finalize;
342 }
343
344 static gboolean
345 _compare_identity_by_pointer (gpointer key, gpointer value, gpointer dead_object)
346 {
347     return value == dead_object;
348 }
349
350 static void
351 _on_identity_disposed (gpointer data, GObject *object)
352 {
353     GSignondDaemon *daemon = GSIGNOND_DAEMON (data);
354
355     DBG ("daemon %p identity %p disposed", daemon, object);
356     g_hash_table_foreach_remove (daemon->priv->identities,
357                 _compare_identity_by_pointer, object);
358 }
359
360 guint32
361 gsignond_daemon_store_identity (GSignondDaemon *daemon, GSignondIdentity *identity)
362 {
363     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), 0);
364     g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), 0);
365
366     GSignondIdentityInfo *info = NULL;
367     guint32 id = 0;
368     gboolean was_new_identity = FALSE;
369     
370     info = gsignond_identity_get_identity_info(identity);
371     if (!info) return 0;
372     
373     was_new_identity = gsignond_identity_info_get_is_identity_new (info);
374
375     id = gsignond_db_credentials_database_update_identity (daemon->priv->db, info);
376
377     if (was_new_identity && id) {
378         g_hash_table_insert (daemon->priv->identities, GUINT_TO_POINTER(id), identity);
379         g_object_weak_ref (G_OBJECT (identity), _on_identity_disposed, daemon);
380     }
381
382     return id;
383 }
384
385 gboolean
386 gsignond_daemon_remove_identity (GSignondDaemon *daemon, guint32 id)
387 {
388     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
389
390     return gsignond_db_credentials_database_remove_identity(daemon->priv->db, id);
391 }
392
393 guint32
394 gsignond_daemon_add_identity_reference (GSignondDaemon *daemon, guint32 identity_id, const GSignondSecurityContext *owner, const gchar *reference)
395 {
396     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), 0);
397
398     return gsignond_db_credentials_database_insert_reference (daemon->priv->db, identity_id, owner, reference);
399 }
400
401 gboolean
402 gsignond_daemon_remove_identity_reference (GSignondDaemon *daemon, guint32 identity_id, const GSignondSecurityContext *owner, const gchar *reference)
403 {
404     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
405
406     return gsignond_db_credentials_database_remove_reference (daemon->priv->db, identity_id, owner, reference);
407 }
408
409 gboolean
410 gsignond_daemon_store_identity_data (GSignondDaemon *daemon, guint32 identity_id, const gchar *method, GSignondDictionary *data)
411 {
412     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
413
414     return gsignond_db_credentials_database_update_data (daemon->priv->db, identity_id, method, data);
415 }
416
417 gboolean
418 gsignond_daemon_clear_identity_data (GSignondDaemon *daemon, guint32 identity_id)
419 {
420     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), FALSE);
421
422     return gsignond_db_credentials_database_remove_data (daemon->priv->db, identity_id, NULL);
423 }
424
425 GSignondDictionary *
426 gsignond_daemon_load_identity_data (GSignondDaemon *daemon, guint32 identity_id, const gchar *method)
427 {
428     g_return_val_if_fail (daemon && GSIGNOND_IS_DAEMON (daemon), NULL);
429     g_return_val_if_fail (identity_id, NULL);
430     g_return_val_if_fail (method, NULL);
431
432     return gsignond_db_credentials_database_load_data (daemon->priv->db, identity_id, method);
433 }
434
435 GSignondIdentity *
436 gsignond_daemon_register_new_identity (GSignondDaemon *daemon,
437                                        const GSignondSecurityContext *ctx,
438                                        GError **error) 
439 {
440     if (!daemon || !GSIGNOND_IS_DAEMON (daemon) || !ctx) {
441         WARN ("assertion failed (daemon && GSIGNOND_IS_DAEMON (daemon)) failed");
442         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
443         return NULL;
444     }
445
446     GSignondIdentityInfo *info = gsignond_identity_info_new ();
447     GSignondIdentity *identity = NULL;
448     GSignondSecurityContext *owner = NULL;
449     GSignondSecurityContextList *acl = NULL;
450
451     owner = gsignond_security_context_copy (ctx);
452
453     gsignond_identity_info_set_owner (info, owner);
454
455     acl = (GSignondSecurityContextList *)g_list_append (NULL, owner);
456     gsignond_identity_info_set_access_control_list (info, acl);
457     gsignond_security_context_free (owner);
458     g_list_free (acl);
459
460     DBG("register_new_identity: cache size : %d", g_hash_table_size(daemon->priv->identities));
461     identity = gsignond_identity_new (daemon, info);
462     if (identity == NULL) {
463         gsignond_identity_info_unref (info);
464         ERR("Unable to register new identity");
465         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, "Internal server error");
466         return NULL;
467     }
468     DBG(" --- registered new identity : %p", identity);
469     return identity;
470 }
471
472 GSignondIdentity *
473 gsignond_daemon_get_identity (GSignondDaemon *daemon,
474                               const guint32 id,
475                               const GSignondSecurityContext *ctx,
476                               GError **error)
477 {
478     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
479         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON (daemon)) failed");
480         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
481         return NULL;
482     }
483     if (id <= 0) {
484         WARN ("client provided invalid identity id");
485         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Invalid identity id");
486         return NULL;
487     }
488
489     GSignondIdentity *identity = NULL;
490     GSignondIdentityInfo *identity_info = NULL;
491
492 #define VALIDATE_IDENTITY_X_ACCESS(info, ctx, ret) \
493 { \
494     GSignondAccessControlManager *acm = daemon->priv->acm; \
495     GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (info); \
496     GSignondSecurityContext *owner = gsignond_identity_info_get_owner (info); \
497     gboolean valid = gsignond_access_control_manager_peer_is_allowed_to_use_identity (acm, ctx, owner, acl); \
498     gsignond_security_context_free (owner); \
499     gsignond_security_context_list_free (acl); \
500     if (!valid) { \
501         WARN ("identity access check failed"); \
502         gsignond_identity_info_unref (info); \
503         if (error) { \
504             *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "Can not read identity"); \
505         } \
506         return ret; \
507     } \
508 }
509     DBG("Get identity for id '%d'\n cache size : %d", id, g_hash_table_size(daemon->priv->identities));
510     identity = GSIGNOND_IDENTITY(g_hash_table_lookup (daemon->priv->identities, GUINT_TO_POINTER(id)));
511     if (identity) {
512         identity_info = gsignond_identity_get_identity_info (identity);
513         gsignond_identity_info_ref (identity_info);
514         VALIDATE_IDENTITY_X_ACCESS (identity_info, ctx, NULL);
515         DBG ("using cased Identity '%p' for id %d", identity, id);
516         gsignond_identity_info_unref (identity_info);
517
518         return GSIGNOND_IDENTITY (g_object_ref (identity));
519     }
520
521     /* identity not found in cache, so try to load form db */
522     identity_info = gsignond_db_credentials_database_load_identity (
523                             daemon->priv->db, id, TRUE);
524     if (!identity_info) {
525         if (error)  {
526             const GError *err = gsignond_db_credentials_database_get_last_error (daemon->priv->db);
527             *error = err ? g_error_copy (err) : gsignond_get_gerror_for_id (
528                         GSIGNOND_ERROR_IDENTITY_NOT_FOUND, "identity not found with id '%d'", id);
529         }
530         return NULL;
531     }
532
533     VALIDATE_IDENTITY_X_ACCESS (identity_info, ctx, NULL);
534
535     identity = gsignond_identity_new (daemon, identity_info);
536     if (!identity) {
537         gsignond_identity_info_unref (identity_info);
538         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, "Internal server error");
539         return NULL;
540     }
541
542     g_hash_table_insert (daemon->priv->identities, GUINT_TO_POINTER(id), identity);
543     g_object_weak_ref (G_OBJECT (identity), _on_identity_disposed, daemon);
544
545     DBG("created new identity '%p' for id '%d'", identity, id);
546
547     return identity;
548
549 #undef VALIDATE_IDENTITY_READ_ACCESS
550 }
551
552 const gchar ** 
553 gsignond_daemon_query_methods (GSignondDaemon *daemon, GError **error)
554 {
555     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
556         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON(daemon)) failed");
557         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
558         return NULL;
559     }
560
561     return gsignond_plugin_proxy_factory_get_plugin_types (
562             daemon->priv->plugin_proxy_factory);
563 }
564
565 const gchar ** 
566 gsignond_daemon_query_mechanisms (GSignondDaemon *daemon, const gchar *method, GError **error) 
567 {
568     if (!daemon || !GSIGNOND_IS_DAEMON (daemon)) {
569         WARN ("assertion (daemon && GSIGNOND_IS_DAEMON(daemon)) failed");
570         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
571         return NULL;
572     }
573
574     const gchar **mechanisms = gsignond_plugin_proxy_factory_get_plugin_mechanisms (
575             daemon->priv->plugin_proxy_factory, method);
576
577     if (!mechanisms || mechanisms[0] == NULL) {
578         DBG("no mechanisms found for method '%s'", method);
579         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN, "method '%s' not found", method);
580     }
581
582     return mechanisms;
583 }
584
585 static gboolean
586 _check_keychain_access (GSignondDaemon *self,
587                         const GSignondSecurityContext *ctx,
588                         GError **error)
589 {
590     GSignondAccessControlManager *acm = self->priv->acm;
591     GSignondSecurityContext *keychain =
592         gsignond_access_control_manager_security_context_of_keychain (acm);
593     gboolean has_access =
594         (gsignond_security_context_compare (keychain, ctx) == 0);
595     DBG ("keychain access compare [%s:%s] vs [%s:%s] = %d",
596          gsignond_security_context_get_system_context (keychain),
597          gsignond_security_context_get_application_context (keychain),
598          gsignond_security_context_get_system_context (ctx),
599          gsignond_security_context_get_application_context (ctx),
600          has_access);
601     gsignond_security_context_free (keychain);
602     if (!has_access) {
603         WARN ("keychain access check failed");
604         if (error) {
605             *error = gsignond_get_gerror_for_id (
606                                     GSIGNOND_ERROR_PERMISSION_DENIED,
607                                     "Can not access keychain functionality");
608         }
609     }
610     return has_access;
611 }
612
613 GSignondIdentityInfoList *
614 gsignond_daemon_query_identities (GSignondDaemon *self,
615                                   GVariant *filter,
616                                   const GSignondSecurityContext *ctx,
617                                   GError **error)
618 {
619     if (!self || !GSIGNOND_IS_DAEMON (self)) {
620         WARN ("assertion (self && GSIGNOND_IS_DAEMON(self)) failed");
621         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN,
622                                                                 "Unknown error");
623         return NULL;
624     }
625
626     GSignondIdentityInfoList *identities  = NULL;
627     GSignondDictionary *filter_map =
628                 gsignond_dictionary_new_from_variant (filter);
629
630     if (!_check_keychain_access (self, ctx, NULL)) {
631         /* Other than 'keychain' app, can only get identities owned by it. */
632         gsignond_dictionary_set (filter_map, "Owner",
633                         gsignond_security_context_to_variant (ctx));
634     }
635
636     identities = gsignond_db_credentials_database_load_identities (
637                       self->priv->db, filter_map);
638
639     gsignond_dictionary_unref (filter_map);
640
641     if (!identities) {
642         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN,
643                                                                 "Not found");
644     }
645
646     return identities;
647 }
648
649 gboolean 
650 gsignond_daemon_clear (GSignondDaemon *self,
651                        const GSignondSecurityContext *ctx,
652                        GError **error)
653 {
654     if (!self || !GSIGNOND_IS_DAEMON (self)) {
655         WARN ("assertion (self && GSIGNOND_IS_DAEMON(self)) failed");
656         if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
657         return FALSE;
658     }
659
660     if (!_check_keychain_access (self, ctx, error))
661         return FALSE;
662
663     gboolean retval = TRUE;
664     GSignondDaemonPrivate *priv = self->priv;
665
666     DBG ("destroy all identities");
667     g_hash_table_foreach_remove (priv->identities, _clear_identity, self);
668     if (g_hash_table_size (priv->identities) > 0) {
669         WARN ("g_hash_table_foreach_remove(identities) failed for some items");
670         retval = FALSE;
671     }
672     DBG ("perform internal clear");
673     if (!gsignond_db_credentials_database_clear (priv->db)) {
674         WARN ("gsignond_db_credentials_database_clear() failed");
675         retval = FALSE;
676     }
677
678     DBG ("close databases");
679     if (!gsignond_db_credentials_database_close_secret_storage (priv->db)) {
680         WARN ("gsignond_db_credentials_database_close_secret_storage() failed");
681         retval = FALSE;
682     }   
683     g_object_unref (priv->db);
684     priv->db = NULL;
685
686     DBG ("clear data");
687     if (!gsignond_storage_manager_delete_storage (priv->storage_manager)) {
688         WARN ("gsignond_storage_manager_delete_storage() 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 }