LCOV - code coverage report
Current view: top level - pkcs11/ssh-store - gkm-ssh-module.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.0 % 94 62
Test Date: 2024-09-14 11:48:09 Functions: 83.3 % 18 15

            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-ssh-module.h"
      24              : #include "gkm-ssh-private-key.h"
      25              : #include "gkm-ssh-public-key.h"
      26              : 
      27              : #include "egg/egg-error.h"
      28              : #include "egg/egg-file-tracker.h"
      29              : 
      30              : #include <string.h>
      31              : 
      32              : struct _GkmSshModule {
      33              :         GkmModule parent;
      34              :         EggFileTracker *tracker;
      35              :         gchar *directory;
      36              :         GHashTable *keys_by_path;
      37              : };
      38              : 
      39              : static const CK_SLOT_INFO gkm_ssh_module_slot_info = {
      40              :         "SSH Keys",
      41              :         "Gnome Keyring",
      42              :         CKF_TOKEN_PRESENT,
      43              :         { 0, 0 },
      44              :         { 0, 0 }
      45              : };
      46              : 
      47              : static const CK_TOKEN_INFO gkm_ssh_module_token_info = {
      48              :         "SSH Keys",
      49              :         "Gnome Keyring",
      50              :         "1.0",
      51              :         "1:SSH:HOME", /* Unique serial number for manufacturer */
      52              :         CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_LOGIN_REQUIRED,
      53              :         CK_EFFECTIVELY_INFINITE,
      54              :         CK_EFFECTIVELY_INFINITE,
      55              :         CK_EFFECTIVELY_INFINITE,
      56              :         CK_EFFECTIVELY_INFINITE,
      57              :         1024,
      58              :         1,
      59              :         CK_UNAVAILABLE_INFORMATION,
      60              :         CK_UNAVAILABLE_INFORMATION,
      61              :         CK_UNAVAILABLE_INFORMATION,
      62              :         CK_UNAVAILABLE_INFORMATION,
      63              :         { 0, 0 },
      64              :         { 0, 0 },
      65              :         ""
      66              : };
      67              : 
      68              : 
      69          247 : G_DEFINE_TYPE (GkmSshModule, gkm_ssh_module, GKM_TYPE_MODULE);
      70              : 
      71              : GkmModule*  _gkm_ssh_store_get_module_for_testing (void);
      72              : 
      73              : /* -----------------------------------------------------------------------------
      74              :  * ACTUAL PKCS#11 Module Implementation
      75              :  */
      76              : 
      77              : /* Include all the module entry points */
      78              : #include "gkm/gkm-module-ep.h"
      79           32 : GKM_DEFINE_MODULE (gkm_ssh_module, GKM_TYPE_SSH_MODULE);
      80              : 
      81              : /* -----------------------------------------------------------------------------
      82              :  * INTERNAL
      83              :  */
      84              : 
      85              : static gchar*
      86            0 : private_path_for_public (const gchar *public_path)
      87              : {
      88              :         gsize length;
      89              : 
      90            0 :         g_assert (public_path);
      91              : 
      92            0 :         length = strlen (public_path);
      93            0 :         if (length > 4 && g_str_equal (public_path + (length - 4), ".pub"))
      94            0 :                 return g_strndup (public_path, length - 4);
      95              : 
      96            0 :         return NULL;
      97              : }
      98              : 
      99              : static void
     100            0 : file_load (EggFileTracker *tracker,
     101              :            const gchar *path,
     102              :            GkmSshModule *self)
     103              : {
     104              :         GkmSshPrivateKey *key;
     105              :         gchar *private_path;
     106            0 :         GError *error = NULL;
     107              :         gchar *unique;
     108              : 
     109            0 :         g_return_if_fail (path);
     110            0 :         g_return_if_fail (GKM_IS_SSH_MODULE (self));
     111              : 
     112            0 :         private_path = private_path_for_public (path);
     113            0 :         if (!private_path || !g_file_test (private_path, G_FILE_TEST_IS_REGULAR)) {
     114            0 :                 g_message ("no private key present for public key: %s", path);
     115            0 :                 g_free (private_path);
     116            0 :                 return;
     117              :         }
     118              : 
     119              :         /* Create a key if necessary */
     120            0 :         key = g_hash_table_lookup (self->keys_by_path, path);
     121            0 :         if (key == NULL) {
     122            0 :                 unique = g_strdup_printf ("ssh-store:%s", private_path);
     123            0 :                 key = gkm_ssh_private_key_new (GKM_MODULE (self), unique);
     124            0 :                 g_free (unique);
     125              : 
     126            0 :                 g_hash_table_replace (self->keys_by_path, g_strdup (path), key);
     127              :         }
     128              : 
     129              :         /* Parse the data into the key */
     130            0 :         if (!gkm_ssh_private_key_parse (key, path, private_path, &error)) {
     131            0 :                 if (error) {
     132            0 :                         g_message ("couldn't parse data: %s: %s", path, egg_error_message (error));
     133            0 :                         g_clear_error (&error);
     134              :                 }
     135            0 :                 gkm_object_expose (GKM_OBJECT (key), FALSE);
     136              : 
     137              :         /* When successful register with the object manager */
     138              :         } else {
     139            0 :                 gkm_object_expose (GKM_OBJECT (key), TRUE);
     140              :         }
     141              : 
     142            0 :         g_free (private_path);
     143              : }
     144              : 
     145              : static void
     146            0 : file_remove (EggFileTracker *tracker,
     147              :              const gchar *path,
     148              :              GkmSshModule *self)
     149              : {
     150            0 :         g_return_if_fail (path);
     151            0 :         g_return_if_fail (GKM_IS_SSH_MODULE (self));
     152            0 :         g_hash_table_remove (self->keys_by_path, path);
     153              : }
     154              : 
     155              : 
     156              : /* -----------------------------------------------------------------------------
     157              :  * OBJECT
     158              :  */
     159              : 
     160              : static const CK_SLOT_INFO*
     161           66 : gkm_ssh_module_real_get_slot_info (GkmModule *self)
     162              : {
     163           66 :         return &gkm_ssh_module_slot_info;
     164              : }
     165              : 
     166              : static const CK_TOKEN_INFO*
     167           29 : gkm_ssh_module_real_get_token_info (GkmModule *self)
     168              : {
     169           29 :         return &gkm_ssh_module_token_info;
     170              : }
     171              : 
     172              : static void
     173           27 : gkm_ssh_module_real_parse_argument (GkmModule *base, const gchar *name, const gchar *value)
     174              : {
     175           27 :         GkmSshModule *self = GKM_SSH_MODULE (base);
     176           27 :         if (g_str_equal (name, "directory")) {
     177           27 :                 g_free (self->directory);
     178           27 :                 self->directory = g_strdup (value);
     179              :         }
     180           27 : }
     181              : 
     182              : static CK_RV
     183            4 : gkm_ssh_module_real_refresh_token (GkmModule *base)
     184              : {
     185            4 :         GkmSshModule *self = GKM_SSH_MODULE (base);
     186            4 :         egg_file_tracker_refresh (self->tracker, FALSE);
     187            4 :         return CKR_OK;
     188              : }
     189              : 
     190              : static GObject*
     191           32 : gkm_ssh_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
     192              : {
     193           32 :         GkmSshModule *self = GKM_SSH_MODULE (G_OBJECT_CLASS (gkm_ssh_module_parent_class)->constructor(type, n_props, props));
     194           32 :         g_return_val_if_fail (self, NULL);
     195              : 
     196           32 :         if (!self->directory)
     197            5 :                 self->directory = g_strdup ("~/.ssh");
     198           32 :         self->tracker = egg_file_tracker_new (self->directory, "*.pub", NULL);
     199           32 :         g_signal_connect (self->tracker, "file-added", G_CALLBACK (file_load), self);
     200           32 :         g_signal_connect (self->tracker, "file-changed", G_CALLBACK (file_load), self);
     201           32 :         g_signal_connect (self->tracker, "file-removed", G_CALLBACK (file_remove), self);
     202              : 
     203           32 :         return G_OBJECT (self);
     204              : }
     205              : 
     206              : static void
     207           32 : gkm_ssh_module_init (GkmSshModule *self)
     208              : {
     209           32 :         self->keys_by_path = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
     210           32 : }
     211              : 
     212              : static void
     213           64 : gkm_ssh_module_dispose (GObject *obj)
     214              : {
     215           64 :         GkmSshModule *self = GKM_SSH_MODULE (obj);
     216              : 
     217           64 :         if (self->tracker)
     218           32 :                 g_object_unref (self->tracker);
     219           64 :         self->tracker = NULL;
     220              : 
     221           64 :         g_hash_table_remove_all (self->keys_by_path);
     222              : 
     223           64 :         G_OBJECT_CLASS (gkm_ssh_module_parent_class)->dispose (obj);
     224           64 : }
     225              : 
     226              : static void
     227           32 : gkm_ssh_module_finalize (GObject *obj)
     228              : {
     229           32 :         GkmSshModule *self = GKM_SSH_MODULE (obj);
     230              : 
     231           32 :         g_assert (self->tracker == NULL);
     232              : 
     233           32 :         g_hash_table_destroy (self->keys_by_path);
     234           32 :         self->keys_by_path = NULL;
     235              : 
     236           32 :         g_free (self->directory);
     237           32 :         self->directory = NULL;
     238              : 
     239           32 :         G_OBJECT_CLASS (gkm_ssh_module_parent_class)->finalize (obj);
     240           32 : }
     241              : 
     242              : static void
     243           28 : gkm_ssh_module_class_init (GkmSshModuleClass *klass)
     244              : {
     245           28 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     246           28 :         GkmModuleClass *module_class = GKM_MODULE_CLASS (klass);
     247              : 
     248           28 :         gobject_class->constructor = gkm_ssh_module_constructor;
     249           28 :         gobject_class->dispose = gkm_ssh_module_dispose;
     250           28 :         gobject_class->finalize = gkm_ssh_module_finalize;
     251              : 
     252           28 :         module_class->get_slot_info = gkm_ssh_module_real_get_slot_info;
     253           28 :         module_class->get_token_info = gkm_ssh_module_real_get_token_info;
     254           28 :         module_class->parse_argument = gkm_ssh_module_real_parse_argument;
     255           28 :         module_class->refresh_token = gkm_ssh_module_real_refresh_token;
     256           28 : }
     257              : 
     258              : /* ----------------------------------------------------------------------------
     259              :  * PUBLIC
     260              :  */
     261              : 
     262              : CK_FUNCTION_LIST_PTR
     263           37 : gkm_ssh_store_get_functions (void)
     264              : {
     265           37 :         gkm_crypto_initialize ();
     266           37 :         return gkm_ssh_module_function_list;
     267              : }
     268              : 
     269              : GkmModule*
     270           10 : _gkm_ssh_store_get_module_for_testing (void)
     271              : {
     272           10 :         return pkcs11_module;
     273              : }
        

Generated by: LCOV version 2.0-1