LCOV - code coverage report
Current view: top level - pkcs11/secret-store - gkm-secret-item.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.6 % 246 186
Test Date: 2024-05-07 18:02:03 Functions: 88.0 % 25 22

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2009 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-secret-data.h"
      24              : #include "gkm-secret-fields.h"
      25              : #include "gkm-secret-item.h"
      26              : 
      27              : #include "gkm/gkm-attributes.h"
      28              : #include "gkm/gkm-module.h"
      29              : #include "gkm/gkm-secret.h"
      30              : #include "gkm/gkm-session.h"
      31              : #include "gkm/gkm-transaction.h"
      32              : 
      33              : #include "pkcs11/pkcs11i.h"
      34              : 
      35              : #include <glib/gi18n.h>
      36              : 
      37              : enum {
      38              :         PROP_0,
      39              :         PROP_COLLECTION,
      40              :         PROP_FIELDS,
      41              :         PROP_SCHEMA
      42              : };
      43              : 
      44              : struct _GkmSecretItem {
      45              :         GkmSecretObject parent;
      46              :         GHashTable *fields;
      47              :         gchar *schema;
      48              :         GkmSecretCollection *collection;
      49              : };
      50              : 
      51        32990 : G_DEFINE_TYPE (GkmSecretItem, gkm_secret_item, GKM_TYPE_SECRET_OBJECT);
      52              : 
      53              : /* -----------------------------------------------------------------------------
      54              :  * INTERNAL
      55              :  */
      56              : 
      57              : static gboolean
      58            0 : complete_set_schema (GkmTransaction *transaction, GObject *obj, gpointer user_data)
      59              : {
      60            0 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
      61            0 :         gchar *old_schema = user_data;
      62              : 
      63            0 :         if (gkm_transaction_get_failed (transaction)) {
      64            0 :                 g_free (self->schema);
      65            0 :                 self->schema = old_schema;
      66              :         } else {
      67            0 :                 gkm_object_notify_attribute (GKM_OBJECT (obj), CKA_G_SCHEMA);
      68            0 :                 g_object_notify (G_OBJECT (obj), "schema");
      69            0 :                 g_free (old_schema);
      70              :         }
      71              : 
      72            0 :         return TRUE;
      73              : }
      74              : 
      75              : static void
      76            0 : begin_set_schema (GkmSecretItem *self, GkmTransaction *transaction, gchar *schema)
      77              : {
      78            0 :         g_assert (GKM_IS_SECRET_OBJECT (self));
      79            0 :         g_assert (!gkm_transaction_get_failed (transaction));
      80              : 
      81            0 :         if (self->schema != schema) {
      82            0 :                 gkm_secret_object_begin_modified (GKM_SECRET_OBJECT (self), transaction);
      83            0 :                 gkm_transaction_add (transaction, self, complete_set_schema, self->schema);
      84            0 :                 self->schema = schema;
      85              :         }
      86            0 : }
      87              : 
      88              : static gboolean
      89            5 : complete_set_secret (GkmTransaction *transaction, GObject *obj, gpointer user_data)
      90              : {
      91            5 :         if (!gkm_transaction_get_failed (transaction)) {
      92            5 :                 gkm_object_notify_attribute (GKM_OBJECT (obj), CKA_VALUE);
      93              :         }
      94              : 
      95            5 :         return TRUE;
      96              : }
      97              : 
      98              : static gboolean
      99            4 : complete_set_fields (GkmTransaction *transaction, GObject *obj, gpointer user_data)
     100              : {
     101            4 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     102            4 :         GHashTable *old_fields = user_data;
     103              : 
     104            4 :         if (gkm_transaction_get_failed (transaction)) {
     105            1 :                 if (self->fields)
     106            1 :                         g_hash_table_unref (self->fields);
     107            1 :                 self->fields = old_fields;
     108              :         } else {
     109            3 :                 gkm_object_notify_attribute (GKM_OBJECT (obj), CKA_G_FIELDS);
     110            3 :                 g_object_notify (G_OBJECT (obj), "fields");
     111            3 :                 if (old_fields)
     112            0 :                         g_hash_table_unref (old_fields);
     113              :         }
     114              : 
     115            4 :         return TRUE;
     116              : }
     117              : 
     118              : static void
     119            4 : begin_set_fields (GkmSecretItem *self, GkmTransaction *transaction, GHashTable *fields)
     120              : {
     121            4 :         g_assert (GKM_IS_SECRET_OBJECT (self));
     122            4 :         g_assert (!gkm_transaction_get_failed (transaction));
     123              : 
     124            4 :         gkm_secret_object_begin_modified (GKM_SECRET_OBJECT (self), transaction);
     125            4 :         gkm_transaction_add (transaction, self, complete_set_fields, self->fields);
     126            4 :         self->fields = fields;
     127            4 : }
     128              : 
     129              : static GkmObject*
     130            8 : factory_create_item (GkmSession *session, GkmTransaction *transaction,
     131              :                      CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     132              : {
     133            8 :         GkmSecretCollection *collection = NULL;
     134              :         GkmSecretItem *item;
     135              :         GkmManager *m_manager;
     136              :         GkmManager *s_manager;
     137              :         CK_ATTRIBUTE *attr;
     138              :         gboolean is_token;
     139              :         gchar *identifier;
     140              : 
     141            8 :         g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
     142            8 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     143              : 
     144              :         /* See if a collection attribute was specified */
     145            8 :         attr = gkm_attributes_find (attrs, n_attrs, CKA_G_COLLECTION);
     146            8 :         if (attr == NULL) {
     147            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
     148            0 :                 return NULL;
     149              :         }
     150              : 
     151            8 :         m_manager = gkm_module_get_manager (gkm_session_get_module (session));
     152            8 :         s_manager = gkm_session_get_manager (session);
     153              : 
     154            8 :         gkm_attribute_consume (attr);
     155            8 :         if (!gkm_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token))
     156            4 :                 collection = gkm_secret_collection_find (session, attr, m_manager, s_manager, NULL);
     157            4 :         else if (is_token)
     158            4 :                 collection = gkm_secret_collection_find (session, attr, m_manager, NULL);
     159              :         else
     160            0 :                 collection = gkm_secret_collection_find (session, attr, s_manager, NULL);
     161              : 
     162            8 :         if (!collection) {
     163            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     164            0 :                 return NULL;
     165              :         }
     166              : 
     167              :         /* If an ID was specified, then try and see if that ID already exists */
     168            8 :         if (gkm_attributes_find_string (attrs, n_attrs, CKA_ID, &identifier)) {
     169            2 :                 item = gkm_secret_collection_get_item (collection, identifier);
     170            2 :                 if (item == NULL) {
     171            0 :                         gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     172            0 :                         return NULL;
     173              :                 } else {
     174            2 :                         gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (item),
     175              :                                                               FALSE, attrs, n_attrs);
     176            2 :                         return GKM_OBJECT (g_object_ref (item));
     177              :                 }
     178              :         }
     179              : 
     180              :         /* Create a new collection which will own the item */
     181            6 :         item = gkm_secret_collection_create_item (collection, transaction);
     182            6 :         gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (item),
     183              :                                               TRUE, attrs, n_attrs);
     184            6 :         return GKM_OBJECT (g_object_ref (item));
     185              : }
     186              : 
     187              : /* -----------------------------------------------------------------------------
     188              :  * OBJECT
     189              :  */
     190              : 
     191              : static gboolean
     192           53 : gkm_secret_item_real_is_locked (GkmSecretObject *obj, GkmSession *session)
     193              : {
     194           53 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     195           53 :         if (!self->collection)
     196            1 :                 return TRUE;
     197           52 :         return gkm_secret_object_is_locked (GKM_SECRET_OBJECT (self->collection), session);
     198              : }
     199              : 
     200              : static CK_RV
     201         8882 : gkm_secret_item_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_PTR attr)
     202              : {
     203         8882 :         GkmSecretItem *self = GKM_SECRET_ITEM (base);
     204              :         GkmSecretData *sdata;
     205              :         const gchar *identifier;
     206              :         const guchar *secret;
     207         8882 :         gsize n_secret = 0;
     208              :         CK_RV rv;
     209              : 
     210         8882 :         g_return_val_if_fail (self->collection, CKR_GENERAL_ERROR);
     211              : 
     212         8882 :         switch (attr->type) {
     213         4256 :         case CKA_CLASS:
     214         4256 :                 return gkm_attribute_set_ulong (attr, CKO_SECRET_KEY);
     215              : 
     216           12 :         case CKA_VALUE:
     217           12 :                 sdata = gkm_secret_collection_unlocked_use (self->collection, session);
     218           12 :                 if (sdata == NULL)
     219            2 :                         return CKR_USER_NOT_LOGGED_IN;
     220           10 :                 identifier = gkm_secret_object_get_identifier (GKM_SECRET_OBJECT (self));
     221           10 :                 secret = gkm_secret_data_get_raw (sdata, identifier, &n_secret);
     222           10 :                 rv = gkm_attribute_set_data (attr, secret, n_secret);
     223           10 :                 gkm_object_mark_used (base);
     224           10 :                 g_object_unref (sdata);
     225           10 :                 return rv;
     226              : 
     227          142 :         case CKA_G_COLLECTION:
     228          142 :                 g_return_val_if_fail (self->collection, CKR_GENERAL_ERROR);
     229          142 :                 identifier = gkm_secret_object_get_identifier (GKM_SECRET_OBJECT (self->collection));
     230          142 :                 return gkm_attribute_set_string (attr, identifier);
     231              : 
     232           11 :         case CKA_G_FIELDS:
     233           11 :                 if (!self->fields)
     234            4 :                         return gkm_attribute_set_data (attr, NULL, 0);
     235            7 :                 return gkm_secret_fields_serialize (attr, self->fields, self->schema);
     236              : 
     237            2 :         case CKA_G_SCHEMA:
     238            2 :                 return gkm_attribute_set_string (attr, self->schema);
     239              :         }
     240              : 
     241         4459 :         return GKM_OBJECT_CLASS (gkm_secret_item_parent_class)->get_attribute (base, session, attr);
     242              : }
     243              : 
     244              : static void
     245           16 : gkm_secret_item_real_set_attribute (GkmObject *base, GkmSession *session,
     246              :                                     GkmTransaction *transaction, CK_ATTRIBUTE_PTR attr)
     247              : {
     248           16 :         GkmSecretItem *self = GKM_SECRET_ITEM (base);
     249              :         const gchar *identifier;
     250              :         GkmSecretData *sdata;
     251              :         GHashTable *fields;
     252              :         gchar *schema_name;
     253              :         GkmSecret *secret;
     254              :         gchar *schema;
     255              :         CK_RV rv;
     256              : 
     257           16 :         if (!self->collection) {
     258            0 :                 gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
     259           11 :                 g_return_if_reached ();
     260              :         }
     261              : 
     262              :         /* Check that the object is not locked */
     263           16 :         if (!gkm_secret_collection_unlocked_have (self->collection, session)) {
     264            2 :                 gkm_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
     265            2 :                 return;
     266              :         }
     267              : 
     268           14 :         switch (attr->type) {
     269            5 :         case CKA_VALUE:
     270            5 :                 sdata = gkm_secret_collection_unlocked_use (self->collection, session);
     271            5 :                 g_return_if_fail (sdata);
     272            5 :                 identifier = gkm_secret_object_get_identifier (GKM_SECRET_OBJECT (self));
     273            5 :                 secret = gkm_secret_new (attr->pValue, attr->ulValueLen);
     274            5 :                 gkm_secret_data_set_transacted (sdata, transaction, identifier, secret);
     275            5 :                 g_object_unref (secret);
     276            5 :                 g_object_unref (sdata);
     277            5 :                 gkm_secret_object_begin_modified (GKM_SECRET_OBJECT (self), transaction);
     278            5 :                 if (!gkm_transaction_get_failed (transaction))
     279            5 :                         gkm_transaction_add (transaction, self, complete_set_secret, NULL);
     280            5 :                 return;
     281              : 
     282            4 :         case CKA_G_FIELDS:
     283            4 :                 rv = gkm_secret_fields_parse (attr, &fields, &schema_name);
     284            4 :                 if (rv != CKR_OK) {
     285            0 :                         gkm_transaction_fail (transaction, rv);
     286              :                 } else {
     287            4 :                         begin_set_fields (self, transaction, fields);
     288            4 :                         if (schema_name)
     289            0 :                                 begin_set_schema (self, transaction, schema_name);
     290              :                 }
     291            4 :                 return;
     292              : 
     293            0 :         case CKA_G_SCHEMA:
     294            0 :                 rv = gkm_attribute_get_string (attr, &schema);
     295            0 :                 if (rv != CKR_OK)
     296            0 :                         gkm_transaction_fail (transaction, rv);
     297              :                 else
     298            0 :                         begin_set_schema (self, transaction, schema);
     299            0 :                 return;
     300              :         }
     301              : 
     302            5 :         GKM_OBJECT_CLASS (gkm_secret_item_parent_class)->set_attribute (base, session, transaction, attr);
     303              : }
     304              : 
     305              : static void
     306         2180 : gkm_secret_item_init (GkmSecretItem *self)
     307              : {
     308              : 
     309         2180 : }
     310              : 
     311              : static GObject*
     312         2180 : gkm_secret_item_constructor (GType type, guint n_props, GObjectConstructParam *props)
     313              : {
     314         2180 :         GkmSecretItem *self = GKM_SECRET_ITEM (G_OBJECT_CLASS (gkm_secret_item_parent_class)->constructor(type, n_props, props));
     315         2180 :         g_return_val_if_fail (self, NULL);
     316              : 
     317         2180 :         g_return_val_if_fail (self->collection, NULL);
     318              : 
     319         2180 :         return G_OBJECT (self);
     320              : }
     321              : 
     322              : static void
     323         2180 : gkm_secret_item_set_property (GObject *obj, guint prop_id, const GValue *value,
     324              :                               GParamSpec *pspec)
     325              : {
     326         2180 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     327              : 
     328         2180 :         switch (prop_id) {
     329         2180 :         case PROP_COLLECTION:
     330         2180 :                 g_return_if_fail (!self->collection);
     331         2180 :                 self->collection = g_value_get_object (value);
     332         2180 :                 g_return_if_fail (self->collection);
     333         2180 :                 g_object_add_weak_pointer (G_OBJECT (self->collection),
     334         2180 :                                            (gpointer*)&(self->collection));
     335         2180 :                 break;
     336            0 :         case PROP_FIELDS:
     337            0 :                 gkm_secret_item_set_fields (self, g_value_get_boxed (value));
     338            0 :                 break;
     339            0 :         case PROP_SCHEMA:
     340            0 :                 gkm_secret_item_set_schema (self, g_value_get_string (value));
     341            0 :                 break;
     342            0 :         default:
     343            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     344            0 :                 break;
     345              :         }
     346              : }
     347              : 
     348              : static void
     349            0 : gkm_secret_item_get_property (GObject *obj, guint prop_id, GValue *value,
     350              :                               GParamSpec *pspec)
     351              : {
     352            0 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     353              : 
     354            0 :         switch (prop_id) {
     355            0 :         case PROP_COLLECTION:
     356            0 :                 g_value_set_object (value, gkm_secret_item_get_collection (self));
     357            0 :                 break;
     358            0 :         case PROP_FIELDS:
     359            0 :                 g_value_set_boxed (value, gkm_secret_item_get_fields (self));
     360            0 :                 break;
     361            0 :         case PROP_SCHEMA:
     362            0 :                 g_value_set_string (value, gkm_secret_item_get_schema (self));
     363            0 :                 break;
     364            0 :         default:
     365            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     366            0 :                 break;
     367              :         }
     368            0 : }
     369              : 
     370              : static void
     371         2180 : gkm_secret_item_dispose (GObject *obj)
     372              : {
     373         2180 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     374              : 
     375         2180 :         if (self->collection)
     376          172 :                 g_object_remove_weak_pointer (G_OBJECT (self->collection),
     377          172 :                                               (gpointer*)&(self->collection));
     378         2180 :         self->collection = NULL;
     379              : 
     380         2180 :         G_OBJECT_CLASS (gkm_secret_item_parent_class)->dispose (obj);
     381         2180 : }
     382              : 
     383              : static void
     384         2180 : gkm_secret_item_finalize (GObject *obj)
     385              : {
     386         2180 :         GkmSecretItem *self = GKM_SECRET_ITEM (obj);
     387              : 
     388         2180 :         g_assert (!self->collection);
     389              : 
     390         2180 :         if (self->fields)
     391         2162 :                 g_hash_table_unref (self->fields);
     392         2180 :         self->fields = NULL;
     393              : 
     394         2180 :         g_free (self->schema);
     395         2180 :         self->schema = NULL;
     396              : 
     397         2180 :         G_OBJECT_CLASS (gkm_secret_item_parent_class)->finalize (obj);
     398         2180 : }
     399              : 
     400              : static void
     401           29 : gkm_secret_item_class_init (GkmSecretItemClass *klass)
     402              : {
     403           29 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     404           29 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     405           29 :         GkmSecretObjectClass *secret_class = GKM_SECRET_OBJECT_CLASS (klass);
     406              : 
     407           29 :         gkm_secret_item_parent_class = g_type_class_peek_parent (klass);
     408              : 
     409           29 :         gobject_class->constructor = gkm_secret_item_constructor;
     410           29 :         gobject_class->dispose = gkm_secret_item_dispose;
     411           29 :         gobject_class->finalize = gkm_secret_item_finalize;
     412           29 :         gobject_class->set_property = gkm_secret_item_set_property;
     413           29 :         gobject_class->get_property = gkm_secret_item_get_property;
     414              : 
     415           29 :         gkm_class->get_attribute = gkm_secret_item_real_get_attribute;
     416           29 :         gkm_class->set_attribute = gkm_secret_item_real_set_attribute;
     417              : 
     418           29 :         secret_class->is_locked = gkm_secret_item_real_is_locked;
     419              : 
     420           29 :         g_object_class_install_property (gobject_class, PROP_COLLECTION,
     421              :                    g_param_spec_object ("collection", "Collection", "Item's Collection",
     422              :                                         GKM_TYPE_SECRET_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     423              : 
     424           29 :         g_object_class_install_property (gobject_class, PROP_FIELDS,
     425              :                    g_param_spec_boxed ("fields", "Fields", "Item's fields",
     426              :                                        GKM_BOXED_SECRET_FIELDS, G_PARAM_READWRITE));
     427              : 
     428           29 :         g_object_class_install_property (gobject_class, PROP_SCHEMA,
     429              :                    g_param_spec_string ("schema", "Schema", "Item's type or schema",
     430              :                                         NULL, G_PARAM_READWRITE));
     431           29 : }
     432              : 
     433              : /* -----------------------------------------------------------------------------
     434              :  * PUBLIC
     435              :  */
     436              : 
     437              : GkmFactory*
     438          111 : gkm_secret_item_get_factory (void)
     439              : {
     440              :         static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
     441              : 
     442              :         static CK_ATTRIBUTE attributes[] = {
     443              :                 { CKA_CLASS, &klass, sizeof (klass) },
     444              :         };
     445              : 
     446              :         static GkmFactory factory = {
     447              :                 attributes,
     448              :                 G_N_ELEMENTS (attributes),
     449              :                 factory_create_item
     450              :         };
     451              : 
     452          111 :         return &factory;
     453              : }
     454              : 
     455              : GkmSecretCollection*
     456         2077 : gkm_secret_item_get_collection (GkmSecretItem *self)
     457              : {
     458         2077 :         g_return_val_if_fail (GKM_IS_SECRET_ITEM (self), NULL);
     459         2077 :         return self->collection;
     460              : }
     461              : 
     462              : GHashTable*
     463         2110 : gkm_secret_item_get_fields (GkmSecretItem *self)
     464              : {
     465         2110 :         g_return_val_if_fail (GKM_IS_SECRET_ITEM (self), NULL);
     466         2110 :         if (self->fields == NULL)
     467           16 :                 self->fields = gkm_secret_fields_new ();
     468         2110 :         return self->fields;
     469              : }
     470              : 
     471              : void
     472         2184 : gkm_secret_item_set_fields (GkmSecretItem *self, GHashTable *fields)
     473              : {
     474         2184 :         g_return_if_fail (GKM_IS_SECRET_ITEM (self));
     475              : 
     476         2184 :         if (fields)
     477         2184 :                 g_hash_table_ref (fields);
     478         2184 :         if (self->fields)
     479           41 :                 g_hash_table_unref (self->fields);
     480         2184 :         self->fields = fields;
     481              : 
     482         2184 :         g_object_notify (G_OBJECT (self), "fields");
     483         2184 :         gkm_object_notify_attribute (GKM_OBJECT (self), CKA_G_FIELDS);
     484              : }
     485              : 
     486              : const gchar*
     487           38 : gkm_secret_item_get_schema (GkmSecretItem *self)
     488              : {
     489           38 :         g_return_val_if_fail (GKM_IS_SECRET_ITEM (self), NULL);
     490           38 :         return self->schema;
     491              : }
     492              : 
     493              : void
     494          167 : gkm_secret_item_set_schema (GkmSecretItem *self, const gchar *schema)
     495              : {
     496          167 :         g_return_if_fail (GKM_IS_SECRET_ITEM (self));
     497              : 
     498          167 :         if (schema != self->schema) {
     499          167 :                 g_free (self->schema);
     500          167 :                 self->schema = g_strdup (schema);
     501          167 :                 g_object_notify (G_OBJECT (self), "schema");
     502          167 :                 gkm_object_notify_attribute (GKM_OBJECT (self), CKA_G_SCHEMA);
     503              :         }
     504              : }
        

Generated by: LCOV version 2.0-1