File ocki-3.2_05_icsf_ldap_handles.patch of Package openCryptoki.2906

diff --git a/usr/lib/pkcs11/cca_stdll/tok_struct.h b/usr/lib/pkcs11/cca_stdll/tok_struct.h
index d3c23ac..68f047d 100644
--- a/usr/lib/pkcs11/cca_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/cca_stdll/tok_struct.h
@@ -159,7 +159,8 @@ token_spec_t token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	&token_specific_object_add
+	&token_specific_object_add,
+	NULL
 };
 
 #endif
diff --git a/usr/lib/pkcs11/common/new_host.c b/usr/lib/pkcs11/common/new_host.c
index b123e5f..c65fc4a 100755
--- a/usr/lib/pkcs11/common/new_host.c
+++ b/usr/lib/pkcs11/common/new_host.c
@@ -1343,7 +1343,13 @@ CK_RV SC_CloseAllSessions( CK_SLOT_ID  sid )
 	rc = session_mgr_close_all_sessions();
 	if (rc != CKR_OK){
 		OCK_LOG_ERR(ERR_SESSION_CLOSEALL);
+	} else {
+		if (token_specific.t_closeallsessions != NULL) {
+			rc = token_specific.t_closeallsessions();
+			OCK_LOG_ERR("Token specific closeallsessions failed\n");
+		}
 	}
+
  done:
 	LLOCK;
 	OCK_LOG_DEBUG("%s:  rc = 0x%08x  slot = %d\n", "C_CloseAllSessions", rc, slot_id );
diff --git a/usr/lib/pkcs11/common/tok_spec_struct.h b/usr/lib/pkcs11/common/tok_spec_struct.h
index 5d43511..1fc792a 100755
--- a/usr/lib/pkcs11/common/tok_spec_struct.h
+++ b/usr/lib/pkcs11/common/tok_spec_struct.h
@@ -589,7 +589,7 @@ struct token_specific_struct {
 				      CK_MECHANISM_INFO_PTR);
 
 	CK_RV (*t_object_add)(OBJECT *);
-
+	CK_RV (*t_closeallsessions)();
 };
 
 typedef struct token_specific_struct token_spec_t;
diff --git a/usr/lib/pkcs11/ep11_stdll/tok_struct.h b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
index b79fe0c..b39139c 100644
--- a/usr/lib/pkcs11/ep11_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
@@ -433,6 +433,7 @@ token_spec_t token_specific = {
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
         &token_specific_object_add,
+	NULL
 };
 
 #endif
diff --git a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
index f186b53..c422787 100644
--- a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
@@ -426,7 +426,8 @@ token_spec_t token_specific = {
 	NULL,		// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+	NULL
 };
 
 #endif
diff --git a/usr/lib/pkcs11/icsf_stdll/icsf_specific.c b/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
index 397df28..528242e 100644
--- a/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
+++ b/usr/lib/pkcs11/icsf_stdll/icsf_specific.c
@@ -905,9 +905,78 @@ token_specific_set_pin(SESSION *sess, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen,
 	return rc;
 }
 
+LDAP *getLDAPhandle(CK_SLOT_ID slot_id)
+{
+	CK_BYTE racfpwd[PIN_SIZE];
+	int racflen;
+	char *ca_dir = NULL;
+	LDAP *new_ld = NULL;
+	CK_RV rc = CKR_OK;
+
+	if (slot_data[slot_id] == NULL) {
+		OCK_LOG_DEBUG("ICSF slot data not initialized.\n");
+		return NULL;
+	}
+	/* Check if using sasl or simple auth */
+	if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) {
+		OCK_LOG_DEBUG("Using SIMPLE auth with slot ID: %lu\n", slot_id);
+		/* get racf passwd */
+		rc = get_racf(master_key, AES_KEY_SIZE_256, racfpwd, &racflen);
+		if (rc != CKR_OK) {
+			OCK_LOG_DEBUG("Failed to get racf passwd.\n");
+			return NULL;
+		}
+
+		/* ok got the passwd, perform simple ldap bind call */
+		rc = icsf_login(&new_ld, slot_data[slot_id]->uri,
+		slot_data[slot_id]->dn, racfpwd);
+		if (rc != CKR_OK) {
+			OCK_LOG_DEBUG("Failed to bind to ldap server.\n");
+			return NULL;
+		}
+	} else {
+		OCK_LOG_DEBUG("Using SASL auth with slot ID: %lu\n", slot_id);
+		rc = icsf_sasl_login(&new_ld, slot_data[slot_id]->uri,
+				     slot_data[slot_id]->cert_file,
+				     slot_data[slot_id]->key_file,
+				     slot_data[slot_id]->ca_file, ca_dir);
+		if (rc != CKR_OK) {
+			OCK_LOG_DEBUG("Failed to bind to ldap server.\n");
+			return NULL;
+		}
+	}
+
+	return new_ld;
+}
+
+CK_RV icsf_get_handles(CK_SLOT_ID slot_id)
+{
+	struct session_state *s;
+
+	/* Any prior sessions without an ldap descriptor, can now get one. */
+	/* Lock sessions list */
+	if (pthread_mutex_lock(&sess_list_mutex)) {
+		OCK_LOG_DEBUG("Failed to lock mutex.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+
+	for_each_list_entry(&sessions, struct session_state, s, sessions) {
+		if (s->ld == NULL)
+			s->ld = getLDAPhandle(slot_id);
+	}
+
+	if (pthread_mutex_unlock(&sess_list_mutex)) {
+		OCK_LOG_DEBUG("Mutex Unlock failed.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+	return CKR_OK;
+}
+
 CK_RV
 token_specific_open_session(SESSION *sess)
 {
+	CK_RV rc = CKR_OK;
+	LDAP *ld;
 	struct session_state *session_state;
 
 	/* Add session to list */
@@ -926,15 +995,36 @@ token_specific_open_session(SESSION *sess)
 		return CKR_FUNCTION_FAILED;
 	}
 
+	/* see if user has logged in to acquire ldap handle for session.
+	 * pkcs#11v2.2 states that all sessions within a process have
+	 * same login state.
+	 */
+	if (global_login_state == CKS_RW_USER_FUNCTIONS ||
+	    global_login_state == CKS_RO_USER_FUNCTIONS) {
+		ld = getLDAPhandle(sess->session_info.slotID);
+		if (ld == NULL) {
+			OCK_LOG_DEBUG("Failed to get LDAP handle for session.\n");
+			rc = CKR_FUNCTION_FAILED;
+			goto done;
+		}
+		/* put the new ldap handle into the session state. */
+		session_state->ld = ld;
+	}
+
+	/* put new session_state into the list */
 	list_insert_head(&sessions, &session_state->sessions);
 
+done:
 	/* Unlock */
 	if (pthread_mutex_unlock(&sess_list_mutex)) {
 		OCK_LOG_ERR(ERR_MUTEX_UNLOCK);
-		return CKR_FUNCTION_FAILED;
+		rc = CKR_FUNCTION_FAILED;
 	}
 
-	return CKR_OK;
+	if (rc != CKR_OK)
+		free(session_state);
+
+	return rc;
 }
 
 /*
@@ -949,6 +1039,12 @@ close_session(struct session_state *session_state)
 	unsigned long i;
 	int reason = 0;
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+
 	if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
 		OCK_LOG_ERR(ERR_MUTEX_LOCK);
 		return CKR_FUNCTION_FAILED;
@@ -1082,18 +1178,13 @@ CK_RV
 token_specific_login(SESSION *sess, CK_USER_TYPE userType, CK_CHAR_PTR pPin,
 		     CK_ULONG ulPinLen)
 {
-	CK_RV rc;
+	CK_RV rc = CKR_OK;
 	char fname[PATH_MAX];
-	CK_BYTE racfpwd[PIN_SIZE];
 	CK_BYTE hash_sha[SHA1_HASH_SIZE];
-	int racflen;
 	int mklen;
 	char pk_dir_buf[PATH_MAX];
 	char *ca_dir = NULL;
 	CK_SLOT_ID slot_id = sess->session_info.slotID;
-	struct session_state *session_state;
-	int sessions_locked = 0;
-	LDAP *ld;
 
 	/* Check Slot ID */
 	if (slot_id < 0 || slot_id > MAX_SLOT_ID) {
@@ -1157,57 +1248,15 @@ token_specific_login(SESSION *sess, CK_USER_TYPE userType, CK_CHAR_PTR pPin,
 		}
 	}
 
-	/* The pPin looks good, so now lets authenticate to ldap server */
-	if (slot_data[slot_id] == NULL) {
-		OCK_LOG_DEBUG("ICSF slot data not initialized.\n");
-		rc = CKR_FUNCTION_FAILED;
-		goto done;
-	}
-
-	/* Check if using sasl or simple auth */
-	if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) {
-		OCK_LOG_DEBUG("Using SIMPLE auth with slot ID: %d\n", slot_id);
-
-		/* get racf passwd */
-		rc = get_racf(master_key, AES_KEY_SIZE_256, racfpwd, &racflen);
-		if (rc != CKR_OK) {
-			OCK_LOG_DEBUG("Failed to get racf passwd.\n");
-			goto done;
-		}
-
-		/* ok got the passwd, perform simple ldap bind call */
-		rc = icsf_login(&ld, slot_data[slot_id]->uri,
-				slot_data[slot_id]->dn, racfpwd);
-		if (rc != CKR_OK) {
-			OCK_LOG_DEBUG("Failed to bind to ldap server.\n");
-			goto done;
-		}
-
-	}
-	else {
-		OCK_LOG_DEBUG("Using SASL auth with slot ID: %d\n", slot_id);
-
-		rc = icsf_sasl_login(&ld, slot_data[slot_id]->uri,
-				     slot_data[slot_id]->cert_file,
-				     slot_data[slot_id]->key_file,
-				     slot_data[slot_id]->ca_file, ca_dir);
-		if (rc != CKR_OK) {
-			OCK_LOG_DEBUG("Failed to bind to ldap server.\n");
-			goto done;
-		}
-	}
-
-	/* Save LDAP handle */
-	if (!(session_state = get_session_state(sess->handle))) {
-		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
-				(unsigned long) sess->handle);
-		rc = CKR_SESSION_HANDLE_INVALID;
-		goto done;
-	}
-	session_state->ld = ld;
-
+	/* Now that user is authenticated, can get racf passwd and
+	 * establish ldap handle for session.
+	 */
 done:
 	XProcUnLock();
+
+	if (rc == CKR_OK)
+		rc = icsf_get_handles(slot_id);
+
 	return rc;
 }
 
@@ -1317,6 +1366,13 @@ token_specific_copy_object(SESSION * session, CK_ATTRIBUTE_PTR attrs,
 		goto done;
 	}
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
+
 	/* Allocate structure for new object */
 	if (!(mapping_dst = malloc(sizeof(*mapping_dst)))) {
 		OCK_LOG_ERR(ERR_HOST_MEMORY);
@@ -1439,8 +1495,14 @@ token_specific_create_object(SESSION *session, CK_ATTRIBUTE_PTR attrs,
 
 	/* Get session state */
 	if (!(session_state = get_session_state(session->handle))) {
-		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
-				(unsigned long) session->handle);
+		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		rc = CKR_FUNCTION_FAILED;
 		goto done;
 	}
@@ -1635,6 +1697,13 @@ token_specific_generate_key_pair(SESSION *session,
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
 				(unsigned long) session->handle);
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		rc = CKR_FUNCTION_FAILED;
 		goto done;
 	}
@@ -1755,6 +1824,13 @@ token_specific_generate_key(SESSION *session, CK_MECHANISM_PTR mech,
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
 				(unsigned long) session->handle);
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		rc = CKR_FUNCTION_FAILED;
 		goto done;
 	}
@@ -1986,6 +2062,13 @@ token_specific_encrypt(SESSION *session, CK_BYTE_PTR input_data,
 		goto done;
 	}
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_ERR("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
+
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
 	if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) {
@@ -2077,6 +2160,13 @@ token_specific_encrypt_update(SESSION *session, CK_BYTE_PTR input_part,
 		goto done;
 	}
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_ERR("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
+
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
 	if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) {
@@ -2242,6 +2332,13 @@ token_specific_encrypt_final(SESSION *session, CK_BYTE_PTR output_part,
 		goto done;
 	}
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
+
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
 	if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) {
@@ -2451,6 +2548,12 @@ token_specific_decrypt(SESSION *session, CK_BYTE_PTR input_data,
 		rc = CKR_SESSION_HANDLE_INVALID;
 		goto done;
 	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
 
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
@@ -2543,6 +2646,12 @@ token_specific_decrypt_update(SESSION *session, CK_BYTE_PTR input_part,
 		rc = CKR_SESSION_HANDLE_INVALID;
 		goto done;
 	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
 
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
@@ -2726,6 +2835,13 @@ token_specific_decrypt_final(SESSION *session, CK_BYTE_PTR output_part,
 		goto done;
 	}
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
+
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
 	if(!(mapping = bt_get_node_value(&objects, decr_ctx->key))) {
@@ -2825,6 +2941,12 @@ token_specific_get_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle,
 	if (!(session_state = get_session_state(sess->handle))) {
 		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
 				(unsigned long) handle);
+		return CKR_SESSION_HANDLE_INVALID;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		return CKR_FUNCTION_FAILED;
 	}
 
@@ -2902,6 +3024,12 @@ token_specific_set_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle,
 	if (!(session_state = get_session_state(sess->handle))) {
 		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
 				(unsigned long) handle);
+		return CKR_SESSION_HANDLE_INVALID;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		return CKR_FUNCTION_FAILED;
 	}
 
@@ -3015,6 +3143,12 @@ token_specific_find_objects_init(SESSION *sess, CK_ATTRIBUTE *pTemplate,
 	if (!(session_state = get_session_state(sess->handle))) {
 		OCK_LOG_DEBUG("Session not found for session id %lu.\n",
 				(unsigned long) sess->handle);
+		return CKR_SESSION_HANDLE_INVALID;
+	}
+
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
 		return CKR_FUNCTION_FAILED;
 	}
 
@@ -3140,9 +3274,15 @@ token_specific_destroy_object(SESSION *sess, CK_OBJECT_HANDLE handle)
         if (!(session_state = get_session_state(sess->handle))) {
                 OCK_LOG_DEBUG("Session not found for session id %lu.\n",
                                 (unsigned long) handle);
-                return CKR_FUNCTION_FAILED;
+                return CKR_SESSION_HANDLE_INVALID;
         }
 
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		return CKR_FUNCTION_FAILED;
+	}
+
 	/* Lock the object list */
 	if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
 		OCK_LOG_ERR(ERR_MUTEX_UNLOCK);
@@ -3422,13 +3562,21 @@ token_specific_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data,
 
 	if (ctx->multi == TRUE) {
 		OCK_LOG_ERR(ERR_OPERATION_ACTIVE);
-		return CKR_OPERATION_ACTIVE;
+		rc = CKR_OPERATION_ACTIVE;
+		goto done;
 	}
 
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -3439,7 +3587,7 @@ token_specific_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	switch (ctx->mech.mechanism) {
 	case CKM_MD5_HMAC:
@@ -3454,10 +3602,12 @@ token_specific_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data,
 			hlen = get_signverify_len(ctx->mech);
 			if (hlen < 0) {
 				OCK_LOG_ERR(ERR_MECHANISM_INVALID);
-				return CKR_MECHANISM_INVALID;
+				rc = CKR_MECHANISM_INVALID;
+				goto done;
 			}
 			*sig_len = hlen;
-			return CKR_OK;
+			rc = CKR_OK;
+			goto done;
 		}
 
 		rc = icsf_hmac_sign(session_state->ld, &reason,
@@ -3513,7 +3663,8 @@ token_specific_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data,
 		rc = CKR_MECHANISM_INVALID;
 	}
 
-	if (rc != CKR_OK)
+done:
+	if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && length_only))
 		free_sv_ctx(ctx);
 
 	return rc;
@@ -3538,7 +3689,14 @@ token_specific_sign_update(SESSION *session, CK_BYTE *in_data,
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -3549,7 +3707,7 @@ token_specific_sign_update(SESSION *session, CK_BYTE *in_data,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	/* indicate this is multipart operation and get chain info from ctx.
 	 * if any mechanisms that cannot do multipart sign come here, they
@@ -3690,7 +3848,14 @@ token_specific_sign_final(SESSION *session, CK_BBOOL length_only,
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -3701,7 +3866,7 @@ token_specific_sign_final(SESSION *session, CK_BBOOL length_only,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	/* get the chain data from ctx */
 	if (ctx->context) {
@@ -3782,7 +3947,7 @@ token_specific_sign_final(SESSION *session, CK_BBOOL length_only,
 	}
 
 done:
-	if (rc != CKR_OK)
+	if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && length_only))
 		free_sv_ctx(ctx);
 	return rc;
 }
@@ -3975,18 +4140,27 @@ token_specific_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len,
 
 	if (!session || !ctx || !in_data || !signature) {
 		OCK_LOG_ERR(ERR_FUNCTION_FAILED);
-		return CKR_FUNCTION_FAILED;
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	if (ctx->multi == TRUE) {
 		OCK_LOG_ERR(ERR_OPERATION_ACTIVE);
-		return CKR_OPERATION_ACTIVE;
+		rc = CKR_OPERATION_ACTIVE;
+		goto done;
 	}
 
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -3997,7 +4171,7 @@ token_specific_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	switch (ctx->mech.mechanism) {
 	case CKM_MD5_HMAC:
@@ -4048,8 +4222,8 @@ token_specific_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len,
 		rc = CKR_MECHANISM_INVALID;
 	}
 
-	if (rc != CKR_OK)
-		free_sv_ctx(ctx);
+done:
+	free_sv_ctx(ctx);
 	return rc;
 }
 
@@ -4071,7 +4245,14 @@ token_specific_verify_update(SESSION *session, CK_BYTE *in_data,
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -4082,7 +4263,7 @@ token_specific_verify_update(SESSION *session, CK_BYTE *in_data,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	/* indicate this is multipart operation and get chain info from ctx.
 	 * if any mechanisms that cannot do multipart verify come here, they
@@ -4214,13 +4395,21 @@ token_specific_verify_final(SESSION *session, CK_BYTE *signature,
 
 	if (!sig_len) {
 		OCK_LOG_ERR(ERR_FUNCTION_FAILED);
-		return CKR_FUNCTION_FAILED;
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check session */
 	if (!(session_state = get_session_state(session->handle))) {
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
-		return CKR_SESSION_HANDLE_INVALID;
+		rc = CKR_SESSION_HANDLE_INVALID;
+		goto done;
+	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
 	}
 
 	/* Check if key exists */
@@ -4231,7 +4420,7 @@ token_specific_verify_final(SESSION *session, CK_BYTE *signature,
 	}
 	pthread_rwlock_unlock(&obj_list_rw_mutex);
 	if (rc != CKR_OK)
-		return rc;
+		goto done;
 
 	/* get the chain data from ctx */
 	if (ctx->context) {
@@ -4297,8 +4486,7 @@ token_specific_verify_final(SESSION *session, CK_BYTE *signature,
 	}
 
 done:
-	if (rc != CKR_OK)
-		free_sv_ctx(ctx);
+	free_sv_ctx(ctx);
 	return rc;
 }
 
@@ -4321,6 +4509,11 @@ token_specific_wrap_key(SESSION *session, CK_MECHANISM_PTR mech,
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
 		return  CKR_SESSION_HANDLE_INVALID;
 	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		return CKR_FUNCTION_FAILED;
+	}
 
 	/* Check if keys exist */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
@@ -4368,6 +4561,11 @@ token_specific_unwrap_key(SESSION *session, CK_MECHANISM_PTR mech,
 		OCK_LOG_ERR(ERR_SESSION_HANDLE_INVALID);
 		return  CKR_SESSION_HANDLE_INVALID;
 	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		return CKR_FUNCTION_FAILED;
+	}
 
 	/* Check if key exists */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
@@ -4497,6 +4695,12 @@ token_specific_derive_key(SESSION *session, CK_MECHANISM_PTR mech,
 		rc = CKR_FUNCTION_FAILED;
 		goto done;
 	}
+	/* check ldap handle */
+	if (session_state->ld == NULL) {
+		OCK_LOG_DEBUG("No LDAP handle.\n");
+		rc = CKR_FUNCTION_FAILED;
+		goto done;
+	}
 
 	/* Convert the OCK_CK_OBJECT_HANDLE_PTR to ICSF */
 	pthread_rwlock_rdlock(&obj_list_rw_mutex);
diff --git a/usr/lib/pkcs11/icsf_stdll/tok_struct.h b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
index ede9486..9d0e939 100644
--- a/usr/lib/pkcs11/icsf_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
@@ -151,6 +151,8 @@ token_spec_t token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,	// get_mechanism_list
 	&token_specific_get_mechanism_info,	// get_mechanism_info
+	NULL,
+	&token_specific_final
 };
 
 #endif
diff --git a/usr/lib/pkcs11/soft_stdll/tok_struct.h b/usr/lib/pkcs11/soft_stdll/tok_struct.h
index 3715f59..bf1d6c8 100644
--- a/usr/lib/pkcs11/soft_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/soft_stdll/tok_struct.h
@@ -441,7 +441,8 @@ token_spec_t token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+	NULL
 };
 
 #endif
diff --git a/usr/lib/pkcs11/tpm_stdll/tok_struct.h b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
index 893f14c..89fc7fc 100644
--- a/usr/lib/pkcs11/tpm_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
@@ -157,5 +157,6 @@ struct token_specific_struct token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+	NULL
 };
openSUSE Build Service is sponsored by