[gnome-keyring] [gck] Add concept of PKCS#11 applications.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-keyring] [gck] Add concept of PKCS#11 applications.
- Date: Thu, 23 Jul 2009 20:00:35 +0000 (UTC)
commit 0275804640ccb2d64ab7f28fa23affdc3ba04420
Author: Stef Walter <stef memberwebs com>
Date: Thu Jul 23 19:59:25 2009 +0000
[gck] Add concept of PKCS#11 applications.
Remove VirtualSlot stuff and hide a lot of the apartment
stuff inside the module whenever possible.
pkcs11/gck/gck-module.c | 406 +++++++++++++++++++----------------
pkcs11/gck/gck-session.c | 27 ++-
pkcs11/gck/gck-session.h | 7 +-
pkcs11/pkcs11g.h | 5 +-
pkcs11/pkcs11i.h | 57 ++---
pkcs11/plex-layer/gck-plex-layer.c | 14 +-
pkcs11/rpc-layer/gck-rpc-dispatch.c | 71 ++++---
7 files changed, 315 insertions(+), 272 deletions(-)
---
diff --git a/pkcs11/gck/gck-module.c b/pkcs11/gck/gck-module.c
index 5b2d1e9..077af6b 100644
--- a/pkcs11/gck/gck-module.c
+++ b/pkcs11/gck/gck-module.c
@@ -48,11 +48,18 @@ enum {
PROP_MUTEX
};
+#define APARTMENT_APP(apt) \
+ ((apt) & ~CK_GNOME_MAX_SLOT)
+#define APARTMENT_SLOT(apt) \
+ ((apt) & CK_GNOME_MAX_SLOT)
+#define APARTMENT_ID(slot, app) \
+ (((slot) & CK_GNOME_MAX_SLOT) | ((app) & ~CK_GNOME_MAX_SLOT))
+
struct _GckModulePrivate {
GMutex *mutex; /* The mutex controlling entry to this module */
- GckManager *token_manager;
- GHashTable *virtual_slots_by_id; /* Various slot partitions by their ID */
+ GckManager *token_manager;
+ GHashTable *apartments_by_id; /* Apartment (slot + application) by their id */
GHashTable *sessions_by_handle; /* Mapping of handle to all open sessions */
gint handle_counter; /* Constantly incrementing counter for handles and the like */
GArray *factories; /* Various registered object factories */
@@ -62,12 +69,15 @@ struct _GckModulePrivate {
GckStore *transient_store; /* Store for trantsient objects. */
};
-typedef struct _VirtualSlot {
+typedef struct _Apartment {
+ CK_ULONG apt_id;
CK_SLOT_ID slot_id;
+ CK_G_APPLICATION_ID app_id;
+ CK_G_APPLICATION_PTR app_ptr;
GckManager *session_manager;
GList *sessions;
CK_USER_TYPE logged_in;
-} VirtualSlot;
+} Apartment;
/* Our slot identifier is 1 */
#define GCK_SLOT_ID 1
@@ -79,7 +89,7 @@ G_DEFINE_TYPE (GckModule, gck_module, G_TYPE_OBJECT);
static const CK_INFO default_module_info = {
{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
"Gnome Keyring",
- CKF_GNOME_APPARTMENTS,
+ CKF_G_APPLICATIONS,
"Gnome Keyring Module",
{ 1, 1 },
};
@@ -177,88 +187,100 @@ extend_space_string (CK_UTF8CHAR_PTR string, gsize length)
}
static void
-virtual_slot_free (gpointer data)
+apartment_free (gpointer data)
{
- VirtualSlot *slot;
+ Apartment *apt;
GList *l;
-
+
g_assert (data != NULL);
- slot = (VirtualSlot*)data;
-
- g_return_if_fail (GCK_IS_MANAGER (slot->session_manager));
-
+ apt = (Apartment*)data;
+
+ g_return_if_fail (GCK_IS_MANAGER (apt->session_manager));
+
/* Unreference all the sessions */
- for (l = slot->sessions; l; l = g_list_next (l)) {
-
+ for (l = apt->sessions; l; l = g_list_next (l)) {
+
/* Some sanity checks to make sure things have remained as expected */
g_return_if_fail (GCK_IS_SESSION (l->data));
- g_return_if_fail (gck_session_get_slot_id (l->data) == slot->slot_id);
- g_return_if_fail (gck_session_get_manager (l->data) == slot->session_manager);
- g_return_if_fail (gck_session_get_logged_in (l->data) == slot->logged_in);
-
+ g_return_if_fail (gck_session_get_apartment (l->data) == apt->apt_id);
+ g_return_if_fail (gck_session_get_manager (l->data) == apt->session_manager);
+ g_return_if_fail (gck_session_get_logged_in (l->data) == apt->logged_in);
+
g_object_unref (l->data);
}
-
- g_list_free (slot->sessions);
- g_object_unref (slot->session_manager);
-
- g_slice_free (VirtualSlot, slot);
+
+ g_list_free (apt->sessions);
+ g_object_unref (apt->session_manager);
+
+ g_slice_free (Apartment, apt);
}
-static VirtualSlot*
-virtual_slot_new (GckModuleClass *klass, CK_SLOT_ID slot_id)
+static Apartment*
+apartment_new (GckModuleClass *klass, CK_SLOT_ID slot_id, CK_G_APPLICATION_PTR app)
{
- VirtualSlot *slot;
+ Apartment *apt;
+
+ apt = g_slice_new0 (Apartment);
+ apt->session_manager = g_object_new (GCK_TYPE_MANAGER, "for-token", FALSE, NULL);
+ apt->logged_in = CKU_NONE;
+ apt->sessions = NULL;
+ apt->slot_id = slot_id;
+
+ if (app) {
+ if (!app->applicationId)
+ app->applicationId = gck_util_next_handle () << 8;
+ apt->app_id = app->applicationId;
+ apt->app_ptr = app;
+ } else {
+ apt->app_id = 0;
+ apt->app_ptr = NULL;
+ }
- slot = g_slice_new0 (VirtualSlot);
- slot->session_manager = g_object_new (GCK_TYPE_MANAGER, "for-token", FALSE, NULL);
- slot->logged_in = CKU_NONE;
- slot->sessions = NULL;
- slot->slot_id = slot_id;
-
- return slot;
+ apt->apt_id = APARTMENT_ID (apt->slot_id, apt->app_id);
+
+ return apt;
}
-static VirtualSlot*
-lookup_virtual_slot (GckModule *self, CK_SLOT_ID slot_id)
+static Apartment*
+lookup_apartment (GckModule *self, CK_ULONG apartment)
{
g_assert (GCK_IS_MODULE (self));
- return g_hash_table_lookup (self->pv->virtual_slots_by_id, &slot_id);
+ return g_hash_table_lookup (self->pv->apartments_by_id, &apartment);
}
static void
-register_virtual_slot (GckModule *self, VirtualSlot *slot)
+register_apartment (GckModule *self, Apartment *apt)
{
- g_assert (slot);
+ g_assert (apt);
g_assert (GCK_IS_MODULE (self));
- g_assert (!g_hash_table_lookup (self->pv->virtual_slots_by_id, &(slot->slot_id)));
-
- g_hash_table_insert (self->pv->virtual_slots_by_id,
- gck_util_ulong_alloc (slot->slot_id), slot);
+ g_assert (!g_hash_table_lookup (self->pv->apartments_by_id, &(apt->apt_id)));
+
+ g_hash_table_insert (self->pv->apartments_by_id,
+ gck_util_ulong_alloc (apt->apt_id), apt);
}
static void
-unregister_virtual_slot (GckModule *self, VirtualSlot *slot)
+unregister_apartment (GckModule *self, Apartment *apt)
{
- g_assert (slot);
+ g_assert (apt);
g_assert (GCK_IS_MODULE (self));
-
- if (!g_hash_table_remove (self->pv->virtual_slots_by_id, &(slot->slot_id)))
+
+ if (!g_hash_table_remove (self->pv->apartments_by_id, &(apt->apt_id)))
g_assert_not_reached ();
}
static void
-mark_login_virtual_slot (GckModule *self, VirtualSlot *slot, CK_USER_TYPE user)
+mark_login_apartment (GckModule *self, Apartment *apt, CK_USER_TYPE user)
{
GList *l;
- g_assert (slot);
+ g_assert (apt);
g_assert (GCK_IS_MODULE (self));
-
+
/* Mark all sessions in the partition as logged in */
- for (l = slot->sessions; l; l = g_list_next (l))
+ for (l = apt->sessions; l; l = g_list_next (l))
gck_session_set_logged_in (l->data, user);
- slot->logged_in = user;
+ apt->logged_in = user;
}
static void
@@ -464,43 +486,43 @@ gck_module_real_login_change (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_P
}
static CK_RV
-gck_module_real_login_user (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+gck_module_real_login_user (GckModule *self, CK_ULONG apartment, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
- VirtualSlot *slot;
-
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ Apartment *apt;
- mark_login_virtual_slot (self, slot, CKU_USER);
+ apt = lookup_apartment (self, apartment);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
+
+ mark_login_apartment (self, apt, CKU_USER);
return CKR_OK;
}
static CK_RV
-gck_module_real_login_so (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+gck_module_real_login_so (GckModule *self, CK_ULONG apartment, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
- VirtualSlot *slot;
-
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ Apartment *apt;
- mark_login_virtual_slot (self, slot, CKU_SO);
+ apt = lookup_apartment (self, apartment);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
+
+ mark_login_apartment (self, apt, CKU_SO);
return CKR_OK;
}
static CK_RV
-gck_module_real_logout_any (GckModule *self, CK_SLOT_ID slot_id)
+gck_module_real_logout_any (GckModule *self, CK_ULONG apartment)
{
- VirtualSlot *slot;
+ Apartment *apt;
/* Calculate the partition identifier */
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ apt = lookup_apartment (self, apartment);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
- mark_login_virtual_slot (self, slot, CKU_NONE);
+ mark_login_apartment (self, apt, CKU_NONE);
return CKR_OK;
}
-static GObject*
+static GObject*
gck_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
{
GckModule *self = GCK_MODULE (G_OBJECT_CLASS (gck_module_parent_class)->constructor(type, n_props, props));
@@ -524,14 +546,14 @@ gck_module_init (GckModule *self)
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_MODULE, GckModulePrivate);
self->pv->token_manager = g_object_new (GCK_TYPE_MANAGER, "for-token", TRUE, NULL);
- self->pv->sessions_by_handle = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal,
+ self->pv->sessions_by_handle = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal,
gck_util_ulong_free, g_object_unref);
- self->pv->virtual_slots_by_id = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal,
- gck_util_ulong_free, virtual_slot_free);
+ self->pv->apartments_by_id = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal,
+ gck_util_ulong_free, apartment_free);
self->pv->factories = g_array_new (FALSE, TRUE, sizeof (GckFactoryInfo));
-
+
g_atomic_int_set (&(self->pv->handle_counter), 1);
-
+
/* Create the store for transient objects */
self->pv->transient_store = GCK_STORE (gck_memory_store_new ());
self->pv->transient_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, gck_util_dispose_unref);
@@ -553,12 +575,12 @@ gck_module_dispose (GObject *obj)
if (self->pv->token_manager)
g_object_unref (self->pv->token_manager);
self->pv->token_manager = NULL;
-
- g_hash_table_remove_all (self->pv->virtual_slots_by_id);
+
+ g_hash_table_remove_all (self->pv->apartments_by_id);
g_hash_table_remove_all (self->pv->sessions_by_handle);
-
+
g_array_set_size (self->pv->factories, 0);
-
+
G_OBJECT_CLASS (gck_module_parent_class)->dispose (obj);
}
@@ -575,10 +597,10 @@ gck_module_finalize (GObject *obj)
g_assert (self->pv->token_manager == NULL);
- g_assert (g_hash_table_size (self->pv->virtual_slots_by_id) == 0);
- g_hash_table_destroy (self->pv->virtual_slots_by_id);
- self->pv->virtual_slots_by_id = NULL;
-
+ g_assert (g_hash_table_size (self->pv->apartments_by_id) == 0);
+ g_hash_table_destroy (self->pv->apartments_by_id);
+ self->pv->apartments_by_id = NULL;
+
g_assert (g_hash_table_size (self->pv->sessions_by_handle) == 0);
g_hash_table_destroy (self->pv->sessions_by_handle);
self->pv->sessions_by_handle = NULL;
@@ -908,9 +930,9 @@ gck_module_C_GetSlotList (GckModule *self, CK_BBOOL token_present, CK_SLOT_ID_PT
}
g_return_val_if_fail (slot_list, CKR_ARGUMENTS_BAD);
-
+
/* Answer C_GetSlotList with 0 for app */
- slot_list[0] = CK_GNOME_MAKE_APPARTMENT (GCK_SLOT_ID, 0);
+ slot_list[0] = GCK_SLOT_ID;
*count = 1;
return CKR_OK;
}
@@ -922,12 +944,12 @@ gck_module_C_GetSlotInfo (GckModule *self, CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
GckModuleClass *klass;
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (id != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
if (info == NULL)
return CKR_ARGUMENTS_BAD;
-
+
/* Any slot ID is valid for partitioned module */
klass = GCK_MODULE_GET_CLASS (self);
@@ -953,12 +975,12 @@ gck_module_C_GetTokenInfo (GckModule *self, CK_SLOT_ID id, CK_TOKEN_INFO_PTR inf
GckModuleClass *klass;
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (id != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
if (info == NULL)
return CKR_ARGUMENTS_BAD;
-
+
/* Any slot ID is valid for partitioned module */
klass = GCK_MODULE_GET_CLASS (self);
@@ -987,12 +1009,12 @@ gck_module_C_GetMechanismList (GckModule *self, CK_SLOT_ID id,
guint i;
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (id != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
if (count == NULL)
return CKR_ARGUMENTS_BAD;
-
+
/* Just want to get the count */
if (mech_list == NULL) {
*count = n_mechanisms;
@@ -1020,8 +1042,8 @@ gck_module_C_GetMechanismInfo (GckModule *self, CK_SLOT_ID id,
guint index;
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (id != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
if (info == NULL)
return CKR_ARGUMENTS_BAD;
@@ -1049,43 +1071,56 @@ CK_RV
gck_module_C_OpenSession (GckModule *self, CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data,
CK_NOTIFY callback, CK_SESSION_HANDLE_PTR result)
{
+ CK_G_APPLICATION_PTR app;
CK_SESSION_HANDLE handle;
- VirtualSlot *slot;
gboolean read_only;
GckSession *session;
-
+ Apartment *apt = NULL;
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (APARTMENT_SLOT (id) != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
if (!result)
return CKR_ARGUMENTS_BAD;
-
+
if (!(flags & CKF_SERIAL_SESSION))
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
- /* Lookup or register the virtual slot */
- slot = lookup_virtual_slot (self, id);
- if (slot == NULL) {
- slot = virtual_slot_new (GCK_MODULE_GET_CLASS (self), id);
- register_virtual_slot (self, slot);
+ /*
+ * If they're calling us with the 'application' extension, then
+ * allocate or use our application identifier.
+ */
+ if (flags & CKF_G_APPLICATION_SESSION) {
+ app = user_data;
+ if (app->applicationId)
+ apt = lookup_apartment (self, APARTMENT_ID (id, app->applicationId));
+ } else {
+ app = NULL;
+ apt = lookup_apartment (self, APARTMENT_ID (id, 0));
+ }
+
+ /* The first time this application is accessing, or closed all sessions, allocate new */
+ if (apt == NULL) {
+ apt = apartment_new (GCK_MODULE_GET_CLASS (self), id, app);
+ register_apartment (self, apt);
}
-
+
/* Can't open read only session if SO login */
- if (slot->logged_in == CKU_SO && !(flags & CKF_RW_SESSION))
- return CKR_SESSION_READ_WRITE_SO_EXISTS;
+ if (apt->logged_in == CKU_SO && !(flags & CKF_RW_SESSION))
+ return CKR_SESSION_READ_WRITE_SO_EXISTS;
/* Make and register a new session */
handle = gck_module_next_handle (self);
read_only = !(flags & CKF_RW_SESSION);
- session = g_object_new (GCK_TYPE_SESSION, "slot-id", slot->slot_id,
- "read-only", read_only, "handle", handle, "module", self,
- "manager", slot->session_manager, "logged-in", slot->logged_in, NULL);
- slot->sessions = g_list_prepend (slot->sessions, session);
-
+ session = g_object_new (GCK_TYPE_SESSION, "slot-id", apt->slot_id, "apartment", apt->apt_id,
+ "read-only", read_only, "handle", handle, "module", self,
+ "manager", apt->session_manager, "logged-in", apt->logged_in, NULL);
+ apt->sessions = g_list_prepend (apt->sessions, session);
+
/* Track the session by handle */
- g_hash_table_insert (self->pv->sessions_by_handle,
- gck_util_ulong_alloc (handle),
+ g_hash_table_insert (self->pv->sessions_by_handle,
+ gck_util_ulong_alloc (handle),
g_object_ref (session));
*result = handle;
@@ -1096,60 +1131,59 @@ CK_RV
gck_module_C_CloseSession (GckModule *self, CK_SESSION_HANDLE handle)
{
GckSession *session;
- CK_SLOT_ID slot_id;
- VirtualSlot *slot;
+ CK_ULONG apt_id;
+ Apartment *apt;
GList *link;
-
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
+
session = gck_module_lookup_session (self, handle);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
/* Calculate the virtual slot */
- slot_id = gck_session_get_slot_id (session);
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ apt_id = gck_session_get_apartment (session);
+ apt = lookup_apartment (self, apt_id);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
- link = g_list_find (slot->sessions, session);
+ link = g_list_find (apt->sessions, session);
g_return_val_if_fail (link, CKR_GENERAL_ERROR);
- slot->sessions = g_list_delete_link (slot->sessions, link);
+ apt->sessions = g_list_delete_link (apt->sessions, link);
g_object_unref (session);
- if (!slot->sessions)
- unregister_virtual_slot (self, slot);
+ if (!apt->sessions)
+ unregister_apartment (self, apt);
if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle))
g_assert_not_reached ();
-
+
return CKR_OK;
}
CK_RV
gck_module_C_CloseAllSessions (GckModule *self, CK_SLOT_ID id)
{
- VirtualSlot *slot;
+ Apartment *apt;
CK_SESSION_HANDLE handle;
GList *l;
-
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
- if (CK_GNOME_APPARTMENT_SLOT (id) != GCK_SLOT_ID)
+
+ if (APARTMENT_SLOT (id) != GCK_SLOT_ID)
return CKR_SLOT_ID_INVALID;
- /* Calculate the virtual slot */
- slot = lookup_virtual_slot (self, id);
- if (slot == NULL)
+ apt = lookup_apartment (self, id);
+ if (apt == NULL)
return CKR_OK;
-
+
/* Unregister all its sessions */
- for (l = slot->sessions; l; l = g_list_next (l)) {
+ for (l = apt->sessions; l; l = g_list_next (l)) {
handle = gck_session_get_handle (l->data);
if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle))
g_assert_not_reached ();
}
- unregister_virtual_slot (self, slot);
- return CKR_OK;
+ unregister_apartment (self, apt);
+ return CKR_OK;
}
CK_RV
@@ -1157,25 +1191,25 @@ gck_module_C_InitPIN (GckModule* self, CK_SESSION_HANDLE handle,
CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
GckSession *session;
- VirtualSlot *slot;
- CK_SLOT_ID slot_id;
-
+ Apartment *apt;
+ CK_ULONG apt_id;
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
+
session = gck_module_lookup_session (self, handle);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
-
+
/* Calculate the virtual slot */
- slot_id = gck_session_get_slot_id (session);
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
-
- if (slot->logged_in != CKU_SO)
+ apt_id = gck_session_get_apartment (session);
+ apt = lookup_apartment (self, apt_id);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
+
+ if (apt->logged_in != CKU_SO)
return CKR_USER_NOT_LOGGED_IN;
/* Our InitPIN assumes an uninitialized PIN */
- return gck_module_login_change (self, slot_id, NULL, 0, pin, n_pin);
+ return gck_module_login_change (self, apt_id, NULL, 0, pin, n_pin);
}
CK_RV
@@ -1183,34 +1217,34 @@ gck_module_C_SetPIN (GckModule* self, CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR
CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len)
{
GckSession *session;
- VirtualSlot *slot;
- CK_SLOT_ID slot_id;
-
+ Apartment *apt;
+ CK_ULONG apt_id;
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
+
session = gck_module_lookup_session (self, handle);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
/* Calculate the virtual slot */
- slot_id = gck_session_get_slot_id (session);
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ apt_id = gck_session_get_apartment (session);
+ apt = lookup_apartment (self, apt_id);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
- return gck_module_login_change (self, slot_id, old_pin, old_pin_len, new_pin, new_pin_len);
+ return gck_module_login_change (self, apt_id, old_pin, old_pin_len, new_pin, new_pin_len);
}
CK_RV
gck_module_C_Login (GckModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
{
- CK_SLOT_ID slot_id;
+ CK_ULONG apt_id;
GckSession *session;
- VirtualSlot *slot;
+ Apartment *apt;
GList *l;
-
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
+
session = gck_module_lookup_session (self, handle);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
@@ -1224,26 +1258,26 @@ gck_module_C_Login (GckModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user
return CKR_USER_TYPE_INVALID;
/* Calculate the virtual slot */
- slot_id = gck_session_get_slot_id (session);
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ apt_id = gck_session_get_apartment (session);
+ apt = lookup_apartment (self, apt_id);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
- if (slot->logged_in != CKU_NONE)
+ if (apt->logged_in != CKU_NONE)
return CKR_USER_ALREADY_LOGGED_IN;
if (user_type == CKU_SO) {
-
+
/* Can't login as SO if read-only sessions exist */
- for (l = slot->sessions; l; l = g_list_next (l)) {
+ for (l = apt->sessions; l; l = g_list_next (l)) {
if (gck_session_get_read_only (l->data))
return CKR_SESSION_READ_ONLY_EXISTS;
}
-
- return gck_module_login_so (self, slot_id, pin, pin_len);
-
+
+ return gck_module_login_so (self, apt_id, pin, pin_len);
+
} else if (user_type == CKU_USER) {
- return gck_module_login_user (self, slot_id, pin, pin_len);
-
+ return gck_module_login_user (self, apt_id, pin, pin_len);
+
} else {
return CKR_USER_TYPE_INVALID;
}
@@ -1252,29 +1286,29 @@ gck_module_C_Login (GckModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user
CK_RV
gck_module_C_Logout (GckModule *self, CK_SESSION_HANDLE handle)
{
- CK_SLOT_ID slot_id;
- VirtualSlot *slot;
+ CK_ULONG apt_id;
+ Apartment *apt;
GckSession *session;
-
+
g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
-
+
session = gck_module_lookup_session (self, handle);
if (session == NULL)
return CKR_SESSION_HANDLE_INVALID;
- slot_id = gck_session_get_slot_id (session);
- slot = lookup_virtual_slot (self, slot_id);
- g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+ apt_id = gck_session_get_apartment (session);
+ apt = lookup_apartment (self, apt_id);
+ g_return_val_if_fail (apt, CKR_GENERAL_ERROR);
- if (slot->logged_in == CKU_NONE)
+ if (apt->logged_in == CKU_NONE)
return CKR_USER_NOT_LOGGED_IN;
-
- else if (slot->logged_in == CKU_USER)
- return gck_module_logout_user (self, slot_id);
- else if (slot->logged_in == CKU_SO)
- return gck_module_logout_so (self, slot_id);
+ else if (apt->logged_in == CKU_USER)
+ return gck_module_logout_user (self, apt_id);
- else
+ else if (apt->logged_in == CKU_SO)
+ return gck_module_logout_so (self, apt_id);
+
+ else
g_return_val_if_reached (CKR_GENERAL_ERROR);
}
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index 1cfcf27..68a2a40 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -40,6 +40,7 @@ enum {
PROP_0,
PROP_MODULE,
PROP_SLOT_ID,
+ PROP_APARTMENT,
PROP_HANDLE,
PROP_READ_ONLY,
PROP_MANAGER,
@@ -50,7 +51,8 @@ struct _GckSessionPrivate {
CK_SESSION_HANDLE handle;
CK_SLOT_ID slot_id;
-
+ CK_ULONG apartment;
+
GckModule *module;
GckManager *manager;
GckStore *store;
@@ -478,6 +480,9 @@ gck_session_set_property (GObject *obj, guint prop_id, const GValue *value,
case PROP_SLOT_ID:
self->pv->slot_id = g_value_get_ulong (value);
break;
+ case PROP_APARTMENT:
+ self->pv->apartment = g_value_get_ulong (value);
+ break;
case PROP_HANDLE:
self->pv->handle = g_value_get_ulong (value);
g_return_if_fail (self->pv->handle != 0);
@@ -510,6 +515,9 @@ gck_session_get_property (GObject *obj, guint prop_id, GValue *value,
case PROP_SLOT_ID:
g_value_set_ulong (value, gck_session_get_slot_id (self));
break;
+ case PROP_APARTMENT:
+ g_value_set_ulong (value, gck_session_get_apartment (self));
+ break;
case PROP_HANDLE:
g_value_set_ulong (value, gck_session_get_handle (self));
break;
@@ -554,11 +562,15 @@ gck_session_class_init (GckSessionClass *klass)
g_object_class_install_property (gobject_class, PROP_SLOT_ID,
g_param_spec_ulong ("slot-id", "Slot ID", "Slot ID this session is opened on",
0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
+
+ g_object_class_install_property (gobject_class, PROP_APARTMENT,
+ g_param_spec_ulong ("apartment", "Apartment", "Apartment this session is opened on",
+ 0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
g_object_class_install_property (gobject_class, PROP_READ_ONLY,
- g_param_spec_boolean ("read-only", "Read Only", "Whether a read-only session or not",
+ g_param_spec_boolean ("read-only", "Read Only", "Whether a read-only session or not",
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
+
g_object_class_install_property (gobject_class, PROP_LOGGED_IN,
g_param_spec_ulong ("logged-in", "Logged in", "Whether this session is logged in or not",
0, G_MAXULONG, CKU_NONE, G_PARAM_READWRITE));
@@ -589,6 +601,13 @@ gck_session_get_slot_id (GckSession *self)
return self->pv->slot_id;
}
+CK_ULONG
+gck_session_get_apartment (GckSession *self)
+{
+ g_return_val_if_fail (GCK_IS_SESSION (self), 0);
+ return self->pv->apartment;
+}
+
GckModule*
gck_session_get_module (GckSession *self)
{
diff --git a/pkcs11/gck/gck-session.h b/pkcs11/gck/gck-session.h
index 3e73780..08d8fba 100644
--- a/pkcs11/gck/gck-session.h
+++ b/pkcs11/gck/gck-session.h
@@ -58,17 +58,14 @@ typedef gboolean (*GckAuthenticatorFunc) (GckAuth
GType gck_session_get_type (void);
-GckSession* gck_session_new (GckModule *module,
- GckManager *manager,
- CK_SLOT_ID slot_id,
- CK_FLAGS flags);
-
GckSession* gck_session_for_session_object (GckObject *obj);
CK_SESSION_HANDLE gck_session_get_handle (GckSession *self);
CK_SLOT_ID gck_session_get_slot_id (GckSession *self);
+CK_ULONG gck_session_get_apartment (GckSession *self);
+
GckModule* gck_session_get_module (GckSession *self);
GckManager* gck_session_get_manager (GckSession *self);
diff --git a/pkcs11/pkcs11g.h b/pkcs11/pkcs11g.h
index 335162b..e71d5a5 100644
--- a/pkcs11/pkcs11g.h
+++ b/pkcs11/pkcs11g.h
@@ -26,8 +26,9 @@
#include "pkcs11.h"
-#define CKA_GNOME (CKA_VENDOR_DEFINED | 0x474E4D45 /* GNME */ )
-#define CKO_GNOME (CKO_VENDOR_DEFINED | 0x474E4D45 /* GNME */ )
+#define CKA_GNOME (CKA_VENDOR_DEFINED | 0x474E4D45 /* GNME */ )
+#define CKO_GNOME (CKO_VENDOR_DEFINED | 0x474E4D45 /* GNME */ )
+#define CKR_GNOME (CKR_VENDOR_DEFINED | 0x474E4D45 /* GNME */ )
/* -------------------------------------------------------------------
* OBJECT UNIQUE IDENTIFIER
diff --git a/pkcs11/pkcs11i.h b/pkcs11/pkcs11i.h
index df6e336..6d3cb7f 100644
--- a/pkcs11/pkcs11i.h
+++ b/pkcs11/pkcs11i.h
@@ -30,50 +30,37 @@
/* Signifies that nobody is logged in */
#define CKU_NONE G_MAXULONG
-/* ----------------------------------------------------------------------
- * APARTMENT SLOTS
- *
- * The lower 10 bits of the CK_SLOT_ID are used as the actual slot identifier,
- * and the remainder are used as application identifiers.
- *
- * This enables a single loaded module to serve multiple applications
- * concurrently. The caller of a module should check the
- * CKF_GNOME_VIRTUAL_SLOTS flag before using this functionality.
- */
+#define CK_GNOME_MAX_SLOT (0x000000FF)
+#define CK_GNOME_MAX_HANDLE (((CK_ULONG)-1) >> 10)
-/* Flag for CK_INFO when virtual slots are supported */
-#define CKF_GNOME_APPARTMENTS 0x40000000
+/* -------------------------------------------------------------------
+ * OBJECT HASH
+ */
-/* Get an actual slot id from a virtual slot */
-#define CK_GNOME_APPARTMENT_SLOT(virt) ((virt) & 0x000003FF)
+#define CKA_GNOME_INTERNAL_SHA1 (CKA_GNOME + 1000)
-/* Get an app id from a virtual slot */
-#define CK_GNOME_APPARTMENT_APP(virt) ((virt) >> 10)
-/* Is the app id valid for use in a virtual slot? */
-#define CK_GNOME_APPARTMENT_IS_APP(app) ((app) < (((CK_ULONG)-1) >> 10))
+/* -------------------------------------------------------------------
+ * APPLICATION
+ */
-/* Build a virtual slot from an actual slot id, and an app id */
-#define CK_GNOME_MAKE_APPARTMENT(slot, app) (((slot) & 0x000003FF) | ((app) << 10))
+/* Flag for CK_INFO when applications are supported */
+#define CKF_G_APPLICATIONS 0x40000000
+/* Call C_OpenSession with this when passing CK_G_APPLICATION */
+#define CKF_G_APPLICATION_SESSION 0x40000000
-/* -------------------------------------------------------------------
- * LIMITED HANDLES
- *
- * The upper 10 bits of a CK_SESSION_HANDLE and CK_OBJECT_HANDLE are
- * never used by Gnome Keyring PKCS#11 modules. These bits are used
- * for tracking purposes when combining modules into a single module.
- */
-
-#define CK_GNOME_MAX_SLOT (0x000003FF)
-#define CK_GNOME_MAX_APP (((CK_ULONG)-1) >> 10)
-#define CK_GNOME_MAX_HANDLE (((CK_ULONG)-1) >> 10)
+typedef CK_ULONG CK_G_APPLICATION_ID;
-/* -------------------------------------------------------------------
- * OBJECT HASH
- */
+typedef struct CK_G_APPLICATION {
+ CK_UTF8CHAR applicationName;
+ CK_VOID_PTR applicationData;
+ CK_FLAGS flags;
+ CK_G_APPLICATION_ID applicationId;
+} CK_G_APPLICATION;
-#define CKA_GNOME_INTERNAL_SHA1 (CKA_GNOME + 1000)
+typedef CK_G_APPLICATION* CK_G_APPLICATION_PTR;
+#define CKR_G_APPLICATION_ID_INVALID (CKR_GNOME + 10)
#endif /* PKCS11I_H */
diff --git a/pkcs11/plex-layer/gck-plex-layer.c b/pkcs11/plex-layer/gck-plex-layer.c
index 67ddefb..db221e7 100644
--- a/pkcs11/plex-layer/gck-plex-layer.c
+++ b/pkcs11/plex-layer/gck-plex-layer.c
@@ -58,9 +58,9 @@ static guint n_plex_mappings = 0;
static gboolean
map_slot_down (CK_SLOT_ID_PTR slot, Mapping *mapping)
{
- CK_SLOT_ID id = CK_GNOME_APPARTMENT_SLOT (*slot);
+ CK_SLOT_ID id = *slot;
gboolean ret = TRUE;
-
+
if (id < PLEX_MAPPING_OFFSET)
return FALSE;
id -= PLEX_MAPPING_OFFSET;
@@ -73,9 +73,9 @@ map_slot_down (CK_SLOT_ID_PTR slot, Mapping *mapping)
ret = FALSE;
} else {
memcpy (mapping, &plex_mappings[id], sizeof (Mapping));
- *slot = CK_GNOME_MAKE_APPARTMENT(mapping->real_slot, CK_GNOME_APPARTMENT_APP (*slot));
+ *slot = mapping->real_slot;
}
-
+
G_UNLOCK (plex_layer);
return ret;
@@ -207,7 +207,7 @@ plex_C_GetInfo (CK_INFO_PTR info)
info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
info->libraryVersion.major = LIBRARY_VERSION_MAJOR;
info->libraryVersion.minor = LIBRARY_VERSION_MINOR;
- info->flags = CKF_GNOME_APPARTMENTS;
+ info->flags = 0;
strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
strncpy ((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32);
return CKR_OK;
@@ -346,8 +346,10 @@ static CK_RV
plex_C_CloseAllSessions (CK_SLOT_ID id)
{
Mapping map;
+ CK_G_APPLICATION_ID app = id & ~CK_GNOME_MAX_SLOT;
+ id = id & CK_GNOME_MAX_SLOT;
MAP_SLOT_DOWN (id, map);
- return (map.funcs->C_CloseAllSessions) (id);
+ return (map.funcs->C_CloseAllSessions) (id | app);
}
static CK_RV
diff --git a/pkcs11/rpc-layer/gck-rpc-dispatch.c b/pkcs11/rpc-layer/gck-rpc-dispatch.c
index 45587ca..ae722d3 100644
--- a/pkcs11/rpc-layer/gck-rpc-dispatch.c
+++ b/pkcs11/rpc-layer/gck-rpc-dispatch.c
@@ -82,7 +82,7 @@ typedef struct _CallState {
GckRpcMessage *req;
GckRpcMessage *resp;
void *allocated;
- CK_ULONG appid;
+ CK_G_APPLICATION application;
} CallState;
static int
@@ -97,7 +97,10 @@ call_init (CallState *cs)
gck_rpc_message_free (cs->resp);
return 0;
}
-
+
+ memset (&cs->application, 0, sizeof (cs->application));
+ cs->application.applicationData = cs;
+
cs->allocated = NULL;
return 1;
}
@@ -780,9 +783,8 @@ rpc_C_Finalize (CallState *cs)
{
CK_SLOT_ID_PTR slots;
CK_ULONG n_slots, i;
- CK_SLOT_ID appartment;
CK_RV ret;
-
+
debug (("C_Finalize: enter"));
assert (cs);
@@ -792,26 +794,26 @@ rpc_C_Finalize (CallState *cs)
* We don't actually C_Finalize lower layers, since this would finalize
* for all appartments, client applications. Anyway this is done by
* the code that loaded us.
- *
+ *
* But we do need to cleanup resources used by this client, so instead
- * we call C_CloseAllSessions for each appartment for this client.
+ * we call C_CloseAllSessions for each slot for this client application.
*/
-
- ret = (pkcs11_module->C_GetSlotList) (TRUE, NULL, &n_slots);
- if (ret == CKR_OK) {
- slots = calloc (n_slots, sizeof (CK_SLOT_ID));
- if (slots == NULL) {
- ret = CKR_DEVICE_MEMORY;
- } else {
- ret = (pkcs11_module->C_GetSlotList) (TRUE, slots, &n_slots);
- for (i = 0; ret == CKR_OK && i < n_slots; ++i) {
- appartment = CK_GNOME_MAKE_APPARTMENT (slots[i], cs->appid);
- ret = (pkcs11_module->C_CloseAllSessions) (appartment);
+
+ if (cs->application.applicationId) {
+ ret = (pkcs11_module->C_GetSlotList) (TRUE, NULL, &n_slots);
+ if (ret == CKR_OK) {
+ slots = calloc (n_slots, sizeof (CK_SLOT_ID));
+ if (slots == NULL) {
+ ret = CKR_DEVICE_MEMORY;
+ } else {
+ ret = (pkcs11_module->C_GetSlotList) (TRUE, slots, &n_slots);
+ for (i = 0; ret == CKR_OK && i < n_slots; ++i)
+ ret = (pkcs11_module->C_CloseAllSessions) (slots[i] | cs->application.applicationId);
+ free (slots);
}
- free (slots);
}
}
-
+
debug (("ret: %d", ret));
return ret;
}
@@ -852,7 +854,6 @@ rpc_C_GetSlotInfo (CallState *cs)
BEGIN_CALL (C_GetSlotInfo);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
PROCESS_CALL ((slot_id, &info));
OUT_SLOT_INFO (info);
END_CALL;
@@ -868,7 +869,6 @@ rpc_C_GetTokenInfo (CallState *cs)
BEGIN_CALL (C_GetTokenInfo);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
PROCESS_CALL ((slot_id, &info));
OUT_TOKEN_INFO (info);
END_CALL;
@@ -885,7 +885,6 @@ rpc_C_GetMechanismList (CallState *cs)
BEGIN_CALL (C_GetMechanismList);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
IN_ULONG_BUFFER (mechanism_list, count);
PROCESS_CALL ((slot_id, mechanism_list, &count));
OUT_ULONG_ARRAY (mechanism_list, count);
@@ -903,7 +902,6 @@ rpc_C_GetMechanismInfo (CallState *cs)
BEGIN_CALL (C_GetMechanismInfo);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
IN_ULONG (type);
PROCESS_CALL ((slot_id, type, &info));
OUT_MECHANISM_INFO (info);
@@ -922,7 +920,6 @@ rpc_C_InitToken (CallState *cs)
BEGIN_CALL (C_InitToken);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
IN_BYTE_ARRAY (pin, pin_len);
IN_STRING (label);
PROCESS_CALL ((slot_id, pin, pin_len, label));
@@ -940,7 +937,6 @@ rpc_C_WaitForSlotEvent (CallState *cs)
BEGIN_CALL (C_WaitForSlotEvent);
IN_ULONG (flags);
PROCESS_CALL ((flags, &slot_id, NULL));
- slot_id = CK_GNOME_APPARTMENT_SLOT (slot_id);
OUT_ULONG (slot_id);
END_CALL;
}
@@ -956,9 +952,9 @@ rpc_C_OpenSession (CallState *cs)
BEGIN_CALL (C_OpenSession);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
IN_ULONG (flags);
- PROCESS_CALL ((slot_id, flags, NULL, NULL, &session));
+ flags |= CKF_G_APPLICATION_SESSION;
+ PROCESS_CALL ((slot_id, flags, &cs->application, NULL, &session));
OUT_ULONG (session);
END_CALL;
}
@@ -984,7 +980,7 @@ rpc_C_CloseAllSessions (CallState *cs)
BEGIN_CALL (C_CloseAllSessions);
IN_ULONG (slot_id);
- slot_id = CK_GNOME_MAKE_APPARTMENT (slot_id, cs->appid);
+ slot_id |= cs->application.applicationId;
PROCESS_CALL ((slot_id));
END_CALL;
}
@@ -1022,7 +1018,6 @@ rpc_C_GetSessionInfo (CallState *cs)
BEGIN_CALL (C_GetSessionInfo);
IN_ULONG (session);
PROCESS_CALL ((session, &info));
- info.slotID = CK_GNOME_APPARTMENT_SLOT (info.slotID);
OUT_SESSION_INFO (info);
END_CALL;
}
@@ -2089,10 +2084,7 @@ run_dispatch_loop (int sock)
gck_rpc_warn ("couldn't read socket credentials");
return;
}
-
- /* The client application */
- cs.appid = pid;
-
+
/* Setup our buffers */
if (!call_init (&cs)) {
gck_rpc_warn ("out of memory");
@@ -2141,7 +2133,18 @@ run_dispatch_loop (int sock)
!write_all (sock, cs.resp->buffer.buf, cs.resp->buffer.len))
break;
}
-
+
+ /*
+ * Close all sessions for the client application
+ *
+ * EXTENSION: In our extended application PKCS#11 model
+ * C_CloseAllSessions accepts an application identifier as well
+ * as slot ids. Calling with an application identifier closes all
+ * sessions for just that application identifier.
+ */
+ if (cs.application.applicationId)
+ (pkcs11_module->C_CloseAllSessions) (cs.application.applicationId);
+
call_uninit (&cs);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]