1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2012 Intel Corporation.
8 * Contact: Imran Zaman <imran.zaman@linux.intel.com>
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.
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.
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
26 #include "gsignond-db-secret-database.h"
27 #include "gsignond-db-error.h"
29 #include "gsignond/gsignond-log.h"
30 #include "gsignond/gsignond-secret-storage.h"
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
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.
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.
47 * GSignondSecretStorage:
49 * Opaque #GSignondSecretStorage data structure.
52 #define GSIGNOND_SECRET_STORAGE_GET_PRIVATE(obj) \
53 (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
54 GSIGNOND_TYPE_SECRET_STORAGE, \
55 GSignondSecretStoragePrivate))
57 struct _GSignondSecretStoragePrivate
59 GSignondDbSecretDatabase *database;
62 G_DEFINE_TYPE (GSignondSecretStorage, gsignond_secret_storage,
72 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
75 _set_property (GObject *object, guint prop_id, const GValue *value,
78 GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (object);
82 g_assert (self->config == NULL);
83 self->config = g_value_dup_object (value);
86 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
93 GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (object);
97 g_value_set_object (value, self->config);
100 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105 _gsignond_secret_storage_dispose (GObject *gobject)
107 g_return_if_fail (GSIGNOND_IS_SECRET_STORAGE (gobject));
108 GSignondSecretStorage *self = GSIGNOND_SECRET_STORAGE (gobject);
110 /* dispose might be called multiple times, so we must guard against
111 * calling g_object_unref() on an invalid GObject.
113 if (self->priv->database) {
114 g_object_unref (self->priv->database);
115 self->priv->database = NULL;
119 g_object_unref (self->config);
123 /* Chain up to the parent class */
124 G_OBJECT_CLASS (gsignond_secret_storage_parent_class)->dispose (
129 _open_db (GSignondSecretStorage *self)
131 const gchar *dir = NULL;
132 const gchar *filename = NULL;
133 gchar *db_filename = NULL;
134 gboolean ret = FALSE;
136 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
137 g_return_val_if_fail (self->config != NULL, FALSE);
139 dir = gsignond_config_get_string (self->config,
140 GSIGNOND_CONFIG_GENERAL_SECURE_DIR);
142 ERR ("No directory specified in config object for secret db...");
145 filename = gsignond_config_get_string (self->config,
146 GSIGNOND_CONFIG_DB_SECRET_DB_FILENAME);
148 ERR ("Database filename not specified");
151 db_filename = g_build_filename (dir, filename, NULL);
153 ERR ("Invalid db filename...");
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);
162 if (self->priv->database == NULL) {
163 self->priv->database = gsignond_db_secret_database_new ();
166 ret = gsignond_db_sql_database_open (
167 GSIGNOND_DB_SQL_DATABASE (self->priv->database),
169 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
170 g_free (db_filename);
172 ERR ("Open DB failed");
173 g_object_unref (self->priv->database);
174 self->priv->database = NULL;
181 _close_db (GSignondSecretStorage *self)
183 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
185 if (self->priv->database != NULL) {
186 gsignond_db_sql_database_close (GSIGNOND_DB_SQL_DATABASE (
187 self->priv->database));
193 _clear_db (GSignondSecretStorage *self)
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));
201 _is_open_db (GSignondSecretStorage *self)
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)));
209 static GSignondCredentials*
211 GSignondSecretStorage *self,
214 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
215 return gsignond_db_secret_database_load_credentials (self->priv->database,
220 _update_credentials (
221 GSignondSecretStorage *self,
222 GSignondCredentials *creds)
224 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
225 return gsignond_db_secret_database_update_credentials (self->priv->database,
230 _remove_credentials (
231 GSignondSecretStorage *self,
234 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
235 return gsignond_db_secret_database_remove_credentials (self->priv->database,
241 GSignondSecretStorage *self,
242 GSignondCredentials *creds)
244 gboolean equal = FALSE;
245 GSignondCredentials *stored_creds = NULL;
247 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
248 g_return_val_if_fail (creds != NULL, FALSE);
250 GSignondSecretStorageClass *klass =
251 GSIGNOND_SECRET_STORAGE_GET_CLASS (self);
253 stored_creds = klass->load_credentials (self,
254 gsignond_credentials_get_id(creds));
257 DBG ("Credentials from DB found");
258 equal = gsignond_credentials_equal(creds, stored_creds);
259 g_object_unref (stored_creds);
267 GSignondSecretStorage *self,
269 const guint32 method)
271 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), NULL);
272 return gsignond_db_secret_database_load_data (self->priv->database,
278 GSignondSecretStorage *self,
280 const guint32 method,
283 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
284 return gsignond_db_secret_database_update_data (self->priv->database,
290 GSignondSecretStorage *self,
292 const guint32 method)
294 g_return_val_if_fail (GSIGNOND_IS_SECRET_STORAGE (self), FALSE);
295 return gsignond_db_secret_database_remove_data (self->priv->database,
299 static const GError *
300 _get_last_error (GSignondSecretStorage *self)
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));
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()
328 * #GSignondSecretStorageClass class containing pointers to class methods.
331 gsignond_secret_storage_class_init (GSignondSecretStorageClass *klass)
333 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
335 gobject_class->set_property = _set_property;
336 gobject_class->get_property = _get_property;
337 gobject_class->dispose = _gsignond_secret_storage_dispose;
339 properties[PROP_CONFIG] = g_param_spec_object ("config",
341 "Configuration object",
342 GSIGNOND_TYPE_CONFIG,
343 G_PARAM_CONSTRUCT_ONLY |
345 G_PARAM_STATIC_STRINGS);
346 g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
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;
362 g_type_class_add_private (klass, sizeof (GSignondSecretStoragePrivate));
366 gsignond_secret_storage_init (GSignondSecretStorage *self)
368 self->priv = GSIGNOND_SECRET_STORAGE_GET_PRIVATE (self);
369 self->priv->database = gsignond_db_secret_database_new ();
374 * gsignond_secret_storage_open_db:
375 * @self: instance of #GSignondSecretStorage
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.
382 * The default implementation is using SQLite for the storage.
384 * Returns: TRUE if successful, FALSE otherwise.
387 gsignond_secret_storage_open_db (GSignondSecretStorage *self)
389 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->open_db (self);
393 * gsignond_secret_storage_close_db:
394 * @self: instance of #GSignondSecretStorage
396 * Closes the database. To reopen it, call gsignond_secret_storage_open_db().
398 * Returns: TRUE if successful, FALSE otherwise.
401 gsignond_secret_storage_close_db (GSignondSecretStorage *self)
403 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->close_db (self);
407 * gsignond_secret_storage_clear_db:
408 * @self: instance of #GSignondSecretStorage
410 * Removes all stored secrets from the database.
412 * Returns: TRUE if successful, FALSE otherwise.
415 gsignond_secret_storage_clear_db (GSignondSecretStorage *self)
417 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->clear_db (self);
421 * gsignond_secret_storage_is_open_db:
422 * @self: instance of #GSignondSecretStorage
424 * Checks if the database is open or not.
426 * Returns: TRUE if successful, FALSE otherwise.
429 gsignond_secret_storage_is_open_db (GSignondSecretStorage *self)
431 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->is_open_db (self);
435 * gsignond_secret_storage_load_credentials:
436 * @self: instance of #GSignondSecretStorage
437 * @id: the identity id whose credentials are being loaded.
439 * Loads the credentials from the database.
441 * Returns: (transfer full): #GSignondCredentials if successful,
445 gsignond_secret_storage_load_credentials (
446 GSignondSecretStorage *self,
449 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->load_credentials (self, id);
453 * gsignond_secret_storage_update_credentials:
454 * @self: instance of #GSignondSecretStorage
455 * @creds: (transfer none): the credentials that are being updated.
457 * Stores/updates the credentials for the given identity.
459 * Returns: TRUE if successful, FALSE otherwise.
462 gsignond_secret_storage_update_credentials (
463 GSignondSecretStorage *self,
464 GSignondCredentials *creds)
466 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->update_credentials (self, creds);
470 * gsignond_secret_storage_remove_credentials:
471 * @self: instance of #GSignondSecretStorage
472 * @id: the identity whose credentials are being updated.
474 * Remove the credentials for the given identity.
476 * Returns: TRUE if successful, FALSE otherwise.
479 gsignond_secret_storage_remove_credentials (
480 GSignondSecretStorage *self,
483 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->remove_credentials (self, id);
487 * gsignond_secret_storage_check_credentials:
488 * @self: instance of #GSignondSecretStorage
489 * @creds: (transfer none): the credentials that are being checked.
491 * Checks whether the given credentials match what is stored in the database.
493 * Returns: TRUE if successful, FALSE otherwise.
496 gsignond_secret_storage_check_credentials (
497 GSignondSecretStorage *self,
498 GSignondCredentials *creds)
500 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->check_credentials (self, creds);
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.
509 * Loads the secret data associated with a given identity and method.
511 * Returns: (transfer full): the secret data
514 gsignond_secret_storage_load_data (
515 GSignondSecretStorage *self,
517 const guint32 method)
519 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->load_data (self, id, method);
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
529 * Calling this method updates the secret data
530 * associated with the given id/method.
532 * Returns: TRUE if successful, FALSE otherwise.
535 gsignond_secret_storage_update_data (
536 GSignondSecretStorage *self,
538 const guint32 method,
539 GSignondDictionary *data)
541 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->update_data (self, id, method, data);
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.
550 * Removes secret data associated with a given id/method.
552 * Returns: TRUE if successful, FALSE otherwise.
555 gsignond_secret_storage_remove_data (
556 GSignondSecretStorage *self,
558 const guint32 method)
560 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->remove_data (self, id, method);
564 * gsignond_secret_storage_get_last_error:
565 * @self: instance of #GSignondSecretStorage
567 * Retrieves the last occurred error that has occured
569 * Returns: (transfer none): last occurred #GError
572 gsignond_secret_storage_get_last_error (GSignondSecretStorage *self)
574 return GSIGNOND_SECRET_STORAGE_GET_CLASS (self)->get_last_error (self);