LCOV - code coverage report
Current view: top level - pkcs11/gnome2-store - gkm-gnome2-module.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.0 % 130 117
Test Date: 2024-05-07 18:02:03 Functions: 95.5 % 22 21

            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 "gkm-gnome2-module.h"
      24              : #include "gkm-gnome2-private-key.h"
      25              : #include "gkm-gnome2-public-key.h"
      26              : #include "gkm-gnome2-storage.h"
      27              : #include "gkm-gnome2-store.h"
      28              : 
      29              : #include "gkm/gkm-certificate.h"
      30              : #include "gkm/gkm-data-asn1.h"
      31              : #define DEBUG_FLAG GKM_DEBUG_STORAGE
      32              : #include "gkm/gkm-debug.h"
      33              : #include "gkm/gkm-manager.h"
      34              : #include "gkm/gkm-secret.h"
      35              : #include "gkm/gkm-transaction.h"
      36              : #include "gkm/gkm-util.h"
      37              : 
      38              : #include <string.h>
      39              : 
      40              : struct _GkmGnome2Module {
      41              :         GkmModule parent;
      42              :         GkmGnome2Storage *storage;
      43              :         gchar *directory;
      44              :         GHashTable *unlocked_apps;
      45              :         CK_TOKEN_INFO token_info;
      46              : };
      47              : 
      48              : static const CK_SLOT_INFO user_module_slot_info = {
      49              :         "Gnome2 Key Storage",
      50              :         "Gnome Keyring",
      51              :         CKF_TOKEN_PRESENT,
      52              :         { 0, 0 },
      53              :         { 0, 0 }
      54              : };
      55              : 
      56              : static const CK_TOKEN_INFO user_module_token_info = {
      57              :         "Gnome2 Key Storage",
      58              :         "Gnome Keyring",
      59              :         "1.0",
      60              :         "1:USER:DEFAULT", /* Unique serial number for manufacturer */
      61              :         CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED | CKF_LOGIN_REQUIRED,
      62              :         CK_EFFECTIVELY_INFINITE,
      63              :         CK_EFFECTIVELY_INFINITE,
      64              :         CK_EFFECTIVELY_INFINITE,
      65              :         CK_EFFECTIVELY_INFINITE,
      66              :         1024,
      67              :         1,
      68              :         CK_UNAVAILABLE_INFORMATION,
      69              :         CK_UNAVAILABLE_INFORMATION,
      70              :         CK_UNAVAILABLE_INFORMATION,
      71              :         CK_UNAVAILABLE_INFORMATION,
      72              :         { 0, 0 },
      73              :         { 0, 0 },
      74              :         ""
      75              : };
      76              : 
      77              : #define UNUSED_VALUE (GUINT_TO_POINTER (1))
      78              : 
      79          291 : G_DEFINE_TYPE (GkmGnome2Module, gkm_gnome2_module, GKM_TYPE_MODULE);
      80              : 
      81              : GkmModule *  _gkm_gnome2_store_get_module_for_testing (void);
      82              : 
      83              : /* -----------------------------------------------------------------------------
      84              :  * ACTUAL PKCS#11 Module Implementation
      85              :  */
      86              : 
      87              : /* Include all the module entry points */
      88              : #include "gkm/gkm-module-ep.h"
      89           34 : GKM_DEFINE_MODULE (gkm_gnome2_module, GKM_TYPE_GNOME2_MODULE);
      90              : 
      91              : /* -----------------------------------------------------------------------------
      92              :  * INTERNAL
      93              :  */
      94              : 
      95              : /* -----------------------------------------------------------------------------
      96              :  * OBJECT
      97              :  */
      98              : 
      99              : static const CK_SLOT_INFO*
     100           66 : gkm_gnome2_module_real_get_slot_info (GkmModule *base)
     101              : {
     102           66 :         return &user_module_slot_info;
     103              : }
     104              : 
     105              : static const CK_TOKEN_INFO*
     106            9 : gkm_gnome2_module_real_get_token_info (GkmModule *base)
     107              : {
     108            9 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     109              : 
     110              :         /* Update the info with current info */
     111            9 :         self->token_info.flags = gkm_gnome2_storage_token_flags (self->storage);
     112              : 
     113            9 :         return &self->token_info;
     114              : }
     115              : 
     116              : static void
     117           28 : gkm_gnome2_module_real_parse_argument (GkmModule *base, const gchar *name, const gchar *value)
     118              : {
     119           28 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     120           28 :         if (g_str_equal (name, "directory")) {
     121           28 :                 g_free (self->directory);
     122           28 :                 self->directory = g_strdup (value);
     123              :         }
     124           28 : }
     125              : 
     126              : static CK_RV
     127            7 : gkm_gnome2_module_real_refresh_token (GkmModule *base)
     128              : {
     129            7 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     130            7 :         gkm_gnome2_storage_refresh (self->storage);
     131            7 :         return CKR_OK;
     132              : }
     133              : 
     134              : static void
     135            3 : gkm_gnome2_module_real_add_token_object (GkmModule *base, GkmTransaction *transaction, GkmObject *object)
     136              : {
     137            3 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     138            3 :         gkm_gnome2_storage_create (self->storage, transaction, object);
     139            3 : }
     140              : 
     141              : static void
     142            3 : gkm_gnome2_module_real_store_token_object (GkmModule *base, GkmTransaction *transaction, GkmObject *object)
     143              : {
     144              :         /* Not necessary */
     145            3 : }
     146              : 
     147              : static void
     148            0 : gkm_gnome2_module_real_remove_token_object (GkmModule *base, GkmTransaction *transaction, GkmObject *object)
     149              : {
     150            0 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     151            0 :         gkm_gnome2_storage_destroy (self->storage, transaction, object);
     152            0 : }
     153              : 
     154              : static CK_RV
     155            3 : gkm_gnome2_module_real_login_change (GkmModule *base, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR old_pin,
     156              :                                    CK_ULONG n_old_pin, CK_UTF8CHAR_PTR new_pin, CK_ULONG n_new_pin)
     157              : {
     158            3 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     159              :         GkmSecret *old_login, *new_login;
     160              :         GkmTransaction *transaction;
     161              :         CK_RV rv;
     162              : 
     163              :         /*
     164              :          * Remember this doesn't affect the currently logged in user. Logged in
     165              :          * sessions will remain logged in, and vice versa.
     166              :          */
     167              : 
     168            3 :         old_login = gkm_secret_new_from_login (old_pin, n_old_pin);
     169            3 :         new_login = gkm_secret_new_from_login (new_pin, n_new_pin);
     170              : 
     171            3 :         transaction = gkm_transaction_new ();
     172              : 
     173            3 :         gkm_gnome2_storage_relock (self->storage, transaction, old_login, new_login);
     174              : 
     175            3 :         g_object_unref (old_login);
     176            3 :         g_object_unref (new_login);
     177              : 
     178            3 :         gkm_transaction_complete (transaction);
     179            3 :         rv = gkm_transaction_get_result (transaction);
     180            3 :         g_object_unref (transaction);
     181              : 
     182            3 :         return rv;
     183              : }
     184              : 
     185              : static CK_RV
     186            5 : gkm_gnome2_module_real_login_user (GkmModule *base, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
     187              : {
     188            5 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     189              :         GkmSecret *login;
     190              :         CK_RV rv;
     191              : 
     192              :         /* See if this application has logged in */
     193            5 :         if (g_hash_table_lookup (self->unlocked_apps, &slot_id))
     194            0 :                 return CKR_USER_ALREADY_LOGGED_IN;
     195              : 
     196            5 :         login = gkm_gnome2_storage_get_login (self->storage);
     197              : 
     198              :         /* No application is logged in */
     199            5 :         if (g_hash_table_size (self->unlocked_apps) == 0) {
     200              : 
     201            5 :                 g_return_val_if_fail (login == NULL, CKR_GENERAL_ERROR);
     202              : 
     203              :                 /* So actually unlock the store */
     204            5 :                 login = gkm_secret_new_from_login (pin, n_pin);
     205            5 :                 rv = gkm_gnome2_storage_unlock (self->storage, login);
     206            5 :                 g_object_unref (login);
     207              : 
     208              :         /* An application is already logged in */
     209              :         } else {
     210              : 
     211            0 :                 g_return_val_if_fail (login != NULL, CKR_GENERAL_ERROR);
     212              : 
     213              :                 /* Compare our pin to the one used originally */
     214            0 :                 if (!gkm_secret_equals (login, pin, n_pin))
     215            0 :                         rv = CKR_PIN_INCORRECT;
     216              :                 else
     217            0 :                         rv = CKR_OK;
     218              :         }
     219              : 
     220              :         /* Note that this application logged in */
     221            5 :         if (rv == CKR_OK) {
     222            5 :                 g_hash_table_insert (self->unlocked_apps, gkm_util_ulong_alloc (slot_id), UNUSED_VALUE);
     223            5 :                 rv = GKM_MODULE_CLASS (gkm_gnome2_module_parent_class)->login_user (base, slot_id, pin, n_pin);
     224              :         }
     225              : 
     226            5 :         return rv;
     227              : }
     228              : 
     229              : static CK_RV
     230            2 : gkm_gnome2_module_real_login_so (GkmModule *base, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
     231              : {
     232            2 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     233              : 
     234              :         /* See if this application has unlocked, in which case we can't login */
     235            2 :         if (g_hash_table_lookup (self->unlocked_apps, &slot_id))
     236            0 :                 return CKR_USER_ALREADY_LOGGED_IN;
     237              : 
     238              :         /* Note that for an SO login, we don't actually unlock, and pin is always blank */
     239            2 :         if (n_pin != 0)
     240            0 :                 return CKR_PIN_INCORRECT;
     241              : 
     242            2 :         return GKM_MODULE_CLASS (gkm_gnome2_module_parent_class)->login_so (base, slot_id, pin, n_pin);
     243              : }
     244              : 
     245              : static CK_RV
     246            4 : gkm_gnome2_module_real_logout_user (GkmModule *base, CK_SLOT_ID slot_id)
     247              : {
     248            4 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (base);
     249              :         CK_RV rv;
     250              : 
     251            4 :         if (!g_hash_table_remove (self->unlocked_apps, &slot_id))
     252            0 :                 return CKR_USER_NOT_LOGGED_IN;
     253              : 
     254            4 :         if (g_hash_table_size (self->unlocked_apps) > 0)
     255            0 :                 return CKR_OK;
     256              : 
     257            4 :         rv = gkm_gnome2_storage_lock (self->storage);
     258            4 :         if (rv == CKR_OK)
     259            4 :                 rv = GKM_MODULE_CLASS (gkm_gnome2_module_parent_class)->logout_user (base, slot_id);
     260              : 
     261            4 :         return rv;
     262              : }
     263              : 
     264              : static GObject*
     265           34 : gkm_gnome2_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
     266              : {
     267           34 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (G_OBJECT_CLASS (gkm_gnome2_module_parent_class)->constructor(type, n_props, props));
     268              : 
     269           34 :         g_return_val_if_fail (self, NULL);
     270              : 
     271           34 :         if (!self->directory)
     272            6 :                 self->directory = gkm_util_locate_keyrings_directory ();
     273           34 :         gkm_debug ("gnome2 module directory: %s", self->directory);
     274              : 
     275           34 :         self->storage = gkm_gnome2_storage_new (GKM_MODULE (self), self->directory);
     276              : 
     277           34 :         return G_OBJECT (self);
     278              : }
     279              : 
     280              : static void
     281           34 : gkm_gnome2_module_init (GkmGnome2Module *self)
     282              : {
     283           34 :         self->unlocked_apps = g_hash_table_new_full (gkm_util_ulong_hash, gkm_util_ulong_equal, gkm_util_ulong_free, NULL);
     284              : 
     285              :         /* Our default token info, updated as module runs */
     286           34 :         memcpy (&self->token_info, &user_module_token_info, sizeof (CK_TOKEN_INFO));
     287              : 
     288              :         /* For creating stored keys */
     289           34 :         gkm_module_register_factory (GKM_MODULE (self), GKM_FACTORY_GNOME2_PRIVATE_KEY);
     290           34 :         gkm_module_register_factory (GKM_MODULE (self), GKM_FACTORY_GNOME2_PUBLIC_KEY);
     291           34 : }
     292              : 
     293              : static void
     294           68 : gkm_gnome2_module_dispose (GObject *obj)
     295              : {
     296           68 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (obj);
     297              : 
     298           68 :         if (self->storage)
     299           34 :                 g_object_unref (self->storage);
     300           68 :         self->storage = NULL;
     301              : 
     302           68 :         g_hash_table_remove_all (self->unlocked_apps);
     303              : 
     304           68 :         G_OBJECT_CLASS (gkm_gnome2_module_parent_class)->dispose (obj);
     305           68 : }
     306              : 
     307              : static void
     308           34 : gkm_gnome2_module_finalize (GObject *obj)
     309              : {
     310           34 :         GkmGnome2Module *self = GKM_GNOME2_MODULE (obj);
     311              : 
     312           34 :         g_assert (self->storage == NULL);
     313              : 
     314           34 :         g_assert (self->unlocked_apps);
     315           34 :         g_hash_table_destroy (self->unlocked_apps);
     316           34 :         self->unlocked_apps = NULL;
     317              : 
     318           34 :         g_free (self->directory);
     319           34 :         self->directory = NULL;
     320              : 
     321           34 :         G_OBJECT_CLASS (gkm_gnome2_module_parent_class)->finalize (obj);
     322           34 : }
     323              : 
     324              : static void
     325           30 : gkm_gnome2_module_class_init (GkmGnome2ModuleClass *klass)
     326              : {
     327           30 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     328           30 :         GkmModuleClass *module_class = GKM_MODULE_CLASS (klass);
     329              : 
     330           30 :         gobject_class->constructor = gkm_gnome2_module_constructor;
     331           30 :         gobject_class->dispose = gkm_gnome2_module_dispose;
     332           30 :         gobject_class->finalize = gkm_gnome2_module_finalize;
     333              : 
     334           30 :         module_class->get_slot_info = gkm_gnome2_module_real_get_slot_info;
     335           30 :         module_class->get_token_info = gkm_gnome2_module_real_get_token_info;
     336           30 :         module_class->parse_argument = gkm_gnome2_module_real_parse_argument;
     337           30 :         module_class->refresh_token = gkm_gnome2_module_real_refresh_token;
     338           30 :         module_class->add_token_object = gkm_gnome2_module_real_add_token_object;
     339           30 :         module_class->store_token_object = gkm_gnome2_module_real_store_token_object;
     340           30 :         module_class->remove_token_object = gkm_gnome2_module_real_remove_token_object;
     341           30 :         module_class->login_user = gkm_gnome2_module_real_login_user;
     342           30 :         module_class->login_so = gkm_gnome2_module_real_login_so;
     343           30 :         module_class->logout_user = gkm_gnome2_module_real_logout_user;
     344           30 :         module_class->login_change = gkm_gnome2_module_real_login_change;
     345           30 : }
     346              : 
     347              : /* ----------------------------------------------------------------------------
     348              :  * PUBLIC
     349              :  */
     350              : 
     351              : CK_FUNCTION_LIST_PTR
     352           40 : gkm_gnome2_store_get_functions (void)
     353              : {
     354           40 :         gkm_crypto_initialize ();
     355           40 :         return gkm_gnome2_module_function_list;
     356              : }
     357              : 
     358              : GkmModule *
     359           12 : _gkm_gnome2_store_get_module_for_testing (void)
     360              : {
     361           12 :         return pkcs11_module;
     362              : }
        

Generated by: LCOV version 2.0-1