LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-credential.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.5 % 247 226
Test Date: 2024-04-08 13:24:42 Functions: 100.0 % 27 27

            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-attributes.h"
      24              : #include "gkm-credential.h"
      25              : #include "gkm-secret.h"
      26              : #include "gkm-session.h"
      27              : #include "gkm-transaction.h"
      28              : 
      29              : #include "pkcs11/pkcs11.h"
      30              : #include "pkcs11/pkcs11i.h"
      31              : 
      32              : enum {
      33              :         PROP_0,
      34              :         PROP_OBJECT,
      35              :         PROP_SECRET
      36              : };
      37              : 
      38              : struct _GkmCredentialPrivate {
      39              : 
      40              :         /* The object we authenticated */
      41              :         GkmObject *object;
      42              : 
      43              :         /* Secret which created this credential */
      44              :         GkmSecret *secret;
      45              : 
      46              :         /* Stored data */
      47              :         GType user_type;
      48              :         gpointer user_data;
      49              : };
      50              : 
      51         3521 : G_DEFINE_TYPE_WITH_PRIVATE (GkmCredential, gkm_credential, GKM_TYPE_OBJECT);
      52              : 
      53              : /* -----------------------------------------------------------------------------
      54              :  * INTERNAL
      55              :  */
      56              : 
      57              : static GkmObject*
      58           69 : factory_create_credential (GkmSession *session, GkmTransaction *transaction,
      59              :                               CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
      60              : {
      61              :         CK_OBJECT_HANDLE handle;
      62              :         GkmCredential *cred;
      63              :         CK_ATTRIBUTE *attr;
      64              :         GkmManager *manager;
      65              :         GkmModule *module;
      66           69 :         GkmObject *object = NULL;
      67              :         CK_RV rv;
      68              : 
      69           69 :         g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
      70           69 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
      71              : 
      72              :         /* The handle is optional */
      73           69 :         if (gkm_attributes_find_ulong (attrs, n_attrs, CKA_G_OBJECT, &handle)) {
      74           24 :                 rv = gkm_session_lookup_readable_object (session, handle, &object);
      75           24 :                 if (rv != CKR_OK) {
      76            1 :                         gkm_transaction_fail (transaction, rv);
      77            1 :                         return NULL;
      78              :                 }
      79              :         } else {
      80           45 :                 object = NULL;
      81              :         }
      82              : 
      83              :         /* The value is optional */
      84           68 :         attr = gkm_attributes_find (attrs, n_attrs, CKA_VALUE);
      85              : 
      86           68 :         gkm_attributes_consume (attrs, n_attrs, CKA_VALUE, CKA_G_OBJECT, G_MAXULONG);
      87              : 
      88           68 :         module = gkm_session_get_module (session);
      89           68 :         manager = gkm_manager_for_template (attrs, n_attrs, session);
      90           68 :         rv = gkm_credential_create (module, manager, object,
      91              :                                     attr ? attr->pValue : NULL,
      92              :                                     attr ? attr->ulValueLen : 0, &cred);
      93              : 
      94           68 :         if (rv == CKR_OK) {
      95           64 :                 gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (cred),
      96              :                                                       TRUE, attrs, n_attrs);
      97           64 :                 return GKM_OBJECT (cred);
      98              :         } else {
      99            4 :                 gkm_transaction_fail (transaction, rv);
     100            4 :                 return NULL;
     101              :         }
     102              : }
     103              : 
     104              : static void
     105           36 : self_destruct (GkmCredential *self)
     106              : {
     107              :         GkmTransaction *transaction;
     108              :         CK_RV rv;
     109              : 
     110           36 :         g_assert (GKM_IS_CREDENTIAL (self));
     111              : 
     112           36 :         transaction = gkm_transaction_new ();
     113              : 
     114              :         /* Destroy ourselves */
     115           36 :         gkm_object_destroy (GKM_OBJECT (self), transaction);
     116              : 
     117           36 :         gkm_transaction_complete (transaction);
     118           36 :         rv = gkm_transaction_get_result (transaction);
     119           36 :         g_object_unref (transaction);
     120              : 
     121           36 :         if (rv != CKR_OK)
     122            0 :                 g_warning ("Couldn't destroy credential object: (code %lu)", (gulong)rv);
     123           36 : }
     124              : 
     125              : static void
     126           36 : object_went_away (gpointer data, GObject *old_object)
     127              : {
     128           36 :         GkmCredential *self = data;
     129           36 :         g_return_if_fail (GKM_IS_CREDENTIAL (self));
     130           36 :         self->pv->object = NULL;
     131           36 :         self_destruct (self);
     132              : }
     133              : 
     134              : static void
     135          478 : clear_data (GkmCredential *self)
     136              : {
     137          478 :         if (!self->pv->user_data)
     138          319 :                 return;
     139          159 :         if (G_TYPE_IS_BOXED (self->pv->user_type))
     140            5 :                 g_boxed_free (self->pv->user_type, self->pv->user_data);
     141          154 :         else if (G_TYPE_IS_OBJECT (self->pv->user_type))
     142          154 :                 g_object_unref (self->pv->user_data);
     143              :         else
     144            0 :                 g_assert_not_reached ();
     145          159 :         self->pv->user_data = NULL;
     146          159 :         self->pv->user_type = 0;
     147              : }
     148              : 
     149              : /* -----------------------------------------------------------------------------
     150              :  * OBJECT
     151              :  */
     152              : 
     153              : static CK_RV
     154          943 : gkm_credential_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
     155              : {
     156          943 :         GkmCredential *self = GKM_CREDENTIAL (base);
     157              :         CK_OBJECT_HANDLE handle;
     158              :         gconstpointer value;
     159              :         gsize n_value;
     160              : 
     161          943 :         switch (attr->type) {
     162              : 
     163          436 :         case CKA_CLASS:
     164          436 :                 return gkm_attribute_set_ulong (attr, CKO_G_CREDENTIAL);
     165              : 
     166            0 :         case CKA_PRIVATE:
     167            0 :                 return gkm_attribute_set_bool (attr, TRUE);
     168              : 
     169          313 :         case CKA_G_OBJECT:
     170          313 :                 handle = self->pv->object ? gkm_object_get_handle (self->pv->object) : 0;
     171          313 :                 return gkm_attribute_set_ulong (attr, handle);
     172              : 
     173            2 :         case CKA_VALUE:
     174            2 :                 if (gkm_session_is_for_application (session))
     175            1 :                         return CKR_ATTRIBUTE_SENSITIVE;
     176            1 :                 if (!self->pv->secret) {
     177            0 :                         value = NULL;
     178            0 :                         n_value = 0;
     179              :                 } else {
     180            1 :                         value = gkm_secret_get (self->pv->secret, &n_value);
     181              :                 }
     182            1 :                 return gkm_attribute_set_data (attr, value, n_value);
     183              :         };
     184              : 
     185          192 :         return GKM_OBJECT_CLASS (gkm_credential_parent_class)->get_attribute (base, session, attr);
     186              : }
     187              : 
     188              : static GObject*
     189          205 : gkm_credential_constructor (GType type, guint n_props, GObjectConstructParam *props)
     190              : {
     191          205 :         GkmCredential *self = GKM_CREDENTIAL (G_OBJECT_CLASS (gkm_credential_parent_class)->constructor(type, n_props, props));
     192          205 :         g_return_val_if_fail (self, NULL);
     193              : 
     194          205 :         return G_OBJECT (self);
     195              : }
     196              : 
     197              : static void
     198          205 : gkm_credential_init (GkmCredential *self)
     199              : {
     200          205 :         self->pv = gkm_credential_get_instance_private (self);
     201          205 : }
     202              : 
     203              : static void
     204          318 : gkm_credential_dispose (GObject *obj)
     205              : {
     206          318 :         GkmCredential *self = GKM_CREDENTIAL (obj);
     207              : 
     208          318 :         if (self->pv->object)
     209          134 :                 g_object_weak_unref (G_OBJECT (self->pv->object), object_went_away, self);
     210          318 :         self->pv->object = NULL;
     211              : 
     212          318 :         if (self->pv->secret)
     213          205 :                 g_object_unref (G_OBJECT (self->pv->secret));
     214          318 :         self->pv->secret = NULL;
     215              : 
     216          318 :         clear_data (self);
     217              : 
     218          318 :         G_OBJECT_CLASS (gkm_credential_parent_class)->dispose (obj);
     219          318 : }
     220              : 
     221              : static void
     222          205 : gkm_credential_finalize (GObject *obj)
     223              : {
     224          205 :         GkmCredential *self = GKM_CREDENTIAL (obj);
     225              : 
     226          205 :         g_assert (!self->pv->object);
     227          205 :         g_assert (!self->pv->user_type);
     228          205 :         g_assert (!self->pv->user_data);
     229              : 
     230          205 :         G_OBJECT_CLASS (gkm_credential_parent_class)->finalize (obj);
     231          205 : }
     232              : 
     233              : static void
     234          410 : gkm_credential_set_property (GObject *obj, guint prop_id, const GValue *value,
     235              :                                 GParamSpec *pspec)
     236              : {
     237          410 :         GkmCredential *self = GKM_CREDENTIAL (obj);
     238              :         GkmObject *object;
     239              : 
     240          410 :         switch (prop_id) {
     241          205 :         case PROP_OBJECT:
     242          205 :                 object = g_value_get_object (value);
     243          205 :                 if (object)
     244          157 :                         gkm_credential_connect (self, object);
     245              :                 else
     246           48 :                         g_return_if_fail (!self->pv->object);
     247          205 :                 break;
     248          205 :         case PROP_SECRET:
     249          205 :                 gkm_credential_set_secret (self, g_value_get_object (value));
     250          205 :                 break;
     251            0 :         default:
     252            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     253            0 :                 break;
     254              :         }
     255              : }
     256              : 
     257              : static void
     258            2 : gkm_credential_get_property (GObject *obj, guint prop_id, GValue *value,
     259              :                               GParamSpec *pspec)
     260              : {
     261            2 :         GkmCredential *self = GKM_CREDENTIAL (obj);
     262              : 
     263            2 :         switch (prop_id) {
     264            1 :         case PROP_OBJECT:
     265            1 :                 g_value_set_object (value, gkm_credential_get_object (self));
     266            1 :                 break;
     267            1 :         case PROP_SECRET:
     268            1 :                 g_value_set_object (value, gkm_credential_get_secret (self));
     269            1 :                 break;
     270            0 :         default:
     271            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     272            0 :                 break;
     273              :         }
     274            2 : }
     275              : 
     276              : static void
     277           36 : gkm_credential_class_init (GkmCredentialClass *klass)
     278              : {
     279           36 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     280           36 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     281              : 
     282           36 :         gobject_class->constructor = gkm_credential_constructor;
     283           36 :         gobject_class->dispose = gkm_credential_dispose;
     284           36 :         gobject_class->finalize = gkm_credential_finalize;
     285           36 :         gobject_class->set_property = gkm_credential_set_property;
     286           36 :         gobject_class->get_property = gkm_credential_get_property;
     287              : 
     288           36 :         gkm_class->get_attribute = gkm_credential_real_get_attribute;
     289              : 
     290           36 :         g_object_class_install_property (gobject_class, PROP_OBJECT,
     291              :                    g_param_spec_object ("object", "Object", "Object authenticated",
     292              :                                         GKM_TYPE_OBJECT, G_PARAM_READWRITE));
     293              : 
     294           36 :         g_object_class_install_property (gobject_class, PROP_SECRET,
     295              :                    g_param_spec_object ("secret", "Secret", "Optiontal secret",
     296              :                                         GKM_TYPE_SECRET, G_PARAM_READWRITE));
     297           36 : }
     298              : 
     299              : /* -----------------------------------------------------------------------------
     300              :  * PUBLIC
     301              :  */
     302              : 
     303              : GkmFactory*
     304          327 : gkm_credential_get_factory (void)
     305              : {
     306              :         static CK_OBJECT_CLASS klass = CKO_G_CREDENTIAL;
     307              : 
     308              :         static CK_ATTRIBUTE attributes[] = {
     309              :                 { CKA_CLASS, &klass, sizeof (klass) },
     310              :         };
     311              : 
     312              :         static GkmFactory factory = {
     313              :                 attributes,
     314              :                 G_N_ELEMENTS (attributes),
     315              :                 factory_create_credential
     316              :         };
     317              : 
     318          327 :         return &factory;
     319              : }
     320              : 
     321              : CK_RV
     322          205 : gkm_credential_create (GkmModule *module, GkmManager *manager, GkmObject *object,
     323              :                        CK_UTF8CHAR_PTR pin, CK_ULONG n_pin, GkmCredential **result)
     324              : {
     325              :         GkmCredential *cred;
     326          205 :         GkmSecret *secret = NULL;
     327              :         CK_RV rv;
     328              : 
     329          205 :         g_return_val_if_fail (GKM_IS_MODULE (module), CKR_GENERAL_ERROR);
     330          205 :         g_return_val_if_fail (!object || GKM_IS_OBJECT (object), CKR_GENERAL_ERROR);
     331          205 :         g_return_val_if_fail (!manager || GKM_IS_MANAGER (manager), CKR_GENERAL_ERROR);
     332          205 :         g_return_val_if_fail (result, CKR_GENERAL_ERROR);
     333              : 
     334          205 :         secret = gkm_secret_new_from_login (pin, n_pin);
     335          205 :         cred = g_object_new (GKM_TYPE_CREDENTIAL,
     336              :                              "module", module,
     337              :                              "manager", manager,
     338              :                              "secret", secret,
     339              :                              "object", object,
     340              :                              NULL);
     341          205 :         g_object_unref (secret);
     342              : 
     343              :         /* If we have an object, the unlock must work */
     344          205 :         if (object) {
     345          157 :                 rv = gkm_object_unlock (object, cred);
     346          157 :                 if (rv == CKR_OK)
     347          150 :                         *result = cred;
     348              :                 else
     349            7 :                         g_object_unref (cred);
     350              : 
     351              :         /* Created credentials without object */
     352              :         } else {
     353           48 :                 *result = cred;
     354           48 :                 rv = CKR_OK;
     355              :         }
     356              : 
     357          205 :         return rv;
     358              : }
     359              : 
     360              : void
     361          170 : gkm_credential_connect (GkmCredential *self, GkmObject *object)
     362              : {
     363          170 :         g_return_if_fail (GKM_IS_CREDENTIAL (self));
     364          170 :         g_return_if_fail (GKM_IS_OBJECT (object));
     365          170 :         g_return_if_fail (self->pv->object == NULL);
     366          170 :         g_return_if_fail (GKM_OBJECT (self) != object);
     367          170 :         self->pv->object = object;
     368          170 :         g_object_weak_ref (G_OBJECT (self->pv->object), object_went_away, self);
     369              : }
     370              : 
     371              : GkmSecret*
     372          163 : gkm_credential_get_secret (GkmCredential *self)
     373              : {
     374          163 :         g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);
     375          163 :         return self->pv->secret;
     376              : }
     377              : 
     378              : void
     379          206 : gkm_credential_set_secret (GkmCredential *self, GkmSecret *secret)
     380              : {
     381          206 :         g_return_if_fail (GKM_IS_CREDENTIAL (self));
     382              : 
     383          206 :         if (secret) {
     384          206 :                 g_return_if_fail (GKM_IS_SECRET (secret));
     385          206 :                 g_object_ref (secret);
     386              :         }
     387          206 :         if (self->pv->secret)
     388            1 :                 g_object_unref (self->pv->secret);
     389          206 :         self->pv->secret = secret;
     390              : 
     391          206 :         g_object_notify (G_OBJECT (self), "secret");
     392              : }
     393              : 
     394              : const gchar*
     395            9 : gkm_credential_get_password (GkmCredential *self, gsize *n_password)
     396              : {
     397            9 :         g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);
     398            9 :         g_return_val_if_fail (n_password, NULL);
     399              : 
     400            9 :         if (!self->pv->secret) {
     401            0 :                 *n_password = 0;
     402            0 :                 return NULL;
     403              :         }
     404              : 
     405            9 :         return gkm_secret_get_password (self->pv->secret, n_password);
     406              : }
     407              : 
     408              : GkmObject*
     409           18 : gkm_credential_get_object (GkmCredential *self)
     410              : {
     411           18 :         g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);
     412           18 :         return self->pv->object;
     413              : }
     414              : 
     415              : gpointer
     416          105 : gkm_credential_peek_data (GkmCredential *self, GType type)
     417              : {
     418          105 :         g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);
     419          105 :         if (!self->pv->user_data)
     420            6 :                 return NULL;
     421           99 :         g_return_val_if_fail (type == self->pv->user_type, NULL);
     422           99 :         return self->pv->user_data;
     423              : }
     424              : 
     425              : gpointer
     426           26 : gkm_credential_pop_data (GkmCredential *self, GType type)
     427              : {
     428           26 :         gpointer data = NULL;
     429           26 :         g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);
     430              : 
     431           26 :         if (self->pv->user_data) {
     432           22 :                 g_return_val_if_fail (type == self->pv->user_type, NULL);
     433           22 :                 if (G_TYPE_IS_BOXED (self->pv->user_type))
     434            1 :                         data = g_boxed_copy (self->pv->user_type, self->pv->user_data);
     435           21 :                 else if (G_TYPE_IS_OBJECT (self->pv->user_type))
     436           21 :                         data = g_object_ref (self->pv->user_data);
     437              :                 else
     438            0 :                         g_assert_not_reached ();
     439              :         }
     440              : 
     441           26 :         gkm_object_mark_used (GKM_OBJECT (self));
     442           26 :         return data;
     443              : }
     444              : 
     445              : void
     446          160 : gkm_credential_set_data (GkmCredential *self, GType type, gpointer data)
     447              : {
     448          160 :         g_return_if_fail (GKM_IS_CREDENTIAL (self));
     449              : 
     450          160 :         if (data) {
     451          159 :                 g_return_if_fail (type);
     452          159 :                 g_return_if_fail (G_TYPE_IS_BOXED (type) || G_TYPE_IS_OBJECT (type));
     453              :         }
     454              : 
     455          160 :         clear_data (self);
     456              : 
     457          160 :         if (data) {
     458          159 :                 self->pv->user_type = type;
     459          159 :                 if (G_TYPE_IS_BOXED (type))
     460            5 :                         self->pv->user_data = g_boxed_copy (type, data);
     461          154 :                 else if (G_TYPE_IS_OBJECT (type))
     462          154 :                         self->pv->user_data = g_object_ref (data);
     463              :                 else
     464            0 :                         g_assert_not_reached ();
     465              :         }
     466              : }
     467              : 
     468              : gboolean
     469          183 : gkm_credential_for_each (GkmSession *session, GkmObject *object,
     470              :                          GkmCredentialFunc func, gpointer user_data)
     471              : {
     472              :         CK_OBJECT_HANDLE handle;
     473              :         CK_OBJECT_CLASS klass;
     474              :         CK_ATTRIBUTE attrs[2];
     475              :         GList *results, *l;
     476              :         GkmCredential *cred;
     477              :         gboolean ret;
     478              : 
     479          183 :         g_return_val_if_fail (GKM_IS_SESSION (session), FALSE);
     480          183 :         g_return_val_if_fail (GKM_IS_OBJECT (object), FALSE);
     481          183 :         g_return_val_if_fail (func, FALSE);
     482              : 
     483              :         /* Do we have one right on the session */
     484          183 :         cred = gkm_session_get_credential (session);
     485          183 :         if (cred && gkm_credential_get_object (cred) == object) {
     486            0 :                 g_object_ref (cred);
     487            0 :                 ret = (func) (cred, object, user_data);
     488            0 :                 g_object_unref (cred);
     489            0 :                 if (ret)
     490            0 :                         return TRUE;
     491              :         }
     492              : 
     493          183 :         klass = CKO_G_CREDENTIAL;
     494          183 :         attrs[0].type = CKA_CLASS;
     495          183 :         attrs[0].pValue = &klass;
     496          183 :         attrs[0].ulValueLen = sizeof (klass);
     497              : 
     498          183 :         handle = gkm_object_get_handle (object);
     499          183 :         attrs[1].type = CKA_G_OBJECT;
     500          183 :         attrs[1].pValue = &handle;
     501          183 :         attrs[1].ulValueLen = sizeof (handle);
     502              : 
     503              :         /* Find any on the session */
     504          183 :         results = gkm_manager_find_by_attributes (gkm_session_get_manager (session),
     505              :                                                   session, attrs, G_N_ELEMENTS (attrs));
     506              : 
     507          191 :         for (l = results; l; l = g_list_next (l)) {
     508           27 :                 g_object_ref (l->data);
     509           27 :                 ret = (func) (l->data, object, user_data);
     510           27 :                 g_object_unref (l->data);
     511           27 :                 if (ret)
     512           19 :                         break;
     513              :         }
     514              : 
     515          183 :         g_list_free (results);
     516              : 
     517          183 :         if (l != NULL)
     518           19 :                 return TRUE;
     519              : 
     520              :         /* Find any in the token */
     521          164 :         results = gkm_manager_find_by_attributes (gkm_module_get_manager (gkm_session_get_module (session)),
     522              :                                                   session, attrs, G_N_ELEMENTS (attrs));
     523              : 
     524          164 :         for (l = results; l; l = g_list_next (l)) {
     525           99 :                 g_object_ref (l->data);
     526           99 :                 ret = (func) (l->data, object, user_data);
     527           99 :                 g_object_unref (l->data);
     528           99 :                 if (ret)
     529           99 :                         break;
     530              :         }
     531              : 
     532          164 :         g_list_free (results);
     533              : 
     534          164 :         return (l != NULL);
     535              : }
        

Generated by: LCOV version 2.0-1