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