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
31 #include "gsignond/gsignond-log.h"
32 #include "gsignond/gsignond-config.h"
33 #include "common/db/gsignond-db-error.h"
34 #include "common/gsignond-identity-info-internal.h"
35 #include "gsignond-db-metadata-database.h"
37 #define GSIGNOND_METADATA_DB_FILENAME "metadata.db"
39 #define RETURN_IF_NOT_OPEN(obj, retval) \
40 if (gsignond_db_sql_database_is_open (obj) == FALSE) { \
41 GError* last_error = gsignond_db_create_error( \
42 GSIGNOND_DB_ERROR_NOT_OPEN,\
44 DBG("MetadataDB is not available"); \
45 gsignond_db_sql_database_set_last_error(obj,\
50 #define GSIGNOND_DB_METADATA_DATABASE_GET_PRIVATE(obj) \
51 (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
52 GSIGNOND_DB_TYPE_METADATA_DATABASE, \
53 GSignondDbMetadataDatabasePrivate))
55 G_DEFINE_TYPE (GSignondDbMetadataDatabase, gsignond_db_metadata_database,
56 GSIGNOND_DB_TYPE_SQL_DATABASE);
58 struct _GSignondDbMetadataDatabasePrivate
69 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
72 _set_property (GObject *object, guint prop_id, const GValue *value,
75 GSignondDbMetadataDatabase *self = GSIGNOND_DB_METADATA_DATABASE (object);
79 g_assert (self->config == NULL);
80 self->config = g_value_dup_object (value);
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
90 GSignondDbMetadataDatabase *self = GSIGNOND_DB_METADATA_DATABASE (object);
94 g_value_set_object (value, self->config);
97 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
102 _gsignond_db_metadata_database_open (
103 GSignondDbSqlDatabase *obj,
104 const gchar *filename,
108 _gsignond_db_metadata_database_create (
109 GSignondDbSqlDatabase *obj);
112 _gsignond_db_metadata_database_clear (
113 GSignondDbSqlDatabase *obj);
116 * @enum GSignondIdentityFlags
117 * Flags for the identity to be stored into db
119 enum GSignondIdentityFlags {
120 GSignondIdentityFlag_Validated = 0x0001,
121 GSignondIdentityFlag_RememberSecret = 0x0002,
122 GSignondIdentityFlag_UserNameIsSecret = 0x0004,
132 return g_strcmp0 (a,b);
136 _gsignond_db_metadata_database_list_to_sequence (GList *list)
138 GSequence *seq = NULL;
139 seq = g_sequence_new ((GDestroyNotify)g_free);
140 list = g_list_first (list);
141 for ( ; list != NULL; list = g_list_next (list)) {
142 g_sequence_insert_sorted (seq, (gchar *) list->data,
143 (GCompareDataFunc)_compare_strings, NULL);
149 _gsignond_db_metadata_database_read_identity (
151 GSignondIdentityInfo *identity)
155 gsignond_identity_info_set_caption (identity,
156 (const gchar *)sqlite3_column_text (stmt, 0));
158 flags = sqlite3_column_int (stmt, 2);
160 gsignond_identity_info_set_username_secret (identity,
161 flags & GSignondIdentityFlag_UserNameIsSecret);
163 if (flags & GSignondIdentityFlag_UserNameIsSecret) {
164 gsignond_identity_info_set_caption (identity, "");
166 gsignond_identity_info_set_username (identity,
167 (const gchar *)sqlite3_column_text (stmt, 1));
170 gsignond_identity_info_set_store_secret (identity,
171 flags & GSignondIdentityFlag_RememberSecret);
173 gsignond_identity_info_set_validated (identity,
174 flags & GSignondIdentityFlag_Validated);
176 gsignond_identity_info_set_identity_type (identity,
177 sqlite3_column_int (stmt, 3));
183 _gsignond_db_metadata_database_exec (
184 GSignondDbMetadataDatabase *self,
185 const gchar *query_format,
188 gboolean ret = FALSE;
192 g_return_val_if_fail (query_format != NULL, FALSE);
194 va_start (args, query_format);
195 query = sqlite3_vmprintf (query_format, args);
198 ret = gsignond_db_sql_database_exec (
199 GSIGNOND_DB_SQL_DATABASE (self),
201 sqlite3_free (query);
208 _gsignond_db_metadata_database_get_sequence (
209 GSignondDbMetadataDatabase *self,
210 const gchar *query_format,
213 GSequence *seq = NULL;
218 g_return_val_if_fail (query_format != NULL, NULL);
220 va_start (args, query_format);
221 query = sqlite3_vmprintf (query_format, args);
224 list = gsignond_db_sql_database_query_exec_string_list (
225 GSIGNOND_DB_SQL_DATABASE (self),
227 sqlite3_free (query);
228 seq = _gsignond_db_metadata_database_list_to_sequence (list);
229 g_list_free (list); /*list elements are owned by sequence*/
235 _gsignond_db_metadata_database_update_credentials (
236 GSignondDbMetadataDatabase *self,
237 GSignondIdentityInfo *identity)
243 const gchar *caption= NULL, *username = NULL;
244 gboolean ret = FALSE;
246 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), 0);
247 g_return_val_if_fail (identity != NULL, 0);
249 if (gsignond_identity_info_get_validated (identity) )
250 flags |= GSignondIdentityFlag_Validated;
251 if (gsignond_identity_info_get_store_secret (identity) )
252 flags |= GSignondIdentityFlag_RememberSecret;
253 if (gsignond_identity_info_get_is_username_secret (identity) ) {
254 flags |= GSignondIdentityFlag_UserNameIsSecret;
256 username = gsignond_identity_info_get_username (identity);
258 caption = gsignond_identity_info_get_caption (identity);
260 id = gsignond_identity_info_get_id (identity);
261 type = gsignond_identity_info_get_identity_type (identity);
262 if (!gsignond_identity_info_get_is_identity_new (identity)) {
263 query = sqlite3_mprintf ("UPDATE IDENTITY SET caption = %Q, "
264 "username = %Q, flags = %u, type = %u WHERE id = %u;",
265 caption ?caption : "",username? username : "", flags, type, id);
267 query = sqlite3_mprintf ("INSERT INTO IDENTITY "
268 "(caption, username, flags, type) "
269 "VALUES(%Q, %Q, %u, %u);",
270 caption ?caption : "",username? username : "", flags, type);
272 ret = gsignond_db_sql_database_exec (
273 GSIGNOND_DB_SQL_DATABASE (self),
275 sqlite3_free (query);
280 if (gsignond_identity_info_get_is_identity_new (identity)) {
281 id = gsignond_db_sql_database_get_last_insert_rowid (
282 GSIGNOND_DB_SQL_DATABASE (self));
288 _gsignond_db_metadata_database_update_realms (
289 GSignondDbMetadataDatabase *self,
290 GSignondIdentityInfo *identity,
294 GSequenceIter *iter = NULL;
296 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
297 g_return_val_if_fail (identity != NULL, FALSE);
299 if (realms && g_sequence_get_length (realms) > 0) {
301 if (!gsignond_identity_info_get_is_identity_new (identity)) {
302 /* remove realms list */
303 DBG ("Remove old realms from DB as identity is not new");
304 _gsignond_db_metadata_database_exec (self,
305 "DELETE FROM REALMS WHERE identity_id = %u;", id);
309 iter = g_sequence_get_begin_iter (realms);
310 while (!g_sequence_iter_is_end (iter)) {
311 if (!_gsignond_db_metadata_database_exec (self,
312 "INSERT OR IGNORE INTO REALMS (identity_id, realm) "
314 id, (const gchar *)g_sequence_get (iter))) {
315 DBG ("Insert realms to DB failed");
318 iter = g_sequence_iter_next (iter);
325 _gsignond_db_metadata_database_insert_methods (
326 GSignondDbMetadataDatabase *self,
327 GSignondIdentityInfo *identity,
330 GSequenceIter *mech_iter = NULL;
331 GHashTableIter method_iter;
332 const gchar *method = NULL;
333 GSequence *mechanisms = NULL;
335 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
336 g_return_val_if_fail (identity != NULL, FALSE);
338 if (!methods || g_hash_table_size (methods) <=0) {
339 DBG ("no authentication methods found to store identity");
343 g_hash_table_iter_init (&method_iter, methods);
344 while (g_hash_table_iter_next (&method_iter,
346 (gpointer)&mechanisms))
348 if (!_gsignond_db_metadata_database_exec ( self,
349 "INSERT OR IGNORE INTO METHODS (method) "
352 DBG ("Insert methods to DB failed");
355 /* mechanisms insert */
356 mech_iter = g_sequence_get_begin_iter (mechanisms);
357 while (!g_sequence_iter_is_end (mech_iter)) {
358 if (!_gsignond_db_metadata_database_exec (self,
359 "INSERT OR IGNORE INTO MECHANISMS (mechanism) "
361 g_sequence_get (mech_iter))) {
362 DBG ("Insert mechanisms to DB failed");
365 mech_iter = g_sequence_iter_next (mech_iter);
373 _gsignond_db_metadata_database_update_acl (
374 GSignondDbMetadataDatabase *self,
375 GSignondIdentityInfo *identity,
376 GSignondSecurityContextList *acl)
378 GSignondSecurityContextList *list = NULL;
379 GSignondSecurityContext *ctx = NULL;
381 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
382 g_return_val_if_fail (identity != NULL, FALSE);
384 if (!acl || g_list_length (acl) <= 0) {
385 DBG ("NULL acl or no acl to be added to DB");
389 for (list = acl; list != NULL; list = g_list_next (list)) {
390 ctx = (GSignondSecurityContext *) list->data;
391 _gsignond_db_metadata_database_exec (self,
392 "INSERT OR IGNORE INTO SECCTX (sysctx, appctx) "
394 ctx->sys_ctx, ctx->app_ctx);
400 _gsignond_db_metadata_database_update_owner (
401 GSignondDbMetadataDatabase *self,
402 GSignondIdentityInfo *identity,
403 GSignondSecurityContext *owner)
405 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
406 g_return_val_if_fail (identity != NULL, FALSE);
409 DBG ("no owner to be added to DB");
413 if (owner->sys_ctx && strlen (owner->sys_ctx) > 0) {
414 _gsignond_db_metadata_database_exec (self,
415 "INSERT OR IGNORE INTO "
416 "SECCTX (sysctx, appctx) "
418 owner->sys_ctx, owner->app_ctx);
425 _gsignond_db_metadata_database_dispose (GObject *gobject)
427 g_return_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (gobject));
428 GSignondDbMetadataDatabase *self = GSIGNOND_DB_METADATA_DATABASE (gobject);
431 g_object_unref (self->config);
435 /* Chain up to the parent class */
436 G_OBJECT_CLASS (gsignond_db_metadata_database_parent_class)->dispose (
441 gsignond_db_metadata_database_class_init (
442 GSignondDbMetadataDatabaseClass *klass)
444 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
446 gobject_class->set_property = _set_property;
447 gobject_class->get_property = _get_property;
448 gobject_class->dispose = _gsignond_db_metadata_database_dispose;
450 properties[PROP_CONFIG] = g_param_spec_object ("config",
452 "Configuration object",
453 GSIGNOND_TYPE_CONFIG,
454 G_PARAM_CONSTRUCT_ONLY |
456 G_PARAM_STATIC_STRINGS);
457 g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
459 GSignondDbSqlDatabaseClass *sql_class =
460 GSIGNOND_DB_SQL_DATABASE_CLASS (klass);
462 sql_class->create = _gsignond_db_metadata_database_create;
463 sql_class->clear = _gsignond_db_metadata_database_clear;
468 gsignond_db_metadata_database_init (
469 GSignondDbMetadataDatabase *self)
475 * gsignond_db_metadata_database_new:
477 * @config: (transfer none) #GSignondConfig config data
479 * Creates new #GSignondDbMetadataDatabase object
481 * Returns : (transfer full) the #GSignondDbMetadataDatabase object
483 GSignondDbMetadataDatabase *
484 gsignond_db_metadata_database_new (GSignondConfig *config)
486 return GSIGNOND_DB_METADATA_DATABASE (
487 g_object_new (GSIGNOND_DB_TYPE_METADATA_DATABASE,
488 "config", config, NULL));
492 _gsignond_db_metadata_database_open (
493 GSignondDbSqlDatabase *obj,
494 const gchar *filename,
497 const gchar *dir = NULL;
498 gchar *db_filename = NULL;
499 gboolean ret = FALSE;
500 gint dir_created = 0;
501 GSignondDbMetadataDatabase *self = NULL;
503 self = GSIGNOND_DB_METADATA_DATABASE (obj);
505 g_return_val_if_fail (self, FALSE);
507 if (!filename || strlen (filename) <= 0) {
508 ERR ("Missing Metadata DB filename");
511 dir = gsignond_config_get_string (self->config,
512 GSIGNOND_CONFIG_GENERAL_SECURE_DIR);
514 ERR ("Invalid Metadata DB directory");
517 db_filename = g_build_filename (dir, filename, NULL);
519 ERR ("Invalid Metadata DB filename");
523 dir_created = g_mkdir_with_parents (dir, S_IRWXU);
524 if (dir_created != 0) {
525 ERR ("Metadata DB directory does not exist");
529 ret = gsignond_db_sql_database_open (obj, db_filename, flags);
532 g_free (db_filename);
537 _gsignond_db_metadata_database_create (
538 GSignondDbSqlDatabase *obj)
540 const gchar *queries = NULL;
541 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (obj), FALSE);
542 RETURN_IF_NOT_OPEN (obj, FALSE);
546 queries = "PRAGMA foreign_keys = 1;";
547 if (!gsignond_db_sql_database_exec (obj, queries)) {
548 ERR ("Metadata DB enabling foreign keys failed");
552 gsignond_db_sql_database_query_exec_int (obj, "PRAGMA foreign_keys;",
555 ERR ("Metadata DB - foreign keys not enabled");
559 version = gsignond_db_sql_database_get_db_version(obj,
560 "PRAGMA user_version;");
562 DBG ("Metadata DB is already created with with version (%d) and "
563 "foreign keys enabled (%d)", version, fk_enabled);
567 queries = "PRAGMA user_version = 1;";
568 if (!gsignond_db_sql_database_exec (obj, queries)) {
569 DBG ("Metadata DB setting version failed");
573 version = gsignond_db_sql_database_get_db_version(obj,
574 "PRAGMA user_version;");
575 DBG ("Metadata DB is to be created with version (%d) and foreign keys "
576 "enabled(%d)", version, fk_enabled);
579 "CREATE TABLE IDENTITY"
580 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
586 "CREATE TABLE METHODS"
587 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
588 "method TEXT UNIQUE);"
590 "CREATE TABLE MECHANISMS"
591 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
592 "mechanism TEXT UNIQUE);"
594 "CREATE TABLE SECCTX"
595 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
598 "CONSTRAINT tokc UNIQUE(sysctx, appctx) ON CONFLICT REPLACE);"
600 "CREATE INDEX sysidx ON SECCTX(sysctx);"
601 "CREATE INDEX appidx ON SECCTX(appctx);"
603 "CREATE TABLE REALMS"
604 "(identity_id INTEGER CONSTRAINT fk_identity_id "
605 "REFERENCES IDENTITY(id) ON DELETE CASCADE,"
608 "PRIMARY KEY (identity_id, realm, hostname));"
611 "(rowid INTEGER PRIMARY KEY AUTOINCREMENT,"
612 "identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES "
613 "IDENTITY(id) ON DELETE CASCADE,"
614 "method_id INTEGER CONSTRAINT fk_method_id REFERENCES "
616 "mechanism_id INTEGER CONSTRAINT fk_mechanism_id "
617 "REFERENCES MECHANISMS(id),"
618 "secctx_id INTEGER CONSTRAINT fk_secctx_id REFERENCES "
622 "(identity_id INTEGER CONSTRAINT fk_identity_id "
623 "REFERENCES IDENTITY(id) ON DELETE CASCADE,"
624 "secctx_id INTEGER CONSTRAINT fk_secctx_id REFERENCES "
627 "PRIMARY KEY (identity_id, secctx_id, ref));"
630 "(rowid INTEGER PRIMARY KEY AUTOINCREMENT,"
631 "identity_id INTEGER CONSTRAINT fk_identity_id "
632 "REFERENCES IDENTITY(id) ON DELETE CASCADE,"
633 "secctx_id INTEGER CONSTRAINT fk_secctx_id REFERENCES SECCTX(id) "
636 // Triggers for deleting orphan SECCTX entries
637 "CREATE TRIGGER fkdstale_ACL_secctx_id_SECCTX_id"
638 "BEFORE DELETE ON [ACL]"
640 " DELETE FROM SECCTX WHERE SECCTX.id = OLD.secctx_id AND "
641 " (SELECT COUNT(*) FROM REFS WHERE "
642 " REFS.secctx_id = OLD.secctx_id) == 0 AND "
643 " (SELECT COUNT(*) FROM OWNER WHERE "
644 " OWNER.secctx_id = OLD.secctx_id) == 0;"
647 "CREATE TRIGGER fkdstale_REFS_secctx_id_SECCTX_id"
648 "BEFORE DELETE ON [REFS]"
650 " DELETE FROM SECCTX WHERE SECCTX.id = OLD.secctx_id AND "
651 " (SELECT COUNT(*) FROM ACL WHERE "
652 " ACL.secctx_id = OLD.secctx_id) == 0 AND "
653 " (SELECT COUNT(*) FROM OWNER WHERE "
654 " OWNER.secctx_id = OLD.secctx_id) == 0;"
657 "CREATE TRIGGER fkdstale_OWNER_secctx_id_SECCTX_id"
658 "BEFORE DELETE ON [OWNER]"
660 " DELETE FROM SECCTX WHERE SECCTX.id = OLD.secctx_id AND "
661 " (SELECT COUNT(*) FROM ACL WHERE "
662 " ACL.secctx_id = OLD.secctx_id) == 0 AND "
663 " (SELECT COUNT(*) FROM REFS WHERE "
664 " REFS.secctx_id = OLD.secctx_id) == 0;"
667 #ifdef ENABLE_DB_ACL_TRIGGERS
668 // Trigger for deleting orphan METHODS entries
669 "CREATE TRIGGER fkdstale_ACL_method_id_METHODS_id"
670 "BEFORE DELETE ON [ACL]"
672 " DELETE FROM METHODS WHERE METHODS.id = OLD.method_id AND "
673 " (SELECT COUNT(*) FROM ACL WHERE "
674 " ACL.method_id = OLD.method_id) == 1;"
677 // Trigger for deleting orphan MECHANISMS entries
678 "CREATE TRIGGER fkdstale_ACL_mechanism_id_MECHANISMS_id"
679 "BEFORE DELETE ON [ACL]"
681 " DELETE FROM MECHANISMS WHERE MECHANISMS.id = OLD.mechanism_id "
682 " AND (SELECT COUNT(*) FROM ACL WHERE "
683 " ACL.mechanism_id = OLD.mechanism_id) == 1;"
688 * triggers generated with
689 * http://www.rcs-comp.com/site/index.php/view/Utilities-
690 * SQLite_foreign_key_trigger_generator
692 /* insert triggers to force foreign keys support */
693 // Foreign Key Preventing insert
694 "CREATE TRIGGER fki_REALMS_identity_id_IDENTITY_id"
695 "BEFORE INSERT ON [REALMS]"
697 " SELECT RAISE(ROLLBACK, 'insert on table REALMS violates foreign "
698 "key constraint fki_REALMS_identity_id_IDENTITY_id')"
699 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM IDENTITY "
700 "WHERE id = NEW.identity_id) IS NULL;"
703 // Foreign key preventing update
704 "CREATE TRIGGER fku_REALMS_identity_id_IDENTITY_id"
705 "BEFORE UPDATE ON [REALMS]"
707 " SELECT RAISE(ROLLBACK, 'update on table REALMS violates "
708 "foreign key constraint fku_REALMS_identity_id_IDENTITY_id')"
709 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM "
710 "IDENTITY WHERE id = NEW.identity_id) IS NULL;"
713 // Foreign Key Preventing insert
714 "CREATE TRIGGER fki_ACL_identity_id_IDENTITY_id"
715 "BEFORE INSERT ON [ACL]"
717 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign "
718 "key constraint fki_ACL_identity_id_IDENTITY_id')"
719 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM IDENTITY "
720 "WHERE id = NEW.identity_id) IS NULL;"
723 // Foreign key preventing update
724 "CREATE TRIGGER fku_ACL_identity_id_IDENTITY_id"
725 "BEFORE UPDATE ON [ACL]"
727 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign "
728 "key constraint fku_ACL_identity_id_IDENTITY_id')"
729 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM "
730 "IDENTITY WHERE id = NEW.identity_id) IS NULL;"
733 // Foreign Key Preventing insert
734 "CREATE TRIGGER fki_ACL_method_id_METHODS_id"
735 "BEFORE INSERT ON [ACL]"
737 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign "
738 "key constraint fki_ACL_method_id_METHODS_id')"
739 " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS "
740 "WHERE id = NEW.method_id) IS NULL;"
743 // Foreign key preventing update
744 "CREATE TRIGGER fku_ACL_method_id_METHODS_id"
745 "BEFORE UPDATE ON [ACL]"
747 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign "
748 "key constraint fku_ACL_method_id_METHODS_id')"
749 " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS "
750 "WHERE id = NEW.method_id) IS NULL;"
753 // Foreign Key Preventing insert
754 "CREATE TRIGGER fki_ACL_mechanism_id_MECHANISMS_id"
755 "BEFORE INSERT ON [ACL]"
757 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign "
758 "key constraint fki_ACL_mechanism_id_MECHANISMS_id')"
759 " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM "
760 "MECHANISMS WHERE id = NEW.mechanism_id) IS NULL;"
763 // Foreign key preventing update
764 "CREATE TRIGGER fku_ACL_mechanism_id_MECHANISMS_id"
765 "BEFORE UPDATE ON [ACL]"
767 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign "
768 "key constraint fku_ACL_mechanism_id_MECHANISMS_id')"
769 " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM "
770 "MECHANISMS WHERE id = NEW.mechanism_id) IS NULL;"
773 // Foreign Key Preventing insert
774 "CREATE TRIGGER fki_ACL_secctx_id_SECCTX_id"
775 "BEFORE INSERT ON [ACL]"
777 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign "
778 "key constraint fki_ACL_secctx_id_SECCTX_id')"
779 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
780 "WHERE id = NEW.secctx_id) IS NULL;"
783 // Foreign key preventing update
784 "CREATE TRIGGER fku_ACL_secctx_id_SECCTX_id"
785 "BEFORE UPDATE ON [ACL]"
787 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign "
788 "key constraint fku_ACL_secctx_id_SECCTX_id')"
789 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
790 "WHERE id = NEW.secctx_id) IS NULL;"
793 // Foreign Key Preventing insert
794 "CREATE TRIGGER fki_REFS_identity_id_IDENTITY_id"
795 "BEFORE INSERT ON [REFS]"
797 " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign "
798 "key constraint fki_REFS_identity_id_IDENTITY_id')"
799 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM IDENTITY "
800 "WHERE id = NEW.identity_id) IS NULL;"
803 // Foreign key preventing update
804 "CREATE TRIGGER fku_REFS_identity_id_IDENTITY_id"
805 "BEFORE UPDATE ON [REFS]"
807 " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign "
808 "key constraint fku_REFS_identity_id_IDENTITY_id')"
809 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM "
810 "IDENTITY WHERE id = NEW.identity_id) IS NULL;"
813 // Foreign Key Preventing insert
814 "CREATE TRIGGER fki_REFS_secctx_id_SECCTX_id"
815 "BEFORE INSERT ON [REFS]"
817 " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign "
818 "key constraint fki_REFS_secctx_id_SECCTX_id')"
819 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
820 "WHERE id = NEW.secctx_id) IS NULL;"
823 // Foreign key preventing update
824 "CREATE TRIGGER fku_REFS_secctx_id_SECCTX_id"
825 "BEFORE UPDATE ON [REFS]"
827 " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign "
828 "key constraint fku_REFS_secctx_id_SECCTX_id')"
829 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
830 "WHERE id = NEW.secctx_id) IS NULL;"
833 // Foreign Key Preventing insert
834 "CREATE TRIGGER fki_OWNER_identity_id_IDENTITY_id"
835 "BEFORE INSERT ON [OWNER]"
837 " SELECT RAISE(ROLLBACK, 'insert on table OWNER violates "
838 "foreign key constraint fki_OWNER_identity_id_IDENTITY_id')"
839 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM "
840 "IDENTITY WHERE id = NEW.identity_id) IS NULL;"
843 // Foreign key preventing update
844 "CREATE TRIGGER fku_OWNER_identity_id_IDENTITY_id"
845 "BEFORE UPDATE ON [OWNER]"
847 " SELECT RAISE(ROLLBACK, 'update on table OWNER violates "
848 "foreign key constraint fku_OWNER_identity_id_IDENTITY_id')"
849 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM "
850 "IDENTITY WHERE id = NEW.identity_id) IS NULL;"
853 // Foreign Key Preventing insert
854 "CREATE TRIGGER fki_OWNER_secctx_id_SECCTX_id"
855 "BEFORE INSERT ON [OWNER]"
857 " SELECT RAISE(ROLLBACK, 'insert on table OWNER violates foreign "
858 "key constraint fki_OWNER_secctx_id_SECCTX_id')"
859 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
860 "WHERE id = NEW.secctx_id) IS NULL;"
863 // Foreign key preventing update
864 "CREATE TRIGGER fku_OWNER_secctx_id_SECCTX_id"
865 "BEFORE UPDATE ON [OWNER]"
867 " SELECT RAISE(ROLLBACK, 'update on table OWNER violates "
868 "foreign key constraint fku_OWNER_secctx_id_SECCTX_id')"
869 " WHERE NEW.secctx_id IS NOT NULL AND (SELECT id FROM SECCTX "
870 "WHERE id = NEW.secctx_id) IS NULL;"
874 return gsignond_db_sql_database_transaction_exec (obj, queries);
878 _gsignond_db_metadata_database_clear (
879 GSignondDbSqlDatabase *obj)
881 const gchar *queries = NULL;
883 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (obj), FALSE);
884 RETURN_IF_NOT_OPEN (obj, FALSE);
887 "DELETE FROM IDENTITY;"
888 "DELETE FROM METHODS;"
889 "DELETE FROM MECHANISMS;"
891 "DELETE FROM REALMS;"
892 "DELETE FROM SECCTX;"
893 "DELETE FROM OWNER;";
895 return gsignond_db_sql_database_transaction_exec (obj, queries);
899 * gsignond_db_metadata_database_open:
901 * @self: instance of #GSignondDbMetadataDatabase
903 * Opens a connection to DB.
905 * Returns: TRUE if successful, FALSE otherwise.
908 gsignond_db_metadata_database_open (GSignondDbMetadataDatabase *self)
910 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
912 if (gsignond_db_sql_database_is_open (GSIGNOND_DB_SQL_DATABASE (self)))
915 return _gsignond_db_metadata_database_open (
916 GSIGNOND_DB_SQL_DATABASE (self),
917 GSIGNOND_METADATA_DB_FILENAME,
918 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
922 * gsignond_db_metadata_database_insert_method:
924 * @self: instance of #GSignondDbMetadataDatabase
925 * @method: the method to be inserted
926 * @method_id: (transfer none) id of the method inserted
928 * Inserts the method into the db.
930 * Returns: TRUE if successful, FALSE otherwise
933 gsignond_db_metadata_database_insert_method (
934 GSignondDbMetadataDatabase *self,
939 gboolean ret = FALSE;
942 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
943 g_return_val_if_fail (method != NULL, FALSE);
944 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), FALSE);
946 query = sqlite3_mprintf ("INSERT INTO METHODS (method) "
949 ret = gsignond_db_sql_database_transaction_exec (
950 GSIGNOND_DB_SQL_DATABASE (self), query);
951 sqlite3_free (query);
953 DBG ("Retrieve method id for the inserted method");
954 *method_id = gsignond_db_metadata_database_get_method_id (self, method);
960 * gsignond_db_metadata_database_get_method_id:
962 * @self: instance of #GSignondDbMetadataDatabase
963 * @method: the method to be fetched
965 * Fetches the id of the specified method.
967 * Returns: the method if successful, 0 otherwise
970 gsignond_db_metadata_database_get_method_id (
971 GSignondDbMetadataDatabase *self,
977 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
978 g_return_val_if_fail (method != NULL, FALSE);
979 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), method_id);
981 query = sqlite3_mprintf ("SELECT id FROM METHODS "
982 "WHERE method = %Q;",
984 gsignond_db_sql_database_query_exec_int (
985 GSIGNOND_DB_SQL_DATABASE (self),
988 sqlite3_free (query);
990 return (guint32) method_id;
994 * gsignond_db_metadata_database_get_methods:
996 * @self: instance of #GSignondDbMetadataDatabase
997 * @identity_id: the id of the identity
998 * @sec_ctx: the security context
1000 * Fetches the list of the methods with the specified identity id.
1002 * Returns: (transfer full) the list if successful, NULL otherwise.
1003 * When done list should be freed with g_list_free_full (list, g_free)
1006 gsignond_db_metadata_database_get_methods (
1007 GSignondDbMetadataDatabase *self,
1008 const guint32 identity_id,
1009 GSignondSecurityContext* sec_ctx)
1011 gchar *query = NULL;
1012 GList *methods = NULL;
1014 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), NULL);
1015 g_return_val_if_fail (sec_ctx != NULL, NULL);
1016 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1018 if (sec_ctx->sys_ctx && strlen (sec_ctx->sys_ctx) <= 0) {
1019 query = sqlite3_mprintf ("SELECT DISTINCT METHODS.method FROM "
1020 "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) "
1021 "WHERE ACL.identity_id = %u;",
1024 query = sqlite3_mprintf ("SELECT DISTINCT METHODS.method FROM "
1025 "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) "
1026 "WHERE ACL.identity_id = %u AND ACL.secctx_id = "
1027 "(SELECT id FROM SECCTX "
1028 "WHERE sysctx = %Q AND appctx = %Q);",
1029 identity_id, sec_ctx->sys_ctx, sec_ctx->app_ctx);
1032 methods = gsignond_db_sql_database_query_exec_string_list (
1033 GSIGNOND_DB_SQL_DATABASE (self),
1035 sqlite3_free (query);
1041 * gsignond_db_metadata_database_update_identity:
1043 * @self: instance of #GSignondDbMetadataDatabase
1044 * @identity: the identity #GSignondIdentityInfo object
1046 * Updates the database with the data in the identity.
1048 * Returns: the id of the identity if successful, 0 otherwise
1051 gsignond_db_metadata_database_update_identity (
1052 GSignondDbMetadataDatabase *self,
1053 GSignondIdentityInfo *identity)
1055 GSignondDbSqlDatabase *sql = NULL;
1058 GHashTable *methods = NULL;
1059 GSequence *realms = NULL;
1060 GSignondSecurityContextList *acl = NULL, *list = NULL;
1061 GSignondSecurityContext *owner = NULL;
1062 GHashTableIter method_iter;
1063 const gchar *method = NULL;
1064 GSequence *mechanisms = NULL;
1065 GSignondIdentityInfoPropFlags edit_flags;
1066 gboolean was_new_identity;
1068 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), 0);
1069 g_return_val_if_fail (identity != NULL, 0);
1070 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), id);
1072 edit_flags = gsignond_identity_info_get_edit_flags (identity);
1074 DBG ("Identity EDIT FLAGS : %x", edit_flags);
1075 if (edit_flags == IDENTITY_INFO_PROP_NONE) {
1076 DBG("No Changes found to update");
1077 return gsignond_identity_info_get_id (identity);
1080 was_new_identity = gsignond_identity_info_get_is_identity_new (identity);
1082 sql = GSIGNOND_DB_SQL_DATABASE (self);
1083 if (!gsignond_db_sql_database_start_transaction (sql)) {
1088 id = _gsignond_db_metadata_database_update_credentials (self, identity);
1090 DBG ("Update credentials failed");
1091 gsignond_db_sql_database_rollback_transaction (sql);
1096 if (edit_flags & IDENTITY_INFO_PROP_REALMS) {
1097 realms = gsignond_identity_info_get_realms (identity);
1098 if (!_gsignond_db_metadata_database_update_realms (self,
1099 identity, id, realms)) {
1100 DBG ("Update realms failed");
1101 gsignond_db_sql_database_rollback_transaction (sql);
1107 owner = gsignond_identity_info_get_owner (identity);
1109 WARN("Missing mandatory owner field");
1110 gsignond_db_sql_database_rollback_transaction (sql);
1114 if (edit_flags & IDENTITY_INFO_PROP_OWNER) {
1115 if (!was_new_identity) {
1117 _gsignond_db_metadata_database_exec (self,
1118 "DELETE FROM OWNER WHERE identity_id = %u;", id);
1120 if (!_gsignond_db_metadata_database_update_owner (self, identity, owner)){
1121 DBG ("Update owner failed");
1122 gsignond_db_sql_database_rollback_transaction (sql);
1127 _gsignond_db_metadata_database_exec (self,
1128 "INSERT OR REPLACE INTO OWNER "
1129 "(identity_id, secctx_id) "
1131 "( SELECT id FROM SECCTX WHERE sysctx = %Q AND appctx = %Q ));",
1132 id, owner->sys_ctx, owner->app_ctx);
1136 acl = gsignond_identity_info_get_access_control_list (identity);
1138 WARN("Missing mandatory ACL field");
1139 gsignond_db_sql_database_rollback_transaction (sql);
1142 if (edit_flags & IDENTITY_INFO_PROP_ACL) {
1143 if (!was_new_identity) {
1145 _gsignond_db_metadata_database_exec (self,
1146 "DELETE FROM ACL WHERE identity_id = %u;", id);
1148 if (!_gsignond_db_metadata_database_update_acl (self, identity, acl)) {
1149 DBG ("Update acl failed");
1150 gsignond_db_sql_database_rollback_transaction (sql);
1156 methods = gsignond_identity_info_get_methods (identity);
1157 if (edit_flags & IDENTITY_INFO_PROP_METHODS) {
1158 if (!_gsignond_db_metadata_database_insert_methods (self, identity,
1160 DBG ("Update methods failed");
1164 if ((edit_flags & IDENTITY_INFO_PROP_ACL ||
1165 edit_flags & IDENTITY_INFO_PROP_METHODS) &&
1167 /* ACL insert, this will do basically identity level ACL */
1168 g_hash_table_iter_init (&method_iter, methods);
1169 while (g_hash_table_iter_next (&method_iter, (gpointer)&method,
1170 (gpointer)&mechanisms)) {
1172 if (g_list_length (acl) > 0) {
1173 for (list = acl; list != NULL; list = g_list_next (list)) {
1174 GSequenceIter *mech_iter = NULL;
1175 GSignondSecurityContext *ctx = NULL;
1177 ctx = (GSignondSecurityContext *) list->data;
1178 mech_iter = g_sequence_get_begin_iter (mechanisms);
1179 while (!g_sequence_iter_is_end (mech_iter)) {
1180 _gsignond_db_metadata_database_exec (self,
1181 "INSERT OR REPLACE INTO ACL "
1182 "(identity_id, method_id, mechanism_id, secctx_id) "
1184 "( SELECT id FROM METHODS WHERE method = %Q ),"
1185 "( SELECT id FROM MECHANISMS WHERE mechanism= %Q ),"
1186 " ( SELECT id FROM SECCTX WHERE sysctx = %Q "
1187 "AND appctx = %Q));",
1188 id, method, g_sequence_get (mech_iter),
1189 ctx->sys_ctx, ctx->app_ctx);
1190 mech_iter = g_sequence_iter_next (mech_iter);
1192 if (g_sequence_get_length (mechanisms) <= 0) {
1193 _gsignond_db_metadata_database_exec (self,
1194 "INSERT OR REPLACE INTO ACL "
1195 "(identity_id, method_id, secctx_id) "
1197 "( SELECT id FROM METHODS WHERE method = %Q),"
1198 "( SELECT id FROM SECCTX WHERE sysctx = %Q AND "
1200 id, method, ctx->sys_ctx, ctx->app_ctx);
1205 GSequenceIter *mech_iter = NULL;
1206 mech_iter = g_sequence_get_begin_iter (mechanisms);
1207 while (!g_sequence_iter_is_end (mech_iter)) {
1208 _gsignond_db_metadata_database_exec (self,
1209 "INSERT OR REPLACE INTO ACL "
1210 "(identity_id, method_id, mechanism_id) "
1212 "( SELECT id FROM METHODS WHERE method = %Q ),"
1213 "( SELECT id FROM MECHANISMS WHERE mechanism= %Q ));",
1214 id, method, g_sequence_get (mech_iter));
1215 mech_iter = g_sequence_iter_next (mech_iter);
1217 if (g_sequence_get_length (mechanisms) <= 0) {
1218 _gsignond_db_metadata_database_exec (self,
1219 "INSERT OR REPLACE INTO ACL (identity_id, method_id) "
1221 "( SELECT id FROM METHODS WHERE method = %Q ));",
1226 /* insert acl in case where methods are missing */
1227 if (g_hash_table_size (methods) <= 0) {
1228 for (list = acl; list != NULL; list = g_list_next (list)) {
1229 GSignondSecurityContext *ctx = NULL;
1231 ctx = (GSignondSecurityContext *) list->data;
1232 _gsignond_db_metadata_database_exec (self,
1233 "INSERT OR REPLACE INTO ACL "
1234 "(identity_id, secctx_id) "
1236 "( SELECT id FROM SECCTX WHERE sysctx = %Q AND "
1238 id, ctx->sys_ctx, ctx->app_ctx);
1243 if (gsignond_db_sql_database_commit_transaction (sql)) {
1244 DBG ("Identity updated");
1249 if (methods) g_hash_table_unref (methods);
1250 if (realms) g_sequence_free (realms);
1251 if (acl) gsignond_security_context_list_free (acl);
1252 if (owner) gsignond_security_context_free (owner);
1258 * gsignond_db_metadata_database_update_identity:
1260 * @self: instance of #GSignondDbMetadataDatabase
1261 * @identity_id: the id of the identity
1263 * Reads the identity data from the database based on the given id.
1265 * Returns: (transfer full) the #GSignondIdentityInfo identity if successful,
1268 GSignondIdentityInfo *
1269 gsignond_db_metadata_database_get_identity (
1270 GSignondDbMetadataDatabase *self,
1271 const guint32 identity_id)
1273 GSignondIdentityInfo *identity = NULL;
1274 gchar *query = NULL;
1276 GSequence *realms = NULL, *mechanisms = NULL;
1277 GHashTable *methods = NULL, *tuples = NULL;
1278 GHashTableIter iter;
1279 gchar *method = NULL;
1281 GSignondSecurityContextList *acl = NULL;
1282 GSignondSecurityContext *owner = NULL;
1284 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), NULL);
1285 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1287 identity = gsignond_identity_info_new ();
1288 query = sqlite3_mprintf ("SELECT caption, username, flags, type "
1289 "FROM IDENTITY WHERE id = %u;",
1291 rows = gsignond_db_sql_database_query_exec (GSIGNOND_DB_SQL_DATABASE (self),
1292 query, (GSignondDbSqlDatabaseQueryCallback)
1293 _gsignond_db_metadata_database_read_identity,
1295 sqlite3_free (query);
1296 if (G_UNLIKELY (rows <= 0)) {
1297 DBG ("Fetch IDENTITY '%d' failed", identity_id);
1298 gsignond_identity_info_unref (identity);
1301 gsignond_identity_info_set_id (identity, identity_id);
1304 realms = _gsignond_db_metadata_database_get_sequence (self,
1305 "SELECT realm FROM REALMS "
1306 "WHERE identity_id = %u;",
1309 gsignond_identity_info_set_realms (identity, realms);
1310 g_sequence_free (realms);
1314 acl = gsignond_db_metadata_database_get_accesscontrol_list (self,
1317 gsignond_identity_info_set_access_control_list (identity, acl);
1318 gsignond_security_context_list_free (acl);
1322 owner = gsignond_db_metadata_database_get_owner (self,
1325 gsignond_identity_info_set_owner (identity, owner);
1326 gsignond_security_context_free (owner);
1330 query = sqlite3_mprintf ("SELECT DISTINCT ACL.method_id, METHODS.method "
1331 "FROM ( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) "
1332 "WHERE ACL.identity_id = %u;",
1334 tuples = gsignond_db_sql_database_query_exec_int_string_tuple (
1335 GSIGNOND_DB_SQL_DATABASE (self),
1337 sqlite3_free (query);
1340 methods = g_hash_table_new_full ((GHashFunc)g_str_hash,
1341 (GEqualFunc)g_str_equal,
1342 (GDestroyNotify)g_free,
1343 (GDestroyNotify)g_sequence_free);
1344 g_hash_table_iter_init(&iter, tuples);
1345 while (g_hash_table_iter_next (&iter, (gpointer *)&method_id,
1346 (gpointer *)&method)) {
1348 mechanisms = _gsignond_db_metadata_database_get_sequence (self,
1349 "SELECT DISTINCT MECHANISMS.mechanism FROM "
1350 "( MECHANISMS JOIN ACL ON ACL.mechanism_id = MECHANISMS.id ) "
1351 "WHERE ACL.method_id = %u AND ACL.identity_id = %u;",
1352 method_id, identity_id);
1353 g_hash_table_insert(methods, g_strdup(method), mechanisms);
1355 g_hash_table_destroy (tuples);
1356 gsignond_identity_info_set_methods (identity, methods);
1357 g_hash_table_destroy (methods);
1364 * gsignond_db_metadata_database_get_identities:
1366 * @self: instance of #GSignondDbMetadataDatabase
1367 * @filter: (transfer none) filter to apply (supported filters: Owner, Type & Caption)
1369 * Reads all the identities that are matched by applying @filter,
1370 * from the database into a list.
1372 * Returns: (transfer full) the list #GSignondIdentityInfoList if successful,
1373 * NULL otherwise. When done the list should be freed with
1374 * gsignond_identity_info_list_free
1376 GSignondIdentityInfoList *
1377 gsignond_db_metadata_database_get_identities (
1378 GSignondDbMetadataDatabase *self,
1379 GSignondDictionary *filter)
1381 GSignondIdentityInfoList *identities = NULL;
1382 gchar *owner_query = NULL;
1383 gchar *caption_query = NULL;
1384 gchar *type_query = NULL;
1385 gchar *query = NULL;
1389 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
1390 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1393 GVariant *owner_var = NULL;
1394 const gchar *caption = NULL;
1396 gboolean append_where = TRUE;
1398 if ((owner_var = gsignond_dictionary_get (filter, "Owner"))) {
1399 GSignondSecurityContext *owner_ctx =
1400 gsignond_security_context_from_variant(owner_var);
1401 owner_query = sqlite3_mprintf ("WHERE id IN "
1402 "(SELECT identity_id FROM owner WHERE secctx_id = "
1403 "(SELECT id FROM secctx WHERE sysctx=%Q AND appctx=%Q))",
1404 gsignond_security_context_get_system_context(owner_ctx),
1405 gsignond_security_context_get_application_context(owner_ctx));
1406 gsignond_security_context_free (owner_ctx);
1407 append_where = FALSE;
1410 if ((caption = gsignond_dictionary_get_string (filter, "Caption"))) {
1411 caption_query = sqlite3_mprintf (" %s caption like '%s%%'",
1412 append_where ? "WHERE" : "AND", caption);
1413 append_where = FALSE;
1416 if (gsignond_dictionary_get_int32 (filter, "Type", &type)) {
1417 type_query = sqlite3_mprintf (" %s type = %d",
1418 append_where ? "WHERE" : "AND", type);
1419 append_where = FALSE;
1423 query = sqlite3_mprintf ("SELECT id FROM IDENTITY %s%s%s ORDER BY id",
1424 owner_query ? owner_query : "",
1425 caption_query ? caption_query : "",
1426 type_query ? type_query : "");
1427 sqlite3_free(owner_query);
1428 sqlite3_free(caption_query);
1429 sqlite3_free(type_query);
1431 ids = gsignond_db_sql_database_query_exec_int_array (
1432 GSIGNOND_DB_SQL_DATABASE (self),
1434 sqlite3_free (query);
1436 DBG ("No identity found");
1440 for (i=0; i < ids->len; i++) {
1441 GSignondIdentityInfo *identity = NULL;
1442 identity = gsignond_db_metadata_database_get_identity (self,
1443 g_array_index (ids, gint, i));
1445 identities = g_list_append (identities, identity);
1448 g_array_free (ids, TRUE);
1453 * gsignond_db_metadata_database_remove_identity:
1455 * @self: instance of #GSignondDbMetadataDatabase
1456 * @identity_id: the id of the identity
1458 * Removes the identity data from the database based on the given id.
1460 * Returns: TRUE if successful,FALSE otherwise.
1463 gsignond_db_metadata_database_remove_identity (
1464 GSignondDbMetadataDatabase *self,
1465 const guint32 identity_id)
1467 gchar *queries = NULL;
1468 gboolean ret = FALSE;
1470 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
1471 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), FALSE);
1473 /* Triggers should handle the cleanup of other tables */
1474 queries = sqlite3_mprintf ("DELETE FROM IDENTITY WHERE id = %u;",
1476 ret = gsignond_db_sql_database_transaction_exec (
1477 GSIGNOND_DB_SQL_DATABASE (self), queries);
1478 sqlite3_free (queries);
1484 * gsignond_db_metadata_database_insert_reference:
1486 * @self: instance of #GSignondDbMetadataDatabase
1487 * @identity_id: the id of the identity
1488 * @ref_owner: the owner security context
1489 * @reference: reference for the given identity
1491 * Insert reference into the database for the given identity id.
1493 * Returns: TRUE if successful,FALSE otherwise.
1496 gsignond_db_metadata_database_insert_reference (
1497 GSignondDbMetadataDatabase *self,
1498 const guint32 identity_id,
1499 const GSignondSecurityContext *ref_owner,
1500 const gchar *reference)
1502 GSignondDbSqlDatabase *sql = NULL;
1504 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), 0);
1505 g_return_val_if_fail (ref_owner != NULL && reference != NULL, FALSE);
1506 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), FALSE);
1508 sql = GSIGNOND_DB_SQL_DATABASE (self);
1509 if (!gsignond_db_sql_database_start_transaction (sql)) {
1510 DBG ("Start transaction failed");
1514 if (!_gsignond_db_metadata_database_exec (self,
1515 "INSERT OR IGNORE INTO SECCTX (sysctx, appctx) "
1516 "VALUES ( %Q, %Q );", ref_owner->sys_ctx, ref_owner->app_ctx)) {
1517 DBG ("Insertion SECCTX to DB failed");
1518 gsignond_db_sql_database_rollback_transaction (sql);
1521 if (!_gsignond_db_metadata_database_exec (self,
1522 "INSERT OR REPLACE INTO REFS "
1523 "(identity_id, secctx_id, ref) "
1525 "( SELECT id FROM SECCTX "
1526 "WHERE sysctx = %Q AND appctx = %Q), %Q );",
1527 identity_id, ref_owner->sys_ctx, ref_owner->app_ctx, reference)) {
1528 DBG ("Insertion to REFS failed");
1529 gsignond_db_sql_database_rollback_transaction (sql);
1533 return gsignond_db_sql_database_commit_transaction (sql);
1537 * gsignond_db_metadata_database_remove_reference:
1539 * @self: instance of #GSignondDbMetadataDatabase
1540 * @identity_id: the id of the identity
1541 * @ref_owner: the owner security context
1542 * @reference: reference for the given identity
1544 * Removes reference from the database for the given identity id.
1546 * Returns: TRUE if successful,FALSE otherwise.
1549 gsignond_db_metadata_database_remove_reference (
1550 GSignondDbMetadataDatabase *self,
1551 const guint32 identity_id,
1552 const GSignondSecurityContext *ref_owner,
1553 const gchar *reference)
1555 GSignondDbSqlDatabase *sql = NULL;
1557 gboolean ret = TRUE;
1560 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), 0);
1561 g_return_val_if_fail (ref_owner != NULL, FALSE);
1562 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), FALSE);
1564 sql = GSIGNOND_DB_SQL_DATABASE (self);
1565 if (!gsignond_db_sql_database_start_transaction (sql)) {
1566 DBG ("Start transaction failed");
1570 refs = gsignond_db_metadata_database_get_references (self,
1571 identity_id, ref_owner);
1573 len = g_list_length (refs);
1574 if (reference && !g_list_find_custom (refs, reference,
1575 (GCompareFunc)g_strcmp0))
1577 g_list_free_full (refs, (GDestroyNotify)g_free);
1578 if (len <= 0 || !ret) {
1579 DBG ("No ref found");
1580 gsignond_db_sql_database_rollback_transaction (sql);
1584 if (!reference || strlen (reference) <= 0) {
1585 ret = _gsignond_db_metadata_database_exec (self,
1587 "WHERE identity_id = %u AND "
1588 "secctx_id = ( SELECT id FROM SECCTX "
1589 "WHERE sysctx = %Q AND appctx = %Q );",
1590 identity_id, ref_owner->sys_ctx, ref_owner->app_ctx);
1592 ret = _gsignond_db_metadata_database_exec (self,
1594 "WHERE identity_id = %u AND "
1595 "secctx_id = ( SELECT id FROM SECCTX "
1596 "WHERE sysctx = %Q AND appctx = %Q ) "
1598 identity_id, ref_owner->sys_ctx, ref_owner->app_ctx, reference);
1601 DBG ("Delete refs from DB failed");
1602 gsignond_db_sql_database_rollback_transaction (sql);
1606 return gsignond_db_sql_database_commit_transaction (sql);
1610 * gsignond_db_metadata_database_get_references:
1612 * @self: instance of #GSignondDbMetadataDatabase
1613 * @identity_id: the id of the identity
1614 * @ref_owner: the owner security context
1616 * Gets references from the database for the given identity id.
1618 * Returns: (transfer full) the list #GList if successful,
1619 * NULL otherwise. When done the list should be freed with
1620 * g_list_free_full (list, g_free)
1623 gsignond_db_metadata_database_get_references (
1624 GSignondDbMetadataDatabase *self,
1625 const guint32 identity_id,
1626 const GSignondSecurityContext* ref_owner)
1628 gchar *query = NULL;
1631 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), NULL);
1632 g_return_val_if_fail (ref_owner != NULL, NULL);
1633 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1635 if (!ref_owner->sys_ctx || strlen (ref_owner->sys_ctx) <= 0) {
1636 query = sqlite3_mprintf ("SELECT ref FROM REFS "
1637 "WHERE identity_id = %u;",
1640 query = sqlite3_mprintf ("SELECT ref FROM REFS "
1641 "WHERE identity_id = %u AND "
1642 "secctx_id = (SELECT id FROM SECCTX "
1643 "WHERE sysctx = %Q AND appctx = %Q );",
1644 identity_id, ref_owner->sys_ctx, ref_owner->app_ctx );
1646 list = gsignond_db_sql_database_query_exec_string_list (
1647 GSIGNOND_DB_SQL_DATABASE (self),
1649 sqlite3_free (query);
1654 * gsignond_db_metadata_database_get_accesscontrol_list:
1656 * @self: instance of #GSignondDbMetadataDatabase
1657 * @identity_id: the id of the identity whose access control list is needed
1659 * Gets all the access control list from the database into a list.
1661 * Returns: (transfer full) the list #GSignondSecurityContextList if successful,
1662 * NULL otherwise. When done the list should be freed with
1663 * gsignond_identity_info_list_free
1665 GSignondSecurityContextList *
1666 gsignond_db_metadata_database_get_accesscontrol_list(
1667 GSignondDbMetadataDatabase *self,
1668 const guint32 identity_id)
1670 GSignondSecurityContextList *list = NULL;
1671 GHashTable *tuples = NULL;
1672 gchar *query = NULL;
1673 GHashTableIter iter;
1674 const gchar *sysctx = NULL, *appctx = NULL;
1675 GSignondSecurityContext *ctx = NULL;
1677 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
1678 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1680 query = sqlite3_mprintf ("SELECT sysctx, appctx FROM SECCTX "
1682 "(SELECT secctx_id FROM ACL WHERE identity_id = %u);",
1684 tuples = gsignond_db_sql_database_query_exec_string_tuple (
1685 GSIGNOND_DB_SQL_DATABASE (self),
1687 sqlite3_free (query);
1690 g_hash_table_iter_init(&iter, tuples);
1691 while (g_hash_table_iter_next (&iter, (gpointer *)&sysctx,
1692 (gpointer *)&appctx)) {
1693 ctx = gsignond_security_context_new_from_values (sysctx, appctx);
1694 list = g_list_append (list, ctx);
1696 g_hash_table_unref (tuples);
1702 * gsignond_db_metadata_database_get_owner:
1704 * @self: instance of #GSignondDbMetadataDatabase
1705 * @identity_id: the id of the identity whose owner list is needed
1707 * Gets the onwer of identity referred by @identity_id from the database.
1709 * Returns: (transfer full) the #GSignondSecurityContext if successful,
1710 * NULL otherwise. When done the list should be freed with
1711 * gsignond_identity_info_unref
1713 GSignondSecurityContext *
1714 gsignond_db_metadata_database_get_owner(
1715 GSignondDbMetadataDatabase *self,
1716 const guint32 identity_id)
1718 GHashTable *tuples = NULL;
1719 gchar *query = NULL;
1720 GSignondSecurityContext *ctx = NULL;
1722 g_return_val_if_fail (GSIGNOND_DB_IS_METADATA_DATABASE (self), FALSE);
1723 RETURN_IF_NOT_OPEN (GSIGNOND_DB_SQL_DATABASE (self), NULL);
1725 query = sqlite3_mprintf ("SELECT sysctx, appctx FROM SECCTX "
1727 "(SELECT secctx_id FROM OWNER WHERE identity_id = %u);",
1729 tuples = gsignond_db_sql_database_query_exec_string_tuple (
1730 GSIGNOND_DB_SQL_DATABASE (self),
1732 sqlite3_free (query);
1735 GHashTableIter iter;
1736 const gchar *sysctx = NULL, *appctx = NULL;
1737 g_hash_table_iter_init(&iter, tuples);
1738 while (g_hash_table_iter_next (&iter, (gpointer *)&sysctx,
1739 (gpointer *)&appctx)) {
1740 ctx = gsignond_security_context_new_from_values (sysctx, appctx);
1743 g_hash_table_unref (tuples);