LCOV - code coverage report
Current view: top level - daemon/dbus - gkd-secret-objects.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 67.2 % 729 490
Test Date: 2024-04-08 13:24:42 Functions: 90.6 % 64 58

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkd-secret-error.h"
      24              : #include "gkd-secret-objects.h"
      25              : #include "gkd-secret-property.h"
      26              : #include "gkd-secret-secret.h"
      27              : #include "gkd-secret-service.h"
      28              : #include "gkd-secret-session.h"
      29              : #include "gkd-secret-types.h"
      30              : #include "gkd-secret-util.h"
      31              : #include "gkd-secrets-generated.h"
      32              : 
      33              : #include "egg/egg-error.h"
      34              : 
      35              : #include "pkcs11/pkcs11i.h"
      36              : 
      37              : #include <string.h>
      38              : 
      39              : struct _GkdSecretObjects {
      40              :         GObject parent;
      41              :         GkdSecretService *service;
      42              :         GckSlot *pkcs11_slot;
      43              :         GHashTable *collections_to_skeletons;
      44              :         GHashTable *items_to_skeletons;
      45              : };
      46              : 
      47              : 
      48              : /* -----------------------------------------------------------------------------
      49              :  * SKELETON
      50              :  */
      51              : 
      52              : typedef struct {
      53              :         GkdExportedCollectionSkeleton parent;
      54              :         GkdSecretObjects *objects;
      55              : } GkdSecretCollectionSkeleton;
      56              : typedef struct {
      57              :         GkdExportedCollectionSkeletonClass parent_class;
      58              : } GkdSecretCollectionSkeletonClass;
      59              : typedef struct {
      60              :         GkdExportedItemSkeleton parent;
      61              :         GkdSecretObjects *objects;
      62              : } GkdSecretItemSkeleton;
      63              : typedef struct {
      64              :         GkdExportedItemSkeletonClass parent_class;
      65              : } GkdSecretItemSkeletonClass;
      66              : 
      67              : static GckObject * secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self,
      68              :                                                               const gchar *sender,
      69              :                                                               const gchar *path,
      70              :                                                               GError **error);
      71              : 
      72              : GType gkd_secret_collection_skeleton_get_type (void);
      73          100 : G_DEFINE_TYPE (GkdSecretCollectionSkeleton, gkd_secret_collection_skeleton, GKD_TYPE_EXPORTED_COLLECTION_SKELETON)
      74              : GType gkd_secret_item_skeleton_get_type (void);
      75           71 : G_DEFINE_TYPE (GkdSecretItemSkeleton, gkd_secret_item_skeleton, GKD_TYPE_EXPORTED_ITEM_SKELETON)
      76              : 
      77              : static void
      78           84 : on_object_path_append_to_builder (GkdSecretObjects *self,
      79              :                                   const gchar *path,
      80              :                                   GckObject *object,
      81              :                                   gpointer user_data)
      82              : {
      83           84 :         GVariantBuilder *builder = user_data;
      84           84 :         g_variant_builder_add (builder, "o", path);
      85           84 : }
      86              : 
      87              : static GVariant *
      88           53 : gkd_secret_objects_append_item_paths (GkdSecretObjects *self,
      89              :                                       const gchar *caller,
      90              :                                       const gchar *base)
      91              : {
      92              :         GVariantBuilder builder;
      93              : 
      94           53 :         g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
      95           53 :         g_return_val_if_fail (base, NULL);
      96              : 
      97           53 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
      98           53 :         gkd_secret_objects_foreach_item (self, caller, base, on_object_path_append_to_builder, &builder);
      99              : 
     100           53 :         return g_variant_builder_end (&builder);
     101              : }
     102              : 
     103              : static gchar **
     104           53 : gkd_secret_objects_get_collection_items (GkdSecretObjects *self,
     105              :                                          const gchar *collection_path)
     106              : {
     107              :         GVariant *items_variant;
     108              :         gchar **items;
     109              : 
     110           53 :         items_variant = gkd_secret_objects_append_item_paths (self, NULL, collection_path);
     111           53 :         items = g_variant_dup_objv (items_variant, NULL);
     112           53 :         g_variant_unref (items_variant);
     113              : 
     114           53 :         return items;
     115              : }
     116              : 
     117              : static gboolean
     118            2 : object_property_set (GkdSecretObjects *objects,
     119              :                      GckObject *object,
     120              :                      const gchar *prop_name,
     121              :                      GVariant *value,
     122              :                      GError **error_out)
     123              : {
     124            2 :         GckBuilder builder = GCK_BUILDER_INIT;
     125            2 :         GError *error = NULL;
     126              :         gulong attr_type;
     127              : 
     128              :         /* What type of property is it? */
     129            2 :         if (!gkd_secret_property_get_type (prop_name, &attr_type)) {
     130            0 :                 g_set_error (error_out, G_DBUS_ERROR,
     131              :                              G_DBUS_ERROR_UNKNOWN_PROPERTY,
     132              :                              "Object does not have the '%s' property",
     133              :                              prop_name);
     134            0 :                 return FALSE;
     135              :         }
     136              : 
     137              :         /* Retrieve the actual attribute value */
     138            2 :         if (!gkd_secret_property_parse_variant (value, prop_name, &builder)) {
     139            0 :                 gck_builder_clear (&builder);
     140            0 :                 g_set_error (error_out, G_DBUS_ERROR,
     141              :                              G_DBUS_ERROR_INVALID_ARGS,
     142              :                              "The property type or value was invalid: %s",
     143              :                              prop_name);
     144            0 :                 return FALSE;
     145              :         }
     146              : 
     147            2 :         gck_object_set (object, gck_builder_end (&builder), NULL, &error);
     148              : 
     149            2 :         if (error != NULL) {
     150            0 :                 if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN))
     151            0 :                         g_set_error (error_out, GKD_SECRET_ERROR,
     152              :                                      GKD_SECRET_ERROR_IS_LOCKED,
     153              :                                      "Cannot set property on a locked object");
     154              :                 else
     155            0 :                         g_set_error (error_out, G_DBUS_ERROR,
     156              :                                      G_DBUS_ERROR_FAILED,
     157              :                                      "Couldn't set '%s' property: %s",
     158              :                                      prop_name, egg_error_message (error));
     159            0 :                 g_clear_error (&error);
     160            0 :                 return FALSE;
     161              :         }
     162              : 
     163            2 :         return TRUE;
     164              : }
     165              : 
     166              : static GVariant *
     167           49 : object_property_get (GkdSecretObjects *objects,
     168              :                      GckObject *object,
     169              :                      const gchar *prop_name,
     170              :                      GError **error_out)
     171              : {
     172           49 :         GError *error = NULL;
     173              :         GckAttribute attr;
     174              :         gpointer value;
     175              :         gsize length;
     176              :         GVariant *res;
     177              : 
     178           49 :         if (!gkd_secret_property_get_type (prop_name, &attr.type)) {
     179            0 :                 g_set_error (error_out, G_DBUS_ERROR,
     180              :                              G_DBUS_ERROR_UNKNOWN_PROPERTY,
     181              :                              "Object does not have the '%s' property",
     182              :                              prop_name);
     183            0 :                 return NULL;
     184              :         }
     185              : 
     186              :         /* Retrieve the actual attribute */
     187           49 :         attr.value = value = gck_object_get_data (object, attr.type, NULL, &length, &error);
     188           49 :         if (error != NULL) {
     189            0 :                 g_set_error (error_out, G_DBUS_ERROR,
     190              :                              G_DBUS_ERROR_FAILED,
     191              :                              "Couldn't retrieve '%s' property: %s",
     192              :                              prop_name, egg_error_message (error));
     193            0 :                 g_clear_error (&error);
     194            0 :                 return NULL;
     195              :         }
     196              : 
     197              :         /* Marshall the data back out */
     198           49 :         attr.length = length;
     199           49 :         res = gkd_secret_property_append_variant (&attr);
     200           49 :         g_free (value);
     201              : 
     202           49 :         return res;
     203              : }
     204              : 
     205              : static gboolean
     206            1 : gkd_secret_collection_skeleton_set_property_dbus (GDBusConnection *connection,
     207              :                                                   const gchar *sender,
     208              :                                                   const gchar *object_path,
     209              :                                                   const gchar *interface_name,
     210              :                                                   const gchar *property_name,
     211              :                                                   GVariant *value,
     212              :                                                   GError **error,
     213              :                                                   gpointer user_data)
     214              : {
     215            1 :         GkdSecretCollectionSkeleton *self = (GkdSecretCollectionSkeleton *) user_data;
     216              :         GckObject *object;
     217              : 
     218            1 :         object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error);
     219            1 :         if (!object)
     220            0 :                 return FALSE;
     221              : 
     222            1 :         if (!object_property_set (self->objects, object, property_name, value, error)) {
     223            0 :                 g_object_unref (object);
     224            0 :                 return FALSE;
     225              :         }
     226              : 
     227            1 :         if (g_strcmp0 (property_name, "Label") == 0) {
     228            1 :                 gkd_exported_collection_set_label (GKD_EXPORTED_COLLECTION (self),
     229              :                                                    g_variant_get_string (value, NULL));
     230              :         }
     231              : 
     232            1 :         gkd_secret_service_emit_collection_changed (self->objects->service, object_path);
     233            1 :         g_object_unref (object);
     234              : 
     235            1 :         return TRUE;
     236              : }
     237              : 
     238              : static GVariant *
     239            3 : gkd_secret_collection_skeleton_get_property_dbus (GDBusConnection *connection,
     240              :                                                   const gchar *sender,
     241              :                                                   const gchar *object_path,
     242              :                                                   const gchar *interface_name,
     243              :                                                   const gchar *property_name,
     244              :                                                   GError **error,
     245              :                                                   gpointer user_data)
     246              : {
     247            3 :         GkdSecretCollectionSkeleton *self = (GkdSecretCollectionSkeleton *) user_data;
     248              :         GckObject *object;
     249              :         GVariant *variant;
     250              : 
     251            3 :         object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error);
     252            3 :         if (!object)
     253            0 :                 return FALSE;
     254              : 
     255            3 :         if (g_strcmp0 (property_name, "Items") == 0)
     256            0 :                 variant = gkd_secret_objects_append_item_paths (self->objects, sender, object_path);
     257              :         else
     258            3 :                 variant = object_property_get (self->objects, object, property_name, error);
     259              : 
     260              : 
     261            3 :         g_object_unref (object);
     262            3 :         return variant;
     263              : }
     264              : 
     265              : static GDBusInterfaceVTable *
     266           54 : gkd_secret_collection_skeleton_get_vtable (GDBusInterfaceSkeleton *skeleton)
     267              : {
     268              :         static GDBusInterfaceVTable vtable;
     269              :         GDBusInterfaceVTable *parent_vtable;
     270              : 
     271           54 :         parent_vtable = G_DBUS_INTERFACE_SKELETON_CLASS (gkd_secret_collection_skeleton_parent_class)->get_vtable (skeleton);
     272              : 
     273           54 :         (&vtable)->get_property = gkd_secret_collection_skeleton_get_property_dbus;
     274           54 :         (&vtable)->set_property = gkd_secret_collection_skeleton_set_property_dbus;
     275           54 :         (&vtable)->method_call = parent_vtable->method_call;
     276              : 
     277           54 :         return &vtable;
     278              : }
     279              : 
     280              : static void
     281           25 : gkd_secret_collection_skeleton_class_init (GkdSecretCollectionSkeletonClass *klass)
     282              : {
     283           25 :         GDBusInterfaceSkeletonClass *skclass = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
     284           25 :         skclass->get_vtable = gkd_secret_collection_skeleton_get_vtable;
     285           25 : }
     286              : 
     287              : static void
     288           50 : gkd_secret_collection_skeleton_init (GkdSecretCollectionSkeleton *self)
     289              : {
     290           50 : }
     291              : 
     292              : static GkdExportedCollection *
     293           50 : gkd_secret_collection_skeleton_new (GkdSecretObjects *objects)
     294              : {
     295           50 :         GkdExportedCollection *self = g_object_new (gkd_secret_collection_skeleton_get_type (), NULL);
     296           50 :         ((GkdSecretCollectionSkeleton *) self)->objects = objects;
     297           50 :         return self;
     298              : }
     299              : 
     300              : static gboolean
     301            1 : gkd_secret_item_skeleton_set_property_dbus (GDBusConnection *connection,
     302              :                                             const gchar *sender,
     303              :                                             const gchar *object_path,
     304              :                                             const gchar *interface_name,
     305              :                                             const gchar *property_name,
     306              :                                             GVariant *value,
     307              :                                             GError **error,
     308              :                                             gpointer user_data)
     309              : {
     310            1 :         GkdSecretItemSkeleton *self = (GkdSecretItemSkeleton *) user_data;
     311              :         GckObject *object;
     312              : 
     313            1 :         object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error);
     314            1 :         if (!object)
     315            0 :                 return FALSE;
     316              : 
     317            1 :         if (!object_property_set (self->objects, object, property_name, value, error)) {
     318            0 :                 g_object_unref (object);
     319            0 :                 return FALSE;
     320              :         }
     321              : 
     322            1 :         if (g_strcmp0 (property_name, "Attributes") == 0) {
     323            0 :                 gkd_exported_item_set_attributes (GKD_EXPORTED_ITEM (self), value);
     324            1 :         } else if (g_strcmp0 (property_name, "Label") == 0) {
     325            1 :                 gkd_exported_item_set_label (GKD_EXPORTED_ITEM (self),
     326              :                                              g_variant_get_string (value, NULL));
     327              :         }
     328              : 
     329            1 :         gkd_secret_objects_emit_item_changed (self->objects, object);
     330            1 :         g_object_unref (object);
     331              : 
     332            1 :         return TRUE;
     333              : }
     334              : 
     335              : static GVariant *
     336            6 : gkd_secret_item_skeleton_get_property_dbus (GDBusConnection *connection,
     337              :                                             const gchar *sender,
     338              :                                             const gchar *object_path,
     339              :                                             const gchar *interface_name,
     340              :                                             const gchar *property_name,
     341              :                                             GError **error,
     342              :                                             gpointer user_data)
     343              : {
     344            6 :         GkdSecretItemSkeleton *self = (GkdSecretItemSkeleton *) user_data;
     345              :         GckObject *object;
     346              :         GVariant *variant;
     347              : 
     348            6 :         object = secret_objects_lookup_gck_object_for_path (self->objects, sender, object_path, error);
     349            6 :         if (!object)
     350            0 :                 return NULL;
     351              : 
     352            6 :         variant = object_property_get (self->objects, object, property_name, error);
     353            6 :         g_object_unref (object);
     354              : 
     355            6 :         return variant;
     356              : }
     357              : 
     358              : static GDBusInterfaceVTable *
     359           26 : gkd_secret_item_skeleton_get_vtable (GDBusInterfaceSkeleton *skeleton)
     360              : {
     361              :         static GDBusInterfaceVTable vtable;
     362              :         GDBusInterfaceVTable *parent_vtable;
     363              : 
     364           26 :         parent_vtable = G_DBUS_INTERFACE_SKELETON_CLASS (gkd_secret_item_skeleton_parent_class)->get_vtable (skeleton);
     365              : 
     366           26 :         (&vtable)->get_property = gkd_secret_item_skeleton_get_property_dbus;
     367           26 :         (&vtable)->set_property = gkd_secret_item_skeleton_set_property_dbus;
     368           26 :         (&vtable)->method_call = parent_vtable->method_call;
     369              : 
     370           26 :         return &vtable;
     371              : }
     372              : 
     373              : static void
     374           23 : gkd_secret_item_skeleton_class_init (GkdSecretItemSkeletonClass *klass)
     375              : {
     376           23 :         GDBusInterfaceSkeletonClass *skclass = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
     377           23 :         skclass->get_vtable = gkd_secret_item_skeleton_get_vtable;
     378           23 : }
     379              : 
     380              : static void
     381           25 : gkd_secret_item_skeleton_init (GkdSecretItemSkeleton *self)
     382              : {
     383           25 : }
     384              : 
     385              : static GkdExportedItem *
     386           25 : gkd_secret_item_skeleton_new (GkdSecretObjects *objects)
     387              : {
     388           25 :         GkdExportedItem *self = g_object_new (gkd_secret_item_skeleton_get_type (), NULL);
     389           25 :         ((GkdSecretItemSkeleton *) self)->objects = objects;
     390           25 :         return self;
     391              : }
     392              : 
     393              : enum {
     394              :         PROP_0,
     395              :         PROP_PKCS11_SLOT,
     396              :         PROP_SERVICE
     397              : };
     398              : 
     399              : static gchar *    object_path_for_item          (const gchar *base,
     400              :                                                  GckObject *item);
     401              : 
     402              : static gchar *    object_path_for_collection    (GckObject *collection);
     403              : 
     404              : static gchar *    collection_path_for_item      (GckObject *item);
     405              : 
     406          445 : G_DEFINE_TYPE (GkdSecretObjects, gkd_secret_objects, G_TYPE_OBJECT);
     407              : 
     408              : /* -----------------------------------------------------------------------------
     409              :  * INTERNAL
     410              :  */
     411              : 
     412              : static GckObject *
     413           15 : secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self,
     414              :                                            const gchar *sender,
     415              :                                            const gchar *path,
     416              :                                            GError **error_out)
     417              : {
     418           15 :         GckBuilder builder = GCK_BUILDER_INIT;
     419              :         GList *objects;
     420              :         GckSession *session;
     421              :         gchar *c_ident;
     422              :         gchar *i_ident;
     423           15 :         GckObject *object = NULL;
     424           15 :         GError *error = NULL;
     425              : 
     426           15 :         g_return_val_if_fail (path, FALSE);
     427              : 
     428           15 :         if (!gkd_secret_util_parse_path (path, &c_ident, &i_ident) || !c_ident)
     429            0 :                 goto out;
     430              : 
     431              :         /* The session we're using to access the object */
     432           15 :         session = gkd_secret_service_get_pkcs11_session (self->service, sender);
     433           15 :         g_return_val_if_fail (session, FALSE);
     434              : 
     435           15 :         if (i_ident) {
     436            8 :                 gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     437            8 :                 gck_builder_add_string (&builder, CKA_G_COLLECTION, c_ident);
     438            8 :                 gck_builder_add_string (&builder, CKA_ID, i_ident);
     439              :         } else {
     440            7 :                 gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
     441            7 :                 gck_builder_add_string (&builder, CKA_ID, c_ident);
     442              :         }
     443              : 
     444           15 :         objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
     445              : 
     446           15 :         g_free (c_ident);
     447           15 :         g_free (i_ident);
     448              : 
     449           15 :         if (error != NULL) {
     450            0 :                 g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error));
     451            0 :                 g_clear_error (&error);
     452              :         }
     453              : 
     454           15 :         if (!objects)
     455            0 :                 goto out;
     456              : 
     457           15 :         object = g_object_ref (objects->data);
     458           15 :         gck_list_unref_free (objects);
     459              : 
     460           15 :  out:
     461           15 :         if (!object)
     462            0 :                 g_set_error (error_out, GKD_SECRET_ERROR,
     463              :                              GKD_SECRET_ERROR_NO_SUCH_OBJECT,
     464              :                              "The '%s' object does not exist",
     465              :                              path);
     466              : 
     467           15 :         return object;
     468              : }
     469              : 
     470              : static GckObject *
     471            4 : secret_objects_lookup_gck_object_for_invocation (GkdSecretObjects *self,
     472              :                                                  GDBusMethodInvocation *invocation)
     473              : {
     474            4 :         GError *error = NULL;
     475              :         GckObject *object;
     476              : 
     477            4 :         object = secret_objects_lookup_gck_object_for_path (self,
     478              :                                                             g_dbus_method_invocation_get_sender (invocation),
     479              :                                                             g_dbus_method_invocation_get_object_path (invocation),
     480              :                                                             &error);
     481              : 
     482            4 :         if (!object)
     483            0 :                 g_dbus_method_invocation_take_error (invocation, error);
     484              : 
     485            4 :         return object;
     486              : }
     487              : 
     488              : static gboolean
     489            1 : item_method_delete (GkdExportedItem *skeleton,
     490              :                     GDBusMethodInvocation *invocation,
     491              :                     GkdSecretObjects *self)
     492              : {
     493            1 :         GError *error = NULL;
     494              :         gchar *collection_path;
     495              :         gchar *item_path;
     496              :         GckObject *collection;
     497              :         GckObject *object;
     498              : 
     499            1 :         object = secret_objects_lookup_gck_object_for_invocation (self, invocation);
     500            1 :         if (!object) {
     501            0 :                 return TRUE;
     502              :         }
     503              : 
     504            1 :         collection_path = collection_path_for_item (object);
     505            1 :         item_path = object_path_for_item (NULL, object);
     506              : 
     507            1 :         if (gck_object_destroy (object, NULL, &error)) {
     508            1 :                 collection = gkd_secret_objects_lookup_collection (self, NULL, collection_path);
     509            1 :                 if (collection != NULL) {
     510            1 :                         gkd_secret_objects_emit_item_deleted (self, collection, item_path);
     511            1 :                         g_object_unref (collection);
     512              :                 }
     513              : 
     514              :                 /* No prompt necessary */
     515            1 :                 gkd_exported_item_complete_delete (skeleton, invocation, "/");
     516              : 
     517              :         } else {
     518            0 :                 if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN))
     519            0 :                         g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR,
     520              :                                                                        GKD_SECRET_ERROR_IS_LOCKED,
     521              :                                                                        "Cannot delete a locked item");
     522              :                 else
     523            0 :                         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
     524              :                                                                G_DBUS_ERROR_FAILED,
     525              :                                                                "Couldn't delete collection: %s",
     526              :                                                                egg_error_message (error));
     527              : 
     528            0 :                 g_clear_error (&error);
     529              :         }
     530              : 
     531            1 :         g_free (collection_path);
     532            1 :         g_free (item_path);
     533            1 :         g_object_unref (object);
     534              : 
     535            1 :         return TRUE;
     536              : }
     537              : 
     538              : static gboolean
     539            0 : item_method_get_secret (GkdExportedItem *skeleton,
     540              :                         GDBusMethodInvocation *invocation,
     541              :                         gchar *path,
     542              :                         GkdSecretObjects *self)
     543              : {
     544              :         GkdSecretSession *session;
     545              :         GkdSecretSecret *secret;
     546              :         GckObject *item;
     547            0 :         GError *error = NULL;
     548              : 
     549            0 :         item = secret_objects_lookup_gck_object_for_invocation (self, invocation);
     550            0 :         if (!item) {
     551            0 :                 return TRUE;
     552              :         }
     553              : 
     554            0 :         session = gkd_secret_service_lookup_session (self->service, path,
     555              :                                                      g_dbus_method_invocation_get_sender (invocation));
     556            0 :         if (session == NULL) {
     557            0 :                 g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR,
     558              :                                                                GKD_SECRET_ERROR_NO_SESSION,
     559              :                                                                "The session does not exist");
     560            0 :                 goto cleanup;
     561              :         }
     562              : 
     563            0 :         secret = gkd_secret_session_get_item_secret (session, item, &error);
     564            0 :         if (secret == NULL) {
     565            0 :                 g_dbus_method_invocation_take_error (invocation, error);
     566            0 :                 goto cleanup;
     567              :         }
     568              : 
     569            0 :         gkd_exported_item_complete_get_secret (skeleton, invocation,
     570              :                                                gkd_secret_secret_append (secret));
     571            0 :         gkd_secret_secret_free (secret);
     572              : 
     573            0 :  cleanup:
     574            0 :         g_object_unref (item);
     575            0 :         return TRUE;
     576              : }
     577              : 
     578              : static gboolean
     579            0 : item_method_set_secret (GkdExportedItem *skeleton,
     580              :                         GDBusMethodInvocation *invocation,
     581              :                         GVariant *secret_variant,
     582              :                         GkdSecretObjects *self)
     583              : {
     584              :         GkdSecretSecret *secret;
     585              :         const char *caller;
     586              :         GckObject *item;
     587            0 :         GError *error = NULL;
     588              : 
     589            0 :         item = secret_objects_lookup_gck_object_for_invocation (self, invocation);
     590            0 :         if (!item) {
     591            0 :                 return TRUE;
     592              :         }
     593              : 
     594            0 :         caller = g_dbus_method_invocation_get_sender (invocation);
     595            0 :         secret = gkd_secret_secret_parse (self->service, caller, secret_variant, &error);
     596            0 :         if (error != NULL) {
     597            0 :                 goto cleanup;
     598              :         }
     599              : 
     600            0 :         gkd_secret_session_set_item_secret (secret->session, item, secret, &error);
     601            0 :         gkd_secret_secret_free (secret);
     602              : 
     603            0 :         if (error != NULL) {
     604            0 :                 goto cleanup;
     605              :         }
     606              : 
     607            0 :  cleanup:
     608            0 :         if (error != NULL) {
     609            0 :                 g_dbus_method_invocation_take_error (invocation, error);
     610              :         } else {
     611            0 :                 gkd_exported_item_complete_set_secret (skeleton, invocation);
     612              :         }
     613              : 
     614            0 :         g_object_unref (item);
     615            0 :         return TRUE;
     616              : }
     617              : 
     618              : static void
     619            1 : item_cleanup_search_results (GckSession *session, GList *items,
     620              :                              GList **locked, GList **unlocked)
     621              : {
     622            1 :         GError *error = NULL;
     623              :         gpointer value;
     624              :         gsize n_value;
     625              :         GList *l;
     626              : 
     627            1 :         *locked = NULL;
     628            1 :         *unlocked = NULL;
     629              : 
     630            2 :         for (l = items; l; l = g_list_next (l)) {
     631            1 :                 value = gck_object_get_data (l->data, CKA_G_LOCKED, NULL, &n_value, &error);
     632            1 :                 if (value == NULL) {
     633            0 :                         if (!g_error_matches (error, GCK_ERROR, CKR_OBJECT_HANDLE_INVALID))
     634            0 :                                 g_warning ("couldn't check if item is locked: %s", egg_error_message (error));
     635            0 :                         g_clear_error (&error);
     636              : 
     637              :                 /* Is not locked */
     638            1 :                 } if (n_value == 1 && *((CK_BBOOL*)value) == CK_FALSE) {
     639            0 :                         *unlocked = g_list_prepend (*unlocked, l->data);
     640              : 
     641              :                 /* Is locked */
     642              :                 } else {
     643            1 :                         *locked = g_list_prepend (*locked, l->data);
     644              :                 }
     645              : 
     646            1 :                 g_free (value);
     647              :         }
     648              : 
     649            1 :         *locked = g_list_reverse (*locked);
     650            1 :         *unlocked = g_list_reverse (*unlocked);
     651            1 : }
     652              : 
     653              : static gboolean
     654            1 : collection_method_search_items (GkdExportedCollection *skeleton,
     655              :                                 GDBusMethodInvocation *invocation,
     656              :                                 GVariant *attributes,
     657              :                                 GkdSecretObjects *self)
     658              : {
     659            1 :         return gkd_secret_objects_handle_search_items (self, invocation, attributes,
     660              :                                                        g_dbus_method_invocation_get_object_path (invocation),
     661              :                                                        FALSE);
     662              : }
     663              : 
     664              : static GckObject*
     665            0 : collection_find_matching_item (GkdSecretObjects *self,
     666              :                                GckSession *session,
     667              :                                const gchar *identifier,
     668              :                                const GckAttribute *fields)
     669              : {
     670            0 :         GckBuilder builder = GCK_BUILDER_INIT;
     671            0 :         GckObject *result = NULL;
     672            0 :         GError *error = NULL;
     673              :         GckObject *search;
     674              :         gpointer data;
     675              :         gsize n_data;
     676              : 
     677              :         /* Find items matching the collection and fields */
     678            0 :         gck_builder_add_attribute (&builder, fields);
     679            0 :         gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
     680            0 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
     681            0 :         gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
     682              : 
     683              :         /* Create the search object */
     684            0 :         search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
     685              : 
     686            0 :         if (error != NULL) {
     687            0 :                 g_warning ("couldn't search for matching item: %s", egg_error_message (error));
     688            0 :                 g_clear_error (&error);
     689            0 :                 return NULL;
     690              :         }
     691              : 
     692              :         /* Get the matched item handles, and delete the search object */
     693            0 :         data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, NULL);
     694            0 :         gck_object_destroy (search, NULL, NULL);
     695            0 :         g_object_unref (search);
     696              : 
     697            0 :         if (n_data >= sizeof (CK_OBJECT_HANDLE))
     698            0 :                 result = gck_object_from_handle (session, *((CK_OBJECT_HANDLE_PTR)data));
     699              : 
     700            0 :         g_free (data);
     701            0 :         return result;
     702              : }
     703              : 
     704              : static gchar *
     705           73 : object_path_for_item (const gchar *base,
     706              :                       GckObject *item)
     707              : {
     708           73 :         GError *error = NULL;
     709              :         gpointer identifier;
     710              :         gsize n_identifier;
     711           73 :         gchar *alloc = NULL;
     712           73 :         gchar *path = NULL;
     713              : 
     714           73 :         if (base == NULL)
     715            3 :                 base = alloc = collection_path_for_item (item);
     716              : 
     717           73 :         identifier = gck_object_get_data (item, CKA_ID, NULL, &n_identifier, &error);
     718           73 :         if (identifier == NULL) {
     719            0 :                 g_warning ("couldn't get item identifier: %s", egg_error_message (error));
     720            0 :                 g_clear_error (&error);
     721            0 :                 path = NULL;
     722              : 
     723              :         } else {
     724           73 :                 path = gkd_secret_util_build_path (base, identifier, n_identifier);
     725           73 :                 g_free (identifier);
     726              :         }
     727              : 
     728           73 :         g_free (alloc);
     729           73 :         return path;
     730              : }
     731              : 
     732              : static gchar *
     733           25 : collection_path_for_item (GckObject *item)
     734              : {
     735           25 :         GError *error = NULL;
     736              :         gpointer identifier;
     737              :         gsize n_identifier;
     738           25 :         gchar *path = NULL;
     739              : 
     740           25 :         identifier = gck_object_get_data (item, CKA_G_COLLECTION, NULL, &n_identifier, &error);
     741           25 :         if (!identifier) {
     742            0 :                 g_warning ("couldn't get item collection identifier: %s", egg_error_message (error));
     743            0 :                 g_clear_error (&error);
     744            0 :                 return NULL;
     745              :         }
     746              : 
     747           25 :         path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
     748           25 :         g_free (identifier);
     749           25 :         return path;
     750              : }
     751              : 
     752              : static gchar *
     753           24 : object_path_for_collection (GckObject *collection)
     754              : {
     755           24 :         GError *error = NULL;
     756              :         gpointer identifier;
     757              :         gsize n_identifier;
     758           24 :         gchar *path = NULL;
     759              : 
     760           24 :         identifier = gck_object_get_data (collection, CKA_ID, NULL, &n_identifier, &error);
     761           24 :         if (identifier == NULL) {
     762            0 :                 g_warning ("couldn't get collection identifier: %s", egg_error_message (error));
     763            0 :                 g_clear_error (&error);
     764            0 :                 path = NULL;
     765              : 
     766              :         } else {
     767           24 :                 path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
     768           24 :                 g_free (identifier);
     769              :         }
     770              : 
     771           24 :         return path;
     772              : }
     773              : 
     774              : static gboolean
     775            2 : collection_method_create_item (GkdExportedCollection *skeleton,
     776              :                                GDBusMethodInvocation *invocation,
     777              :                                GVariant *properties,
     778              :                                GVariant *secret_variant,
     779              :                                gboolean replace,
     780              :                                GkdSecretObjects *self)
     781              : {
     782            2 :         GckBuilder builder = GCK_BUILDER_INIT;
     783            2 :         GckSession *pkcs11_session = NULL;
     784            2 :         GkdSecretSecret *secret = NULL;
     785            2 :         GckAttributes *attrs = NULL;
     786              :         const GckAttribute *fields;
     787            2 :         GckObject *item = NULL;
     788              :         const gchar *base;
     789            2 :         GError *error = NULL;
     790            2 :         gchar *path = NULL;
     791              :         gchar *identifier;
     792            2 :         gboolean created = FALSE;
     793              :         GckObject *object;
     794              : 
     795            2 :         object = secret_objects_lookup_gck_object_for_invocation (self, invocation);
     796            2 :         if (!object) {
     797            0 :                 return TRUE;
     798              :         }
     799              : 
     800            2 :         if (!gkd_secret_property_parse_all (properties, SECRET_ITEM_INTERFACE, &builder)) {
     801            0 :                 g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR,
     802              :                                                                G_DBUS_ERROR_INVALID_ARGS,
     803              :                                                                "Invalid properties argument");
     804            0 :                 goto cleanup;
     805              :         }
     806              : 
     807            2 :         base = g_dbus_method_invocation_get_object_path (invocation);
     808            2 :         secret = gkd_secret_secret_parse (self->service, g_dbus_method_invocation_get_sender (invocation),
     809              :                                           secret_variant, &error);
     810              : 
     811            2 :         if (secret == NULL) {
     812            0 :                 g_dbus_method_invocation_take_error (invocation, error);
     813            0 :                 error = NULL;
     814            0 :                 goto cleanup;
     815              :         }
     816              : 
     817            2 :         if (!gkd_secret_util_parse_path (base, &identifier, NULL))
     818            0 :                 g_return_val_if_reached (FALSE);
     819            2 :         g_return_val_if_fail (identifier, FALSE);
     820              : 
     821            2 :         pkcs11_session = gck_object_get_session (object);
     822            2 :         g_return_val_if_fail (pkcs11_session, FALSE);
     823              : 
     824            2 :         attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
     825              : 
     826            2 :         if (replace) {
     827            1 :                 fields = gck_attributes_find (attrs, CKA_G_FIELDS);
     828            1 :                 if (fields)
     829            0 :                         item = collection_find_matching_item (self, pkcs11_session, identifier, fields);
     830              :         }
     831              : 
     832              :         /* Replace the item */
     833            2 :         if (item) {
     834            0 :                 if (!gck_object_set (item, attrs, NULL, &error))
     835            0 :                         goto cleanup;
     836              : 
     837              :         /* Create a new item */
     838              :         } else {
     839            2 :                 gck_builder_add_all (&builder, attrs);
     840            2 :                 gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
     841            2 :                 gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
     842            2 :                 item = gck_session_create_object (pkcs11_session, gck_builder_end (&builder), NULL, &error);
     843            2 :                 if (item == NULL)
     844            0 :                         goto cleanup;
     845            2 :                 created = TRUE;
     846              :         }
     847              : 
     848              :         /* Set the secret */
     849            2 :         if (!gkd_secret_session_set_item_secret (secret->session, item, secret, &error)) {
     850            0 :                 if (created) /* If we created, then try to destroy on failure */
     851            0 :                         gck_object_destroy (item, NULL, NULL);
     852            0 :                 goto cleanup;
     853              :         }
     854              : 
     855            2 :         path = object_path_for_item (base, item);
     856            2 :         gkd_secret_objects_emit_item_created (self, object, path);
     857              : 
     858            2 :         gkd_exported_collection_complete_create_item (skeleton, invocation, path, "/");
     859              : 
     860            2 : cleanup:
     861            2 :         if (error) {
     862            0 :                 if (g_error_matches (error, GCK_ERROR, CKR_USER_NOT_LOGGED_IN))
     863            0 :                         g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR,
     864              :                                                                        GKD_SECRET_ERROR_IS_LOCKED,
     865              :                                                                        "Cannot create an item in a locked collection");
     866              :                 else
     867            0 :                         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
     868              :                                                                G_DBUS_ERROR_FAILED,
     869              :                                                                "Couldn't create item: %s",
     870              :                                                                egg_error_message (error));
     871            0 :                 g_clear_error (&error);
     872              :         }
     873              : 
     874            2 :         gkd_secret_secret_free (secret);
     875            2 :         gck_attributes_unref (attrs);
     876            2 :         if (item)
     877            2 :                 g_object_unref (item);
     878            2 :         if (pkcs11_session)
     879            2 :                 g_object_unref (pkcs11_session);
     880            2 :         g_free (path);
     881            2 :         g_object_unref (object);
     882              : 
     883            2 :         return TRUE;
     884              : }
     885              : 
     886              : static gboolean
     887            1 : collection_method_delete (GkdExportedCollection *skeleton,
     888              :                           GDBusMethodInvocation *invocation,
     889              :                           GkdSecretObjects *self)
     890              : {
     891            1 :         GError *error = NULL;
     892              :         gchar *path;
     893              :         GckObject *object;
     894              : 
     895            1 :         object = secret_objects_lookup_gck_object_for_invocation (self, invocation);
     896            1 :         if (!object) {
     897            0 :                 return TRUE;
     898              :         }
     899              : 
     900            1 :         path = object_path_for_collection (object);
     901            1 :         g_return_val_if_fail (path != NULL, FALSE);
     902              : 
     903            1 :         if (!gck_object_destroy (object, NULL, &error)) {
     904            0 :                 g_dbus_method_invocation_return_error (invocation,
     905              :                                                        G_DBUS_ERROR,
     906              :                                                        G_DBUS_ERROR_FAILED,
     907              :                                                        "Couldn't delete collection: %s",
     908              :                                                        egg_error_message (error));
     909            0 :                 g_clear_error (&error);
     910            0 :                 goto cleanup;
     911              :         }
     912              : 
     913              :         /* Notify the callers that a collection was deleted */
     914            1 :         gkd_secret_service_emit_collection_deleted (self->service, path);
     915            1 :         gkd_exported_collection_complete_delete (skeleton, invocation, "/");
     916              : 
     917            1 :  cleanup:
     918            1 :         g_free (path);
     919            1 :         g_object_unref (object);
     920              : 
     921            1 :         return TRUE;
     922              : }
     923              : 
     924              : /* -----------------------------------------------------------------------------
     925              :  * OBJECT
     926              :  */
     927              : 
     928              : static void
     929           75 : skeleton_destroy_func (gpointer user_data)
     930              : {
     931           75 :         GDBusInterfaceSkeleton *skeleton = user_data;
     932           75 :         g_dbus_interface_skeleton_unexport (skeleton);
     933           75 :         g_object_unref (skeleton);
     934           75 : }
     935              : 
     936              : static void
     937           25 : gkd_secret_objects_init (GkdSecretObjects *self)
     938              : {
     939           25 :         self->collections_to_skeletons = g_hash_table_new_full (g_str_hash, g_str_equal,
     940              :                                                                 g_free, skeleton_destroy_func);
     941           25 :         self->items_to_skeletons = g_hash_table_new_full (g_str_hash, g_str_equal,
     942              :                                                           g_free, skeleton_destroy_func);
     943           25 : }
     944              : 
     945              : static void
     946           50 : gkd_secret_objects_dispose (GObject *obj)
     947              : {
     948           50 :         GkdSecretObjects *self = GKD_SECRET_OBJECTS (obj);
     949              : 
     950           50 :         if (self->pkcs11_slot) {
     951           25 :                 g_object_unref (self->pkcs11_slot);
     952           25 :                 self->pkcs11_slot = NULL;
     953              :         }
     954              : 
     955           50 :         if (self->service) {
     956           25 :                 g_object_remove_weak_pointer (G_OBJECT (self->service),
     957           25 :                                               (gpointer*)&(self->service));
     958           25 :                 self->service = NULL;
     959              :         }
     960              : 
     961           50 :         g_clear_pointer (&self->collections_to_skeletons, g_hash_table_unref);
     962           50 :         g_clear_pointer (&self->items_to_skeletons, g_hash_table_unref);
     963              : 
     964           50 :         G_OBJECT_CLASS (gkd_secret_objects_parent_class)->dispose (obj);
     965           50 : }
     966              : 
     967              : static void
     968           50 : gkd_secret_objects_set_property (GObject *obj, guint prop_id, const GValue *value,
     969              :                                  GParamSpec *pspec)
     970              : {
     971           50 :         GkdSecretObjects *self = GKD_SECRET_OBJECTS (obj);
     972              : 
     973           50 :         switch (prop_id) {
     974           25 :         case PROP_PKCS11_SLOT:
     975           25 :                 g_return_if_fail (!self->pkcs11_slot);
     976           25 :                 self->pkcs11_slot = g_value_dup_object (value);
     977           25 :                 g_return_if_fail (self->pkcs11_slot);
     978           25 :                 break;
     979           25 :         case PROP_SERVICE:
     980           25 :                 g_return_if_fail (!self->service);
     981           25 :                 self->service = g_value_get_object (value);
     982           25 :                 g_return_if_fail (self->service);
     983           25 :                 g_object_add_weak_pointer (G_OBJECT (self->service),
     984           25 :                                            (gpointer*)&(self->service));
     985           25 :                 break;
     986            0 :         default:
     987            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     988            0 :                 break;
     989              :         }
     990              : }
     991              : 
     992              : static void
     993            0 : gkd_secret_objects_get_property (GObject *obj, guint prop_id, GValue *value,
     994              :                                      GParamSpec *pspec)
     995              : {
     996            0 :         GkdSecretObjects *self = GKD_SECRET_OBJECTS (obj);
     997              : 
     998            0 :         switch (prop_id) {
     999            0 :         case PROP_PKCS11_SLOT:
    1000            0 :                 g_value_set_object (value, gkd_secret_objects_get_pkcs11_slot (self));
    1001            0 :                 break;
    1002            0 :         case PROP_SERVICE:
    1003            0 :                 g_value_set_object (value, self->service);
    1004            0 :                 break;
    1005            0 :         default:
    1006            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
    1007            0 :                 break;
    1008              :         }
    1009            0 : }
    1010              : 
    1011              : static void
    1012           25 : gkd_secret_objects_class_init (GkdSecretObjectsClass *klass)
    1013              : {
    1014           25 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
    1015              : 
    1016           25 :         gobject_class->dispose = gkd_secret_objects_dispose;
    1017           25 :         gobject_class->set_property = gkd_secret_objects_set_property;
    1018           25 :         gobject_class->get_property = gkd_secret_objects_get_property;
    1019              : 
    1020           25 :         g_object_class_install_property (gobject_class, PROP_PKCS11_SLOT,
    1021              :                 g_param_spec_object ("pkcs11-slot", "Pkcs11 Slot", "PKCS#11 slot that we use for secrets",
    1022              :                                      GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
    1023              : 
    1024           25 :         g_object_class_install_property (gobject_class, PROP_SERVICE,
    1025              :                 g_param_spec_object ("service", "Service", "Service which owns this objects",
    1026              :                                      GKD_SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
    1027           25 : }
    1028              : 
    1029              : /* -----------------------------------------------------------------------------
    1030              :  * PUBLIC
    1031              :  */
    1032              : 
    1033              : GckSlot*
    1034           41 : gkd_secret_objects_get_pkcs11_slot (GkdSecretObjects *self)
    1035              : {
    1036           41 :         g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
    1037           41 :         return self->pkcs11_slot;
    1038              : }
    1039              : 
    1040              : GckObject*
    1041           23 : gkd_secret_objects_lookup_collection (GkdSecretObjects *self, const gchar *caller,
    1042              :                                       const gchar *path)
    1043              : {
    1044           23 :         GckBuilder builder = GCK_BUILDER_INIT;
    1045           23 :         GckObject *object = NULL;
    1046           23 :         GError *error = NULL;
    1047              :         GList *objects;
    1048              :         GckSession *session;
    1049              :         gchar *identifier;
    1050              :         const gchar *real_identifier;
    1051              : 
    1052           23 :         g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
    1053           23 :         g_return_val_if_fail (path, NULL);
    1054              : 
    1055           23 :         if (!gkd_secret_util_parse_path (path, &identifier, NULL))
    1056            0 :                 return NULL;
    1057              : 
    1058           23 :         if (g_str_has_prefix (path, SECRET_ALIAS_PREFIX))
    1059            0 :                 real_identifier = gkd_secret_service_get_alias (self->service, identifier);
    1060              :         else
    1061           23 :                 real_identifier = identifier;
    1062              : 
    1063              :         /* The session we're using to access the object */
    1064           23 :         if (caller == NULL)
    1065            1 :                 session = gkd_secret_service_internal_pkcs11_session (self->service);
    1066              :         else
    1067           22 :                 session = gkd_secret_service_get_pkcs11_session (self->service, caller);
    1068           23 :         g_return_val_if_fail (session, NULL);
    1069              : 
    1070           23 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
    1071           23 :         gck_builder_add_string (&builder, CKA_ID, real_identifier);
    1072              : 
    1073           23 :         objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
    1074              : 
    1075           23 :         g_free (identifier);
    1076              : 
    1077           23 :         if (error != NULL) {
    1078            0 :                 g_warning ("couldn't lookup collection: %s: %s", path, egg_error_message (error));
    1079            0 :                 g_clear_error (&error);
    1080              :         }
    1081              : 
    1082           23 :         if (objects)
    1083           23 :                 object = g_object_ref (objects->data);
    1084              : 
    1085           23 :         gck_list_unref_free (objects);
    1086           23 :         return object;
    1087              : }
    1088              : 
    1089              : GckObject*
    1090            0 : gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller,
    1091              :                                 const gchar *path)
    1092              : {
    1093            0 :         GckBuilder builder = GCK_BUILDER_INIT;
    1094            0 :         GckObject *object = NULL;
    1095            0 :         GError *error = NULL;
    1096              :         GList *objects;
    1097              :         GckSession *session;
    1098              :         gchar *collection;
    1099              :         gchar *identifier;
    1100              : 
    1101            0 :         g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
    1102            0 :         g_return_val_if_fail (caller, NULL);
    1103            0 :         g_return_val_if_fail (path, NULL);
    1104              : 
    1105            0 :         if (!gkd_secret_util_parse_path (path, &collection, &identifier))
    1106            0 :                 return NULL;
    1107              : 
    1108              :         /* The session we're using to access the object */
    1109            0 :         session = gkd_secret_service_get_pkcs11_session (self->service, caller);
    1110            0 :         g_return_val_if_fail (session, NULL);
    1111              : 
    1112            0 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
    1113            0 :         gck_builder_add_string (&builder, CKA_ID, identifier);
    1114            0 :         gck_builder_add_string (&builder, CKA_G_COLLECTION, collection);
    1115              : 
    1116            0 :         objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
    1117              : 
    1118            0 :         g_free (identifier);
    1119            0 :         g_free (collection);
    1120              : 
    1121            0 :         if (error != NULL) {
    1122            0 :                 g_warning ("couldn't lookup item: %s: %s", path, egg_error_message (error));
    1123            0 :                 g_clear_error (&error);
    1124              :         }
    1125              : 
    1126            0 :         if (objects)
    1127            0 :                 object = g_object_ref (objects->data);
    1128              : 
    1129            0 :         gck_list_unref_free (objects);
    1130            0 :         return object;
    1131              : }
    1132              : 
    1133              : static void
    1134           76 : objects_foreach_item (GkdSecretObjects *self,
    1135              :                       GList *items,
    1136              :                       const gchar *base,
    1137              :                       GkdSecretObjectsForeach callback,
    1138              :                       gpointer user_data)
    1139              : {
    1140              :         gchar *path;
    1141              :         GList *l;
    1142              : 
    1143          125 :         for (l = items; l; l = g_list_next (l)) {
    1144           49 :                 path = object_path_for_item (base, l->data);
    1145           49 :                 (callback) (self, path, l->data, user_data);
    1146           49 :                 g_free (path);
    1147              :         }
    1148           76 : }
    1149              : 
    1150              : void
    1151           73 : gkd_secret_objects_foreach_item (GkdSecretObjects *self,
    1152              :                                  const gchar *caller,
    1153              :                                  const gchar *base,
    1154              :                                  GkdSecretObjectsForeach callback,
    1155              :                                  gpointer user_data)
    1156              : {
    1157           73 :         GckBuilder builder = GCK_BUILDER_INIT;
    1158              :         GckSession *session;
    1159           73 :         GError *error = NULL;
    1160              :         gchar *identifier;
    1161              :         GList *items;
    1162              : 
    1163           73 :         g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
    1164           73 :         g_return_if_fail (base != NULL);
    1165           73 :         g_return_if_fail (callback != NULL);
    1166              : 
    1167              :         /* The session we're using to access the object */
    1168           73 :         if (caller == NULL) {
    1169           73 :                 session = gkd_secret_service_internal_pkcs11_session (self->service);
    1170              :         } else {
    1171            0 :                 session = gkd_secret_service_get_pkcs11_session (self->service, caller);
    1172              :         }
    1173              : 
    1174           73 :         if (!gkd_secret_util_parse_path (base, &identifier, NULL))
    1175            0 :                 g_return_if_reached ();
    1176              : 
    1177           73 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY);
    1178           73 :         gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
    1179              : 
    1180           73 :         items = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
    1181              : 
    1182           73 :         if (error == NULL) {
    1183           73 :                 objects_foreach_item (self, items, base, callback, user_data);
    1184              : 
    1185              :         } else {
    1186            0 :                 g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error));
    1187            0 :                 g_clear_error (&error);
    1188              :         }
    1189              : 
    1190           73 :         gck_list_unref_free (items);
    1191           73 :         g_free (identifier);
    1192              : }
    1193              : 
    1194              : void
    1195           28 : gkd_secret_objects_foreach_collection (GkdSecretObjects *self,
    1196              :                                        const gchar *caller,
    1197              :                                        GkdSecretObjectsForeach callback,
    1198              :                                        gpointer user_data)
    1199              : {
    1200           28 :         GckBuilder builder = GCK_BUILDER_INIT;
    1201              :         GckSession *session;
    1202           28 :         GError *error = NULL;
    1203              :         GList *collections, *l;
    1204              :         gpointer identifier;
    1205              :         gsize n_identifier;
    1206              :         gchar *path;
    1207              : 
    1208           28 :         g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
    1209           28 :         g_return_if_fail (callback);
    1210              : 
    1211              :         /* The session we're using to access the object */
    1212           28 :         if (caller == NULL) {
    1213           28 :                 session = gkd_secret_service_internal_pkcs11_session (self->service);
    1214              :         } else {
    1215            0 :                 session = gkd_secret_service_get_pkcs11_session (self->service, caller);
    1216              :         }
    1217              : 
    1218           28 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION);
    1219              : 
    1220           28 :         collections = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error);
    1221              : 
    1222           28 :         if (error != NULL) {
    1223            0 :                 g_warning ("couldn't lookup collections: %s", egg_error_message (error));
    1224            0 :                 g_clear_error (&error);
    1225            0 :                 return;
    1226              :         }
    1227              : 
    1228           83 :         for (l = collections; l; l = g_list_next (l)) {
    1229           55 :                 identifier = gck_object_get_data (l->data, CKA_ID, NULL, &n_identifier, &error);
    1230           55 :                 if (identifier == NULL) {
    1231            0 :                         g_warning ("couldn't get collection identifier: %s", egg_error_message (error));
    1232            0 :                         g_clear_error (&error);
    1233            0 :                         continue;
    1234              :                 }
    1235              : 
    1236           55 :                 path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
    1237           55 :                 g_free (identifier);
    1238              : 
    1239           55 :                 (callback) (self, path, l->data, user_data);
    1240           55 :                 g_free (path);
    1241              :         }
    1242              : 
    1243           28 :         gck_list_unref_free (collections);
    1244              : }
    1245              : 
    1246              : GVariant *
    1247           28 : gkd_secret_objects_append_collection_paths (GkdSecretObjects *self,
    1248              :                                             const gchar *caller)
    1249              : {
    1250              :         GVariantBuilder builder;
    1251              : 
    1252           28 :         g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL);
    1253              : 
    1254           28 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
    1255           28 :         gkd_secret_objects_foreach_collection (self, caller, on_object_path_append_to_builder, &builder);
    1256              : 
    1257           28 :         return g_variant_builder_end (&builder);
    1258              : }
    1259              : 
    1260              : gboolean
    1261            2 : gkd_secret_objects_handle_search_items (GkdSecretObjects *self,
    1262              :                                         GDBusMethodInvocation *invocation,
    1263              :                                         GVariant *attributes,
    1264              :                                         const gchar *base,
    1265              :                                         gboolean separate_locked)
    1266              : {
    1267            2 :         GckBuilder builder = GCK_BUILDER_INIT;
    1268              :         GckObject *search;
    1269              :         GckSession *session;
    1270            2 :         GError *error = NULL;
    1271              :         gchar *identifier;
    1272              :         gpointer data;
    1273              :         gsize n_data;
    1274              :         GList *locked, *unlocked;
    1275              :         GList *items;
    1276              :         GVariantBuilder result;
    1277              : 
    1278            2 :         if (!gkd_secret_property_parse_fields (attributes, &builder)) {
    1279            0 :                 gck_builder_clear (&builder);
    1280            0 :                 g_dbus_method_invocation_return_error_literal (invocation,
    1281              :                                                                G_DBUS_ERROR,
    1282              :                                                                G_DBUS_ERROR_FAILED,
    1283              :                                                                "Invalid data in attributes argument");
    1284            0 :                 return TRUE;
    1285              :         }
    1286              : 
    1287            2 :         if (base != NULL) {
    1288            1 :                 if (!gkd_secret_util_parse_path (base, &identifier, NULL))
    1289            0 :                         g_return_val_if_reached (FALSE);
    1290            1 :                 gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier);
    1291            1 :                 g_free (identifier);
    1292              :         }
    1293              : 
    1294            2 :         gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH);
    1295            2 :         gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE);
    1296              : 
    1297              :         /* The session we're using to access the object */
    1298            2 :         session = gkd_secret_service_get_pkcs11_session (self->service, g_dbus_method_invocation_get_sender (invocation));
    1299            2 :         g_return_val_if_fail (session, FALSE);
    1300              : 
    1301              :         /* Create the search object */
    1302            2 :         search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error);
    1303              : 
    1304            2 :         if (error != NULL) {
    1305            0 :                 g_dbus_method_invocation_return_error (invocation,
    1306              :                                                        G_DBUS_ERROR,
    1307              :                                                        G_DBUS_ERROR_FAILED,
    1308              :                                                        "Couldn't search for items: %s",
    1309              :                                                        egg_error_message (error));
    1310            0 :                 g_clear_error (&error);
    1311            0 :                 return TRUE;
    1312              :         }
    1313              : 
    1314              :         /* Get the matched item handles, and delete the search object */
    1315            2 :         data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, &error);
    1316            2 :         gck_object_destroy (search, NULL, NULL);
    1317            2 :         g_object_unref (search);
    1318              : 
    1319            2 :         if (error != NULL) {
    1320            0 :                 g_dbus_method_invocation_return_error (invocation,
    1321              :                                                        G_DBUS_ERROR,
    1322              :                                                        G_DBUS_ERROR_FAILED,
    1323              :                                                        "Couldn't retrieve matched items: %s",
    1324              :                                                        egg_error_message (error));
    1325            0 :                 g_clear_error (&error);
    1326            0 :                 return TRUE;
    1327              :         }
    1328              : 
    1329              :         /* Build a list of object handles */
    1330            2 :         items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE));
    1331            2 :         g_free (data);
    1332              : 
    1333              :         /* Filter out the locked items */
    1334            2 :         if (separate_locked) {
    1335              :                 GVariant *unlocked_variant, *locked_variant;
    1336              : 
    1337            1 :                 item_cleanup_search_results (session, items, &locked, &unlocked);
    1338              : 
    1339            1 :                 g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
    1340            1 :                 objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_builder, &result);
    1341            1 :                 unlocked_variant = g_variant_builder_end (&result);
    1342              : 
    1343            1 :                 g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
    1344            1 :                 objects_foreach_item (self, locked, NULL, on_object_path_append_to_builder, &result);
    1345            1 :                 locked_variant = g_variant_builder_end (&result);
    1346              : 
    1347            1 :                 g_list_free (locked);
    1348            1 :                 g_list_free (unlocked);
    1349              : 
    1350            1 :                 g_dbus_method_invocation_return_value (invocation,
    1351              :                                                        g_variant_new ("(@ao@ao)",
    1352              :                                                                       unlocked_variant,
    1353              :                                                                       locked_variant));
    1354              :         } else {
    1355            1 :                 g_variant_builder_init (&result, G_VARIANT_TYPE ("ao"));
    1356            1 :                 objects_foreach_item (self, items, NULL, on_object_path_append_to_builder, &result);
    1357              : 
    1358            1 :                 g_dbus_method_invocation_return_value (invocation,
    1359              :                                                        g_variant_new ("(@ao)", g_variant_builder_end (&result)));
    1360              :         }
    1361              : 
    1362            2 :         gck_list_unref_free (items);
    1363              : 
    1364            2 :         return TRUE;
    1365              : }
    1366              : 
    1367              : gboolean
    1368            0 : gkd_secret_objects_handle_get_secrets (GkdSecretObjects *self,
    1369              :                                        GDBusMethodInvocation *invocation,
    1370              :                                        const gchar **paths,
    1371              :                                        const gchar *session_path)
    1372              : {
    1373              :         GkdSecretSession *session;
    1374              :         GkdSecretSecret *secret;
    1375              :         GckObject *item;
    1376              :         const char *caller;
    1377              :         int i;
    1378              :         GVariantBuilder builder;
    1379            0 :         GError *error = NULL;
    1380              : 
    1381            0 :         caller = g_dbus_method_invocation_get_sender (invocation);
    1382            0 :         session = gkd_secret_service_lookup_session (self->service, session_path, caller);
    1383            0 :         if (session == NULL) {
    1384            0 :                 g_dbus_method_invocation_return_error_literal (invocation, GKD_SECRET_ERROR,
    1385              :                                                                GKD_SECRET_ERROR_NO_SESSION,
    1386              :                                                                "The session does not exist");
    1387            0 :                 return TRUE;
    1388              :         }
    1389              : 
    1390            0 :         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{o(oayays)}"));
    1391              : 
    1392            0 :         for (i = 0; paths[i] != NULL; ++i) {
    1393              : 
    1394              :                 /* Try to find the item, if it doesn't exist, just ignore */
    1395            0 :                 item = gkd_secret_objects_lookup_item (self, caller, paths[i]);
    1396            0 :                 if (!item)
    1397            0 :                         continue;
    1398              : 
    1399            0 :                 secret = gkd_secret_session_get_item_secret (session, item, &error);
    1400            0 :                 g_object_unref (item);
    1401              : 
    1402            0 :                 if (secret == NULL) {
    1403              :                         /* We ignore is locked, and just leave out from response */
    1404            0 :                         if (g_error_matches (error, GKD_SECRET_ERROR, GKD_SECRET_ERROR_IS_LOCKED)) {
    1405            0 :                                 g_clear_error (&error);
    1406            0 :                                 continue;
    1407              : 
    1408              :                         /* All other errors stop the operation */
    1409              :                         } else {
    1410            0 :                                 g_dbus_method_invocation_take_error (invocation, error);
    1411            0 :                                 return TRUE;
    1412              :                         }
    1413              :                 }
    1414              : 
    1415            0 :                 g_variant_builder_add (&builder, "{o@(oayays)}", paths[i], gkd_secret_secret_append (secret));
    1416            0 :                 gkd_secret_secret_free (secret);
    1417              :         }
    1418              : 
    1419            0 :         g_dbus_method_invocation_return_value (invocation,
    1420              :                                                g_variant_new ("(@a{o(oayays)})", g_variant_builder_end (&builder)));
    1421            0 :         return TRUE;
    1422              : }
    1423              : 
    1424              : static void
    1425           20 : on_each_item_emit_locked (GkdSecretObjects *self,
    1426              :                           const gchar *path,
    1427              :                           GckObject *object,
    1428              :                           gpointer user_data)
    1429              : {
    1430              :         GkdExportedItem *skeleton;
    1431              :         GVariant *value;
    1432           20 :         GError *error = NULL;
    1433              : 
    1434           20 :         skeleton = g_hash_table_lookup (self->items_to_skeletons, path);
    1435           20 :         if (skeleton == NULL) {
    1436            0 :                 g_warning ("setting locked state on item %s, but no skeleton found", path);
    1437            0 :                 return;
    1438              :         }
    1439              : 
    1440           20 :         value = object_property_get (self, object, "Locked", &error);
    1441           20 :         if (!value) {
    1442            0 :                 g_warning ("setting locked state on item %s, but no property value: %s",
    1443              :                            path, error->message);
    1444            0 :                 g_error_free (error);
    1445            0 :                 return;
    1446              :         }
    1447              : 
    1448           20 :         gkd_exported_item_set_locked (skeleton, g_variant_get_boolean (value));
    1449           20 :         g_variant_unref (value);
    1450              : 
    1451           20 :         gkd_secret_objects_emit_item_changed (self, object);
    1452              : }
    1453              : 
    1454              : void
    1455           20 : gkd_secret_objects_emit_collection_locked (GkdSecretObjects *self,
    1456              :                                            GckObject *collection)
    1457              : {
    1458              :         gchar *collection_path;
    1459              :         GkdExportedCollection *skeleton;
    1460              :         GVariant *value;
    1461           20 :         GError *error = NULL;
    1462              : 
    1463           20 :         collection_path = object_path_for_collection (collection);
    1464           20 :         gkd_secret_objects_foreach_item (self, NULL, collection_path,
    1465              :                                          on_each_item_emit_locked, NULL);
    1466              : 
    1467           20 :         skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
    1468           20 :         if (skeleton == NULL) {
    1469            0 :                 g_warning ("setting locked state on collection %s, but no skeleton found", collection_path);
    1470            0 :                 return;
    1471              :         }
    1472              : 
    1473           20 :         value = object_property_get (self, collection, "Locked", &error);
    1474           20 :         if (!value) {
    1475            0 :                 g_warning ("setting locked state on item %s, but no property value: %s",
    1476              :                            collection_path, error->message);
    1477            0 :                 g_error_free (error);
    1478            0 :                 return;
    1479              :         }
    1480              : 
    1481           20 :         gkd_exported_collection_set_locked (skeleton, g_variant_get_boolean (value));
    1482           20 :         g_variant_unref (value);
    1483              : 
    1484           20 :         gkd_secret_service_emit_collection_changed (self->service, collection_path);
    1485           20 :         g_free (collection_path);
    1486              : }
    1487              : 
    1488              : static void
    1489           25 : gkd_secret_objects_register_item (GkdSecretObjects *self,
    1490              :                                   const gchar *item_path)
    1491              : {
    1492              :         GkdExportedItem *skeleton;
    1493           25 :         GError *error = NULL;
    1494              : 
    1495           25 :         skeleton = g_hash_table_lookup (self->items_to_skeletons, item_path);
    1496           25 :         if (skeleton != NULL) {
    1497            0 :                 g_warning ("asked to register item %s, but it's already registered", item_path);
    1498            0 :                 return;
    1499              :         }
    1500              : 
    1501           25 :         skeleton = gkd_secret_item_skeleton_new (self);
    1502           25 :         g_hash_table_insert (self->items_to_skeletons, g_strdup (item_path), skeleton);
    1503              : 
    1504           25 :         g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
    1505              :                                           gkd_secret_service_get_connection (self->service),
    1506              :                                           item_path, &error);
    1507           25 :         if (error != NULL) {
    1508            0 :                 g_warning ("could not register secret item on session bus: %s", error->message);
    1509            0 :                 g_error_free (error);
    1510              :         }
    1511              : 
    1512           25 :         g_signal_connect (skeleton, "handle-delete",
    1513              :                           G_CALLBACK (item_method_delete), self);
    1514           25 :         g_signal_connect (skeleton, "handle-get-secret",
    1515              :                           G_CALLBACK (item_method_get_secret), self);
    1516           25 :         g_signal_connect (skeleton, "handle-set-secret",
    1517              :                           G_CALLBACK (item_method_set_secret), self);
    1518              : }
    1519              : 
    1520              : static void
    1521            1 : gkd_secret_objects_unregister_item (GkdSecretObjects *self,
    1522              :                                     const gchar *item_path)
    1523              : {
    1524            1 :         if (!g_hash_table_remove (self->items_to_skeletons, item_path)) {
    1525            0 :                 g_warning ("asked to unregister item %s, but it wasn't found", item_path);
    1526            0 :                 return;
    1527              :         }
    1528              : }
    1529              : 
    1530              : void
    1531            2 : gkd_secret_objects_emit_item_created (GkdSecretObjects *self,
    1532              :                                       GckObject *collection,
    1533              :                                       const gchar *item_path)
    1534              : {
    1535              :         GkdExportedCollection *skeleton;
    1536              :         gchar *collection_path;
    1537              :         gchar **items;
    1538              : 
    1539            2 :         g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
    1540            2 :         g_return_if_fail (GCK_OBJECT (collection));
    1541            2 :         g_return_if_fail (item_path != NULL);
    1542              : 
    1543            2 :         collection_path = object_path_for_collection (collection);
    1544            2 :         skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
    1545            2 :         g_return_if_fail (skeleton != NULL);
    1546              : 
    1547            2 :         gkd_secret_objects_register_item (self, item_path);
    1548            2 :         gkd_exported_collection_emit_item_created (skeleton, item_path);
    1549              : 
    1550            2 :         items = gkd_secret_objects_get_collection_items (self, collection_path);
    1551            2 :         gkd_exported_collection_set_items (skeleton, (const gchar **) items);
    1552              : 
    1553            2 :         g_free (collection_path);
    1554            2 :         g_strfreev (items);
    1555              : }
    1556              : 
    1557              : void
    1558           21 : gkd_secret_objects_emit_item_changed (GkdSecretObjects *self,
    1559              :                                       GckObject *item)
    1560              : {
    1561              :         GkdExportedCollection *skeleton;
    1562              :         gchar *collection_path;
    1563              :         gchar *item_path;
    1564              : 
    1565           21 :         g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
    1566           21 :         g_return_if_fail (GCK_OBJECT (item));
    1567              : 
    1568           21 :         collection_path = collection_path_for_item (item);
    1569           21 :         skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
    1570           21 :         g_return_if_fail (skeleton != NULL);
    1571              : 
    1572           21 :         item_path = object_path_for_item (collection_path, item);
    1573           21 :         gkd_exported_collection_emit_item_changed (skeleton, item_path);
    1574              : 
    1575           21 :         g_free (item_path);
    1576           21 :         g_free (collection_path);
    1577              : }
    1578              : 
    1579              : void
    1580            1 : gkd_secret_objects_emit_item_deleted (GkdSecretObjects *self,
    1581              :                                       GckObject *collection,
    1582              :                                       const gchar *item_path)
    1583              : {
    1584              :         GkdExportedCollection *skeleton;
    1585              :         gchar *collection_path;
    1586              :         gchar **items;
    1587              : 
    1588            1 :         g_return_if_fail (GKD_SECRET_IS_OBJECTS (self));
    1589            1 :         g_return_if_fail (GCK_OBJECT (collection));
    1590            1 :         g_return_if_fail (item_path != NULL);
    1591              : 
    1592            1 :         collection_path = object_path_for_collection (collection);
    1593            1 :         skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
    1594            1 :         g_return_if_fail (skeleton != NULL);
    1595              : 
    1596            1 :         gkd_secret_objects_unregister_item (self, item_path);
    1597            1 :         gkd_exported_collection_emit_item_deleted (skeleton, item_path);
    1598              : 
    1599            1 :         items = gkd_secret_objects_get_collection_items (self, collection_path);
    1600            1 :         gkd_exported_collection_set_items (skeleton, (const gchar **) items);
    1601              : 
    1602            1 :         g_strfreev (items);
    1603            1 :         g_free (collection_path);
    1604              : }
    1605              : 
    1606              : static void
    1607           50 : gkd_secret_objects_init_collection_items (GkdSecretObjects *self,
    1608              :                                           const gchar *collection_path)
    1609              : {
    1610              :         gchar **items;
    1611              :         gint idx;
    1612              : 
    1613           50 :         items = gkd_secret_objects_get_collection_items (self, collection_path);
    1614           73 :         for (idx = 0; items[idx] != NULL; idx++)
    1615           23 :                 gkd_secret_objects_register_item (self, items[idx]);
    1616              : 
    1617           50 :         g_strfreev (items);
    1618           50 : }
    1619              : 
    1620              : void
    1621           50 : gkd_secret_objects_register_collection (GkdSecretObjects *self,
    1622              :                                         const gchar *collection_path)
    1623              : {
    1624              :         GkdExportedCollection *skeleton;
    1625           50 :         GError *error = NULL;
    1626              : 
    1627           50 :         skeleton = g_hash_table_lookup (self->collections_to_skeletons, collection_path);
    1628           50 :         if (skeleton != NULL) {
    1629            0 :                 g_warning ("asked to register collection %s, but it's already registered", collection_path);
    1630            0 :                 return;
    1631              :         }
    1632              : 
    1633           50 :         skeleton = gkd_secret_collection_skeleton_new (self);
    1634           50 :         g_hash_table_insert (self->collections_to_skeletons, g_strdup (collection_path), skeleton);
    1635              : 
    1636           50 :         g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
    1637              :                                           gkd_secret_service_get_connection (self->service),
    1638              :                                           collection_path, &error);
    1639           50 :         if (error != NULL) {
    1640            0 :                 g_warning ("could not register secret collection on session bus: %s", error->message);
    1641            0 :                 g_error_free (error);
    1642              :         }
    1643              : 
    1644           50 :         g_signal_connect (skeleton, "handle-create-item",
    1645              :                           G_CALLBACK (collection_method_create_item), self);
    1646           50 :         g_signal_connect (skeleton, "handle-delete",
    1647              :                           G_CALLBACK (collection_method_delete), self);
    1648           50 :         g_signal_connect (skeleton, "handle-search-items",
    1649              :                           G_CALLBACK (collection_method_search_items), self);
    1650              : 
    1651           50 :         gkd_secret_objects_init_collection_items (self, collection_path);
    1652              : }
    1653              : 
    1654              : void
    1655            1 : gkd_secret_objects_unregister_collection (GkdSecretObjects *self,
    1656              :                                           const gchar *collection_path)
    1657              : {
    1658            1 :         if (!g_hash_table_remove (self->collections_to_skeletons, collection_path)) {
    1659            0 :                 g_warning ("asked to unregister collection %s, but it wasn't found", collection_path);
    1660            0 :                 return;
    1661              :         }
    1662              : }
        

Generated by: LCOV version 2.0-1