97e021d2def3381420f4d790061b4ebade1ba44a
[profile/ivi/gsignond.git] / src / common / db / gsignond-secret-storage.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 Intel Corporation.
7  *
8  * Contact: Imran Zaman <imran.zaman@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-db-secret-database.h"
27 #include "gsignond-db-error.h"
28
29 #include "gsignond/gsignond-log.h"
30 #include "gsignond/gsignond-secret-storage.h"
31
32 /**
33  * SECTION:gsignond-secret-storage
34  * @short_description: provides access to the database that stores user credentials and identity/method cache
35  * @include: gsignond/gsignond-secret-storage.h
36  *
37  * #GSignondSecretStorage provides access to the database where sensitive identity
38  * data (#GSignondCredentials) and identity/method cache are stored. It's preferred 
39  * that this database is protected against access by processes other than gSSO.
40  *
41  * gSSO can be configured to use a custom extension
42  * that provides a subclassed implementation of #GSignondSecretStorage
43  * (see #GSignondExtension), otherwise a default implementation is used.
44  * 
45  */
46 /**
47  * GSignondSecretStorage:
48  *
49  * Opaque #GSignondSecretStorage data structure.
50  */
51
52 #define GSIGNOND_SECRET_STORAGE_GET_PRIVATE(obj) \
53                                           (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
54                                            GSIGNOND_TYPE_SECRET_STORAGE, \
55                                            GSignondSecretStoragePrivate))
56
57 struct _GSignondSecretStoragePrivate
58 {
59     GSignondDbSecretDatabase *database;
60 };
61
62 G_DEFINE_TYPE (GSignondSecretStorage, gsignond_secret_storage,
63         G_TYPE_OBJECT);
64
65 enum
66 {
67     PROP_0,
68     PROP_CONFIG,
69     N_PROPERTIES
70 };
71
72 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
73
74 static void
75 _set_property (GObject *object, guint prop_id, const GValue *value,
76                GParamSpec *pspec)
77 {
78     GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (object);
79
80     switch (prop_id) {
81         case PROP_CONFIG:
82             g_assert (self->config == NULL);
83             self->config = g_value_dup_object (value);
84             break;
85         default:
86             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
87     }
88 }
89
90 static void
91 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
92 {
93     GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (object);
94
95     switch (prop_id) {
96         case PROP_CONFIG:
97             g_value_set_object (value, self->config);
98             break;
99         default:
100             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101     }
102 }
103
104 static void
105 _gsignond_secret_storage_dispose (GObject *gobject)
106 {
107     g_return_if_fail (GSIGNOND_IS_SECRET_STORAGE (gobject));
108     GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (gobject);
109
110     /* dispose might be called multiple times, so we must guard against
111       * calling g_object_unref() on an invalid GObject.
112     */
113     if (self->priv->database) {
114         g_object_unref (self->priv->database);
115         self->priv->database = NULL;
116     }
117
118     if (self->config) {
119         g_object_unref (self->config);
120         self->config = NULL;
121     }
122
123     /* Chain up to the parent class */
124     G_OBJECT_CLASS (gsignond_secret_storage_parent_class)->dispose (
125             gobject);
126 }
127
128 static gboolean
129 _open_db (GSignondSecretStorage *self)
130 {
131     const gchar *dir = NULL;
132     const gchar *filename = NULL;
133     gchar *db_filename = NULL;
134     gboolean ret = FALSE;
135
136     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
137     g_return_val_if_fail (self->config != NULL, FALSE);
138
139     dir = gsignond_config_get_string (self->config,
140             GSIGNOND_CONFIG_GENERAL_SECURE_DIR);
141     if (!dir) {
142         ERR ("No directory specified in config object for secret db...");
143         return FALSE;
144     }
145     filename = gsignond_config_get_string (self->config,
146             GSIGNOND_CONFIG_DB_SECRET_DB_FILENAME);
147     if (!filename) {
148         ERR ("Database filename not specified");
149         return FALSE;
150     }
151     db_filename = g_build_filename (dir, filename, NULL);
152     if (!db_filename) {
153         ERR ("Invalid db filename...");
154         return FALSE;
155     }
156
157     if (gsignond_secret_storage_is_open_db (self)) {
158         g_debug("SecretDB is already open. Closing first to start again...");
159         gsignond_secret_storage_close_db (self);
160     }
161
162     if (self->priv->database == NULL) {
163         self->priv->database = gsignond_db_secret_database_new ();
164     }
165
166     ret = gsignond_db_sql_database_open (
167                 GSIGNOND_DB_SQL_DATABASE (self->priv->database),
168                 db_filename,
169                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
170     g_free (db_filename);
171     if (!ret) {
172         ERR ("Open DB failed");
173         g_object_unref (self->priv->database);
174         self->priv->database = NULL;
175         return FALSE;
176     }
177     return TRUE;
178 }
179
180 static gboolean
181 _close_db (GSignondSecretStorage *self)
182 {
183     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
184
185     if (self->priv->database != NULL) {
186         gsignond_db_sql_database_close (GSIGNOND_DB_SQL_DATABASE (
187                 self->priv->database));
188     }
189     return TRUE;
190 }
191
192 static gboolean
193 _clear_db (GSignondSecretStorage *self)
194 {
195     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
196     return gsignond_db_sql_database_clear (GSIGNOND_DB_SQL_DATABASE (
197             self->priv->database));
198 }
199
200 static gboolean
201 _is_open_db (GSignondSecretStorage *self)
202 {
203     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
204     return ((self->priv->database != NULL) &&
205             gsignond_db_sql_database_is_open (GSIGNOND_DB_SQL_DATABASE (
206                     self->priv->database)));
207 }
208
209 static GSignondCredentials*
210 _load_credentials (
211         GSignondSecretStorage *self,
212         const guint32 id)
213 {
214     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
215     return gsignond_db_secret_database_load_credentials (self->priv->database,
216             id);
217 }
218
219 static gboolean
220 _update_credentials (
221         GSignondSecretStorage *self,
222         GSignondCredentials *creds)
223 {
224     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
225     return gsignond_db_secret_database_update_credentials (self->priv->database,
226             creds);
227 }
228
229 static gboolean
230 _remove_credentials (
231         GSignondSecretStorage *self,
232         const guint32 id)
233 {
234     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
235     return gsignond_db_secret_database_remove_credentials (self->priv->database,
236             id);
237 }
238
239 static gboolean
240 _check_credentials (
241         GSignondSecretStorage *self,
242         GSignondCredentials *creds)
243 {
244     gboolean equal = FALSE;
245     GSignondCredentials *stored_creds = NULL;
246
247     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
248     g_return_val_if_fail (creds != NULL, FALSE);
249
250     GSignondSecretStorageClass *klass =
251             GSIGNOND_SECRET_STORAGE_GET_CLASS (self);
252
253     stored_creds = klass->load_credentials (self,
254             gsignond_credentials_get_id(creds));
255
256     if (stored_creds) {
257         DBG ("Credentials from DB found");
258         equal = gsignond_credentials_equal(creds, stored_creds);
259         g_object_unref (stored_creds);
260     }
261
262     return equal;
263 }
264
265 static GHashTable*
266 _load_data (
267         GSignondSecretStorage *self,
268         const guint32 id,
269         const guint32 method)
270 {
271     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), NULL);
272     return gsignond_db_secret_database_load_data (self->priv->database,
273             id, method);
274 }
275
276 static gboolean
277 _update_data (
278         GSignondSecretStorage *self,
279         const guint32 id,
280         const guint32 method,
281         GHashTable *data)
282 {
283     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
284     return gsignond_db_secret_database_update_data (self->priv->database,
285             id, method, data);
286 }
287
288 static gboolean
289 _remove_data (
290         GSignondSecretStorage *self,
291         const guint32 id,
292         const guint32 method)
293 {
294     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
295     return gsignond_db_secret_database_remove_data (self->priv->database,
296             id, method);
297 }
298
299 static const GError *
300 _get_last_error (GSignondSecretStorage *self)
301 {
302     g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), NULL);
303     if (self->priv->database != NULL) {
304         return gsignond_db_sql_database_get_last_error (
305                 GSIGNOND_DB_SQL_DATABASE (self->priv->database));
306     }
307     return NULL;
308 }
309
310
311
312 /**
313  * GSignondSecretStorageClass:
314  * @parent_class: parent class.
315  * @open_db: an implementation of gsignond_secret_storage_open_db()
316  * @close_db: an implementation of gsignond_secret_storage_close_db()
317  * @clear_db: an implementation of gsignond_secret_storage_clear_db()
318  * @is_open_db: an implementation of gsignond_secret_storage_is_open_db()
319  * @load_credentials: an implementation of gsignond_secret_storage_load_credentials()
320  * @update_credentials: an implementation of gsignond_secret_storage_update_credentials()
321  * @remove_credentials: an implementation of gsignond_secret_storage_remove_credentials()
322  * @check_credentials: an implementation of gsignond_secret_storage_check_credentials()
323  * @load_data: an implementation of gsignond_secret_storage_load_data()
324  * @update_data: an implementation of gsignond_secret_storage_update_data()
325  * @remove_data: an implementation of gsignond_secret_storage_remove_data()
326  * @get_last_error: an implementation of gsignond_secret_storage_get_last_error()
327  * 
328  * #GSignondSecretStorageClass class containing pointers to class methods.
329  */
330 static void
331 gsignond_secret_storage_class_init (GSignondSecretStorageClass *klass)
332 {
333     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
334
335     gobject_class->set_property = _set_property;
336     gobject_class->get_property = _get_property;
337     gobject_class->dispose = _gsignond_secret_storage_dispose;
338
339     properties[PROP_CONFIG] = g_param_spec_object ("config",
340                                                    "config",
341                                                    "Configuration object",
342                                                    GSIGNOND_TYPE_CONFIG,
343                                                    G_PARAM_CONSTRUCT_ONLY |
344                                                    G_PARAM_READWRITE |
345                                                    G_PARAM_STATIC_STRINGS);
346     g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
347
348     /* virtual methods */
349     klass->open_db = _open_db;
350     klass->close_db = _close_db;
351     klass->clear_db = _clear_db;
352     klass->is_open_db = _is_open_db;
353     klass->load_credentials = _load_credentials;
354     klass->update_credentials = _update_credentials;
355     klass->remove_credentials = _remove_credentials;
356     klass->check_credentials = _check_credentials;
357     klass->load_data = _load_data;
358     klass->update_data = _update_data;
359     klass->remove_data = _remove_data;
360     klass->get_last_error = _get_last_error;
361
362     g_type_class_add_private (klass, sizeof (GSignondSecretStoragePrivate));
363 }
364
365 static void
366 gsignond_secret_storage_init (GSignondSecretStorage *self)
367 {
368     self->priv = GSIGNOND_SECRET_STORAGE_GET_PRIVATE (self);
369     self->priv->database = gsignond_db_secret_database_new ();
370     self->config = NULL;
371 }
372
373 /**
374  * gsignond_secret_storage_open_db:
375  * @self: instance of #GSignondSecretStorage
376  *
377  * Opens (and initializes) the database. The implementation should take
378  * care of creating the DB, if it doesn't exist, and it should use
379  * #GSIGNOND_CONFIG_GENERAL_SECURE_DIR and #GSIGNOND_CONFIG_DB_SECRET_DB_FILENAME
380  * to determine database location in the filesystem.
381  * 
382  * The default implementation is using SQLite for the storage.
383  *
384  * Returns: TRUE if successful, FALSE otherwise.
385  */
386 gboolean
387 gsignond_secret_storage_open_db (GSignondSecretStorage *self)
388 {
389     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->open_db (self);
390 }
391
392 /**
393  * gsignond_secret_storage_close_db:
394  * @self: instance of #GSignondSecretStorage
395  *
396  * Closes the database. To reopen it, call gsignond_secret_storage_open_db().
397  *
398  * Returns: TRUE if successful, FALSE otherwise.
399  */
400 gboolean
401 gsignond_secret_storage_close_db (GSignondSecretStorage *self)
402 {
403     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->close_db (self);
404 }
405
406 /**
407  * gsignond_secret_storage_clear_db:
408  * @self: instance of #GSignondSecretStorage
409  *
410  * Removes all stored secrets from the database.
411  *
412  * Returns: TRUE if successful, FALSE otherwise.
413  */
414 gboolean
415 gsignond_secret_storage_clear_db (GSignondSecretStorage *self)
416 {
417     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->clear_db (self);
418 }
419
420 /**
421  * gsignond_secret_storage_is_open_db:
422  * @self: instance of #GSignondSecretStorage
423  *
424  * Checks if the database is open or not.
425  *
426  * Returns: TRUE if successful, FALSE otherwise.
427  */
428 gboolean
429 gsignond_secret_storage_is_open_db (GSignondSecretStorage *self)
430 {
431     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->is_open_db (self);
432 }
433
434 /**
435  * gsignond_secret_storage_load_credentials:
436  * @self: instance of #GSignondSecretStorage
437  * @id: the identity id whose credentials are being loaded.
438  *
439  * Loads the credentials from the database.
440  *
441  * Returns: (transfer full): #GSignondCredentials if successful,
442  * NULL otherwise.
443  */
444 GSignondCredentials*
445 gsignond_secret_storage_load_credentials (
446         GSignondSecretStorage *self,
447         const guint32 id)
448 {
449     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->load_credentials (self, id);
450 }
451
452 /**
453  * gsignond_secret_storage_update_credentials:
454  * @self: instance of #GSignondSecretStorage
455  * @creds: (transfer none): the credentials that are being updated.
456  *
457  * Stores/updates the credentials for the given identity.
458  *
459  * Returns: TRUE if successful, FALSE otherwise.
460  */
461 gboolean
462 gsignond_secret_storage_update_credentials (
463         GSignondSecretStorage *self,
464         GSignondCredentials *creds)
465 {
466     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->update_credentials (self, creds);
467 }
468
469 /**
470  * gsignond_secret_storage_remove_credentials:
471  * @self: instance of #GSignondSecretStorage
472  * @id: the identity whose credentials are being updated.
473  *
474  * Remove the credentials for the given identity.
475  *
476  * Returns: TRUE if successful, FALSE otherwise.
477  */
478 gboolean
479 gsignond_secret_storage_remove_credentials (
480         GSignondSecretStorage *self,
481         const guint32 id)
482 {
483     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->remove_credentials (self, id);
484 }
485
486 /**
487  * gsignond_secret_storage_check_credentials:
488  * @self: instance of #GSignondSecretStorage
489  * @creds: (transfer none): the credentials that are being checked.
490  *
491  * Checks whether the given credentials match what is stored in the database.
492  *
493  * Returns: TRUE if successful, FALSE otherwise.
494  */
495 gboolean
496 gsignond_secret_storage_check_credentials (
497         GSignondSecretStorage *self,
498         GSignondCredentials *creds)
499 {
500     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->check_credentials (self, creds);
501 }
502
503 /**
504  * gsignond_secret_storage_load_data:
505  * @self: instance of #GSignondSecretStorage
506  * @id: the identity id whose data are fetched
507  * @method: the authentication method the data is used for.
508  *
509  * Loads the secret data associated with a given identity and method.
510  *
511  * Returns: (transfer full): the secret data
512  */
513 GSignondDictionary*
514 gsignond_secret_storage_load_data (
515         GSignondSecretStorage *self,
516         const guint32 id,
517         const guint32 method)
518 {
519     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->load_data (self, id, method);
520 }
521
522 /**
523  * gsignond_secret_storage_update_data:
524  * @self: instance of #GSignondSecretStorage
525  * @id: the identity whose data are fetched.
526  * @method: the authentication method the data is used for.
527  * @data: (transfer none): the data to update
528  *
529  * Calling this method updates the secret data
530  * associated with the given id/method.
531  *
532  * Returns: TRUE if successful, FALSE otherwise.
533  */
534 gboolean
535 gsignond_secret_storage_update_data (
536         GSignondSecretStorage *self,
537         const guint32 id,
538         const guint32 method,
539         GSignondDictionary *data)
540 {
541     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->update_data (self, id, method, data);
542 }
543
544 /**
545  * gsignond_secret_storage_remove_data:
546  * @self: instance of #GSignondSecretStorage
547  * @id: the identity whose data are fetched.
548  * @method: the authentication method the data is used for.
549  *
550  * Removes secret data associated with a given id/method.
551  *
552  * Returns: TRUE if successful, FALSE otherwise.
553  */
554 gboolean
555 gsignond_secret_storage_remove_data (
556         GSignondSecretStorage *self,
557         const guint32 id,
558         const guint32 method)
559 {
560     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->remove_data (self, id, method);
561 }
562
563 /**
564  * gsignond_secret_storage_get_last_error:
565  * @self: instance of #GSignondSecretStorage
566  *
567  * Retrieves the last occurred error that has occured
568  *
569  * Returns: (transfer none): last occurred #GError
570  */
571 const GError *
572 gsignond_secret_storage_get_last_error (GSignondSecretStorage *self)
573 {
574     return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->get_last_error (self);
575 }
576