LCOV - code coverage report
Current view: top level - pkcs11/xdg-store - gkm-xdg-module.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.0 % 244 222
Test Date: 2024-04-08 13:24:42 Functions: 100.0 % 28 28

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2010 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-xdg-assertion.h"
      24              : #include "gkm-xdg-module.h"
      25              : #include "gkm-xdg-store.h"
      26              : #include "gkm-xdg-trust.h"
      27              : 
      28              : #include "egg/egg-asn1x.h"
      29              : #include "egg/egg-asn1-defs.h"
      30              : #include "egg/egg-dn.h"
      31              : #include "egg/egg-error.h"
      32              : #include "egg/egg-file-tracker.h"
      33              : #include "egg/egg-hex.h"
      34              : 
      35              : #include "gkm/gkm-assertion.h"
      36              : #include "gkm/gkm-certificate.h"
      37              : #define DEBUG_FLAG GKM_DEBUG_STORAGE
      38              : #include "gkm/gkm-debug.h"
      39              : #include "gkm/gkm-serializable.h"
      40              : #include "gkm/gkm-transaction.h"
      41              : #include "gkm/gkm-util.h"
      42              : 
      43              : #include "pkcs11x.h"
      44              : 
      45              : #include <string.h>
      46              : 
      47              : struct _GkmXdgModule {
      48              :         GkmModule parent;
      49              :         gchar *directory;
      50              :         GHashTable *objects_by_path;
      51              :         EggFileTracker *tracker;
      52              :         CK_TOKEN_INFO token_info;
      53              : };
      54              : 
      55              : static const CK_SLOT_INFO user_module_slot_info = {
      56              :         "User Key Storage",
      57              :         "Gnome Keyring",
      58              :         CKF_TOKEN_PRESENT,
      59              :         { 0, 0 },
      60              :         { 0, 0 }
      61              : };
      62              : 
      63              : static const CK_TOKEN_INFO user_module_token_info = {
      64              :         "User Key Storage",
      65              :         "Gnome Keyring",
      66              :         "1.0",
      67              :         "1:XDG:DEFAULT", /* Unique serial number for manufacturer */
      68              :         CKF_TOKEN_INITIALIZED,
      69              :         CK_EFFECTIVELY_INFINITE,
      70              :         CK_EFFECTIVELY_INFINITE,
      71              :         CK_EFFECTIVELY_INFINITE,
      72              :         CK_EFFECTIVELY_INFINITE,
      73              :         1024,
      74              :         1,
      75              :         CK_UNAVAILABLE_INFORMATION,
      76              :         CK_UNAVAILABLE_INFORMATION,
      77              :         CK_UNAVAILABLE_INFORMATION,
      78              :         CK_UNAVAILABLE_INFORMATION,
      79              :         { 0, 0 },
      80              :         { 0, 0 },
      81              :         ""
      82              : };
      83              : 
      84              : #define UNUSED_VALUE (GUINT_TO_POINTER (1))
      85              : 
      86              : #define UNWANTED_FILENAME_CHARS  ":/\\<>|\t\n\r\v "
      87              : 
      88          513 : G_DEFINE_TYPE (GkmXdgModule, gkm_xdg_module, GKM_TYPE_MODULE);
      89              : 
      90              : GkmModule*  _gkm_xdg_store_get_module_for_testing (void);
      91              : 
      92              : /* Forward declarations */
      93              : static void  remove_object_from_module (GkmXdgModule *self, GkmObject *object,
      94              :                                         const gchar *filename, GkmTransaction *transaction);
      95              : static void  add_object_to_module (GkmXdgModule *self, GkmObject *object,
      96              :                                    const gchar *filename, GkmTransaction *transaction);
      97              : 
      98              : /* -----------------------------------------------------------------------------
      99              :  * ACTUAL PKCS#11 Module Implementation
     100              :  */
     101              : 
     102              : /* Include all the module entry points */
     103              : #include "gkm/gkm-module-ep.h"
     104           59 : GKM_DEFINE_MODULE (gkm_xdg_module, GKM_TYPE_XDG_MODULE);
     105              : 
     106              : /* -----------------------------------------------------------------------------
     107              :  * INTERNAL
     108              :  */
     109              : 
     110              : static GType
     111           52 : type_from_path (const gchar *path)
     112              : {
     113              :         const gchar *ext;
     114              : 
     115           52 :         ext = strrchr (path, '.');
     116              : 
     117              :         /* The file tracker doesn't match files without exts */
     118           52 :         g_return_val_if_fail (ext, 0);
     119              : 
     120           52 :         if (g_str_equal (ext, ".trust"))
     121           24 :                 return GKM_XDG_TYPE_TRUST;
     122           28 :         else if (strcmp (ext, ".cer") == 0)
     123           12 :                 return GKM_TYPE_CERTIFICATE;
     124              : 
     125           16 :         return 0;
     126              : }
     127              : 
     128              : static const gchar*
     129           36 : lookup_filename_for_object (GkmObject *object)
     130              : {
     131           36 :         return g_object_get_data (G_OBJECT (object), "xdg-module-filename");
     132              : }
     133              : 
     134              : static gboolean
     135            2 : complete_add_object (GkmTransaction *transaction, GObject *module, gpointer user_data)
     136              : {
     137            2 :         GkmXdgModule *self = GKM_XDG_MODULE (module);
     138            2 :         GkmObject *object = GKM_OBJECT (user_data);
     139              :         const gchar *filename;
     140              : 
     141              :         /* If the transaction failed, revert it */
     142            2 :         if (gkm_transaction_get_failed (transaction)) {
     143            0 :                 filename = g_object_get_data (G_OBJECT (object), "xdg-module-filename");
     144            0 :                 g_return_val_if_fail (filename, FALSE);
     145            0 :                 remove_object_from_module (self, object, filename, NULL);
     146              :         }
     147              : 
     148            2 :         g_object_unref (object);
     149            2 :         return TRUE;
     150              : }
     151              : 
     152              : static void
     153           26 : add_object_to_module (GkmXdgModule *self, GkmObject *object,
     154              :                       const gchar *filename, GkmTransaction *transaction)
     155              : {
     156           26 :         g_assert (!g_hash_table_lookup (self->objects_by_path, filename));
     157           52 :         g_hash_table_insert (self->objects_by_path, g_strdup (filename), g_object_ref (object));
     158              : 
     159           26 :         g_assert (!lookup_filename_for_object (object));
     160           26 :         g_object_set_data_full (G_OBJECT (object), "xdg-module-filename",
     161           26 :                                 g_strdup (filename), g_free);
     162              : 
     163           26 :         gkm_object_expose (object, TRUE);
     164              : 
     165           26 :         if (transaction != NULL)
     166            2 :                 gkm_transaction_add (transaction, self, complete_add_object, g_object_ref (object));
     167           26 : }
     168              : 
     169              : static gboolean
     170            2 : complete_remove_object (GkmTransaction *transaction, GObject *module, gpointer user_data)
     171              : {
     172            2 :         GkmXdgModule *self = GKM_XDG_MODULE (module);
     173            2 :         GkmObject *object = GKM_OBJECT (user_data);
     174              :         const gchar *filename;
     175              : 
     176              :         /* If the transaction failed, revert it */
     177            2 :         if (gkm_transaction_get_failed (transaction)) {
     178            0 :                 filename = g_object_get_data (G_OBJECT (object), "xdg-module-filename");
     179            0 :                 g_return_val_if_fail (filename, FALSE);
     180            0 :                 add_object_to_module (self, object, filename, NULL);
     181              :         }
     182              : 
     183            2 :         g_object_unref (object);
     184            2 :         return TRUE;
     185              : }
     186              : 
     187              : static void
     188            4 : remove_object_from_module (GkmXdgModule *self, GkmObject *object,
     189              :                            const gchar *filename, GkmTransaction *transaction)
     190              : {
     191            4 :         gkm_object_expose (object, FALSE);
     192              : 
     193            4 :         if (transaction != NULL)
     194            2 :                 gkm_transaction_add (transaction, self, complete_remove_object, g_object_ref (object));
     195              : 
     196            4 :         g_assert (g_hash_table_lookup (self->objects_by_path, filename) == object);
     197            4 :         g_hash_table_remove (self->objects_by_path, filename);
     198            4 : }
     199              : 
     200              : static void
     201           54 : file_load (EggFileTracker *tracker,
     202              :            const gchar *path,
     203              :            GkmXdgModule *self)
     204              : {
     205              :         GkmObject *object;
     206              :         GkmManager *manager;
     207           54 :         gboolean added = FALSE;
     208           54 :         GError *error = NULL;
     209              :         GBytes *bytes;
     210              :         GType type;
     211              :         guchar *data;
     212              :         gsize n_data;
     213              : 
     214           70 :         g_return_if_fail (path);
     215           54 :         g_return_if_fail (GKM_IS_XDG_MODULE (self));
     216              : 
     217           54 :         manager = gkm_module_get_manager (GKM_MODULE (self));
     218              : 
     219              :         /* Already have this object? */
     220           54 :         object = g_hash_table_lookup (self->objects_by_path, path);
     221           54 :         if (object == NULL) {
     222              : 
     223              :                 /* Figure out what type of object we're dealing with */
     224           52 :                 type = type_from_path (path);
     225           52 :                 if (type == 0) {
     226           16 :                         gkm_debug ("don't know how to load file in key store: %s", path);
     227           16 :                         return;
     228              :                 }
     229              : 
     230              :                 /* Create a new object for this identifier */
     231           36 :                 object = g_object_new (type,
     232           36 :                                        "module", GKM_MODULE (self),
     233              :                                        "manager", manager, NULL);
     234           36 :                 g_return_if_fail (GKM_IS_SERIALIZABLE (object));
     235           36 :                 g_return_if_fail (GKM_SERIALIZABLE_GET_INTERFACE (object)->extension);
     236              : 
     237           36 :                 added = TRUE;
     238              : 
     239              :         } else {
     240            2 :                 g_object_ref (object);
     241              :         }
     242              : 
     243              :         /* Read the file in */
     244           38 :         if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) {
     245            0 :                 g_warning ("couldn't read file in key store: %s: %s", path,
     246              :                            egg_error_message (error));
     247            0 :                 g_object_unref (object);
     248            0 :                 g_clear_error (&error);
     249            0 :                 return;
     250              :         }
     251              : 
     252           38 :         bytes = g_bytes_new_take (data, n_data);
     253              : 
     254              :         /* And load the data into it */
     255           38 :         if (gkm_serializable_load (GKM_SERIALIZABLE (object), NULL, bytes)) {
     256           25 :                 if (added)
     257           24 :                         add_object_to_module (self, object, path, NULL);
     258           25 :                 gkm_object_expose (object, TRUE);
     259              : 
     260              :         } else {
     261           13 :                 g_message ("failed to load file in user store: %s", path);
     262           13 :                 if (!added) {
     263            1 :                         gkm_object_expose (object, FALSE);
     264            1 :                         remove_object_from_module (self, object, path, NULL);
     265              :                 }
     266              :         }
     267              : 
     268           38 :         g_bytes_unref (bytes);
     269           38 :         g_object_unref (object);
     270              : }
     271              : 
     272              : static void
     273            2 : file_remove (EggFileTracker *tracker,
     274              :              const gchar *path,
     275              :              GkmXdgModule *self)
     276              : {
     277              :         GkmObject *object;
     278              : 
     279            2 :         g_return_if_fail (path);
     280            2 :         g_return_if_fail (GKM_IS_XDG_MODULE (self));
     281              : 
     282            2 :         object = g_hash_table_lookup (self->objects_by_path, path);
     283            2 :         if (object != NULL)
     284            1 :                 remove_object_from_module (self, object, path, NULL);
     285              : }
     286              : 
     287              : static gchar*
     288            1 : name_for_subject (gconstpointer data,
     289              :                   gsize n_data)
     290              : {
     291              :         GBytes *subject;
     292              :         GNode *asn;
     293              :         gchar *name;
     294              : 
     295            1 :         g_assert (data != NULL);
     296              : 
     297            1 :         subject = g_bytes_new (data, n_data);
     298            1 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Name", subject);
     299            1 :         g_return_val_if_fail (asn != NULL, NULL);
     300            1 :         g_bytes_unref (subject);
     301              : 
     302            1 :         name = egg_dn_read_part (egg_asn1x_node (asn, "rdnSequence", NULL), "CN");
     303            1 :         egg_asn1x_destroy (asn);
     304              : 
     305            1 :         return name;
     306              : }
     307              : 
     308              : static gchar*
     309            2 : guess_basename_for_object (GkmObject *object)
     310              : {
     311              :         GkmSerializableIface *serial;
     312              :         const gchar *ext;
     313              :         gchar *filename;
     314            2 :         gchar *name = NULL;
     315              :         guchar *data;
     316              :         gsize n_data;
     317              : 
     318            2 :         g_assert (GKM_IS_OBJECT (object));
     319            2 :         g_assert (GKM_IS_SERIALIZABLE (object));
     320              : 
     321              :         /* Figure out the extension and prefix */
     322            2 :         serial = GKM_SERIALIZABLE_GET_INTERFACE (object);
     323            2 :         ext = serial->extension;
     324            2 :         g_return_val_if_fail (ext, NULL);
     325              : 
     326              :         /* First we try to use the CN of a subject */
     327            2 :         data = gkm_object_get_attribute_data (object, NULL, CKA_SUBJECT, &n_data);
     328            2 :         if (data && n_data)
     329            1 :                 name = name_for_subject (data, n_data);
     330            2 :         g_free (data);
     331              : 
     332              :         /* Next we try and see if it has a peer (is a trust assertion) */
     333            2 :         if (name == NULL) {
     334            1 :                 data = gkm_object_get_attribute_data (object, NULL, CKA_X_PEER, &n_data);
     335            1 :                 if (data && n_data)
     336            0 :                         name = g_strndup ((gchar *)data, n_data);
     337            1 :                 g_free (data);
     338              :         }
     339              : 
     340              :         /* Next we try hex encoding the ID */
     341            2 :         if (name == NULL) {
     342            1 :                 data = gkm_object_get_attribute_data (object, NULL, CKA_ID, &n_data);
     343            1 :                 if (data && n_data)
     344            0 :                         name = egg_hex_encode (data, n_data);
     345            1 :                 g_free (data);
     346              :         }
     347              : 
     348            2 :         if (name == NULL)
     349            1 :                 name = g_strdup_printf ("object-%08x", ABS (g_random_int ()));
     350              : 
     351              :         /* Build up the identifier */
     352            2 :         filename = g_strconcat (name, ext, NULL);
     353            2 :         g_strdelimit (filename, UNWANTED_FILENAME_CHARS, '_');
     354              : 
     355            2 :         g_free (name);
     356            2 :         return filename;
     357              : }
     358              : 
     359              : /* -----------------------------------------------------------------------------
     360              :  * OBJECT
     361              :  */
     362              : 
     363              : static const CK_SLOT_INFO*
     364           67 : gkm_xdg_module_real_get_slot_info (GkmModule *base)
     365              : {
     366           67 :         return &user_module_slot_info;
     367              : }
     368              : 
     369              : static const CK_TOKEN_INFO*
     370            9 : gkm_xdg_module_real_get_token_info (GkmModule *base)
     371              : {
     372            9 :         GkmXdgModule *self = GKM_XDG_MODULE (base);
     373              : 
     374              :         /* TODO: Update the info with current info */
     375            9 :         return &self->token_info;
     376              : }
     377              : 
     378              : static void
     379           59 : gkm_xdg_module_real_parse_argument (GkmModule *base, const gchar *name, const gchar *value)
     380              : {
     381           59 :         GkmXdgModule *self = GKM_XDG_MODULE (base);
     382           59 :         if (g_str_equal (name, "directory")) {
     383           59 :                 g_free (self->directory);
     384           59 :                 self->directory = g_strdup (value);
     385              :         }
     386           59 : }
     387              : 
     388              : static CK_RV
     389           22 : gkm_xdg_module_real_refresh_token (GkmModule *base)
     390              : {
     391           22 :         GkmXdgModule *self = GKM_XDG_MODULE (base);
     392           22 :         egg_file_tracker_refresh (self->tracker, FALSE);
     393           22 :         return CKR_OK;
     394              : }
     395              : 
     396              : static void
     397            4 : gkm_xdg_module_real_add_token_object (GkmModule *module, GkmTransaction *transaction,
     398              :                                       GkmObject *object)
     399              : {
     400            4 :         gchar *filename = NULL;
     401              :         GkmXdgModule *self;
     402              :         GkmTrust *trust;
     403              :         gchar *basename;
     404              :         gchar *actual;
     405              : 
     406            4 :         self = GKM_XDG_MODULE (module);
     407              : 
     408              :         /* Always serialize the trust object for each assertion */
     409            4 :         if (GKM_XDG_IS_ASSERTION (object)) {
     410            2 :                 trust = gkm_assertion_get_trust_object (GKM_ASSERTION (object));
     411            2 :                 object = GKM_OBJECT (trust);
     412              : 
     413              :                 /* If this trust object has already been added, then ignore */
     414            2 :                 if (lookup_filename_for_object (object))
     415            2 :                         return;
     416              :         }
     417              : 
     418              :         /* Double check that the object is in fact serializable */
     419            2 :         if (!GKM_IS_SERIALIZABLE (object)) {
     420            0 :                 g_message ("can't store object of type '%s' on token", G_OBJECT_TYPE_NAME (object));
     421            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     422            0 :                 return;
     423              :         }
     424              : 
     425            2 :         g_return_if_fail (lookup_filename_for_object (object) == NULL);
     426              : 
     427            2 :         basename = guess_basename_for_object (object);
     428            2 :         g_return_if_fail (basename);
     429              : 
     430            2 :         actual = gkm_transaction_unique_file (transaction, self->directory, basename);
     431            2 :         if (!gkm_transaction_get_failed (transaction)) {
     432            2 :                 filename = g_build_filename (self->directory, actual, NULL);
     433            2 :                 add_object_to_module (self, object, filename, transaction);
     434            2 :                 g_free (filename);
     435              :         }
     436              : 
     437            2 :         g_free (actual);
     438            2 :         g_free (basename);
     439              : }
     440              : 
     441              : static void
     442            4 : gkm_xdg_module_real_store_token_object (GkmModule *module, GkmTransaction *transaction,
     443              :                                         GkmObject *object)
     444              : {
     445            4 :         GkmXdgModule *self = GKM_XDG_MODULE (module);
     446              :         const gchar *filename;
     447              :         GBytes *bytes;
     448              :         GkmTrust *trust;
     449              : 
     450              :         /* Always serialize the trust object for each assertion */
     451            4 :         if (GKM_XDG_IS_ASSERTION (object)) {
     452            2 :                 trust = gkm_assertion_get_trust_object (GKM_ASSERTION (object));
     453            2 :                 object = GKM_OBJECT (trust);
     454              :         }
     455              : 
     456              :         /* Double check that the object is in fact serializable */
     457            4 :         if (!GKM_IS_SERIALIZABLE (object)) {
     458            0 :                 g_message ("can't store object of type '%s' on token", G_OBJECT_TYPE_NAME (object));
     459            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     460            0 :                 return;
     461              :         }
     462              : 
     463              :         /* Serialize the object in question */
     464            4 :         bytes = gkm_serializable_save (GKM_SERIALIZABLE (object), NULL);
     465              : 
     466            4 :         if (bytes == NULL) {
     467            0 :                 gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
     468            0 :                 g_return_if_reached ();
     469              :         }
     470              : 
     471            4 :         filename = lookup_filename_for_object (object);
     472            4 :         g_return_if_fail (filename != NULL);
     473            4 :         g_return_if_fail (g_hash_table_lookup (self->objects_by_path, filename) == object);
     474              : 
     475            4 :         gkm_transaction_write_file (transaction, filename,
     476              :                                     g_bytes_get_data (bytes, NULL),
     477              :                                     g_bytes_get_size (bytes));
     478            4 :         g_bytes_unref (bytes);
     479              : }
     480              : 
     481              : static void
     482            2 : gkm_xdg_module_real_remove_token_object (GkmModule *module, GkmTransaction *transaction,
     483              :                                          GkmObject *object)
     484              : {
     485            2 :         GkmXdgModule *self = GKM_XDG_MODULE (module);
     486              :         const gchar *filename;
     487              :         GkmXdgTrust *trust;
     488              : 
     489              :         /* Always serialize the trust object for each assertion */
     490            2 :         if (GKM_XDG_IS_ASSERTION (object)) {
     491            1 :                 trust = GKM_XDG_TRUST (gkm_assertion_get_trust_object (GKM_ASSERTION (object)));
     492            1 :                 gkm_xdg_trust_remove_assertion (trust, GKM_ASSERTION (object), transaction);
     493              : 
     494              :                 /* Remove the trust object if it has no assertions */
     495            1 :                 if (!gkm_xdg_trust_have_assertion (trust))
     496            1 :                         object = GKM_OBJECT (trust);
     497              :                 else
     498            0 :                         object = NULL;
     499              :         }
     500              : 
     501            2 :         if (object && !gkm_transaction_get_failed (transaction)) {
     502            2 :                 filename = lookup_filename_for_object (object);
     503            2 :                 g_return_if_fail (filename != NULL);
     504            2 :                 g_return_if_fail (g_hash_table_lookup (self->objects_by_path, filename) == object);
     505              : 
     506            2 :                 gkm_transaction_remove_file (transaction, filename);
     507            2 :                 remove_object_from_module (self, object, filename, transaction);
     508              :         }
     509              : }
     510              : 
     511              : static GObject*
     512           59 : gkm_xdg_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
     513              : {
     514           59 :         GkmXdgModule *self = GKM_XDG_MODULE (G_OBJECT_CLASS (gkm_xdg_module_parent_class)->constructor(type, n_props, props));
     515           59 :         g_return_val_if_fail (self, NULL);
     516              : 
     517           59 :         if (!self->directory)
     518            0 :                 self->directory = g_build_filename (g_get_user_data_dir (), "keystore", NULL);
     519              : 
     520           59 :         self->tracker = egg_file_tracker_new (self->directory, "*.*", NULL);
     521           59 :         g_signal_connect (self->tracker, "file-added", G_CALLBACK (file_load), self);
     522           59 :         g_signal_connect (self->tracker, "file-changed", G_CALLBACK (file_load), self);
     523           59 :         g_signal_connect (self->tracker, "file-removed", G_CALLBACK (file_remove), self);
     524              : 
     525           59 :         return G_OBJECT (self);
     526              : }
     527              : 
     528              : static void
     529           59 : gkm_xdg_module_init (GkmXdgModule *self)
     530              : {
     531           59 :         self->objects_by_path = g_hash_table_new_full (g_str_hash, g_str_equal,
     532              :                                                        g_free, gkm_util_dispose_unref);
     533              : 
     534              :         /* Our default token info, updated as module runs */
     535           59 :         memcpy (&self->token_info, &user_module_token_info, sizeof (CK_TOKEN_INFO));
     536              : 
     537              :         /* For creating stored objects */
     538           59 :         gkm_module_register_factory (GKM_MODULE (self), GKM_XDG_FACTORY_ASSERTION);
     539           59 :         gkm_module_register_factory (GKM_MODULE (self), GKM_FACTORY_CERTIFICATE);
     540           59 : }
     541              : 
     542              : static void
     543          118 : gkm_xdg_module_dispose (GObject *obj)
     544              : {
     545          118 :         GkmXdgModule *self = GKM_XDG_MODULE (obj);
     546              : 
     547          118 :         if (self->tracker)
     548           59 :                 g_object_unref (self->tracker);
     549          118 :         self->tracker = NULL;
     550              : 
     551          118 :         g_hash_table_remove_all (self->objects_by_path);
     552              : 
     553          118 :         G_OBJECT_CLASS (gkm_xdg_module_parent_class)->dispose (obj);
     554          118 : }
     555              : 
     556              : static void
     557           59 : gkm_xdg_module_finalize (GObject *obj)
     558              : {
     559           59 :         GkmXdgModule *self = GKM_XDG_MODULE (obj);
     560              : 
     561           59 :         g_assert (self->tracker == NULL);
     562              : 
     563           59 :         g_hash_table_destroy (self->objects_by_path);
     564           59 :         self->objects_by_path = NULL;
     565              : 
     566           59 :         g_free (self->directory);
     567           59 :         self->directory = NULL;
     568              : 
     569           59 :         G_OBJECT_CLASS (gkm_xdg_module_parent_class)->finalize (obj);
     570           59 : }
     571              : 
     572              : static void
     573           29 : gkm_xdg_module_class_init (GkmXdgModuleClass *klass)
     574              : {
     575           29 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     576           29 :         GkmModuleClass *module_class = GKM_MODULE_CLASS (klass);
     577              : 
     578           29 :         gobject_class->constructor = gkm_xdg_module_constructor;
     579           29 :         gobject_class->dispose = gkm_xdg_module_dispose;
     580           29 :         gobject_class->finalize = gkm_xdg_module_finalize;
     581              : 
     582           29 :         module_class->get_slot_info = gkm_xdg_module_real_get_slot_info;
     583           29 :         module_class->get_token_info = gkm_xdg_module_real_get_token_info;
     584           29 :         module_class->parse_argument = gkm_xdg_module_real_parse_argument;
     585           29 :         module_class->refresh_token = gkm_xdg_module_real_refresh_token;
     586           29 :         module_class->add_token_object = gkm_xdg_module_real_add_token_object;
     587           29 :         module_class->store_token_object = gkm_xdg_module_real_store_token_object;
     588           29 :         module_class->remove_token_object = gkm_xdg_module_real_remove_token_object;
     589           29 : }
     590              : 
     591              : /* ----------------------------------------------------------------------------
     592              :  * PUBLIC
     593              :  */
     594              : 
     595              : CK_FUNCTION_LIST_PTR
     596           91 : gkm_xdg_store_get_functions (void)
     597              : {
     598           91 :         gkm_crypto_initialize ();
     599           91 :         return gkm_xdg_module_function_list;
     600              : }
     601              : 
     602              : GkmModule*
     603           64 : _gkm_xdg_store_get_module_for_testing (void)
     604              : {
     605           64 :         return pkcs11_module;
     606              : }
        

Generated by: LCOV version 2.0-1