Home | History | Annotate | Download | only in common
      1     0  stevel /*
      2     0  stevel  * CDDL HEADER START
      3     0  stevel  *
      4     0  stevel  * The contents of this file are subject to the terms of the
      5  4841  haimay  * Common Development and Distribution License (the "License").
      6  4841  haimay  * You may not use this file except in compliance with the License.
      7     0  stevel  *
      8     0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0  stevel  * or http://www.opensolaris.org/os/licensing.
     10     0  stevel  * See the License for the specific language governing permissions
     11     0  stevel  * and limitations under the License.
     12     0  stevel  *
     13     0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0  stevel  *
     19     0  stevel  * CDDL HEADER END
     20     0  stevel  */
     21     0  stevel /*
     22  7136  wyllys  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23     0  stevel  * Use is subject to license terms.
     24     0  stevel  */
     25     0  stevel 
     26     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27     0  stevel 
     28     0  stevel /*
     29     0  stevel  * Functions for dealing with provider sessions
     30     0  stevel  */
     31     0  stevel 
     32     0  stevel #include <string.h>
     33     0  stevel #include <cryptoutil.h>
     34     0  stevel #include "metaGlobal.h"
     35     0  stevel #include "pkcs11Session.h"
     36     0  stevel #include "pkcs11Global.h"
     37     0  stevel 
     38     0  stevel 
     39     0  stevel /*
     40     0  stevel  * This is just a **WILD** guess for the maximum idle sessions to
     41     0  stevel  * keep for each slot.  This number should probably be adjusted
     42     0  stevel  * when there's more data from actual application use
     43     0  stevel  */
     44     0  stevel #define	MAX_IDLE_SESSIONS	100
     45     0  stevel 
     46     0  stevel /*
     47     0  stevel  * The following 5 variables are initialized at the time metaslot
     48     0  stevel  * is initialized.  They are not modified after they are initialized
     49     0  stevel  *
     50     0  stevel  * During initialization time, they are protected by the "initmutex"
     51     0  stevel  * defined in metaGeneral.c
     52     0  stevel  */
     53     0  stevel slot_data_t *slots;
     54     0  stevel CK_SLOT_ID metaslot_keystore_slotid;
     55     0  stevel static CK_ULONG num_slots;
     56     0  stevel static CK_ULONG objtok_slotnum;
     57  4841  haimay static CK_ULONG softtoken_slotnum;
     58     0  stevel static boolean_t write_protected;
     59     0  stevel 
     60     0  stevel /* protects the "metaslotLoggedIn" variable */
     61     0  stevel static pthread_mutex_t metaslotLoggedIn_mutex = PTHREAD_MUTEX_INITIALIZER;
     62     0  stevel static boolean_t metaslotLoggedIn;
     63     0  stevel 
     64     0  stevel /*
     65     0  stevel  * meta_slotManager_initialize
     66     0  stevel  *
     67     0  stevel  * Called from C_Initialize. Allocates and initializes the storage needed
     68     0  stevel  * by the slot manager.
     69     0  stevel  */
     70     0  stevel CK_RV
     71     0  stevel meta_slotManager_initialize() {
     72     0  stevel 	CK_ULONG slot_count = 0;
     73     0  stevel 	CK_RV rv;
     74     0  stevel 	CK_SLOT_ID i;
     75     0  stevel 
     76     0  stevel 	/* Initialize the static variables */
     77     0  stevel 	write_protected = B_FALSE;
     78     0  stevel 	metaslotLoggedIn = B_FALSE;
     79     0  stevel 
     80     0  stevel 	/*
     81     0  stevel 	 * Count the number of slots in the framework.
     82     0  stevel 	 * We start at ((slottable->st_first) + 1) instead of
     83     0  stevel 	 * slottable->st_first because when we are here, metaslot is
     84     0  stevel 	 * enabled, and st_first is always metaslot, which doesn't
     85     0  stevel 	 * need to be counted.
     86     0  stevel 	 */
     87     0  stevel 	for (i = (slottable->st_first) + 1; i <= slottable->st_last; i++) {
     88     0  stevel 		slot_count++;
     89     0  stevel 	}
     90     0  stevel 
     91     0  stevel 	/*
     92     0  stevel 	 * This shouldn't happen, because there should at least
     93     0  stevel 	 * be 1 other slot besides metaslot.
     94     0  stevel 	 */
     95     0  stevel 	if (slot_count < 1) {
     96     0  stevel 		rv = CKR_FUNCTION_FAILED;
     97     0  stevel 		goto clean_exit;
     98     0  stevel 	}
     99     0  stevel 
    100     0  stevel 	slots = calloc(slot_count, sizeof (slot_data_t));
    101     0  stevel 	if (slots == NULL) {
    102     0  stevel 		rv = CKR_HOST_MEMORY;
    103     0  stevel 		goto clean_exit;
    104     0  stevel 	}
    105     0  stevel 
    106     0  stevel 	/*
    107     0  stevel 	 * Store the slot IDs. Adjust for the fact that the first slot is
    108     0  stevel 	 * actually us (metaslot).
    109     0  stevel 	 */
    110     0  stevel 	for (i = 0; i < slot_count; i++) {
    111     0  stevel 		slots[i].fw_st_id = i + 1;
    112     0  stevel 		(void) pthread_rwlock_init(
    113     0  stevel 		    &(slots[i].tokenobject_list_lock), NULL);
    114     0  stevel 	}
    115     0  stevel 	num_slots = slot_count;
    116     0  stevel 
    117     0  stevel 	return (CKR_OK);
    118     0  stevel 
    119     0  stevel clean_exit:
    120     0  stevel 	if (slots) {
    121     0  stevel 		free(slots);
    122     0  stevel 		slots = NULL;
    123     0  stevel 	}
    124     0  stevel 
    125     0  stevel 	num_slots = 0;
    126     0  stevel 
    127     0  stevel 	return (rv);
    128     0  stevel }
    129     0  stevel 
    130     0  stevel 
    131     0  stevel /*
    132     0  stevel  * meta_slotManager_finalize
    133     0  stevel  *
    134     0  stevel  * Called from C_Finalize. Deallocates any storage held by the slot manager.
    135     0  stevel  */
    136     0  stevel void
    137     0  stevel meta_slotManager_finalize() {
    138     0  stevel 	CK_ULONG slot;
    139     0  stevel 
    140  7136  wyllys 	/* If no slots to free, return */
    141  7136  wyllys 	if (slots == NULL)
    142  7136  wyllys 		return;
    143     0  stevel 	/*
    144     0  stevel 	 * No need to lock pool, we assume all meta sessions are closed.
    145     0  stevel 	 *
    146     0  stevel 	 * Close all sessions in the idle and persist list.
    147     0  stevel 	 * The active list is empty.  It doesn't need to be checked.
    148     0  stevel 	 */
    149     0  stevel 
    150     0  stevel 	for (slot = 0; slot < num_slots; slot++) {
    151     0  stevel 		slot_session_t *session, *next_session;
    152     0  stevel 
    153     0  stevel 		/*
    154     0  stevel 		 * The slotobjects associated with the session should have
    155     0  stevel 		 * been closed when the metaobjects were closed. Thus, no
    156     0  stevel 		 * need to do anything here.
    157     0  stevel 		 */
    158     0  stevel 
    159     0  stevel 		session = slots[slot].session_pool.idle_list_head;
    160     0  stevel 		while (session) {
    161     0  stevel 			next_session = session->next;
    162     0  stevel 			(void) FUNCLIST(session->fw_st_id)->C_CloseSession(
    163     0  stevel 			    session->hSession);
    164     0  stevel 			(void) pthread_rwlock_destroy(
    165     0  stevel 				&session->object_list_lock);
    166     0  stevel 			free(session);
    167     0  stevel 			session = next_session;
    168     0  stevel 		}
    169     0  stevel 
    170     0  stevel 		session = slots[slot].session_pool.persist_list_head;
    171     0  stevel 		while (session) {
    172     0  stevel 			next_session = session->next;
    173     0  stevel 			(void) FUNCLIST(session->fw_st_id)->C_CloseSession(
    174     0  stevel 			    session->hSession);
    175     0  stevel 			(void) pthread_rwlock_destroy(
    176     0  stevel 				&session->object_list_lock);
    177     0  stevel 			free(session);
    178     0  stevel 			session = next_session;
    179     0  stevel 		}
    180     0  stevel 
    181     0  stevel 		(void) pthread_rwlock_destroy(
    182     0  stevel 			&slots[slot].tokenobject_list_lock);
    183     0  stevel 	}
    184     0  stevel 
    185     0  stevel 	free(slots);
    186     0  stevel 	slots = NULL;
    187  7136  wyllys 	num_slots = 0;
    188     0  stevel }
    189     0  stevel 
    190     0  stevel 
    191     0  stevel /*
    192     0  stevel  * meta_slotManager_find_object_token()
    193     0  stevel  *
    194     0  stevel  * Called from meta_Initialize. Searches for the "object token," which is used
    195     0  stevel  * for storing token objects and loging into.
    196     0  stevel  *
    197     0  stevel  * We do the search using the following algorithm.
    198     0  stevel  *
    199     0  stevel  * If either ${METASLOT_OBJECTSTORE_SLOT} or ${METASLOT_OBJECTSTORE_TOKEN}
    200     0  stevel  * environment variable is defined, the value of the defined variable(s)
    201     0  stevel  * will be used for the match.  All token and slot values defined system-wide
    202     0  stevel  * will be ignored.
    203     0  stevel  *
    204     0  stevel  * If neither variables above are defined, the system-wide values defined
    205     0  stevel  * in pkcs11.conf are used.
    206     0  stevel  *
    207     0  stevel  * If neither environment variables or system-wide values are defined,
    208     0  stevel  * or if none of the existing slots/tokens match the defined
    209     0  stevel  * values, the first slot after metaslot will be used as the default.
    210     0  stevel  *
    211     0  stevel  */
    212     0  stevel void
    213     0  stevel meta_slotManager_find_object_token() {
    214     0  stevel 	CK_ULONG slot;
    215     0  stevel 	boolean_t found = B_FALSE;
    216     0  stevel 	CK_RV rv;
    217     0  stevel 	unsigned int num_match_needed = 0;
    218     0  stevel 	CK_SLOT_INFO slotinfo;
    219     0  stevel 	CK_TOKEN_INFO tokeninfo;
    220     0  stevel 
    221     0  stevel 	if (metaslot_config.keystore_token_specified) {
    222     0  stevel 		num_match_needed++;
    223     0  stevel 	}
    224     0  stevel 
    225     0  stevel 	if (metaslot_config.keystore_slot_specified) {
    226     0  stevel 		num_match_needed++;
    227     0  stevel 	}
    228     0  stevel 
    229     0  stevel 	if (num_match_needed == 0) {
    230     0  stevel 		goto skip_search;
    231     0  stevel 	}
    232     0  stevel 
    233     0  stevel 	for (slot = 0; slot < num_slots; slot++) {
    234     0  stevel 		unsigned int num_matched = 0;
    235     0  stevel 		boolean_t have_tokeninfo = B_FALSE;
    236     0  stevel 		CK_SLOT_ID true_id, fw_st_id;
    237     0  stevel 
    238     0  stevel 		fw_st_id = slots[slot].fw_st_id;
    239     0  stevel 		true_id = TRUEID(fw_st_id);
    240  4841  haimay 
    241  4841  haimay 		(void) memset(&slotinfo, 0, sizeof (CK_SLOT_INFO));
    242  4841  haimay 		rv = FUNCLIST(fw_st_id)->C_GetSlotInfo(true_id,
    243  4841  haimay 		    &slotinfo);
    244  4841  haimay 		if (rv != CKR_OK)
    245  4841  haimay 			continue;
    246  4841  haimay 
    247  4841  haimay 		if (strncmp((char *)SOFT_SLOT_DESCRIPTION,
    248  4841  haimay 		    (char *)slotinfo.slotDescription,
    249  4841  haimay 		    SLOT_DESCRIPTION_SIZE) == 0) {
    250  4841  haimay 			softtoken_slotnum = slot;
    251  4841  haimay 		}
    252     0  stevel 
    253     0  stevel 		if (metaslot_config.keystore_slot_specified) {
    254     0  stevel 
    255     0  stevel 			unsigned char *slot;
    256     0  stevel 			size_t slot_str_len;
    257     0  stevel 
    258     0  stevel 			rv = FUNCLIST(fw_st_id)->C_GetSlotInfo(true_id,
    259     0  stevel 			    &slotinfo);
    260     0  stevel 			if (rv != CKR_OK)
    261     0  stevel 				continue;
    262     0  stevel 
    263     0  stevel 			/*
    264     0  stevel 			 * pad slot description from user/system configuration
    265     0  stevel 			 * with spaces
    266     0  stevel 			 */
    267     0  stevel 			slot = metaslot_config.keystore_slot;
    268     0  stevel 			slot_str_len = strlen((char *)slot);
    269     0  stevel 			(void) memset(slot + slot_str_len, ' ',
    270     0  stevel 			    SLOT_DESCRIPTION_SIZE - slot_str_len);
    271     0  stevel 
    272     0  stevel 			/*
    273     0  stevel 			 * The PKCS#11 strings are not null-terminated, so,
    274     0  stevel 			 * we just compare SLOT_DESCRIPTION_SIZE bytes
    275     0  stevel 			 */
    276     0  stevel 			if (strncmp((char *)slot,
    277     0  stevel 			    (char *)slotinfo.slotDescription,
    278     0  stevel 			    SLOT_DESCRIPTION_SIZE) == 0) {
    279     0  stevel 				num_matched++;
    280     0  stevel 			}
    281     0  stevel 		}
    282     0  stevel 
    283     0  stevel 		if (metaslot_config.keystore_token_specified) {
    284     0  stevel 			unsigned char *token;
    285     0  stevel 			size_t token_str_len;
    286     0  stevel 
    287     0  stevel 			rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(true_id,
    288     0  stevel 			    &tokeninfo);
    289     0  stevel 
    290     0  stevel 			if (rv != CKR_OK) {
    291     0  stevel 				continue;
    292     0  stevel 			}
    293     0  stevel 
    294     0  stevel 			have_tokeninfo = B_TRUE;
    295     0  stevel 
    296     0  stevel 			/*
    297     0  stevel 			 * pad slot description from user/system configuration
    298     0  stevel 			 * with spaces
    299     0  stevel 			 */
    300     0  stevel 			token = metaslot_config.keystore_token;
    301     0  stevel 			token_str_len = strlen((char *)token);
    302     0  stevel 			(void) memset(token + token_str_len, ' ',
    303     0  stevel 			    TOKEN_LABEL_SIZE - token_str_len);
    304     0  stevel 
    305     0  stevel 			/*
    306     0  stevel 			 * The PKCS#11 strings are not null-terminated.
    307     0  stevel 			 * So, just compare TOKEN_LABEL_SIZE bytes
    308     0  stevel 			 */
    309     0  stevel 			if (strncmp((char *)token, (char *)tokeninfo.label,
    310     0  stevel 			    TOKEN_LABEL_SIZE) == 0) {
    311     0  stevel 				num_matched++;
    312     0  stevel 			}
    313     0  stevel 		}
    314     0  stevel 
    315     0  stevel 		if (num_match_needed == num_matched) {
    316     0  stevel 			/* match is found */
    317     0  stevel 
    318     0  stevel 			if (!have_tokeninfo) {
    319     0  stevel 				rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(true_id,
    320     0  stevel 				    &tokeninfo);
    321     0  stevel 				if (rv != CKR_OK) {
    322     0  stevel 					continue;
    323     0  stevel 				}
    324     0  stevel 			}
    325     0  stevel 
    326     0  stevel 
    327     0  stevel 			if (tokeninfo.flags & CKF_WRITE_PROTECTED) {
    328     0  stevel 				/*
    329     0  stevel 				 * Currently this is the only time that
    330     0  stevel 				 * the write_protected state is set, and
    331     0  stevel 				 * it is never cleared. The token could
    332     0  stevel 				 * clear (or set!) this flag later on.
    333     0  stevel 				 * We might want to adjust the state
    334     0  stevel 				 * of metaslot, but there's know way to know
    335     0  stevel 				 * when a token changes this flag.
    336     0  stevel 				 */
    337     0  stevel 				write_protected = B_TRUE;
    338     0  stevel 			}
    339     0  stevel 
    340     0  stevel 			found = B_TRUE;
    341     0  stevel 			break;
    342     0  stevel 		}
    343     0  stevel 	}
    344     0  stevel 
    345     0  stevel skip_search:
    346     0  stevel 	if (found) {
    347     0  stevel 		objtok_slotnum = slot;
    348     0  stevel 	} else {
    349     0  stevel 		/*
    350     0  stevel 		 * if slot and/or token is not defined for the keystore,
    351     0  stevel 		 * just use the first available slot as keystore
    352     0  stevel 		 */
    353     0  stevel 		objtok_slotnum = 0;
    354     0  stevel 	}
    355     0  stevel 	slots[objtok_slotnum].session_pool.keep_one_alive = B_TRUE;
    356     0  stevel 	metaslot_keystore_slotid = slots[objtok_slotnum].fw_st_id;
    357     0  stevel }
    358     0  stevel 
    359     0  stevel 
    360     0  stevel CK_ULONG
    361     0  stevel get_keystore_slotnum()
    362     0  stevel {
    363     0  stevel 	return (objtok_slotnum);
    364     0  stevel }
    365     0  stevel 
    366  4841  haimay CK_ULONG
    367  4841  haimay get_softtoken_slotnum()
    368  4841  haimay {
    369  4841  haimay 	return (softtoken_slotnum);
    370  4841  haimay }
    371     0  stevel 
    372     0  stevel CK_SLOT_ID
    373     0  stevel meta_slotManager_get_framework_table_id(CK_ULONG slotnum)
    374     0  stevel {
    375     0  stevel 	/*
    376     0  stevel 	 * This is only used internally, and so the slotnum should always
    377     0  stevel 	 * be valid.
    378     0  stevel 	 */
    379     0  stevel 	return (slots[slotnum].fw_st_id);
    380     0  stevel }
    381     0  stevel 
    382     0  stevel CK_ULONG
    383     0  stevel meta_slotManager_get_slotcount()
    384     0  stevel {
    385     0  stevel 	return (num_slots);
    386     0  stevel }
    387     0  stevel 
    388     0  stevel boolean_t
    389     0  stevel meta_slotManager_token_write_protected()
    390     0  stevel {
    391     0  stevel 	return (write_protected);
    392     0  stevel }
    393     0  stevel 
    394     0  stevel /*
    395     0  stevel  * Find a session in the given list that matches the specified flags.
    396     0  stevel  * If such a session is found, it will be removed from the list, and
    397     0  stevel  * returned to the caller.  If such a session is not found, will
    398     0  stevel  * return NULL
    399     0  stevel  */
    400     0  stevel static slot_session_t *
    401     0  stevel get_session(slot_session_t **session_list, CK_FLAGS flags)
    402     0  stevel {
    403     0  stevel 
    404     0  stevel 	slot_session_t *tmp_session;
    405     0  stevel 
    406     0  stevel 	tmp_session = *session_list;
    407     0  stevel 
    408     0  stevel 	while (tmp_session != NULL) {
    409     0  stevel 		if (tmp_session->session_flags == flags) {
    410     0  stevel 			break;
    411     0  stevel 		} else {
    412     0  stevel 			tmp_session = tmp_session->next;
    413     0  stevel 		}
    414     0  stevel 
    415     0  stevel 	}
    416     0  stevel 
    417     0  stevel 	if (tmp_session == NULL) {
    418     0  stevel 		/* no match */
    419     0  stevel 		return (NULL);
    420     0  stevel 	}
    421     0  stevel 
    422     0  stevel 	/* Remove from list */
    423     0  stevel 	REMOVE_FROM_LIST(*session_list, tmp_session);
    424     0  stevel 	return (tmp_session);
    425     0  stevel }
    426     0  stevel 
    427     0  stevel /*
    428     0  stevel  * meta_get_slot_session
    429     0  stevel  *
    430     0  stevel  * Call to get a session with a specific slot/token.
    431     0  stevel  *
    432     0  stevel  * NOTE - We assume the slot allows an unlimited number of sessions. We
    433     0  stevel  * could look at what's reported in the token info, but that information is
    434     0  stevel  * not always set. It's also unclear when we should (A) wait for one to become
    435     0  stevel  * available, (B) skip the slot for now or (C) return a fatal error. The
    436     0  stevel  * extra complexity is not worth it.
    437     0  stevel  *
    438     0  stevel  */
    439     0  stevel CK_RV
    440     0  stevel meta_get_slot_session(CK_ULONG slotnum, slot_session_t **session,
    441     0  stevel     CK_FLAGS flags) {
    442     0  stevel 	session_pool_t *pool;
    443     0  stevel 	slot_session_t *new_session, *tmp_session;
    444     0  stevel 	CK_RV rv;
    445     0  stevel 	CK_SLOT_ID fw_st_id, true_id;
    446     0  stevel 
    447     0  stevel 	if (slotnum >= num_slots) {
    448     0  stevel 		return (CKR_SLOT_ID_INVALID);
    449     0  stevel 	}
    450     0  stevel 
    451     0  stevel 	pool = &slots[slotnum].session_pool;
    452     0  stevel 
    453     0  stevel 	/*
    454     0  stevel 	 * Try to reuse an existing session.
    455     0  stevel 	 */
    456     0  stevel 
    457     0  stevel 	(void) pthread_mutex_lock(&pool->list_lock);
    458     0  stevel 
    459     0  stevel 	if (pool->idle_list_head != NULL) {
    460     0  stevel 		tmp_session = get_session(&(pool->idle_list_head), flags);
    461     0  stevel 		if (tmp_session != NULL) {
    462     0  stevel 			/* Add to active list */
    463     0  stevel 			INSERT_INTO_LIST(pool->active_list_head, tmp_session);
    464     0  stevel 			*session = tmp_session;
    465     0  stevel 			pool->num_idle_sessions--;
    466     0  stevel 			(void) pthread_mutex_unlock(&pool->list_lock);
    467     0  stevel 			return (CKR_OK);
    468     0  stevel 		}
    469     0  stevel 	}
    470     0  stevel 
    471     0  stevel 	if (pool->persist_list_head != NULL) {
    472     0  stevel 		tmp_session = get_session(&(pool->persist_list_head), flags);
    473     0  stevel 		if (tmp_session != NULL) {
    474     0  stevel 			/* Add to active list */
    475     0  stevel 			INSERT_INTO_LIST(pool->active_list_head, tmp_session);
    476     0  stevel 			*session = tmp_session;
    477     0  stevel 			(void) pthread_mutex_unlock(&pool->list_lock);
    478     0  stevel 			return (CKR_OK);
    479     0  stevel 		}
    480     0  stevel 	}
    481     0  stevel 	(void) pthread_mutex_unlock(&pool->list_lock);
    482     0  stevel 
    483     0  stevel 	fw_st_id = slots[slotnum].fw_st_id;
    484     0  stevel 	true_id = TRUEID(fw_st_id);
    485     0  stevel 
    486     0  stevel 	new_session = calloc(1, sizeof (slot_session_t));
    487     0  stevel 	if (new_session == NULL) {
    488     0  stevel 		return (CKR_HOST_MEMORY);
    489     0  stevel 	}
    490     0  stevel 
    491     0  stevel 	/* initialize slotsession */
    492     0  stevel 	new_session->slotnum = slotnum;
    493     0  stevel 	new_session->fw_st_id = fw_st_id;
    494     0  stevel 	new_session->object_list_head = NULL;
    495     0  stevel 	new_session->session_flags = flags;
    496     0  stevel 	(void) pthread_rwlock_init(&new_session->object_list_lock, NULL);
    497     0  stevel 
    498     0  stevel 	rv = FUNCLIST(fw_st_id)->C_OpenSession(true_id, flags, NULL, NULL,
    499     0  stevel 	    &new_session->hSession);
    500     0  stevel 
    501     0  stevel 	if (rv == CKR_TOKEN_WRITE_PROTECTED) {
    502     0  stevel 		/* Retry with a RO session. */
    503     0  stevel 		new_session->session_flags &= ~CKF_SERIAL_SESSION;
    504     0  stevel 		rv = FUNCLIST(fw_st_id)->C_OpenSession(true_id,
    505     0  stevel 		    new_session->session_flags, NULL, NULL,
    506     0  stevel 		    &new_session->hSession);
    507     0  stevel 	}
    508     0  stevel 
    509     0  stevel 	if (rv != CKR_OK) {
    510     0  stevel 		free(new_session);
    511     0  stevel 		return (CKR_FUNCTION_FAILED);
    512     0  stevel 	}
    513     0  stevel 
    514     0  stevel 	/* Insert session into active list */
    515     0  stevel 	(void) pthread_mutex_lock(&pool->list_lock);
    516     0  stevel 	INSERT_INTO_LIST(pool->active_list_head, new_session);
    517     0  stevel 	(void) pthread_mutex_unlock(&pool->list_lock);
    518     0  stevel 	*session = new_session;
    519     0  stevel 	return (CKR_OK);
    520     0  stevel }
    521     0  stevel 
    522     0  stevel 
    523     0  stevel /*
    524     0  stevel  * meta_release_slot_session
    525     0  stevel  *
    526     0  stevel  * Call to release a session obtained via meta_get_slot_session()
    527     0  stevel  */
    528     0  stevel void
    529     0  stevel meta_release_slot_session(slot_session_t *session) {
    530     0  stevel 	session_pool_t *pool;
    531     0  stevel 	boolean_t must_retain, can_close = B_FALSE;
    532     0  stevel 	boolean_t this_is_last_session = B_FALSE;
    533     0  stevel 
    534     0  stevel 	pool = &slots[session->slotnum].session_pool;
    535     0  stevel 
    536     0  stevel 	/* Note that the active_list must have >= 1 entry (this session) */
    537     0  stevel 	if (pool->persist_list_head == NULL &&
    538     0  stevel 	    pool->idle_list_head == NULL &&
    539     0  stevel 	    pool->active_list_head->next == NULL)
    540     0  stevel 		this_is_last_session = B_TRUE;
    541     0  stevel 
    542     0  stevel 	/*
    543     0  stevel 	 * If the session has session objects, we need to retain it. Also
    544     0  stevel 	 * retain it if it's the only session holding login state (or handles
    545     0  stevel 	 * to public token objects)
    546     0  stevel 	 */
    547     0  stevel 	must_retain = session->object_list_head != NULL ||
    548     0  stevel 	    (pool->keep_one_alive && this_is_last_session);
    549     0  stevel 
    550     0  stevel 	if ((!must_retain) && (pool->num_idle_sessions > MAX_IDLE_SESSIONS)) {
    551     0  stevel 		can_close = B_TRUE;
    552     0  stevel 	}
    553     0  stevel 
    554     0  stevel 	(void) pthread_mutex_lock(&pool->list_lock);
    555     0  stevel 	/* remove from active list */
    556     0  stevel 	REMOVE_FROM_LIST(pool->active_list_head, session);
    557     0  stevel 
    558     0  stevel 	if (must_retain) {
    559     0  stevel 		/* insert into persist list */
    560     0  stevel 		INSERT_INTO_LIST(pool->persist_list_head, session);
    561     0  stevel 		(void) pthread_mutex_unlock(&pool->list_lock);
    562     0  stevel 		return;
    563     0  stevel 	} else if (!can_close) {
    564     0  stevel 		/* insert into idle list */
    565     0  stevel 		INSERT_INTO_LIST(pool->idle_list_head, session);
    566     0  stevel 		pool->num_idle_sessions++;
    567     0  stevel 		(void) pthread_mutex_unlock(&pool->list_lock);
    568     0  stevel 		return;
    569     0  stevel 	}
    570     0  stevel 
    571     0  stevel 	(void) pthread_mutex_unlock(&pool->list_lock);
    572     0  stevel 
    573     0  stevel 	(void) FUNCLIST(session->fw_st_id)->C_CloseSession(session->hSession);
    574     0  stevel 
    575     0  stevel 	(void) pthread_rwlock_destroy(&session->object_list_lock);
    576     0  stevel 	free(session);
    577     0  stevel }
    578     0  stevel 
    579     0  stevel /*
    580     0  stevel  * Returns whether metaslot has directly logged in
    581     0  stevel  */
    582     0  stevel boolean_t
    583     0  stevel metaslot_logged_in()
    584     0  stevel {
    585     0  stevel 	return (metaslotLoggedIn);
    586     0  stevel }
    587     0  stevel 
    588     0  stevel void
    589     0  stevel metaslot_set_logged_in_flag(boolean_t value)
    590     0  stevel {
    591     0  stevel 	(void) pthread_mutex_lock(&metaslotLoggedIn_mutex);
    592     0  stevel 	metaslotLoggedIn = value;
    593     0  stevel 	(void) pthread_mutex_unlock(&metaslotLoggedIn_mutex);
    594     0  stevel }
    595