[gnome-keyring] [gck] Add concept of PKCS#11 applications.



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]