LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-manager.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.9 % 469 342
Test Date: 2024-04-08 13:24:42 Functions: 84.0 % 50 42

            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 "gkm-attributes.h"
      24              : #include "gkm-manager.h"
      25              : #include "gkm-marshal.h"
      26              : #include "gkm-module.h"
      27              : #include "gkm-session.h"
      28              : #include "gkm-util.h"
      29              : 
      30              : #include <glib.h>
      31              : #include <glib/gi18n.h>
      32              : 
      33              : #include <stdarg.h>
      34              : 
      35              : enum {
      36              :         PROP_0,
      37              :         PROP_FOR_TOKEN
      38              : };
      39              : 
      40              : enum {
      41              :         OBJECT_ADDED,
      42              :         OBJECT_REMOVED,
      43              :         ATTRIBUTE_CHANGED,
      44              :         LAST_SIGNAL
      45              : };
      46              : 
      47              : static guint signals[LAST_SIGNAL] = { 0 };
      48              : 
      49              : struct _GkmManagerPrivate {
      50              :         gboolean for_token;
      51              :         GList *objects;
      52              :         GHashTable *index_by_attribute;
      53              :         GHashTable *index_by_property;
      54              : };
      55              : 
      56              : typedef struct _Index {
      57              :         gboolean unique;
      58              :         CK_ATTRIBUTE_TYPE attribute_type;
      59              :         gchar *property_name;
      60              :         GHashTable *values;
      61              :         GHashTable *objects;
      62              : } Index;
      63              : 
      64              : typedef struct _Finder {
      65              :         GkmManager *manager;
      66              :         void (*accumulator) (struct _Finder *ctx, GkmObject *found);
      67              :         gpointer results;
      68              :         CK_ATTRIBUTE_PTR attrs;
      69              :         CK_ULONG n_attrs;
      70              :         GkmSession *session;
      71              : } Finder;
      72              : 
      73        42354 : G_DEFINE_TYPE_WITH_PRIVATE (GkmManager, gkm_manager, G_TYPE_OBJECT);
      74              : 
      75              : /* Friend functions for GkmObject */
      76              : void  _gkm_manager_register_object    (GkmManager *self, GkmObject *object);
      77              : void  _gkm_manager_unregister_object  (GkmManager *self, GkmObject *object);
      78              : 
      79              : /* -----------------------------------------------------------------------------
      80              :  * HELPERS
      81              :  */
      82              : 
      83              : static void
      84         7710 : attribute_free (gpointer data)
      85              : {
      86         7710 :         CK_ATTRIBUTE_PTR attr = data;
      87         7710 :         if (attr) {
      88         7710 :                 g_free (attr->pValue);
      89         7710 :                 g_slice_free (CK_ATTRIBUTE, attr);
      90              :         }
      91         7710 : }
      92              : 
      93              : static Index*
      94         1485 : index_new (gboolean unique)
      95              : {
      96         1485 :         Index *index = g_slice_new0 (Index);
      97         1485 :         index->unique = unique;
      98              : 
      99         1485 :         if (unique)
     100          495 :                 index->values = g_hash_table_new_full (gkm_attribute_hash, gkm_attribute_equal, attribute_free, NULL);
     101              :         else
     102          990 :                 index->values = g_hash_table_new_full (gkm_attribute_hash, gkm_attribute_equal, attribute_free,
     103              :                                                        (GDestroyNotify)g_hash_table_destroy);
     104              : 
     105         1485 :         index->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
     106              : 
     107         1485 :         return index;
     108              : }
     109              : 
     110              : static void
     111         1485 : index_free (gpointer data)
     112              : {
     113         1485 :         Index *index = data;
     114         1485 :         if (index) {
     115         1485 :                 g_hash_table_destroy (index->values);
     116         1485 :                 g_hash_table_destroy (index->objects);
     117         1485 :                 g_free (index->property_name);
     118         1485 :                 g_slice_free (Index, index);
     119              :         }
     120         1485 : }
     121              : 
     122              : static gboolean
     123         5340 : read_attribute(GkmObject *object, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR *result)
     124              : {
     125              :         CK_ATTRIBUTE attr;
     126              :         CK_RV rv;
     127              : 
     128         5340 :         g_assert (GKM_IS_OBJECT (object));
     129         5340 :         g_assert (result);
     130              : 
     131         5340 :         *result = NULL;
     132              : 
     133         5340 :         attr.type = type;
     134         5340 :         attr.pValue = NULL;
     135         5340 :         attr.ulValueLen = 0;
     136              : 
     137              :         /* Figure out memory length */
     138         5340 :         rv = gkm_object_get_attribute (object, NULL, &attr);
     139              : 
     140              :         /* Not an error, just not present */
     141         5340 :         if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
     142          300 :                 *result = NULL;
     143          300 :                 return TRUE;
     144              :         }
     145              : 
     146         5040 :         if (rv != CKR_OK) {
     147            0 :                 g_warning ("accessing indexed attribute failed");
     148            0 :                 return FALSE;
     149              :         }
     150              : 
     151              :         /* Allocate memory length */
     152         5040 :         if (attr.ulValueLen) {
     153         5022 :                 attr.pValue = g_malloc0 (attr.ulValueLen);
     154         5022 :                 rv = gkm_object_get_attribute (object, NULL, &attr);
     155         5022 :                 if (rv != CKR_OK) {
     156            0 :                         g_warning ("accessing indexed attribute failed");
     157            0 :                         g_free (attr.pValue);
     158            0 :                         return FALSE;
     159              :                 }
     160              :         }
     161              : 
     162         5040 :         *result = g_slice_new (CK_ATTRIBUTE);
     163         5040 :         memcpy (*result, &attr, sizeof (CK_ATTRIBUTE));
     164         5040 :         return TRUE;
     165              : }
     166              : 
     167              : static gboolean
     168         2670 : read_value (GkmObject *object, const gchar *property, CK_ATTRIBUTE_PTR *result)
     169              : {
     170              :         CK_ATTRIBUTE attr;
     171              :         GParamSpec *spec;
     172         2670 :         GValue value = { 0, };
     173              :         CK_ULONG number;
     174              :         CK_BBOOL boolean;
     175              : 
     176         2670 :         g_assert (GKM_IS_OBJECT (object));
     177         2670 :         g_assert (property);
     178         2670 :         g_assert (result);
     179              : 
     180         2670 :         spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
     181              :                                              property);
     182              : 
     183              :         /* Not an error, just no such property on object */
     184         2670 :         if (spec == NULL) {
     185            0 :                 *result = NULL;
     186            0 :                 return TRUE;
     187              :         }
     188              : 
     189         2670 :         g_value_init(&value, spec->value_type);
     190         2670 :         g_object_get_property (G_OBJECT (object), property, &value);
     191              : 
     192         2670 :         attr.type = (CK_ATTRIBUTE_TYPE)-1;
     193         2670 :         attr.pValue = NULL;
     194         2670 :         attr.ulValueLen = 0;
     195              : 
     196              :         /* We only support specific types of values */
     197         2670 :         switch (spec->value_type)
     198              :         {
     199            0 :         case G_TYPE_STRING:
     200            0 :                 attr.pValue = g_value_dup_string (&value);
     201            0 :                 attr.ulValueLen = attr.pValue ? strlen (attr.pValue) : 0;
     202            0 :                 break;
     203            0 :         case G_TYPE_INT:
     204            0 :                 number = g_value_get_int (&value);
     205            0 :                 attr.ulValueLen = sizeof (number);
     206            0 :                 attr.pValue = g_memdup (&number, attr.ulValueLen);
     207            0 :                 break;
     208            0 :         case G_TYPE_UINT:
     209            0 :                 number = g_value_get_uint (&value);
     210            0 :                 attr.ulValueLen = sizeof (number);
     211            0 :                 attr.pValue = g_memdup (&number, attr.ulValueLen);
     212            0 :                 break;
     213            0 :         case G_TYPE_LONG:
     214            0 :                 number = g_value_get_long (&value);
     215            0 :                 attr.ulValueLen = sizeof (number);
     216            0 :                 attr.pValue = g_memdup (&number, attr.ulValueLen);
     217            0 :                 break;
     218         2670 :         case G_TYPE_ULONG:
     219         2670 :                 number = g_value_get_ulong (&value);
     220         2670 :                 attr.ulValueLen = sizeof (number);
     221         2670 :                 attr.pValue = g_memdup (&number, attr.ulValueLen);
     222         2670 :                 break;
     223            0 :         case G_TYPE_BOOLEAN:
     224            0 :                 boolean = g_value_get_boolean (&value) ? CK_TRUE : CK_FALSE;
     225            0 :                 attr.ulValueLen = sizeof (boolean);
     226            0 :                 attr.pValue = g_memdup (&boolean, attr.ulValueLen);
     227            0 :                 break;
     228            0 :         default:
     229            0 :                 g_warning ("couldn't convert value from type %s into attribute",
     230              :                            g_type_name (spec->value_type));
     231            0 :                 g_value_unset (&value);
     232            0 :                 return FALSE;
     233              :         };
     234              : 
     235         2670 :         if (attr.pValue) {
     236         2670 :                 *result = g_slice_new (CK_ATTRIBUTE);
     237         2670 :                 memcpy (*result, &attr, sizeof (CK_ATTRIBUTE));
     238              :         } else {
     239            0 :                 *result = NULL;
     240              :         }
     241              : 
     242         2670 :         g_value_unset (&value);
     243         2670 :         return TRUE;
     244              : }
     245              : 
     246              : static void
     247         7710 : index_remove_attr (Index *index, gpointer object, CK_ATTRIBUTE_PTR attr)
     248              : {
     249              :         GHashTable *objects;
     250              : 
     251         7710 :         g_assert (index);
     252         7710 :         g_assert (object);
     253         7710 :         g_assert (attr);
     254              : 
     255         7710 :         if (index->unique) {
     256         2670 :                 if (!g_hash_table_remove (index->values, attr))
     257            0 :                         g_assert_not_reached ();
     258              :         } else {
     259         5040 :                 objects = g_hash_table_lookup (index->values, attr);
     260         5040 :                 g_assert (objects);
     261         5040 :                 if (!g_hash_table_remove (objects, object))
     262            0 :                         g_assert_not_reached ();
     263         5040 :                 if (g_hash_table_size (objects) == 0)
     264         2787 :                         if (!g_hash_table_remove (index->values, attr))
     265            0 :                                 g_assert_not_reached ();
     266              :         }
     267         7710 : }
     268              : 
     269              : static void
     270         8010 : index_remove (Index *index, gpointer object)
     271              : {
     272              :         CK_ATTRIBUTE_PTR attr;
     273              : 
     274              :         /*
     275              :          * We don't actually access the object. We want to be able to
     276              :          * handle objects that have been destroyed as well.
     277              :          */
     278              : 
     279         8010 :         g_assert (object);
     280         8010 :         g_assert (index);
     281              : 
     282         8010 :         attr = g_hash_table_lookup (index->objects, object);
     283              : 
     284              :         /* Object not in this index */
     285         8010 :         if (attr == NULL)
     286          300 :                 return;
     287              : 
     288              :         /* Remove the actual value */
     289         7710 :         index_remove_attr (index, object, attr);
     290              : 
     291         7710 :         if (!g_hash_table_remove (index->objects, object))
     292            0 :                 g_assert_not_reached ();
     293              : }
     294              : 
     295              : static void
     296         8010 : index_update (Index *index, GkmObject *object)
     297              : {
     298         8010 :         CK_ATTRIBUTE_PTR attr = NULL;
     299              :         CK_ATTRIBUTE_PTR prev;
     300              :         GHashTable *objects;
     301              :         gboolean ret;
     302              : 
     303         8010 :         g_assert (GKM_IS_OBJECT (object));
     304         8010 :         g_assert (index);
     305              : 
     306              :         /* Get the value for this index */
     307         8010 :         if (index->property_name)
     308         2670 :                 ret = read_value (object, index->property_name, &attr);
     309              :         else
     310         5340 :                 ret = read_attribute (object, index->attribute_type, &attr);
     311         8310 :         g_return_if_fail (ret);
     312              : 
     313              :         /* No such attribute/property on object */
     314         8010 :         if (attr == NULL)
     315          300 :                 return;
     316              : 
     317         7710 :         prev = g_hash_table_lookup (index->objects, object);
     318         7710 :         if (prev != NULL) {
     319              : 
     320              :                 /* The previous one is same, ignore */
     321            0 :                 if (gkm_attribute_equal (prev, attr)) {
     322            0 :                         attribute_free (attr);
     323            0 :                         return;
     324              :                 }
     325              : 
     326              :                 /* Remove the previous one */
     327            0 :                 index_remove_attr (index, object, prev);
     328              :         }
     329              : 
     330              :         /* In this case values is a direct pointer to the object */
     331         7710 :         if (index->unique) {
     332         2670 :                 g_return_if_fail (g_hash_table_lookup (index->values, attr) == NULL);
     333         2670 :                 g_hash_table_replace (index->values, attr, object);
     334         2670 :                 g_hash_table_replace (index->objects, object, attr);
     335              : 
     336              :         /* In this case values is a pointer to a hash set of objects */
     337              :         } else {
     338              :                 gpointer key, value;
     339         5040 :                 if (g_hash_table_lookup_extended (index->values, attr, &key, &value)) {
     340         2253 :                         attribute_free (attr);
     341         2253 :                         objects = value;
     342         2253 :                         attr = key;
     343              :                 } else {
     344         2787 :                         objects = g_hash_table_new (g_direct_hash, g_direct_equal);
     345         2787 :                         g_hash_table_insert (index->values, attr, objects);
     346              :                 }
     347              : 
     348         5040 :                 g_hash_table_insert (objects, object, object);
     349         5040 :                 g_hash_table_replace (index->objects, object, attr);
     350              :         }
     351              : }
     352              : 
     353              : static gboolean
     354          112 : index_contains (Index *index, GkmObject *object, CK_ATTRIBUTE_PTR attr)
     355              : {
     356              :         GHashTable *objects;
     357              : 
     358          112 :         g_assert (index);
     359          112 :         g_assert (GKM_IS_OBJECT (object));
     360          112 :         g_assert (attr);
     361              : 
     362          112 :         if (index->unique) {
     363            0 :                 return (g_hash_table_lookup (index->values, attr) == object);
     364              :         } else {
     365          112 :                 objects = g_hash_table_lookup (index->values, attr);
     366          112 :                 return (objects && g_hash_table_lookup (objects, object) == object);
     367              :         }
     368              : }
     369              : 
     370              : static void
     371         8010 : index_object_each (gpointer key, gpointer value, gpointer user_data)
     372              : {
     373         8010 :         index_update (value, user_data);
     374         8010 : }
     375              : 
     376              : static void
     377         8010 : index_remove_each (gpointer key, gpointer value, gpointer user_data)
     378              : {
     379         8010 :         index_remove (value, user_data);
     380         8010 : }
     381              : 
     382              : static void
     383         2080 : notify_attribute (GkmObject *object, CK_ATTRIBUTE_TYPE attr_type, GkmManager *self)
     384              : {
     385              :         Index *index;
     386              : 
     387         2080 :         g_return_if_fail (GKM_IS_OBJECT (object));
     388         2080 :         g_return_if_fail (GKM_IS_MANAGER (self));
     389         2080 :         g_return_if_fail (gkm_object_get_manager (object) == self);
     390              : 
     391         2080 :         index = g_hash_table_lookup (self->pv->index_by_attribute, &attr_type);
     392         2080 :         if (index != NULL)
     393            0 :                 index_update (index, object);
     394              : 
     395              :         /* Tell everyone that this attribute changed on this object */
     396         2080 :         g_signal_emit (self, signals[ATTRIBUTE_CHANGED], 0, object, attr_type);
     397              : }
     398              : 
     399              : static void
     400         4237 : notify_property (GkmObject *object, GParamSpec *spec, GkmManager *self)
     401              : {
     402              :         Index *index;
     403              : 
     404         4237 :         g_return_if_fail (GKM_IS_OBJECT (object));
     405         4237 :         g_return_if_fail (GKM_IS_MANAGER (self));
     406         4237 :         g_return_if_fail (gkm_object_get_manager (object) == self);
     407              : 
     408         4237 :         index = g_hash_table_lookup (self->pv->index_by_property, spec->name);
     409         4237 :         if (index != NULL)
     410            0 :                 index_update (index, object);
     411              : }
     412              : 
     413              : static void
     414         2670 : add_object (GkmManager *self, GkmObject *object)
     415              : {
     416              :         CK_OBJECT_HANDLE handle;
     417              : 
     418         2670 :         g_assert (GKM_IS_MANAGER (self));
     419         2670 :         g_assert (GKM_IS_OBJECT (object));
     420         2670 :         g_assert (gkm_object_get_manager (object) == self);
     421              : 
     422         2670 :         handle = gkm_object_get_handle (object);
     423         2670 :         if (!handle) {
     424              :                 /* Make a new handle */
     425         2669 :                 handle = gkm_util_next_handle ();
     426         2669 :                 gkm_object_set_handle (object, handle);
     427              :         }
     428              : 
     429              :         /*
     430              :          * We don't ref the objects or anything. They're expected to
     431              :          * unregister upon dispose.
     432              :          */
     433              : 
     434              :         /* Note objects is being managed */
     435         2670 :         self->pv->objects = g_list_prepend (self->pv->objects, object);
     436              : 
     437              :         /* Now index the object properly */
     438         2670 :         g_hash_table_foreach (self->pv->index_by_attribute, index_object_each, object);
     439         2670 :         g_hash_table_foreach (self->pv->index_by_property, index_object_each, object);
     440         2670 :         g_signal_connect (object, "notify-attribute", G_CALLBACK (notify_attribute), self);
     441         2670 :         g_signal_connect (object, "notify", G_CALLBACK (notify_property), self);
     442              : 
     443              :         /* Tell everyone we added this object */
     444         2670 :         g_signal_emit (self, signals[OBJECT_ADDED], 0, object);
     445         2670 : }
     446              : 
     447              : static void
     448         2670 : remove_object (GkmManager *self, GkmObject *object)
     449              : {
     450              :         CK_OBJECT_HANDLE handle;
     451              : 
     452         2670 :         g_assert (GKM_IS_MANAGER (self));
     453         2670 :         g_assert (GKM_IS_OBJECT (object));
     454         2670 :         g_assert (gkm_object_get_manager (object) == self);
     455              : 
     456         2670 :         handle = gkm_object_get_handle (object);
     457         2670 :         g_assert (handle);
     458              : 
     459              :         /* Remove from all indexes */
     460         2670 :         g_signal_handlers_disconnect_by_func (object, G_CALLBACK (notify_attribute), self);
     461         2670 :         g_signal_handlers_disconnect_by_func (object, G_CALLBACK (notify_property), self);
     462         2670 :         g_hash_table_foreach (self->pv->index_by_attribute, index_remove_each, object);
     463         2670 :         g_hash_table_foreach (self->pv->index_by_property, index_remove_each, object);
     464              : 
     465              :         /* Release object management */
     466         2670 :         self->pv->objects = g_list_remove (self->pv->objects, object);
     467              : 
     468              :         /* Tell everyone this object is gone */
     469         2670 :         g_signal_emit (self, signals[OBJECT_REMOVED], 0, object);
     470         2670 : }
     471              : 
     472              : static void
     473         2710 : find_each_object (gpointer unused, gpointer object, gpointer user_data)
     474              : {
     475         2710 :         Finder *finder = user_data;
     476              :         CK_ATTRIBUTE_PTR attr;
     477              :         Index *index;
     478              :         CK_ULONG i;
     479              : 
     480         2710 :         g_assert (finder);
     481         2710 :         g_assert (GKM_IS_MANAGER (finder->manager));
     482              : 
     483              :         /* Match the object against all the other attributes */
     484         3053 :         for (i = 0; i < finder->n_attrs; ++i) {
     485          628 :                 attr = &(finder->attrs[i]);
     486          628 :                 index = g_hash_table_lookup (finder->manager->pv->index_by_attribute, &attr->type);
     487          628 :                 if (index) {
     488          112 :                         if (!index_contains (index, object, attr))
     489           58 :                                 return;
     490              :                 } else {
     491          516 :                         if (!gkm_object_match (object, finder->session, attr))
     492          227 :                                 return;
     493              :                 }
     494              :         }
     495              : 
     496         2425 :         (finder->accumulator) (finder, object);
     497              : }
     498              : 
     499              : static void
     500          803 : find_for_attributes (Finder *finder)
     501              : {
     502              :         GHashTable *objects;
     503              :         CK_ATTRIBUTE_PTR first;
     504              :         GkmObject *object;
     505              :         Index *index;
     506              :         GList *l;
     507              : 
     508          803 :         g_assert (finder);
     509          803 :         g_assert (GKM_IS_MANAGER (finder->manager));
     510          803 :         g_assert (!finder->n_attrs || finder->attrs);
     511              : 
     512              :         /* All the objects */
     513          803 :         if (!finder->n_attrs) {
     514           26 :                 for (l = finder->manager->pv->objects; l; l = g_list_next (l))
     515           14 :                         (finder->accumulator) (finder, l->data);
     516           12 :                 return;
     517              :         }
     518              : 
     519          791 :         first = finder->attrs;
     520          791 :         finder->attrs = finder->attrs + 1;
     521          791 :         finder->n_attrs = finder->n_attrs - 1;
     522              : 
     523          791 :         index = g_hash_table_lookup (finder->manager->pv->index_by_attribute,
     524          791 :                                      &first->type);
     525              : 
     526              : 
     527              :         /* No indexes, have to manually match */
     528          791 :         if (!index) {
     529              : 
     530           69 :                 for (l = finder->manager->pv->objects; l; l = g_list_next (l)) {
     531           43 :                         if (gkm_object_match (l->data, NULL, first))
     532            8 :                                 find_each_object (NULL, l->data, finder);
     533              :                 }
     534              : 
     535           26 :                 return;
     536              :         }
     537              : 
     538              :         /* Yay, an index */
     539          765 :         if (index->unique) {
     540            0 :                 object = g_hash_table_lookup (index->values, first);
     541            0 :                 if (object)
     542            0 :                         find_each_object (NULL, object, finder);
     543              :         } else {
     544          765 :                 objects = g_hash_table_lookup (index->values, first);
     545          765 :                 if (objects)
     546          437 :                         g_hash_table_foreach (objects, find_each_object, finder);
     547              :         }
     548              : }
     549              : 
     550              : static void
     551         2240 : accumulate_list (Finder *finder, GkmObject *object)
     552              : {
     553         2240 :         finder->results = g_list_prepend (finder->results, object);
     554         2240 : }
     555              : 
     556              : static void
     557            4 : accumulate_one (Finder *finder, GkmObject *object)
     558              : {
     559            4 :         if (!finder->results)
     560            4 :                 finder->results = object;
     561            4 : }
     562              : 
     563              : static void
     564          195 : accumulate_handles (Finder *finder, GkmObject *object)
     565              : {
     566          195 :         CK_OBJECT_HANDLE handle = gkm_object_get_handle (object);
     567          195 :         g_return_if_fail (handle);
     568          195 :         g_array_append_val (finder->results, handle);
     569              : }
     570              : 
     571              : static void
     572            0 : accumulate_public_handles (Finder *finder, GkmObject *object)
     573              : {
     574              :         gboolean is_private;
     575            0 :         if (gkm_object_get_attribute_boolean (object, NULL, CKA_PRIVATE, &is_private) && is_private)
     576            0 :                 return;
     577            0 :         accumulate_handles (finder, object);
     578              : }
     579              : 
     580              : static void
     581            0 : values_to_list (gpointer key, gpointer value, gpointer user_data)
     582              : {
     583            0 :         GList** list = (GList**)user_data;
     584            0 :         *list = g_list_prepend (*list, value);
     585            0 : }
     586              : 
     587              : static GList*
     588            0 : find_all_for_property (GkmManager *self, const gchar *property, CK_ATTRIBUTE_PTR attr)
     589              : {
     590              :         GkmObject *object;
     591              :         GHashTable *objects;
     592            0 :         GList *results = NULL;
     593              :         Index *index;
     594              : 
     595            0 :         g_assert (GKM_IS_MANAGER (self));
     596            0 :         g_assert (property);
     597            0 :         g_assert (attr);
     598              : 
     599            0 :         index = g_hash_table_lookup (self->pv->index_by_property, property);
     600            0 :         g_return_val_if_fail (index, NULL);
     601              : 
     602            0 :         if (index->unique) {
     603            0 :                 object = g_hash_table_lookup (index->values, attr);
     604            0 :                 return object ? g_list_prepend (NULL, object) : NULL;
     605              :         } else {
     606            0 :                 objects = g_hash_table_lookup (index->values, attr);
     607            0 :                 if (!objects)
     608            0 :                         return NULL;
     609            0 :                 g_hash_table_foreach (objects, values_to_list, &results);
     610            0 :                 return results;
     611              :         }
     612              : }
     613              : 
     614              : static GkmObject*
     615         4772 : find_one_for_property (GkmManager *self, const gchar *property, CK_ATTRIBUTE_PTR attr)
     616              : {
     617              :         GkmObject *object;
     618              :         GHashTable *objects;
     619         4772 :         GList *results = NULL;
     620              :         Index *index;
     621              : 
     622         4772 :         g_assert (GKM_IS_MANAGER (self));
     623         4772 :         g_assert (property);
     624         4772 :         g_assert (attr);
     625              : 
     626         4772 :         index = g_hash_table_lookup (self->pv->index_by_property, property);
     627         4772 :         g_return_val_if_fail (index, NULL);
     628              : 
     629         4772 :         if (index->unique) {
     630         4772 :                 return g_hash_table_lookup (index->values, attr);
     631              :         } else {
     632            0 :                 objects = g_hash_table_lookup (index->values, attr);
     633            0 :                 if (!objects)
     634            0 :                         return NULL;
     635            0 :                 g_hash_table_foreach (objects, values_to_list, &results);
     636            0 :                 object = results ? results->data : NULL;
     637            0 :                 g_list_free (results);
     638            0 :                 return object;
     639              :         }
     640              : }
     641              : 
     642              : /* -----------------------------------------------------------------------------
     643              :  * OBJECT
     644              :  */
     645              : 
     646              : static void
     647          495 : gkm_manager_init (GkmManager *self)
     648              : {
     649          495 :         self->pv = gkm_manager_get_instance_private (self);
     650          495 :         self->pv->index_by_attribute = g_hash_table_new_full (gkm_util_ulong_hash, gkm_util_ulong_equal,
     651              :                                                               gkm_util_ulong_free, index_free);
     652          495 :         self->pv->index_by_property = g_hash_table_new_full (g_str_hash, g_str_equal,
     653              :                                                              g_free, index_free);
     654          495 :         gkm_manager_add_property_index (self, "handle", TRUE);
     655          495 :         gkm_manager_add_attribute_index (self, CKA_ID, FALSE);
     656          495 :         gkm_manager_add_attribute_index (self, CKA_CLASS, FALSE);
     657          495 : }
     658              : 
     659              : static void
     660          495 : gkm_manager_set_property (GObject *obj, guint prop_id, const GValue *value,
     661              :                           GParamSpec *pspec)
     662              : {
     663          495 :         GkmManager *self = GKM_MANAGER (obj);
     664              : 
     665          495 :         switch (prop_id) {
     666          495 :         case PROP_FOR_TOKEN:
     667          495 :                 self->pv->for_token = g_value_get_boolean (value);
     668          495 :                 break;
     669            0 :         default:
     670            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     671            0 :                 break;
     672              :         }
     673          495 : }
     674              : 
     675              : static void
     676            0 : gkm_manager_get_property (GObject *obj, guint prop_id, GValue *value,
     677              :                           GParamSpec *pspec)
     678              : {
     679            0 :         GkmManager *self = GKM_MANAGER (obj);
     680              : 
     681            0 :         switch (prop_id) {
     682            0 :         case PROP_FOR_TOKEN:
     683            0 :                 g_value_set_boolean (value, gkm_manager_get_for_token (self));
     684            0 :                 break;
     685            0 :         default:
     686            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     687            0 :                 break;
     688              :         }
     689            0 : }
     690              : 
     691              : 
     692              : static void
     693          495 : gkm_manager_dispose (GObject *obj)
     694              : {
     695          495 :         GkmManager *self = GKM_MANAGER (obj);
     696              :         GList *objects, *l;
     697              : 
     698              :         /* Unregister all objects */
     699          495 :         objects = g_list_copy (self->pv->objects);
     700          495 :         for (l = objects; l; l = g_list_next (l))
     701            0 :                 remove_object (self, GKM_OBJECT (l->data));
     702          495 :         g_list_free (objects);
     703              : 
     704          495 :         g_return_if_fail (self->pv->objects == NULL);
     705              : 
     706          495 :         G_OBJECT_CLASS (gkm_manager_parent_class)->dispose (obj);
     707              : }
     708              : 
     709              : static void
     710          495 : gkm_manager_finalize (GObject *obj)
     711              : {
     712          495 :         GkmManager *self = GKM_MANAGER (obj);
     713              : 
     714          495 :         g_assert (!self->pv->objects);
     715          495 :         g_hash_table_destroy (self->pv->index_by_attribute);
     716          495 :         g_hash_table_destroy (self->pv->index_by_property);
     717              : 
     718          495 :         G_OBJECT_CLASS (gkm_manager_parent_class)->finalize (obj);
     719          495 : }
     720              : 
     721              : static void
     722           47 : gkm_manager_class_init (GkmManagerClass *klass)
     723              : {
     724              :         GObjectClass *gobject_class;
     725           47 :         gobject_class = (GObjectClass*)klass;
     726              : 
     727           47 :         gobject_class->dispose = gkm_manager_dispose;
     728           47 :         gobject_class->get_property = gkm_manager_get_property;
     729           47 :         gobject_class->set_property = gkm_manager_set_property;
     730           47 :         gobject_class->finalize = gkm_manager_finalize;
     731              : 
     732           47 :         g_object_class_install_property (gobject_class, PROP_FOR_TOKEN,
     733              :                  g_param_spec_boolean ("for-token", "For Token", "Whether this manager is for token objects or not",
     734              :                                        FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     735              : 
     736           47 :         signals[OBJECT_ADDED] = g_signal_new ("object-added", GKM_TYPE_MANAGER,
     737              :                                               G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, object_added),
     738              :                                               NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
     739              :                                               G_TYPE_NONE, 1, GKM_TYPE_OBJECT);
     740              : 
     741           47 :         signals[OBJECT_REMOVED] = g_signal_new ("object-removed", GKM_TYPE_MANAGER,
     742              :                                                 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, object_removed),
     743              :                                                 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
     744              :                                                 G_TYPE_NONE, 1, GKM_TYPE_OBJECT);
     745              : 
     746           47 :         signals[ATTRIBUTE_CHANGED] = g_signal_new ("attribute-changed", GKM_TYPE_MANAGER,
     747              :                                                    G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, attribute_changed),
     748              :                                                    NULL, NULL, gkm_marshal_VOID__OBJECT_ULONG,
     749              :                                                    G_TYPE_NONE, 2, GKM_TYPE_OBJECT, G_TYPE_ULONG);
     750           47 : }
     751              : 
     752              : /* ------------------------------------------------------------------------
     753              :  * PUBLIC METHODS
     754              :  */
     755              : 
     756              : gboolean
     757          613 : gkm_manager_get_for_token (GkmManager *self)
     758              : {
     759          613 :         g_return_val_if_fail (GKM_IS_MANAGER (self), FALSE);
     760          613 :         return self->pv->for_token;
     761              : }
     762              : 
     763              : void
     764          990 : gkm_manager_add_attribute_index (GkmManager *self, CK_ATTRIBUTE_TYPE attr, gboolean unique)
     765              : {
     766              :         Index *index;
     767              :         GList *l;
     768              : 
     769          990 :         g_return_if_fail (GKM_IS_MANAGER (self));
     770          990 :         g_return_if_fail (!g_hash_table_lookup (self->pv->index_by_attribute, &attr));
     771              : 
     772          990 :         index = index_new (unique);
     773          990 :         index->attribute_type = attr;
     774          990 :         g_hash_table_replace (self->pv->index_by_attribute, gkm_util_ulong_alloc (attr), index);
     775              : 
     776          990 :         for (l = self->pv->objects; l; l = g_list_next (l))
     777            0 :                 index_update (index, l->data);
     778              : }
     779              : 
     780              : void
     781          495 : gkm_manager_add_property_index (GkmManager *self, const gchar *property, gboolean unique)
     782              : {
     783              :         Index *index;
     784              :         GList *l;
     785              : 
     786          495 :         g_return_if_fail (GKM_IS_MANAGER (self));
     787          495 :         g_return_if_fail (property);
     788          495 :         g_return_if_fail (!g_hash_table_lookup (self->pv->index_by_property, property));
     789              : 
     790          495 :         index = index_new (unique);
     791          495 :         index->property_name = g_strdup (property);
     792          495 :         g_hash_table_replace (self->pv->index_by_property, g_strdup (property), index);
     793              : 
     794          495 :         for (l = self->pv->objects; l; l = g_list_next (l))
     795            0 :                 index_update (index, l->data);
     796              : }
     797              : 
     798              : void
     799         2670 : _gkm_manager_register_object (GkmManager *self, GkmObject *object)
     800              : {
     801         2670 :         g_return_if_fail (GKM_IS_MANAGER (self));
     802         2670 :         g_return_if_fail (GKM_IS_OBJECT (object));
     803         2670 :         g_return_if_fail (gkm_object_get_manager (object) == self);
     804              : 
     805         2670 :         add_object (self, object);
     806              : }
     807              : 
     808              : void
     809         2670 : _gkm_manager_unregister_object (GkmManager *self, GkmObject *object)
     810              : {
     811         2670 :         g_return_if_fail (GKM_IS_MANAGER (self));
     812         2670 :         g_return_if_fail (GKM_IS_OBJECT (object));
     813         2670 :         g_return_if_fail (gkm_object_get_manager (object) == self);
     814              : 
     815         2670 :         remove_object (self, object);
     816              : }
     817              : 
     818              : GkmObject*
     819         4772 : gkm_manager_find_by_handle (GkmManager *self, CK_OBJECT_HANDLE handle)
     820              : {
     821         4772 :         g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
     822         4772 :         g_return_val_if_fail (handle != 0, NULL);
     823              : 
     824         4772 :         return gkm_manager_find_one_by_number_property (self, "handle", handle);
     825              : }
     826              : 
     827              : GList*
     828            0 : gkm_manager_find_by_number_property (GkmManager *self, const gchar *property, gulong value)
     829              : {
     830              :         CK_ATTRIBUTE attr;
     831            0 :         CK_ULONG number = value;
     832              : 
     833            0 :         attr.type = (CK_ATTRIBUTE_TYPE)-1;
     834            0 :         attr.pValue = &number;
     835            0 :         attr.ulValueLen = sizeof (number);
     836              : 
     837            0 :         return find_all_for_property (self, property, &attr);
     838              : }
     839              : 
     840              : GkmObject*
     841         4772 : gkm_manager_find_one_by_number_property (GkmManager *self, const gchar *property, gulong value)
     842              : {
     843              :         CK_ATTRIBUTE attr;
     844         4772 :         CK_ULONG number = value;
     845              : 
     846         4772 :         attr.type = (CK_ATTRIBUTE_TYPE)-1;
     847         4772 :         attr.pValue = &number;
     848         4772 :         attr.ulValueLen = sizeof (number);
     849              : 
     850         4772 :         return find_one_for_property (self, property, &attr);
     851              : }
     852              : 
     853              : GList*
     854            0 : gkm_manager_find_by_string_property (GkmManager *self, const gchar *property, const gchar *value)
     855              : {
     856              :         CK_ATTRIBUTE attr;
     857              : 
     858            0 :         attr.type = (CK_ATTRIBUTE_TYPE)-1;
     859            0 :         attr.pValue = (void*)value;
     860            0 :         attr.ulValueLen = value ? strlen (value) : 0;
     861              : 
     862            0 :         return find_all_for_property (self, property, &attr);
     863              : }
     864              : 
     865              : GkmObject*
     866            0 : gkm_manager_find_one_by_string_property (GkmManager *self, const gchar *property, const gchar *value)
     867              : {
     868              :         CK_ATTRIBUTE attr;
     869              : 
     870            0 :         attr.type = (CK_ATTRIBUTE_TYPE)-1;
     871            0 :         attr.pValue = (void*)value;
     872            0 :         attr.ulValueLen = value ? strlen (value) : 0;
     873              : 
     874            0 :         return find_one_for_property (self, property, &attr);
     875              : }
     876              : 
     877              : GkmObject*
     878            4 : gkm_manager_find_one_by_attributes (GkmManager *self, GkmSession *session,
     879              :                                     CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     880              : {
     881            4 :         Finder finder = { 0, };
     882              : 
     883            4 :         g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
     884            4 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     885              : 
     886            4 :         finder.accumulator = accumulate_one;
     887            4 :         finder.results = NULL;
     888            4 :         finder.manager = self;
     889            4 :         finder.attrs = attrs;
     890            4 :         finder.n_attrs = n_attrs;
     891            4 :         finder.session = session;
     892              : 
     893            4 :         find_for_attributes (&finder);
     894              : 
     895            4 :         return finder.results;
     896              : }
     897              : 
     898              : GList*
     899          433 : gkm_manager_find_by_attributes (GkmManager *self, GkmSession *session,
     900              :                                 CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     901              : {
     902          433 :         Finder finder = { 0, };
     903              : 
     904          433 :         g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
     905          433 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     906              : 
     907          433 :         finder.accumulator = accumulate_list;
     908          433 :         finder.results = NULL;
     909          433 :         finder.manager = self;
     910          433 :         finder.attrs = attrs;
     911          433 :         finder.n_attrs = n_attrs;
     912          433 :         finder.session = session;
     913              : 
     914          433 :         find_for_attributes (&finder);
     915              : 
     916          433 :         return finder.results;
     917              : }
     918              : 
     919              : GList*
     920           40 : gkm_manager_find_by_class (GkmManager *self, GkmSession *session, CK_OBJECT_CLASS klass)
     921              : {
     922              :         CK_ATTRIBUTE attr;
     923              : 
     924           40 :         g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
     925              : 
     926           40 :         attr.type = CKA_CLASS;
     927           40 :         attr.ulValueLen = sizeof (klass);
     928           40 :         attr.pValue = &klass;
     929              : 
     930           40 :         return gkm_manager_find_by_attributes (self, session, &attr, 1);
     931              : }
     932              : 
     933              : GkmObject*
     934            0 : gkm_manager_find_related (GkmManager *self, GkmSession *session,
     935              :                           CK_OBJECT_CLASS klass, GkmObject *related_to)
     936              : {
     937              :         CK_ATTRIBUTE attrs[2];
     938              :         GkmObject *object;
     939              :         guchar *id;
     940              :         gsize n_id;
     941              : 
     942            0 :         g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
     943            0 :         g_return_val_if_fail (GKM_IS_OBJECT (related_to), NULL);
     944              : 
     945            0 :         id = gkm_object_get_attribute_data (related_to, NULL, CKA_ID, &n_id);
     946            0 :         if (id == NULL)
     947            0 :                 return NULL;
     948              : 
     949            0 :         attrs[0].type = CKA_ID;
     950            0 :         attrs[0].pValue = id;
     951            0 :         attrs[0].ulValueLen = n_id;
     952              : 
     953            0 :         attrs[1].type = CKA_CLASS;
     954            0 :         attrs[1].pValue = &klass;
     955            0 :         attrs[1].ulValueLen = sizeof (klass);
     956              : 
     957            0 :         object = gkm_manager_find_one_by_attributes (self, session, attrs, 2);
     958            0 :         g_free (id);
     959              : 
     960            0 :         return object;
     961              : }
     962              : 
     963              : CK_RV
     964          366 : gkm_manager_find_handles (GkmManager *self, GkmSession *session,
     965              :                           gboolean also_private, CK_ATTRIBUTE_PTR attrs,
     966              :                           CK_ULONG n_attrs, GArray *found)
     967              : {
     968          366 :         Finder finder = { 0, };
     969              : 
     970          366 :         g_return_val_if_fail (GKM_IS_MANAGER (self), CKR_GENERAL_ERROR);
     971          366 :         g_return_val_if_fail (attrs || !n_attrs, CKR_GENERAL_ERROR);
     972              : 
     973          366 :         finder.accumulator = also_private ? accumulate_handles : accumulate_public_handles;
     974          366 :         finder.results = found;
     975          366 :         finder.manager = self;
     976          366 :         finder.attrs = attrs;
     977          366 :         finder.n_attrs = n_attrs;
     978          366 :         finder.session = session;
     979              : 
     980          366 :         find_for_attributes (&finder);
     981              : 
     982          366 :         return CKR_OK;
     983              : }
     984              : 
     985              : /* Odd place for this function */
     986              : 
     987              : GkmManager*
     988          150 : gkm_manager_for_template (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GkmSession *session)
     989              : {
     990              :         gboolean is_token;
     991          150 :         if (!gkm_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token) || !is_token)
     992          112 :                 return gkm_session_get_manager (session);
     993              :         else
     994           38 :                 return gkm_module_get_manager (gkm_session_get_module (session));
     995              : }
        

Generated by: LCOV version 2.0-1