LCOV - code coverage report
Current view: top level - pkcs11/secret-store - gkm-secret-object.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.9 % 199 163
Test Date: 2024-04-08 13:24:42 Functions: 96.6 % 29 28

            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-object.h"
      24              : 
      25              : #include "gkm/gkm-attributes.h"
      26              : #include "gkm/gkm-session.h"
      27              : #include "gkm/gkm-transaction.h"
      28              : 
      29              : #include "pkcs11/pkcs11i.h"
      30              : 
      31              : #include <glib/gi18n.h>
      32              : 
      33              : enum {
      34              :         PROP_0,
      35              :         PROP_LABEL,
      36              :         PROP_IDENTIFIER,
      37              :         PROP_CREATED,
      38              :         PROP_MODIFIED
      39              : };
      40              : 
      41              : struct _GkmSecretObjectPrivate {
      42              :         gchar *identifier;
      43              :         gchar *label;
      44              :         glong created;
      45              :         glong modified;
      46              : };
      47              : 
      48       121615 : G_DEFINE_TYPE_WITH_PRIVATE (GkmSecretObject, gkm_secret_object, GKM_TYPE_OBJECT);
      49              : 
      50              : /* -----------------------------------------------------------------------------
      51              :  * INTERNAL
      52              :  */
      53              : 
      54              : static gboolean
      55            8 : complete_set_label (GkmTransaction *transaction, GObject *obj, gpointer user_data)
      56              : {
      57            8 :         GkmSecretObject *self = GKM_SECRET_OBJECT (obj);
      58            8 :         gchar *old_label = user_data;
      59              : 
      60            8 :         if (gkm_transaction_get_failed (transaction)) {
      61            1 :                 g_free (self->pv->label);
      62            1 :                 self->pv->label = old_label;
      63              :         } else {
      64            7 :                 gkm_object_notify_attribute (GKM_OBJECT (obj), CKA_LABEL);
      65            7 :                 g_object_notify (G_OBJECT (obj), "label");
      66            7 :                 g_free (old_label);
      67              :         }
      68              : 
      69            8 :         return TRUE;
      70              : }
      71              : 
      72              : static void
      73            8 : begin_set_label (GkmSecretObject *self, GkmTransaction *transaction, gchar *label)
      74              : {
      75            8 :         g_assert (GKM_IS_SECRET_OBJECT (self));
      76            8 :         g_assert (!gkm_transaction_get_failed (transaction));
      77              : 
      78            8 :         gkm_secret_object_begin_modified (GKM_SECRET_OBJECT (self), transaction);
      79            8 :         gkm_transaction_add (transaction, self, complete_set_label, self->pv->label);
      80            8 :         self->pv->label = label;
      81            8 : }
      82              : 
      83              : static gchar*
      84         2445 : register_identifier (GkmSecretObjectClass *klass, const gchar *identifier)
      85              : {
      86              :         gchar *result;
      87              :         gint i;
      88              : 
      89         2445 :         g_assert (klass);
      90         2445 :         g_assert (identifier);
      91              : 
      92         2445 :         if (!klass->identifiers)
      93         2193 :                 return g_strdup (identifier);
      94              : 
      95          254 :         for (i = 0; i < G_MAXINT; ++i) {
      96          254 :                 if (i == 0)
      97          252 :                         result = g_strdup (identifier);
      98              :                 else
      99            2 :                         result = g_strdup_printf ("%s_%d", identifier, i);
     100          254 :                 if (g_hash_table_lookup (klass->identifiers, result)) {
     101            2 :                         g_free (result);
     102              :                 } else {
     103          252 :                         g_hash_table_insert (klass->identifiers, result, result);
     104          252 :                         return result;
     105              :                 }
     106              :         }
     107              : 
     108            0 :         g_assert_not_reached ();
     109              : }
     110              : 
     111              : static void
     112         2445 : unregister_identifier (GkmSecretObjectClass *klass, gchar *identifier)
     113              : {
     114         2445 :         g_assert (klass);
     115         2445 :         g_assert (identifier);
     116              : 
     117         2445 :         if (klass->identifiers)
     118          252 :                 g_hash_table_remove (klass->identifiers, identifier);
     119         2445 :         g_free (identifier);
     120         2445 : }
     121              : 
     122              : /* -----------------------------------------------------------------------------
     123              :  * OBJECT
     124              :  */
     125              : 
     126              : static CK_RV
     127         5147 : gkm_secret_object_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_PTR attr)
     128              : {
     129         5147 :         GkmSecretObject *self = GKM_SECRET_OBJECT (base);
     130              : 
     131         5147 :         switch (attr->type) {
     132            0 :         case CKA_MODIFIABLE:
     133            0 :                 return gkm_attribute_set_bool (attr, TRUE);
     134              : 
     135         4967 :         case CKA_ID:
     136         4967 :                 return gkm_attribute_set_string (attr, gkm_secret_object_get_identifier (self));
     137              : 
     138           19 :         case CKA_LABEL:
     139           19 :                 return gkm_attribute_set_string (attr, gkm_secret_object_get_label (self));
     140              : 
     141          133 :         case CKA_G_LOCKED:
     142          133 :                 return gkm_attribute_set_bool (attr, gkm_secret_object_is_locked (self, session));
     143              : 
     144            3 :         case CKA_G_CREATED:
     145            3 :                 return gkm_attribute_set_time (attr, gkm_secret_object_get_created (self));
     146              : 
     147            3 :         case CKA_G_MODIFIED:
     148            3 :                 return gkm_attribute_set_time (attr, gkm_secret_object_get_modified (self));
     149              :         }
     150              : 
     151           22 :         return GKM_OBJECT_CLASS (gkm_secret_object_parent_class)->get_attribute (base, session, attr);
     152              : }
     153              : 
     154              : static void
     155            8 : gkm_secret_object_set_attribute (GkmObject *base, GkmSession *session,
     156              :                                  GkmTransaction *transaction, CK_ATTRIBUTE_PTR attr)
     157              : {
     158            8 :         GkmSecretObject *self = GKM_SECRET_OBJECT (base);
     159              :         gchar *label;
     160              :         CK_RV rv;
     161              : 
     162            8 :         switch (attr->type) {
     163              : 
     164            8 :         case CKA_LABEL:
     165              :                 /* Check that the object is not locked */
     166            8 :                 if (gkm_secret_object_is_locked (self, session))
     167            0 :                         rv = CKR_USER_NOT_LOGGED_IN;
     168              :                 else
     169            8 :                         rv = gkm_attribute_get_string (attr, &label);
     170            8 :                 if (rv != CKR_OK)
     171            0 :                         gkm_transaction_fail (transaction, rv);
     172              :                 else
     173            8 :                         begin_set_label (self, transaction, label);
     174            8 :                 return;
     175              :         }
     176              : 
     177            0 :         GKM_OBJECT_CLASS (gkm_secret_object_parent_class)->set_attribute (base, session, transaction, attr);
     178              : }
     179              : 
     180              : static gboolean
     181            4 : gkm_secret_object_real_is_locked (GkmSecretObject *self, GkmSession *session)
     182              : {
     183              :         /* Derived classes override us */
     184            4 :         return FALSE;
     185              : }
     186              : 
     187              : static void
     188         2445 : gkm_secret_object_init (GkmSecretObject *self)
     189              : {
     190         2445 :         self->pv = gkm_secret_object_get_instance_private (self);
     191         2445 : }
     192              : 
     193              : static GObject*
     194         2445 : gkm_secret_object_constructor (GType type, guint n_props, GObjectConstructParam *props)
     195              : {
     196         2445 :         GkmSecretObject *self = GKM_SECRET_OBJECT (G_OBJECT_CLASS (gkm_secret_object_parent_class)->constructor(type, n_props, props));
     197         2445 :         g_return_val_if_fail (self, NULL);
     198              : 
     199              :         /* Must be created with an identifier */
     200         2445 :         g_return_val_if_fail (self->pv->identifier, NULL);
     201              : 
     202         2445 :         return G_OBJECT (self);
     203              : }
     204              : 
     205              : static void
     206         4890 : gkm_secret_object_set_property (GObject *obj, guint prop_id, const GValue *value,
     207              :                                 GParamSpec *pspec)
     208              : {
     209         4890 :         GkmSecretObjectClass *klass = GKM_SECRET_OBJECT_GET_CLASS (obj);
     210         4890 :         GkmSecretObject *self = GKM_SECRET_OBJECT (obj);
     211              :         const gchar *identifier;
     212              : 
     213         4890 :         switch (prop_id) {
     214         2445 :         case PROP_LABEL:
     215         2445 :                 gkm_secret_object_set_label (self, g_value_get_string (value));
     216         2445 :                 break;
     217         2445 :         case PROP_IDENTIFIER:
     218         2445 :                 g_return_if_fail (!self->pv->identifier);
     219         2445 :                 identifier = g_value_get_string (value);
     220         2445 :                 g_return_if_fail (identifier);
     221         2445 :                 self->pv->identifier = register_identifier (klass, identifier);
     222         2445 :                 break;
     223            0 :         case PROP_CREATED:
     224            0 :                 gkm_secret_object_set_created (self, g_value_get_long (value));
     225            0 :                 break;
     226            0 :         case PROP_MODIFIED:
     227            0 :                 gkm_secret_object_set_modified (self, g_value_get_long (value));
     228            0 :                 break;
     229            0 :         default:
     230            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     231            0 :                 break;
     232              :         }
     233              : }
     234              : 
     235              : static void
     236            0 : gkm_secret_object_get_property (GObject *obj, guint prop_id, GValue *value,
     237              :                                     GParamSpec *pspec)
     238              : {
     239            0 :         GkmSecretObject *self = GKM_SECRET_OBJECT (obj);
     240              : 
     241            0 :         switch (prop_id) {
     242            0 :         case PROP_LABEL:
     243            0 :                 g_value_set_string (value, gkm_secret_object_get_label (self));
     244            0 :                 break;
     245            0 :         case PROP_IDENTIFIER:
     246            0 :                 g_value_set_string (value, gkm_secret_object_get_identifier (self));
     247            0 :                 break;
     248            0 :         case PROP_CREATED:
     249            0 :                 g_value_set_long (value, gkm_secret_object_get_created (self));
     250            0 :                 break;
     251            0 :         case PROP_MODIFIED:
     252            0 :                 g_value_set_long (value, gkm_secret_object_get_modified (self));
     253            0 :                 break;
     254            0 :         default:
     255            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     256            0 :                 break;
     257              :         }
     258            0 : }
     259              : 
     260              : static void
     261         2445 : gkm_secret_object_finalize (GObject *obj)
     262              : {
     263         2445 :         GkmSecretObjectClass *klass = GKM_SECRET_OBJECT_GET_CLASS (obj);
     264         2445 :         GkmSecretObject *self = GKM_SECRET_OBJECT (obj);
     265              : 
     266         2445 :         if (self->pv->identifier)
     267         2445 :                 unregister_identifier (klass, self->pv->identifier);
     268         2445 :         self->pv->identifier = NULL;
     269              : 
     270         2445 :         g_free (self->pv->label);
     271         2445 :         self->pv->label = NULL;
     272              : 
     273         2445 :         self->pv->created = 0;
     274         2445 :         self->pv->modified = 0;
     275              : 
     276         2445 :         G_OBJECT_CLASS (gkm_secret_object_parent_class)->finalize (obj);
     277         2445 : }
     278              : 
     279              : static void
     280           34 : gkm_secret_object_class_init (GkmSecretObjectClass *klass)
     281              : {
     282           34 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     283           34 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     284              : 
     285           34 :         gobject_class->constructor = gkm_secret_object_constructor;
     286           34 :         gobject_class->finalize = gkm_secret_object_finalize;
     287           34 :         gobject_class->set_property = gkm_secret_object_set_property;
     288           34 :         gobject_class->get_property = gkm_secret_object_get_property;
     289              : 
     290           34 :         gkm_class->get_attribute = gkm_secret_object_get_attribute;
     291           34 :         gkm_class->set_attribute = gkm_secret_object_set_attribute;
     292              : 
     293           34 :         klass->is_locked = gkm_secret_object_real_is_locked;
     294              : 
     295           34 :         g_object_class_install_property (gobject_class, PROP_IDENTIFIER,
     296              :                    g_param_spec_string ("identifier", "Identifier", "Object Identifier",
     297              :                                         NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     298              : 
     299           34 :         g_object_class_install_property (gobject_class, PROP_LABEL,
     300              :                    g_param_spec_string ("label", "Label", "Object Label",
     301              :                                         "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
     302              : 
     303           34 :         g_object_class_install_property (gobject_class, PROP_CREATED,
     304              :                    g_param_spec_long ("created", "Created", "Object Create Time",
     305              :                                       0, G_MAXLONG, 0, G_PARAM_READABLE));
     306              : 
     307           34 :         g_object_class_install_property (gobject_class, PROP_MODIFIED,
     308              :                    g_param_spec_long ("modified", "Modified", "Object Modify Time",
     309              :                                       0, G_MAXLONG, 0, G_PARAM_READABLE));
     310           34 : }
     311              : 
     312              : /* -----------------------------------------------------------------------------
     313              :  * PUBLIC
     314              :  */
     315              : 
     316              : void
     317           34 : gkm_secret_object_class_unique_identifiers (GkmSecretObjectClass *klass)
     318              : {
     319           34 :         if (!klass->identifiers)
     320           34 :                 klass->identifiers = g_hash_table_new (g_str_hash, g_str_equal);
     321           34 : }
     322              : 
     323              : const gchar*
     324         9732 : gkm_secret_object_get_identifier (GkmSecretObject *self)
     325              : {
     326         9732 :         g_return_val_if_fail (GKM_IS_SECRET_OBJECT (self), NULL);
     327         9732 :         return self->pv->identifier;
     328              : }
     329              : 
     330              : const gchar*
     331           81 : gkm_secret_object_get_label (GkmSecretObject *self)
     332              : {
     333           81 :         g_return_val_if_fail (GKM_IS_SECRET_OBJECT (self), NULL);
     334           81 :         return self->pv->label;
     335              : }
     336              : 
     337              : void
     338         2733 : gkm_secret_object_set_label (GkmSecretObject *self, const gchar *label)
     339              : {
     340         2733 :         g_return_if_fail (GKM_IS_SECRET_OBJECT (self));
     341              : 
     342         2733 :         if (self->pv->label == label)
     343            0 :                 return;
     344              : 
     345         2733 :         g_free (self->pv->label);
     346         2733 :         self->pv->label = g_strdup (label);
     347         2733 :         g_object_notify (G_OBJECT (self), "label");
     348              : }
     349              : 
     350              : glong
     351           67 : gkm_secret_object_get_created (GkmSecretObject *self)
     352              : {
     353           67 :         g_return_val_if_fail (GKM_IS_SECRET_OBJECT (self), 0);
     354           67 :         return self->pv->created;
     355              : }
     356              : 
     357              : void
     358          295 : gkm_secret_object_set_created (GkmSecretObject *self, glong when)
     359              : {
     360          295 :         g_return_if_fail (GKM_IS_SECRET_OBJECT (self));
     361              : 
     362          295 :         if (when < 0) {
     363            0 :                 when = g_get_real_time () / G_USEC_PER_SEC;
     364              :         }
     365              : 
     366          295 :         self->pv->created = when;
     367          295 :         g_object_notify (G_OBJECT (self), "created");
     368              : }
     369              : 
     370              : void
     371           20 : gkm_secret_object_mark_created (GkmSecretObject *self)
     372              : {
     373           20 :         g_return_if_fail (GKM_IS_SECRET_OBJECT (self));
     374              : 
     375           20 :         gkm_secret_object_set_created (self, g_get_real_time () / G_USEC_PER_SEC);
     376              : }
     377              : 
     378              : glong
     379        40785 : gkm_secret_object_get_modified (GkmSecretObject *self)
     380              : {
     381        40785 :         g_return_val_if_fail (GKM_IS_SECRET_OBJECT (self), 0);
     382        40785 :         return self->pv->modified;
     383              : }
     384              : 
     385              : void
     386         2275 : gkm_secret_object_set_modified (GkmSecretObject *self, glong when)
     387              : {
     388         2275 :         g_return_if_fail (GKM_IS_SECRET_OBJECT (self));
     389         2275 :         self->pv->modified = when;
     390         2275 :         g_object_notify (G_OBJECT (self), "modified");
     391              : }
     392              : 
     393              : static gboolean
     394           18 : complete_set_modified (GkmTransaction *transaction,
     395              :                        GObject *obj,
     396              :                        gpointer user_data)
     397              : {
     398           18 :         GkmSecretObject *self = GKM_SECRET_OBJECT (obj);
     399           18 :         glong *old_modified = user_data;
     400              : 
     401           18 :         if (gkm_transaction_get_failed (transaction)) {
     402            2 :                 self->pv->modified = *old_modified;
     403              : 
     404              :         } else {
     405           16 :                 gkm_object_notify_attribute (GKM_OBJECT (obj), CKA_G_MODIFIED);
     406           16 :                 g_object_notify (G_OBJECT (obj), "modified");
     407              :         }
     408              : 
     409           18 :         g_free (old_modified);
     410           18 :         return TRUE;
     411              : }
     412              : 
     413              : void
     414           18 : gkm_secret_object_begin_modified (GkmSecretObject *self,
     415              :                                   GkmTransaction *transaction)
     416              : {
     417           18 :         g_return_if_fail (!gkm_transaction_get_failed (transaction));
     418           18 :         gkm_transaction_add (transaction, self, complete_set_modified,
     419           18 :                              g_memdup (&self->pv->modified, sizeof (gulong)));
     420              : 
     421           18 :         self->pv->modified = g_get_real_time () / G_USEC_PER_SEC;
     422              : }
     423              : 
     424              : gboolean
     425          201 : gkm_secret_object_is_locked (GkmSecretObject *self, GkmSession *session)
     426              : {
     427          201 :         g_return_val_if_fail (GKM_IS_SECRET_OBJECT (self), TRUE);
     428          201 :         g_return_val_if_fail (GKM_SECRET_OBJECT_GET_CLASS (self)->is_locked, TRUE);
     429          201 :         return GKM_SECRET_OBJECT_GET_CLASS (self)->is_locked (self, session);
     430              : }
        

Generated by: LCOV version 2.0-1