/*
* gnome-keyring
*
* Copyright (C) 2008 Stefan Walter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, see
* .
*/
#include "config.h"
#include "gkd-util.h"
#include "gkd-pkcs11.h"
#include "egg/egg-cleanup.h"
#include "pkcs11/wrap-layer/gkm-wrap-layer.h"
#include "pkcs11/rpc-layer/gkm-rpc-layer.h"
#include "pkcs11/secret-store/gkm-secret-store.h"
#include "pkcs11/ssh-store/gkm-ssh-store.h"
#include "pkcs11/gnome2-store/gkm-gnome2-store.h"
#include "pkcs11/xdg-store/gkm-xdg-store.h"
#include "ssh-agent/gkd-ssh-agent-service.h"
#include
/* The top level of our internal PKCS#11 module stack */
static CK_FUNCTION_LIST_PTR pkcs11_roof = NULL;
/* The top level of our internal PKCS#11 module stack, but below prompting */
static CK_FUNCTION_LIST_PTR pkcs11_base = NULL;
static void
pkcs11_daemon_cleanup (gpointer unused)
{
CK_RV rv;
g_assert (pkcs11_roof);
gkm_rpc_layer_uninitialize ();
rv = (pkcs11_roof->C_Finalize) (NULL);
if (rv != CKR_OK)
g_warning ("couldn't finalize internal PKCS#11 stack (code: %d)", (gint)rv);
pkcs11_roof = NULL;
}
gboolean
gkd_pkcs11_initialize (void)
{
CK_FUNCTION_LIST_PTR secret_store;
CK_FUNCTION_LIST_PTR ssh_store;
CK_FUNCTION_LIST_PTR gnome2_store;
CK_FUNCTION_LIST_PTR xdg_store;
CK_C_INITIALIZE_ARGS init_args;
CK_RV rv;
/* Secrets */
secret_store = gkm_secret_store_get_functions ();
/* SSH storage */
ssh_store = gkm_ssh_store_get_functions ();
/* Old User certificates */
gnome2_store = gkm_gnome2_store_get_functions ();
/* User certificates */
xdg_store = gkm_xdg_store_get_functions ();
/* Add all of those into the wrapper layer */
gkm_wrap_layer_add_module (ssh_store);
gkm_wrap_layer_add_module (secret_store);
gkm_wrap_layer_add_module (gnome2_store);
gkm_wrap_layer_add_module (xdg_store);
pkcs11_roof = gkm_wrap_layer_get_functions ();
pkcs11_base = gkm_wrap_layer_get_functions_no_prompts ();
memset (&init_args, 0, sizeof (init_args));
init_args.flags = CKF_OS_LOCKING_OK;
#if WITH_DEBUG
{
const gchar *path = g_getenv ("GNOME_KEYRING_TEST_PATH");
if (path && path[0])
init_args.pReserved = g_strdup_printf ("directory=\"%s\"", path);
}
#endif
/* Initialize the whole caboodle */
rv = (pkcs11_roof->C_Initialize) (&init_args);
g_free (init_args.pReserved);
if (rv != CKR_OK) {
g_warning ("couldn't initialize internal PKCS#11 stack (code: %d)", (gint)rv);
return FALSE;
}
egg_cleanup_register (pkcs11_daemon_cleanup, NULL);
return gkm_rpc_layer_initialize (pkcs11_roof);
}
static void
pkcs11_rpc_cleanup (gpointer unused)
{
gkm_rpc_layer_shutdown ();
}
static gboolean
accept_rpc_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
{
if (cond == G_IO_IN)
gkm_rpc_layer_accept ();
return TRUE;
}
gboolean
gkd_pkcs11_startup_pkcs11 (void)
{
GIOChannel *channel;
const gchar *base_dir;
int sock;
base_dir = gkd_util_get_master_directory ();
g_return_val_if_fail (base_dir, FALSE);
sock = gkm_rpc_layer_startup (base_dir);
if (sock == -1)
return FALSE;
channel = g_io_channel_unix_new (sock);
g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_rpc_client, NULL);
g_io_channel_unref (channel);
egg_cleanup_register (pkcs11_rpc_cleanup, NULL);
return TRUE;
}
CK_FUNCTION_LIST_PTR
gkd_pkcs11_get_functions (void)
{
return pkcs11_roof;
}
CK_FUNCTION_LIST_PTR
gkd_pkcs11_get_base_functions (void)
{
return pkcs11_base;
}