LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-object.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.7 % 461 363
Test Date: 2024-04-08 13:24:42 Functions: 91.7 % 48 44

            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 "pkcs11/pkcs11.h"
      24              : #include "pkcs11/pkcs11i.h"
      25              : 
      26              : #include "gkm-attributes.h"
      27              : #include "gkm-credential.h"
      28              : #define DEBUG_FLAG GKM_DEBUG_OBJECT
      29              : #include "gkm-debug.h"
      30              : #include "gkm-manager.h"
      31              : #include "gkm-object.h"
      32              : #include "gkm-transaction.h"
      33              : #include "gkm-session.h"
      34              : #include "gkm-store.h"
      35              : #include "gkm-timer.h"
      36              : #include "gkm-util.h"
      37              : 
      38              : enum {
      39              :         PROP_0,
      40              :         PROP_HANDLE,
      41              :         PROP_MODULE,
      42              :         PROP_MANAGER,
      43              :         PROP_STORE,
      44              :         PROP_UNIQUE,
      45              :         PROP_TRANSIENT
      46              : };
      47              : 
      48              : enum {
      49              :         EXPOSE_OBJECT,
      50              :         NOTIFY_ATTRIBUTE,
      51              :         LAST_SIGNAL
      52              : };
      53              : 
      54              : static guint signals[LAST_SIGNAL] = { 0 };
      55              : 
      56              : typedef struct _GkmObjectTransient {
      57              :         GkmTimer *timer;
      58              :         gulong timed_after;
      59              :         gulong timed_idle;
      60              :         glong stamp_used;
      61              :         glong stamp_created;
      62              :         gulong uses_remaining;
      63              : } GkmObjectTransient;
      64              : 
      65              : struct _GkmObjectPrivate {
      66              :         CK_OBJECT_HANDLE handle;
      67              :         GkmModule *module;
      68              :         GkmManager *manager;
      69              :         GkmStore *store;
      70              :         gchar *unique;
      71              :         gboolean exposed;
      72              :         GkmObjectTransient *transient;
      73              : };
      74              : 
      75       155097 : G_DEFINE_TYPE_WITH_PRIVATE (GkmObject, gkm_object, G_TYPE_OBJECT);
      76              : 
      77              : /* Private friend functions from the manager */
      78              : void  _gkm_manager_register_object   (GkmManager *self, GkmObject *object);
      79              : void  _gkm_manager_unregister_object (GkmManager *self, GkmObject *object);
      80              : 
      81              : /* -----------------------------------------------------------------------------
      82              :  * INTERNAL
      83              :  */
      84              : 
      85              : static void
      86            1 : self_destruct (GkmObject *self)
      87              : {
      88              :         GkmTransaction *transaction;
      89              :         CK_RV rv;
      90              : 
      91            1 :         transaction = gkm_transaction_new ();
      92              : 
      93            1 :         gkm_object_destroy (self, transaction);
      94              : 
      95            1 :         gkm_transaction_complete (transaction);
      96            1 :         rv = gkm_transaction_get_result (transaction);
      97            1 :         g_object_unref (transaction);
      98            1 :         if (rv != CKR_OK)
      99            0 :                 g_warning ("Unexpected failure to auto destruct object (code: %lu)", (gulong)rv);
     100            1 : }
     101              : 
     102              : static void
     103            2 : timer_callback (GkmTimer *timer, gpointer user_data)
     104              : {
     105            2 :         GkmObject *self = user_data;
     106              :         glong after, idle, offset;
     107              :         GkmObjectTransient *transient;
     108              :         gint64 now;
     109              : 
     110            2 :         g_return_if_fail (GKM_IS_OBJECT (self));
     111              : 
     112            2 :         g_object_ref (self);
     113              : 
     114            2 :         g_return_if_fail (self->pv->transient);
     115            2 :         transient = self->pv->transient;
     116            2 :         g_return_if_fail (timer == transient->timer);
     117            2 :         transient->timer = NULL;
     118              : 
     119            2 :         now = g_get_real_time () / G_USEC_PER_SEC;
     120            2 :         idle = after = G_MAXLONG;
     121              : 
     122              :         /* Are we supposed to be destroyed after a certain time? */
     123            2 :         if (transient->timed_after) {
     124            2 :                 g_return_if_fail (transient->stamp_created);
     125            2 :                 after = (transient->stamp_created + transient->timed_after) - now;
     126              :         }
     127              : 
     128              :         /* Are we supposed to be destroyed after an idle time? */
     129            2 :         if (transient->timed_idle) {
     130            0 :                 g_return_if_fail (transient->stamp_used);
     131            0 :                 idle = (transient->stamp_used + transient->timed_idle) - now;
     132              :         }
     133              : 
     134              :         /* Okay, time to destroy? */
     135            2 :         offset = MIN (after, idle);
     136            2 :         if (offset <= 0)
     137            1 :                 self_destruct (self);
     138              : 
     139              :         /* Setup the next timer */
     140              :         else
     141            1 :                 transient->timer = gkm_timer_start (self->pv->module, offset, timer_callback, self);
     142              : 
     143            2 :         g_object_unref (self);
     144              : }
     145              : 
     146              : static gboolean
     147            1 : start_callback (GkmTransaction *transaction, GObject *obj, gpointer user_data)
     148              : {
     149            1 :         GkmObject *self = GKM_OBJECT (obj);
     150              :         GkmObjectTransient *transient;
     151              :         gint64 now;
     152              : 
     153            1 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     154            1 :         g_return_val_if_fail (self->pv->transient, FALSE);
     155            1 :         transient = self->pv->transient;
     156            1 :         g_return_val_if_fail (!transient->timer, FALSE);
     157              : 
     158            1 :         now = g_get_real_time () / G_USEC_PER_SEC;
     159            1 :         transient->stamp_created = now;
     160            1 :         transient->stamp_used = now;
     161              : 
     162              :         /* Start the timer going */
     163            1 :         timer_callback (NULL, self);
     164            1 :         return TRUE;
     165              : }
     166              : 
     167              : static void
     168            0 : module_went_away (gpointer data, GObject *old_module)
     169              : {
     170            0 :         GkmObject *self = GKM_OBJECT (data);
     171            0 :         g_return_if_fail (self->pv->module);
     172            0 :         g_warning ("module destroyed before %s that module contained",
     173              :                    G_OBJECT_TYPE_NAME (self));
     174            0 :         self->pv->module = NULL;
     175              : }
     176              : 
     177              : static gboolean
     178           37 : complete_destroy (GkmTransaction *transaction, GObject *unused, gpointer user_data)
     179              : {
     180           37 :         gkm_util_dispose_unref (user_data);
     181           37 :         return TRUE;
     182              : }
     183              : 
     184              : static gboolean
     185          161 : complete_expose (GkmTransaction *transaction, GObject *obj, gpointer user_data)
     186              : {
     187          161 :         GkmObject *self = GKM_OBJECT (obj);
     188          161 :         gboolean expose = GPOINTER_TO_UINT (user_data);
     189              : 
     190          161 :         if (gkm_transaction_get_failed (transaction))
     191            1 :                 gkm_object_expose (self, !expose);
     192              : 
     193          161 :         return TRUE;
     194              : }
     195              : 
     196              : static gboolean
     197            0 : find_credential (GkmCredential *cred, GkmObject *object, gpointer user_data)
     198              : {
     199            0 :         CK_OBJECT_HANDLE *result = user_data;
     200            0 :         g_return_val_if_fail (!*result, FALSE);
     201            0 :         *result = gkm_object_get_handle (GKM_OBJECT (cred));
     202            0 :         return TRUE;
     203              : }
     204              : 
     205              : static void
     206          133 : mark_object_transient (GkmObject *self)
     207              : {
     208          133 :         if (!self->pv->transient)
     209          133 :                 self->pv->transient = g_slice_new0 (GkmObjectTransient);
     210          133 : }
     211              : 
     212              : /* -----------------------------------------------------------------------------
     213              :  * OBJECT
     214              :  */
     215              : 
     216              : static CK_RV
     217          394 : gkm_object_real_get_attribute (GkmObject *self, GkmSession *session, CK_ATTRIBUTE* attr)
     218              : {
     219          394 :         CK_OBJECT_HANDLE handle = 0;
     220              :         CK_RV rv;
     221              : 
     222          394 :         switch (attr->type)
     223              :         {
     224            0 :         case CKA_CLASS:
     225            0 :                 g_warning ("Derived class should have overridden CKA_CLASS");
     226            0 :                 return CKR_GENERAL_ERROR;
     227            0 :         case CKA_MODIFIABLE:
     228            0 :                 return gkm_attribute_set_bool (attr, self->pv->store ? TRUE : FALSE);
     229            0 :         case CKA_PRIVATE:
     230            0 :                 return gkm_attribute_set_bool (attr, FALSE);
     231           39 :         case CKA_TOKEN:
     232           39 :                 return gkm_attribute_set_bool (attr, gkm_object_is_token (self));
     233            0 :         case CKA_G_CREDENTIAL:
     234            0 :                 gkm_credential_for_each (session, GKM_OBJECT (self), find_credential, &handle);
     235            0 :                 return gkm_attribute_set_ulong (attr, handle);
     236            8 :         case CKA_GNOME_UNIQUE:
     237            8 :                 if (self->pv->unique)
     238            0 :                         return gkm_attribute_set_string (attr, self->pv->unique);
     239            8 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no CKA_GNOME_UNIQUE on object");
     240            8 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     241            4 :         case CKA_GNOME_TRANSIENT:
     242            4 :                 return gkm_attribute_set_bool (attr, self->pv->transient ? TRUE : FALSE);
     243            1 :         case CKA_G_DESTRUCT_AFTER:
     244            2 :                 return gkm_attribute_set_ulong (attr, self->pv->transient ?
     245            1 :                                                       self->pv->transient->timed_after : 0);
     246            0 :         case CKA_G_DESTRUCT_IDLE:
     247            0 :                 return gkm_attribute_set_ulong (attr, self->pv->transient ?
     248            0 :                                                       self->pv->transient->timed_idle : 0);
     249            0 :         case CKA_G_DESTRUCT_USES:
     250            0 :                 return gkm_attribute_set_ulong (attr, self->pv->transient ?
     251            0 :                                                       self->pv->transient->uses_remaining : 0);
     252              :         };
     253              : 
     254              :         /* Give store a shot */
     255          342 :         if (self->pv->store) {
     256          133 :                 rv = gkm_store_get_attribute (self->pv->store, self, attr);
     257          133 :                 if (rv != CKR_ATTRIBUTE_TYPE_INVALID)
     258            1 :                         return rv;
     259              :         }
     260              : 
     261              :         /* Now some more defaults */
     262          341 :         switch (attr->type) {
     263            0 :         case CKA_LABEL:
     264            0 :                 return gkm_attribute_set_data (attr, "", 0);
     265              :         }
     266              : 
     267          341 :         gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no %s attribute", gkm_log_attr_type (attr->type));
     268          341 :         return CKR_ATTRIBUTE_TYPE_INVALID;
     269              : }
     270              : 
     271              : static void
     272            3 : gkm_object_real_set_attribute (GkmObject *self, GkmSession *session,
     273              :                                GkmTransaction* transaction, CK_ATTRIBUTE* attr)
     274              : {
     275              :         CK_ATTRIBUTE check;
     276              :         CK_RV rv;
     277              : 
     278            3 :         switch (attr->type) {
     279            0 :         case CKA_TOKEN:
     280              :         case CKA_PRIVATE:
     281              :         case CKA_MODIFIABLE:
     282              :         case CKA_CLASS:
     283            0 :                 gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY);
     284            3 :                 return;
     285            0 :         case CKA_GNOME_UNIQUE:
     286            0 :                 gkm_transaction_fail (transaction, self->pv->unique ?
     287              :                                                        CKR_ATTRIBUTE_READ_ONLY :
     288              :                                                        CKR_ATTRIBUTE_TYPE_INVALID);
     289            0 :                 return;
     290              :         };
     291              : 
     292              :         /* Give store a shot */
     293            3 :         if (self->pv->store) {
     294            3 :                 gkm_store_set_attribute (self->pv->store, transaction, self, attr);
     295            3 :                 return;
     296              :         }
     297              : 
     298              :         /* Now some more defaults */
     299            0 :         switch (attr->type) {
     300            0 :         case CKA_LABEL:
     301            0 :                 gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY);
     302            0 :                 return;
     303              :         }
     304              : 
     305              :         /* Check if this attribute exists */
     306            0 :         check.type = attr->type;
     307            0 :         check.pValue = 0;
     308            0 :         check.ulValueLen = 0;
     309            0 :         rv = gkm_object_get_attribute (self, session, &check);
     310            0 :         if (rv == CKR_ATTRIBUTE_TYPE_INVALID)
     311            0 :                 gkm_transaction_fail (transaction, CKR_ATTRIBUTE_TYPE_INVALID);
     312              :         else
     313            0 :                 gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY);
     314              : }
     315              : 
     316              : static void
     317          175 : gkm_object_real_create_attributes (GkmObject *self, GkmSession *session,
     318              :                                    GkmTransaction *transaction, CK_ATTRIBUTE *attrs, CK_ULONG n_attrs)
     319              : {
     320              :         CK_ATTRIBUTE_PTR transient_attr;
     321          175 :         gboolean transient = FALSE;
     322          175 :         gulong after = 0;
     323          175 :         gulong idle = 0;
     324              :         CK_RV rv;
     325              : 
     326              :         /* Parse the transient attribute */
     327          175 :         transient_attr = gkm_attributes_find (attrs, n_attrs, CKA_GNOME_TRANSIENT);
     328          175 :         if (transient_attr) {
     329           25 :                 rv = gkm_attribute_get_bool (transient_attr, &transient);
     330           25 :                 if (rv != CKR_OK) {
     331            1 :                         gkm_transaction_fail (transaction, rv);
     332            2 :                         return;
     333              :                 }
     334              :         }
     335              : 
     336              :         /* Parse the auto destruct attribute */
     337          174 :         if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_G_DESTRUCT_AFTER, &after))
     338          172 :                 after = 0;
     339          174 :         if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_G_DESTRUCT_IDLE, &idle))
     340          174 :                 idle = 0;
     341              :         /* Default for the transient attribute */
     342          174 :         if (!transient_attr && (idle || after))
     343            1 :                 transient = TRUE;
     344              : 
     345              :         /* Used up these attributes */
     346          174 :         gkm_attributes_consume (attrs, n_attrs, CKA_G_DESTRUCT_AFTER,
     347              :                                 CKA_G_DESTRUCT_IDLE, CKA_GNOME_TRANSIENT, G_MAXULONG);
     348              : 
     349          174 :         if (transient) {
     350           24 :                 mark_object_transient (self);
     351           24 :                 self->pv->transient->timed_after = after;
     352           24 :                 self->pv->transient->timed_idle = idle;
     353              :         }
     354              : 
     355          174 :         if (after || idle) {
     356            2 :                 if (!self->pv->transient) {
     357            1 :                         gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     358            1 :                         return;
     359              :                 }
     360              : 
     361            1 :                 gkm_transaction_add (transaction, self, start_callback, NULL);
     362              :         }
     363              : }
     364              : 
     365              : static CK_RV
     366            0 : gkm_object_real_unlock (GkmObject *self, GkmCredential *cred)
     367              : {
     368              :         /* A derived class should have overridden this */
     369            0 :         return CKR_FUNCTION_FAILED;
     370              : }
     371              : 
     372              : static void
     373         5340 : gkm_object_real_expose_object (GkmObject *self, gboolean expose)
     374              : {
     375         5340 :         g_return_if_fail (expose != self->pv->exposed);
     376         5340 :         g_return_if_fail (self->pv->manager);
     377              : 
     378         5340 :         self->pv->exposed = expose;
     379         5340 :         if (expose)
     380         2670 :                 _gkm_manager_register_object (self->pv->manager, self);
     381              :         else
     382         2670 :                 _gkm_manager_unregister_object (self->pv->manager, self);
     383              : }
     384              : 
     385              : static GObject*
     386         2907 : gkm_object_constructor (GType type, guint n_props, GObjectConstructParam *props)
     387              : {
     388         2907 :         GkmObject *self = GKM_OBJECT (G_OBJECT_CLASS (gkm_object_parent_class)->constructor(type, n_props, props));
     389              : 
     390         2907 :         g_return_val_if_fail (self, NULL);
     391         2907 :         g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL);
     392              : 
     393         2907 :         return G_OBJECT (self);
     394              : }
     395              : 
     396              : static void
     397         2907 : gkm_object_init (GkmObject *self)
     398              : {
     399         2907 :         self->pv = gkm_object_get_instance_private (self);
     400              : 
     401         2907 : }
     402              : 
     403              : static void
     404         3316 : gkm_object_dispose (GObject *obj)
     405              : {
     406         3316 :         GkmObject *self = GKM_OBJECT (obj);
     407              :         GkmObjectTransient *transient;
     408              : 
     409         3316 :         if (self->pv->manager) {
     410         2757 :                 if (self->pv->exposed)
     411         2569 :                         gkm_object_expose (self, FALSE);
     412         2757 :                 g_return_if_fail (!self->pv->exposed);
     413         2757 :                 g_object_remove_weak_pointer (G_OBJECT (self->pv->manager),
     414         2757 :                                               (gpointer*)&(self->pv->manager));
     415         2757 :                 self->pv->manager = NULL;
     416              :         }
     417              : 
     418         3316 :         g_object_set (self, "store", NULL, NULL);
     419         3316 :         g_assert (self->pv->store == NULL);
     420              : 
     421         3316 :         if (self->pv->transient) {
     422          283 :                 transient = self->pv->transient;
     423          283 :                 if (transient->timer)
     424            0 :                         gkm_timer_cancel (transient->timer);
     425          283 :                 transient->timer = NULL;
     426              :         }
     427              : 
     428         3316 :         G_OBJECT_CLASS (gkm_object_parent_class)->dispose (obj);
     429              : }
     430              : 
     431              : static void
     432         2907 : gkm_object_finalize (GObject *obj)
     433              : {
     434         2907 :         GkmObject *self = GKM_OBJECT (obj);
     435              : 
     436         2907 :         g_assert (self->pv->manager == NULL);
     437         2907 :         g_free (self->pv->unique);
     438              : 
     439              :         /* This is done here, as an object must have a module even after dispose */
     440         2907 :         g_object_weak_unref (G_OBJECT (self->pv->module), module_went_away, self);
     441         2907 :         self->pv->module = NULL;
     442              : 
     443         2907 :         if (self->pv->transient) {
     444          133 :                 g_slice_free (GkmObjectTransient, self->pv->transient);
     445          133 :                 self->pv->transient = NULL;
     446              :         }
     447              : 
     448         2907 :         G_OBJECT_CLASS (gkm_object_parent_class)->finalize (obj);
     449         2907 : }
     450              : 
     451              : static void
     452        15295 : gkm_object_set_property (GObject *obj, guint prop_id, const GValue *value,
     453              :                            GParamSpec *pspec)
     454              : {
     455        15295 :         GkmObject *self = GKM_OBJECT (obj);
     456              :         GkmStore *store;
     457              : 
     458        15295 :         switch (prop_id) {
     459            0 :         case PROP_HANDLE:
     460            0 :                 gkm_object_set_handle (self, g_value_get_ulong (value));
     461            0 :                 break;
     462         2907 :         case PROP_MODULE:
     463         2907 :                 g_return_if_fail (!self->pv->module);
     464         2907 :                 self->pv->module = g_value_get_object (value);
     465         2907 :                 g_return_if_fail (GKM_IS_MODULE (self->pv->module));
     466         2907 :                 g_object_weak_ref (G_OBJECT (self->pv->module), module_went_away, self);
     467         2907 :                 break;
     468         2907 :         case PROP_MANAGER:
     469         2907 :                 g_return_if_fail (!self->pv->manager);
     470         2907 :                 self->pv->manager = g_value_get_object (value);
     471         2907 :                 if (self->pv->manager) {
     472         2757 :                         g_object_add_weak_pointer (G_OBJECT (self->pv->manager),
     473         2757 :                                                    (gpointer*)&(self->pv->manager));
     474              :                 }
     475         2907 :                 break;
     476         3667 :         case PROP_STORE:
     477         3667 :                 store = g_value_get_object (value);
     478         3667 :                 if (self->pv->store) {
     479          299 :                         g_return_if_fail (!store);
     480          299 :                         g_object_remove_weak_pointer (G_OBJECT (self->pv->store),
     481          299 :                                                       (gpointer*)&(self->pv->store));
     482              :                 }
     483         3667 :                 self->pv->store = store;
     484         3667 :                 if (self->pv->store)
     485          299 :                         g_object_add_weak_pointer (G_OBJECT (self->pv->store),
     486          299 :                                                    (gpointer*)&(self->pv->store));
     487              : 
     488         3667 :                 g_object_notify (G_OBJECT (self), "store");
     489         3667 :                 break;
     490         2907 :         case PROP_UNIQUE:
     491         2907 :                 g_return_if_fail (!self->pv->unique);
     492         2907 :                 self->pv->unique = g_value_dup_string (value);
     493         2907 :                 break;
     494         2907 :         case PROP_TRANSIENT:
     495         2907 :                 g_return_if_fail (!self->pv->transient);
     496         2907 :                 if (g_value_get_boolean (value))
     497          109 :                         mark_object_transient (self);
     498         2907 :                 break;
     499            0 :         default:
     500            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     501            0 :                 break;
     502              :         }
     503              : }
     504              : 
     505              : static void
     506         2670 : gkm_object_get_property (GObject *obj, guint prop_id, GValue *value,
     507              :                            GParamSpec *pspec)
     508              : {
     509         2670 :         GkmObject *self = GKM_OBJECT (obj);
     510              : 
     511         2670 :         switch (prop_id) {
     512         2670 :         case PROP_HANDLE:
     513         2670 :                 g_value_set_ulong (value, gkm_object_get_handle (self));
     514         2670 :                 break;
     515            0 :         case PROP_MODULE:
     516            0 :                 g_return_if_fail (GKM_IS_MODULE (self->pv->module));
     517            0 :                 g_value_set_object (value, gkm_object_get_module (self));
     518            0 :                 break;
     519            0 :         case PROP_MANAGER:
     520            0 :                 g_value_set_object (value, gkm_object_get_manager (self));
     521            0 :                 break;
     522            0 :         case PROP_STORE:
     523            0 :                 g_value_set_object (value, self->pv->store);
     524            0 :                 break;
     525            0 :         case PROP_UNIQUE:
     526            0 :                 g_value_set_string (value, gkm_object_get_unique (self));
     527            0 :                 break;
     528            0 :         case PROP_TRANSIENT:
     529            0 :                 g_value_set_boolean (value, gkm_object_is_transient (self));
     530            0 :                 break;
     531            0 :         default:
     532            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     533            0 :                 break;
     534              :         }
     535              : }
     536              : 
     537              : static void
     538           45 : gkm_object_class_init (GkmObjectClass *klass)
     539              : {
     540           45 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     541              : 
     542           45 :         gobject_class->constructor = gkm_object_constructor;
     543           45 :         gobject_class->dispose = gkm_object_dispose;
     544           45 :         gobject_class->finalize = gkm_object_finalize;
     545           45 :         gobject_class->set_property = gkm_object_set_property;
     546           45 :         gobject_class->get_property = gkm_object_get_property;
     547              : 
     548           45 :         klass->unlock = gkm_object_real_unlock;
     549           45 :         klass->get_attribute = gkm_object_real_get_attribute;
     550           45 :         klass->set_attribute = gkm_object_real_set_attribute;
     551           45 :         klass->create_attributes = gkm_object_real_create_attributes;
     552              : 
     553           45 :         klass->expose_object = gkm_object_real_expose_object;
     554              : 
     555           45 :         g_object_class_install_property (gobject_class, PROP_HANDLE,
     556              :                    g_param_spec_ulong ("handle", "Handle", "Object handle",
     557              :                                        0, G_MAXULONG, 0, G_PARAM_READWRITE));
     558              : 
     559           45 :         g_object_class_install_property (gobject_class, PROP_MODULE,
     560              :                    g_param_spec_object ("module", "Module", "Object module",
     561              :                                         GKM_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     562              : 
     563           45 :         g_object_class_install_property (gobject_class, PROP_MANAGER,
     564              :                    g_param_spec_object ("manager", "Manager", "Object manager",
     565              :                                         GKM_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     566              : 
     567           45 :         g_object_class_install_property (gobject_class, PROP_STORE,
     568              :                    g_param_spec_object ("store", "Store", "Object store",
     569              :                                         GKM_TYPE_STORE, G_PARAM_READWRITE));
     570              : 
     571           45 :         g_object_class_install_property (gobject_class, PROP_UNIQUE,
     572              :                    g_param_spec_string ("unique", "Unique Identifer", "Machine unique identifier",
     573              :                                         NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     574              : 
     575           45 :         g_object_class_install_property (gobject_class, PROP_TRANSIENT,
     576              :                    g_param_spec_boolean ("transient", "Transient Object", "Transient Object",
     577              :                                          FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
     578              : 
     579           45 :         signals[EXPOSE_OBJECT] = g_signal_new ("expose-object", GKM_TYPE_OBJECT,
     580              :                                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmObjectClass, expose_object),
     581              :                                                NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
     582              :                                                G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
     583              : 
     584           45 :         signals[NOTIFY_ATTRIBUTE] = g_signal_new ("notify-attribute", GKM_TYPE_OBJECT,
     585              :                                         G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmObjectClass, notify_attribute),
     586              :                                         NULL, NULL, g_cclosure_marshal_VOID__ULONG,
     587              :                                         G_TYPE_NONE, 1, G_TYPE_ULONG);
     588           45 : }
     589              : 
     590              : /* -----------------------------------------------------------------------------
     591              :  * PUBLIC
     592              :  */
     593              : 
     594              : CK_RV
     595        12030 : gkm_object_get_attribute (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_PTR attr)
     596              : {
     597        12030 :         g_return_val_if_fail (GKM_IS_OBJECT (self), CKR_GENERAL_ERROR);
     598        12030 :         g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
     599        12030 :         g_assert (GKM_OBJECT_GET_CLASS (self)->get_attribute);
     600        12030 :         return GKM_OBJECT_GET_CLASS (self)->get_attribute (self, session, attr);
     601              : }
     602              : 
     603              : void
     604          268 : gkm_object_set_attribute (GkmObject *self, GkmSession *session,
     605              :                           GkmTransaction *transaction, CK_ATTRIBUTE_PTR attr)
     606              : {
     607          268 :         g_return_if_fail (GKM_IS_OBJECT (self));
     608          268 :         g_return_if_fail (GKM_IS_TRANSACTION (transaction));
     609          268 :         g_return_if_fail (!gkm_transaction_get_failed (transaction));
     610          268 :         g_return_if_fail (attr);
     611              : 
     612          268 :         g_assert (GKM_OBJECT_GET_CLASS (self)->set_attribute);
     613              : 
     614              :         /* Check that the value will actually change */
     615          268 :         if (!gkm_object_match (self, session, attr))
     616           24 :                 GKM_OBJECT_GET_CLASS (self)->set_attribute (self, session, transaction, attr);
     617              : }
     618              : 
     619              : void
     620          193 : gkm_object_create_attributes (GkmObject *self, GkmSession *session, GkmTransaction *transaction,
     621              :                               CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     622              : {
     623          193 :         g_return_if_fail (GKM_IS_OBJECT (self));
     624          193 :         g_return_if_fail (GKM_IS_TRANSACTION (transaction));
     625          193 :         g_return_if_fail (!gkm_transaction_get_failed (transaction));
     626          193 :         g_return_if_fail (GKM_IS_SESSION (session));
     627          193 :         g_return_if_fail (attrs);
     628              : 
     629          193 :         g_assert (GKM_OBJECT_GET_CLASS (self)->create_attributes);
     630              : 
     631              :         /* Check that the value will actually change */
     632          193 :         GKM_OBJECT_GET_CLASS (self)->create_attributes (self, session, transaction, attrs, n_attrs);
     633              : }
     634              : 
     635              : void
     636         4411 : gkm_object_notify_attribute  (GkmObject *self, CK_ATTRIBUTE_TYPE attr_type)
     637              : {
     638         4411 :         g_return_if_fail (GKM_IS_OBJECT (self));
     639         4411 :         g_signal_emit (self, signals[NOTIFY_ATTRIBUTE], 0, attr_type);
     640              : }
     641              : 
     642              : gboolean
     643          827 : gkm_object_match (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_PTR match)
     644              : {
     645              :         CK_ATTRIBUTE attr;
     646          827 :         gboolean matched = FALSE;
     647              :         CK_RV rv;
     648              : 
     649          827 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     650              : 
     651          827 :         if (!match->pValue)
     652            0 :                 return FALSE;
     653              : 
     654          827 :         attr.type = match->type;
     655          827 :         attr.pValue = g_malloc0 (match->ulValueLen > 4 ? match->ulValueLen : 4);
     656          827 :         attr.ulValueLen = match->ulValueLen;
     657              : 
     658          827 :         matched = FALSE;
     659              : 
     660          827 :         rv = gkm_object_get_attribute (self, session, &attr);
     661         1595 :         matched = (rv == CKR_OK) &&
     662         1551 :                   (match->ulValueLen == attr.ulValueLen) &&
     663          724 :                   (memcmp (match->pValue, attr.pValue, attr.ulValueLen) == 0);
     664              : 
     665          827 :         g_free (attr.pValue);
     666          827 :         return matched;
     667              : }
     668              : 
     669              : gboolean
     670            0 : gkm_object_match_all (GkmObject *self, GkmSession *session,
     671              :                       CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     672              : {
     673              :         CK_ULONG i;
     674              : 
     675            0 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     676              : 
     677            0 :         for (i = 0; i < n_attrs; ++i) {
     678            0 :                 if (!gkm_object_match (self, session, &attrs[i]))
     679            0 :                         return FALSE;
     680              :         }
     681              : 
     682            0 :         return TRUE;
     683              : }
     684              : 
     685              : CK_OBJECT_HANDLE
     686        10940 : gkm_object_get_handle (GkmObject *self)
     687              : {
     688        10940 :         g_return_val_if_fail (GKM_IS_OBJECT (self), 0);
     689        10940 :         return self->pv->handle;
     690              : }
     691              : 
     692              : void
     693         2669 : gkm_object_set_handle (GkmObject *self, CK_OBJECT_HANDLE handle)
     694              : {
     695         2669 :         g_return_if_fail (GKM_IS_OBJECT (self));
     696         2669 :         g_return_if_fail (handle != 0);
     697         2669 :         g_return_if_fail (self->pv->handle == 0);
     698              : 
     699         2669 :         self->pv->handle = handle;
     700         2669 :         g_object_notify (G_OBJECT (self), "handle");
     701              : }
     702              : 
     703              : GkmManager*
     704        19532 : gkm_object_get_manager (GkmObject *self)
     705              : {
     706        19532 :         g_return_val_if_fail (GKM_IS_OBJECT (self), NULL);
     707        19532 :         return self->pv->manager;
     708              : }
     709              : 
     710              : GkmModule*
     711         2259 : gkm_object_get_module (GkmObject *self)
     712              : {
     713         2259 :         g_return_val_if_fail (GKM_IS_OBJECT (self), NULL);
     714         2259 :         g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL);
     715         2259 :         return self->pv->module;
     716              : }
     717              : 
     718              : const gchar*
     719            9 : gkm_object_get_unique (GkmObject *self)
     720              : {
     721            9 :         g_return_val_if_fail (GKM_IS_OBJECT (self), NULL);
     722            9 :         return self->pv->unique;
     723              : }
     724              : 
     725              : gboolean
     726          613 : gkm_object_is_token (GkmObject *self)
     727              : {
     728          613 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     729          613 :         if (!self->pv->manager)
     730            0 :                 return FALSE;
     731          613 :         return gkm_manager_get_for_token (self->pv->manager);
     732              : }
     733              : 
     734              : gboolean
     735          408 : gkm_object_is_transient (GkmObject *self)
     736              : {
     737          408 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     738          408 :         return self->pv->transient ? TRUE : FALSE;
     739              : }
     740              : 
     741              : void
     742           36 : gkm_object_mark_used (GkmObject *self)
     743              : {
     744              :         GkmObjectTransient *transient;
     745              : 
     746           36 :         g_return_if_fail (GKM_IS_OBJECT (self));
     747           36 :         transient = self->pv->transient;
     748              : 
     749           36 :         if (transient) {
     750           12 :                 if (transient->timed_idle) {
     751            0 :                         transient->stamp_used = g_get_real_time () / G_USEC_PER_SEC;
     752              :                 }
     753           12 :                 if (transient->uses_remaining) {
     754            0 :                         --(transient->uses_remaining);
     755            0 :                         if (transient->uses_remaining == 0)
     756            0 :                                 self_destruct (self);
     757              :                 }
     758              :         }
     759              : }
     760              : 
     761              : CK_RV
     762          157 : gkm_object_unlock (GkmObject *self, GkmCredential *cred)
     763              : {
     764          157 :         g_return_val_if_fail (GKM_IS_OBJECT (self), CKR_GENERAL_ERROR);
     765          157 :         g_return_val_if_fail (GKM_OBJECT_GET_CLASS (self)->unlock, CKR_GENERAL_ERROR);
     766          157 :         return GKM_OBJECT_GET_CLASS (self)->unlock (self, cred);
     767              : }
     768              : 
     769              : 
     770              : gboolean
     771           37 : gkm_object_get_attribute_boolean (GkmObject *self, GkmSession *session,
     772              :                                   CK_ATTRIBUTE_TYPE type, gboolean *value)
     773              : {
     774              :         CK_ATTRIBUTE attr;
     775              :         CK_BBOOL bvalue;
     776              : 
     777           37 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     778           37 :         g_return_val_if_fail (value, FALSE);
     779              : 
     780           37 :         attr.type = type;
     781           37 :         attr.ulValueLen = sizeof (CK_BBOOL);
     782           37 :         attr.pValue = &bvalue;
     783              : 
     784           37 :         if (gkm_object_get_attribute (self, session, &attr) != CKR_OK)
     785            0 :                 return FALSE;
     786              : 
     787           37 :         *value = (bvalue == CK_TRUE) ? TRUE : FALSE;
     788           37 :         return TRUE;
     789              : }
     790              : 
     791              : gboolean
     792            1 : gkm_object_get_attribute_ulong (GkmObject *self, GkmSession *session,
     793              :                                 CK_ATTRIBUTE_TYPE type, gulong *value)
     794              : {
     795              :         CK_ATTRIBUTE attr;
     796              :         CK_ULONG uvalue;
     797              : 
     798            1 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     799            1 :         g_return_val_if_fail (value, FALSE);
     800              : 
     801            1 :         attr.type = type;
     802            1 :         attr.ulValueLen = sizeof (CK_ULONG);
     803            1 :         attr.pValue = &uvalue;
     804              : 
     805            1 :         if (gkm_object_get_attribute (self, session, &attr) != CKR_OK)
     806            0 :                 return FALSE;
     807              : 
     808            1 :         *value = uvalue;
     809            1 :         return TRUE;
     810              : }
     811              : 
     812              : void*
     813           55 : gkm_object_get_attribute_data (GkmObject *self, GkmSession *session,
     814              :                                CK_ATTRIBUTE_TYPE type, gsize *n_data)
     815              : {
     816              :         CK_ATTRIBUTE attr;
     817              : 
     818           55 :         g_return_val_if_fail (GKM_IS_OBJECT (self), NULL);
     819           55 :         g_return_val_if_fail (n_data, NULL);
     820              : 
     821           55 :         attr.type = type;
     822           55 :         attr.ulValueLen = 0;
     823           55 :         attr.pValue = NULL;
     824              : 
     825           55 :         if (gkm_object_get_attribute (self, session, &attr) != CKR_OK)
     826            3 :                 return NULL;
     827              : 
     828           52 :         if (attr.ulValueLen == 0)
     829            8 :                 attr.ulValueLen = 1;
     830              : 
     831           52 :         attr.pValue = g_malloc0 (attr.ulValueLen);
     832              : 
     833           52 :         if (gkm_object_get_attribute (self, session, &attr) != CKR_OK) {
     834            0 :                 g_free (attr.pValue);
     835            0 :                 return NULL;
     836              :         }
     837              : 
     838           52 :         *n_data = attr.ulValueLen;
     839           52 :         return attr.pValue;
     840              : }
     841              : 
     842              : gboolean
     843           21 : gkm_object_has_attribute_ulong (GkmObject *self, GkmSession *session,
     844              :                                 CK_ATTRIBUTE_TYPE type, gulong value)
     845              : {
     846              :         gulong *data;
     847              :         gsize n_data, i;
     848              : 
     849           21 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     850           21 :         g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);
     851              : 
     852           21 :         data = gkm_object_get_attribute_data (self, session, type, &n_data);
     853           21 :         if (data == NULL)
     854            0 :                 return FALSE;
     855              : 
     856           21 :         g_return_val_if_fail (n_data % sizeof (gulong) == 0, FALSE);
     857           21 :         for (i = 0; i < n_data / sizeof (gulong); ++i) {
     858           21 :                 if (data[i] == value) {
     859           21 :                         g_free (data);
     860           21 :                         return TRUE;
     861              :                 }
     862              :         }
     863              : 
     864            0 :         g_free (data);
     865            0 :         return FALSE;
     866              : }
     867              : 
     868              : gboolean
     869           21 : gkm_object_has_attribute_boolean (GkmObject *self, GkmSession *session,
     870              :                                   CK_ATTRIBUTE_TYPE type, gboolean value)
     871              : {
     872              :         gboolean data;
     873              : 
     874           21 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     875           21 :         g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);
     876              : 
     877           21 :         if (!gkm_object_get_attribute_boolean (self, session, type, &data))
     878            0 :                 return FALSE;
     879           21 :         return data == value;
     880              : }
     881              : 
     882              : void
     883           37 : gkm_object_destroy (GkmObject *self, GkmTransaction *transaction)
     884              : {
     885              :         GkmSession *session;
     886              :         GkmManager *manager;
     887              :         GkmModule *module;
     888              : 
     889           37 :         g_return_if_fail (GKM_IS_OBJECT (self));
     890           37 :         g_return_if_fail (GKM_IS_TRANSACTION (transaction));
     891           37 :         g_return_if_fail (!gkm_transaction_get_failed (transaction));
     892           37 :         g_return_if_fail (self->pv->module);
     893              : 
     894           37 :         g_object_ref (self);
     895              : 
     896           37 :         session = gkm_session_for_session_object (self);
     897           37 :         if (session != NULL) {
     898           21 :                 gkm_session_destroy_session_object (session, transaction, self);
     899              :         } else {
     900           16 :                 manager = gkm_object_get_manager (self);
     901           16 :                 module = gkm_object_get_module (self);
     902           16 :                 if (manager == gkm_module_get_manager (module))
     903           16 :                         gkm_module_remove_token_object (module, transaction, self);
     904              :         }
     905              : 
     906              :         /* Forcefully dispose of the object once the transaction completes */
     907           37 :         gkm_transaction_add (transaction, NULL, complete_destroy, g_object_ref (self));
     908              : 
     909           37 :         g_object_unref (self);
     910              : }
     911              : 
     912              : gboolean
     913         2228 : gkm_object_is_exposed (GkmObject *self)
     914              : {
     915         2228 :         g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE);
     916         2228 :         return self->pv->exposed;
     917              : }
     918              : 
     919              : void
     920         7497 : gkm_object_expose (GkmObject *self, gboolean expose)
     921              : {
     922         7497 :         if (!expose && !self)
     923            0 :                 return;
     924              : 
     925         7497 :         g_return_if_fail (GKM_IS_OBJECT (self));
     926              : 
     927         7497 :         if (self->pv->exposed != expose)
     928         5340 :                 g_signal_emit (self, signals[EXPOSE_OBJECT], 0, expose);
     929              : }
     930              : 
     931              : void
     932         2277 : gkm_object_expose_full (GkmObject *self, GkmTransaction *transaction, gboolean expose)
     933              : {
     934         2277 :         if (!expose && !self)
     935            0 :                 return;
     936              : 
     937         2277 :         g_return_if_fail (GKM_IS_OBJECT (self));
     938         2277 :         g_return_if_fail (!transaction || !gkm_transaction_get_failed (transaction));
     939              : 
     940         2277 :         if (self->pv->exposed != expose) {
     941         2233 :                 if (transaction)
     942          161 :                         gkm_transaction_add (transaction, self, complete_expose, GUINT_TO_POINTER (expose));
     943         2233 :                 gkm_object_expose (self, expose);
     944              :         }
     945              : }
        

Generated by: LCOV version 2.0-1