Blame usr/lib/common/lock_sess_mgr.c

Packit 8681c6
/*
Packit 8681c6
 * COPYRIGHT (c) International Business Machines Corp. 2001-2017
Packit 8681c6
 *
Packit 8681c6
 * This program is provided under the terms of the Common Public License,
Packit 8681c6
 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
Packit 8681c6
 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
Packit 8681c6
 * found in the file LICENSE file or at
Packit 8681c6
 * https://opensource.org/licenses/cpl1.0.php
Packit 8681c6
 */
Packit 8681c6
Packit 8681c6
// File:  session.c
Packit 8681c6
//
Packit 8681c6
// Session manager related functions
Packit 8681c6
//
Packit 8681c6
#include <stdlib.h>
Packit 8681c6
#include <string.h>             // for memcmp() et al
Packit 8681c6
#include <pthread.h>
Packit 8681c6
Packit 8681c6
#include "pkcs11types.h"
Packit 8681c6
#include "local_types.h"
Packit 8681c6
#include "defs.h"
Packit 8681c6
#include "host_defs.h"
Packit 8681c6
#include "h_extern.h"
Packit 8681c6
#include "tok_spec_struct.h"
Packit 8681c6
#include "trace.h"
Packit 8681c6
Packit 8681c6
// session_mgr_find()
Packit 8681c6
//
Packit 8681c6
// search for the specified session. returning a pointer to the session
Packit 8681c6
// might be dangerous, but performs well.
Packit 8681c6
//
Packit 8681c6
// The returned session must be put back (using bt_put_node_value()) by the
Packit 8681c6
// caller to decrease the reference count!
Packit 8681c6
//
Packit 8681c6
// Returns:  SESSION * or NULL
Packit 8681c6
//
Packit 8681c6
SESSION *session_mgr_find(STDLL_TokData_t *tokdata, CK_SESSION_HANDLE handle)
Packit 8681c6
{
Packit 8681c6
    SESSION *result = NULL;
Packit 8681c6
Packit 8681c6
    if (!handle) {
Packit 8681c6
        return NULL;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    result = bt_get_node_value(&tokdata->sess_btree, handle);
Packit 8681c6
Packit 8681c6
    return result;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
void session_mgr_put(STDLL_TokData_t *tokdata, SESSION *session)
Packit 8681c6
{
Packit 8681c6
    bt_put_node_value(&tokdata->sess_btree, session);
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// session_mgr_new()
Packit 8681c6
//
Packit 8681c6
// creates a new session structure and adds it to the process's list
Packit 8681c6
// of sessions
Packit 8681c6
//
Packit 8681c6
// Args:  CK_ULONG      flags : session flags                   (INPUT)
Packit 8681c6
//        SESSION **     sess : new session pointer             (OUTPUT)
Packit 8681c6
//
Packit 8681c6
// Returns:  CK_RV
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_new(STDLL_TokData_t *tokdata, CK_ULONG flags,
Packit 8681c6
                      CK_SLOT_ID slot_id, CK_SESSION_HANDLE_PTR phSession)
Packit 8681c6
{
Packit 8681c6
    SESSION *new_session = NULL;
Packit 8681c6
    CK_BBOOL user_session = FALSE;
Packit 8681c6
    CK_BBOOL so_session = FALSE;
Packit 8681c6
    CK_RV rc = CKR_OK;
Packit 8681c6
Packit 8681c6
Packit 8681c6
    new_session = (SESSION *) malloc(sizeof(SESSION));
Packit 8681c6
    if (!new_session) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
        rc = CKR_HOST_MEMORY;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    memset(new_session, 0x0, sizeof(SESSION));
Packit 8681c6
Packit 8681c6
    // find an unused session handle. session handles will wrap automatically...
Packit 8681c6
    //
Packit 8681c6
    new_session->session_info.slotID = slot_id;
Packit 8681c6
    new_session->session_info.flags = flags;
Packit 8681c6
    new_session->session_info.ulDeviceError = 0;
Packit 8681c6
Packit 8681c6
Packit 8681c6
    // determine the login/logout status of the new session. PKCS 11 requires
Packit 8681c6
    // that all sessions belonging to a process have the same login/logout
Packit 8681c6
    // status
Packit 8681c6
    //
Packit 8681c6
    so_session = session_mgr_so_session_exists(tokdata);
Packit 8681c6
    user_session = session_mgr_user_session_exists(tokdata);
Packit 8681c6
Packit 8681c6
    if (pthread_rwlock_wrlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Write Lock failed.\n");
Packit 8681c6
        rc = CKR_CANT_LOCK;
Packit 8681c6
        goto done;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    // we don't have to worry about having a user and SO session at the same
Packit 8681c6
    // time. that is prevented in the login routine
Packit 8681c6
    //
Packit 8681c6
    if (user_session) {
Packit 8681c6
        if (new_session->session_info.flags & CKF_RW_SESSION) {
Packit 8681c6
            new_session->session_info.state = CKS_RW_USER_FUNCTIONS;
Packit 8681c6
        } else {
Packit 8681c6
            new_session->session_info.state = CKS_RO_USER_FUNCTIONS;
Packit 8681c6
            tokdata->ro_session_count++;
Packit 8681c6
        }
Packit 8681c6
    } else if (so_session) {
Packit 8681c6
        new_session->session_info.state = CKS_RW_SO_FUNCTIONS;
Packit 8681c6
    } else {
Packit 8681c6
        if (new_session->session_info.flags & CKF_RW_SESSION) {
Packit 8681c6
            new_session->session_info.state = CKS_RW_PUBLIC_SESSION;
Packit 8681c6
        } else {
Packit 8681c6
            new_session->session_info.state = CKS_RO_PUBLIC_SESSION;
Packit 8681c6
            tokdata->ro_session_count++;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    *phSession = bt_node_add(&tokdata->sess_btree, new_session);
Packit 8681c6
    if (*phSession == 0) {
Packit 8681c6
        rc = CKR_HOST_MEMORY;
Packit 8681c6
        /* new_session will be free'd below */
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
done:
Packit 8681c6
    if (rc != CKR_OK && new_session != NULL) {
Packit 8681c6
        TRACE_ERROR("Failed to add session to the btree.\n");
Packit 8681c6
        free(new_session);
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
// session_mgr_so_session_exists()
Packit 8681c6
//
Packit 8681c6
// determines whether a RW_SO session exists for the specified process
Packit 8681c6
//
Packit 8681c6
// Returns:  TRUE or FALSE
Packit 8681c6
//
Packit 8681c6
CK_BBOOL session_mgr_so_session_exists(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    CK_BBOOL result;
Packit 8681c6
Packit 8681c6
    /* we must acquire sess_list_rwlock in order to inspect
Packit 8681c6
     * global_login_state */
Packit 8681c6
    if (pthread_rwlock_rdlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Read Lock failed.\n");
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
    result = (tokdata->global_login_state == CKS_RW_SO_FUNCTIONS);
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return result;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
// session_mgr_user_session_exists()
Packit 8681c6
//
Packit 8681c6
// determines whether a USER session exists for the specified process
Packit 8681c6
//
Packit 8681c6
// Returns:  TRUE or FALSE
Packit 8681c6
//
Packit 8681c6
CK_BBOOL session_mgr_user_session_exists(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    CK_BBOOL result;
Packit 8681c6
Packit 8681c6
    /* we must acquire sess_list_rwlock in order to inspect
Packit 8681c6
     * glogal_login_state */
Packit 8681c6
    if (pthread_rwlock_rdlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Read Lock failed.\n");
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
    result = ((tokdata->global_login_state == CKS_RO_USER_FUNCTIONS) ||
Packit 8681c6
              (tokdata->global_login_state == CKS_RW_USER_FUNCTIONS));
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return result;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
// session_mgr_public_session_exists()
Packit 8681c6
//
Packit 8681c6
// determines whether a PUBLIC session exists for the specified process
Packit 8681c6
//
Packit 8681c6
// Returns:  TRUE or FALSE
Packit 8681c6
//
Packit 8681c6
CK_BBOOL session_mgr_public_session_exists(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    CK_BBOOL result;
Packit 8681c6
Packit 8681c6
    /* we must acquire sess_list_rwlock in order to inspect
Packit 8681c6
     * global_login_state */
Packit 8681c6
    if (pthread_rwlock_rdlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Read Lock failed.\n");
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
    result = ((tokdata->global_login_state == CKS_RO_PUBLIC_SESSION) ||
Packit 8681c6
              (tokdata->global_login_state == CKS_RW_PUBLIC_SESSION));
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return result;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
// session_mgr_readonly_exists()
Packit 8681c6
//
Packit 8681c6
// determines whether the specified process owns any read-only sessions. this is
Packit 8681c6
// useful because the SO cannot log in if a read-only session exists.
Packit 8681c6
//
Packit 8681c6
CK_BBOOL session_mgr_readonly_session_exists(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    CK_BBOOL result;
Packit 8681c6
Packit 8681c6
    /* we must acquire sess_list_rwlock in order to inspect ro_session_count */
Packit 8681c6
    if (pthread_rwlock_rdlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Read Lock failed.\n");
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    result = (tokdata->ro_session_count > 0);
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return result;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
// session_mgr_close_session()
Packit 8681c6
//
Packit 8681c6
// removes the specified session from the process' session list
Packit 8681c6
//
Packit 8681c6
// Args:   PROCESS *    proc  :  parent process
Packit 8681c6
//         SESSION * session  :  session to remove
Packit 8681c6
//
Packit 8681c6
// Returns:  TRUE on success else FALSE
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_close_session(STDLL_TokData_t *tokdata,
Packit 8681c6
                                CK_SESSION_HANDLE handle)
Packit 8681c6
{
Packit 8681c6
    SESSION *sess;
Packit 8681c6
    CK_RV rc = CKR_OK;
Packit 8681c6
Packit 8681c6
    sess = bt_get_node_value(&tokdata->sess_btree, handle);
Packit 8681c6
    if (!sess) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID));
Packit 8681c6
        return CKR_SESSION_HANDLE_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (pthread_rwlock_wrlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Write Lock failed.\n");
Packit 8681c6
        bt_put_node_value(&tokdata->sess_btree, sess);
Packit 8681c6
        sess = NULL;
Packit 8681c6
        return CKR_CANT_LOCK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    object_mgr_purge_session_objects(tokdata, sess, ALL);
Packit 8681c6
Packit 8681c6
    if ((sess->session_info.state == CKS_RO_PUBLIC_SESSION) ||
Packit 8681c6
        (sess->session_info.state == CKS_RO_USER_FUNCTIONS)) {
Packit 8681c6
        tokdata->ro_session_count--;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    // Make sure this address is now invalid
Packit 8681c6
    sess->handle = CK_INVALID_HANDLE;
Packit 8681c6
Packit 8681c6
    if (sess->find_list)
Packit 8681c6
        free(sess->find_list);
Packit 8681c6
Packit 8681c6
    if (sess->encr_ctx.context)
Packit 8681c6
        free(sess->encr_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->encr_ctx.mech.pParameter)
Packit 8681c6
        free(sess->encr_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.context)
Packit 8681c6
        free(sess->decr_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.mech.pParameter)
Packit 8681c6
        free(sess->decr_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.context)
Packit 8681c6
        free(sess->digest_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.mech.pParameter)
Packit 8681c6
        free(sess->digest_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.context)
Packit 8681c6
        free(sess->sign_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.mech.pParameter)
Packit 8681c6
        free(sess->sign_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.context)
Packit 8681c6
        free(sess->verify_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.mech.pParameter)
Packit 8681c6
        free(sess->verify_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    bt_put_node_value(&tokdata->sess_btree, sess);
Packit 8681c6
    sess = NULL;
Packit 8681c6
    bt_node_free(&tokdata->sess_btree, handle, TRUE);
Packit 8681c6
Packit 8681c6
    // XXX XXX  Not having this is a problem
Packit 8681c6
    //  for IHS.  The spec states that there is an implicit logout
Packit 8681c6
    //  when the last session is closed.  Cannonicaly this is what other
Packit 8681c6
    //  implementaitons do.  however on linux for some reason IHS can't seem
Packit 8681c6
    //  to keep the session open, which means that they go through the login
Packit 8681c6
    //  path EVERY time, which of course causes a reload of the private
Packit 8681c6
    //  objects EVERY time.   If we are logged out, we MUST purge the private
Packit 8681c6
    //  objects from this process..
Packit 8681c6
    //
Packit 8681c6
    if (bt_is_empty(&tokdata->sess_btree)) {
Packit 8681c6
        // SAB  XXX  if all sessions are closed.  Is this effectivly logging out
Packit 8681c6
        if (token_specific.t_logout) {
Packit 8681c6
            rc = token_specific.t_logout(tokdata);
Packit 8681c6
        }
Packit 8681c6
        object_mgr_purge_private_token_objects(tokdata);
Packit 8681c6
Packit 8681c6
        tokdata->global_login_state = CKS_RO_PUBLIC_SESSION;
Packit 8681c6
        // The objects really need to be purged .. but this impacts the
Packit 8681c6
        // performance under linux.   So we need to make sure that the
Packit 8681c6
        // login state is valid.    I don't really like this.
Packit 8681c6
        object_mgr_purge_map(tokdata, (SESSION *) 0xFFFF, PRIVATE);
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
/* session_free
Packit 8681c6
 *
Packit 8681c6
 * Callback used to free an individual SESSION object
Packit 8681c6
 */
Packit 8681c6
void session_free(STDLL_TokData_t *tokdata, void *node_value,
Packit 8681c6
                  unsigned long node_idx, void *p3)
Packit 8681c6
{
Packit 8681c6
    SESSION *sess = (SESSION *) node_value;
Packit 8681c6
Packit 8681c6
    UNUSED(p3);
Packit 8681c6
Packit 8681c6
    object_mgr_purge_session_objects(tokdata, sess, ALL);
Packit 8681c6
    sess->handle = CK_INVALID_HANDLE;
Packit 8681c6
Packit 8681c6
    if (sess->find_list)
Packit 8681c6
        free(sess->find_list);
Packit 8681c6
Packit 8681c6
    if (sess->encr_ctx.context)
Packit 8681c6
        free(sess->encr_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->encr_ctx.mech.pParameter)
Packit 8681c6
        free(sess->encr_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.context)
Packit 8681c6
        free(sess->decr_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.mech.pParameter)
Packit 8681c6
        free(sess->decr_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.context)
Packit 8681c6
        free(sess->digest_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.mech.pParameter)
Packit 8681c6
        free(sess->digest_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.context)
Packit 8681c6
        free(sess->sign_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.mech.pParameter)
Packit 8681c6
        free(sess->sign_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.context)
Packit 8681c6
        free(sess->verify_ctx.context);
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.mech.pParameter)
Packit 8681c6
        free(sess->verify_ctx.mech.pParameter);
Packit 8681c6
Packit 8681c6
    /* NB: any access to sess or @node_value after this returns will segfault */
Packit 8681c6
    bt_node_free(&tokdata->sess_btree, node_idx, TRUE);
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// session_mgr_close_all_sessions()
Packit 8681c6
//
Packit 8681c6
// removes all sessions from the specified process.
Packit 8681c6
// If tokdata is not NULL, then only sessions for that token instance are
Packit 8681c6
// removed.
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_close_all_sessions(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    bt_for_each_node(tokdata, &tokdata->sess_btree, session_free, NULL);
Packit 8681c6
Packit 8681c6
    if (pthread_rwlock_wrlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Write Lock failed.\n");
Packit 8681c6
        return CKR_CANT_LOCK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    tokdata->global_login_state = CKS_RO_PUBLIC_SESSION;
Packit 8681c6
    tokdata->ro_session_count = 0;
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
/* session_login
Packit 8681c6
 *
Packit 8681c6
 * Callback used to update a SESSION object's login state to logged in based on
Packit 8681c6
 * user type
Packit 8681c6
 */
Packit 8681c6
void session_login(STDLL_TokData_t *tokdata, void *node_value,
Packit 8681c6
                   unsigned long node_idx, void *p3)
Packit 8681c6
{
Packit 8681c6
    SESSION *s = (SESSION *) node_value;
Packit 8681c6
    CK_USER_TYPE user_type = *(CK_USER_TYPE *) p3;
Packit 8681c6
Packit 8681c6
    UNUSED(tokdata);
Packit 8681c6
    UNUSED(node_idx);
Packit 8681c6
Packit 8681c6
    if (s->session_info.flags & CKF_RW_SESSION) {
Packit 8681c6
        if (user_type == CKU_USER)
Packit 8681c6
            s->session_info.state = CKS_RW_USER_FUNCTIONS;
Packit 8681c6
        else
Packit 8681c6
            s->session_info.state = CKS_RW_SO_FUNCTIONS;
Packit 8681c6
    } else {
Packit 8681c6
        if (user_type == CKU_USER)
Packit 8681c6
            s->session_info.state = CKS_RO_USER_FUNCTIONS;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    tokdata->global_login_state = s->session_info.state; // SAB
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// session_mgr_login_all()
Packit 8681c6
//
Packit 8681c6
// changes the login status of all sessions in the token
Packit 8681c6
//
Packit 8681c6
// Arg:  CK_USER_TYPE  user_type : USER or SO
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_login_all(STDLL_TokData_t *tokdata, CK_USER_TYPE user_type)
Packit 8681c6
{
Packit 8681c6
    if (pthread_rwlock_wrlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Write Lock failed.\n");
Packit 8681c6
        return CKR_CANT_LOCK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    bt_for_each_node(tokdata, &tokdata->sess_btree, session_login,
Packit 8681c6
                     (void *)&user_type);
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
/* session_logout
Packit 8681c6
 *
Packit 8681c6
 * Callback used to update a SESSION object's login state to be logged out
Packit 8681c6
 */
Packit 8681c6
void session_logout(STDLL_TokData_t *tokdata, void *node_value,
Packit 8681c6
                    unsigned long node_idx, void *p3)
Packit 8681c6
{
Packit 8681c6
    SESSION *s = (SESSION *) node_value;
Packit 8681c6
Packit 8681c6
    UNUSED(node_idx);
Packit 8681c6
    UNUSED(p3);
Packit 8681c6
Packit 8681c6
    // all sessions get logged out so destroy any private objects
Packit 8681c6
    // public objects are left alone
Packit 8681c6
    //
Packit 8681c6
    object_mgr_purge_session_objects(tokdata, s, PRIVATE);
Packit 8681c6
Packit 8681c6
    if (s->session_info.flags & CKF_RW_SESSION)
Packit 8681c6
        s->session_info.state = CKS_RW_PUBLIC_SESSION;
Packit 8681c6
    else
Packit 8681c6
        s->session_info.state = CKS_RO_PUBLIC_SESSION;
Packit 8681c6
Packit 8681c6
    tokdata->global_login_state = s->session_info.state; // SAB
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// session_mgr_logout_all()
Packit 8681c6
//
Packit 8681c6
// changes the login status of all sessions in the token
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_logout_all(STDLL_TokData_t *tokdata)
Packit 8681c6
{
Packit 8681c6
    if (pthread_rwlock_wrlock(&tokdata->sess_list_rwlock)) {
Packit 8681c6
        TRACE_ERROR("Write Lock failed.\n");
Packit 8681c6
        return CKR_CANT_LOCK;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    bt_for_each_node(tokdata, &tokdata->sess_btree, session_logout, NULL);
Packit 8681c6
Packit 8681c6
    pthread_rwlock_unlock(&tokdata->sess_list_rwlock);
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
//
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_get_op_state(SESSION *sess,
Packit 8681c6
                               CK_BBOOL length_only,
Packit 8681c6
                               CK_BYTE *data, CK_ULONG *data_len)
Packit 8681c6
{
Packit 8681c6
    OP_STATE_DATA *op_data = NULL;
Packit 8681c6
    CK_ULONG op_data_len = 0;
Packit 8681c6
    CK_ULONG offset, active_ops;
Packit 8681c6
Packit 8681c6
    if (!sess) {
Packit 8681c6
        TRACE_ERROR("Invalid function arguments.\n");
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (sess->find_active == TRUE) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
        return CKR_STATE_UNSAVEABLE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    // ensure that at least one operation is active
Packit 8681c6
    //
Packit 8681c6
    active_ops = 0;
Packit 8681c6
Packit 8681c6
    if (sess->encr_ctx.active == TRUE) {
Packit 8681c6
        active_ops++;
Packit 8681c6
        if (op_data != NULL) {
Packit 8681c6
            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
            return CKR_STATE_UNSAVEABLE;
Packit 8681c6
        }
Packit 8681c6
        op_data_len = sizeof(OP_STATE_DATA) +
Packit 8681c6
            sizeof(ENCR_DECR_CONTEXT) +
Packit 8681c6
            sess->encr_ctx.context_len + sess->encr_ctx.mech.ulParameterLen;
Packit 8681c6
Packit 8681c6
        if (length_only == FALSE) {
Packit 8681c6
            op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
            op_data->data_len = op_data_len - sizeof(OP_STATE_DATA);
Packit 8681c6
            op_data->session_state = sess->session_info.state;
Packit 8681c6
            op_data->active_operation = STATE_ENCR;
Packit 8681c6
Packit 8681c6
            offset = sizeof(OP_STATE_DATA);
Packit 8681c6
Packit 8681c6
            memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                   &sess->encr_ctx, sizeof(ENCR_DECR_CONTEXT));
Packit 8681c6
Packit 8681c6
            offset += sizeof(ENCR_DECR_CONTEXT);
Packit 8681c6
Packit 8681c6
            if (sess->encr_ctx.context_len != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->encr_ctx.context, sess->encr_ctx.context_len);
Packit 8681c6
Packit 8681c6
                offset += sess->encr_ctx.context_len;
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (sess->encr_ctx.mech.ulParameterLen != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->encr_ctx.mech.pParameter,
Packit 8681c6
                       sess->encr_ctx.mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.active == TRUE) {
Packit 8681c6
        active_ops++;
Packit 8681c6
        if (op_data != NULL) {
Packit 8681c6
            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
            return CKR_STATE_UNSAVEABLE;
Packit 8681c6
        }
Packit 8681c6
        op_data_len = sizeof(OP_STATE_DATA) +
Packit 8681c6
            sizeof(ENCR_DECR_CONTEXT) +
Packit 8681c6
            sess->decr_ctx.context_len + sess->decr_ctx.mech.ulParameterLen;
Packit 8681c6
Packit 8681c6
        if (length_only == FALSE) {
Packit 8681c6
            op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
            op_data->data_len = op_data_len - sizeof(OP_STATE_DATA);
Packit 8681c6
            op_data->session_state = sess->session_info.state;
Packit 8681c6
            op_data->active_operation = STATE_DECR;
Packit 8681c6
Packit 8681c6
            offset = sizeof(OP_STATE_DATA);
Packit 8681c6
Packit 8681c6
            memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                   &sess->decr_ctx, sizeof(ENCR_DECR_CONTEXT));
Packit 8681c6
Packit 8681c6
            offset += sizeof(ENCR_DECR_CONTEXT);
Packit 8681c6
Packit 8681c6
            if (sess->decr_ctx.context_len != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->decr_ctx.context, sess->decr_ctx.context_len);
Packit 8681c6
Packit 8681c6
                offset += sess->decr_ctx.context_len;
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (sess->decr_ctx.mech.ulParameterLen != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->decr_ctx.mech.pParameter,
Packit 8681c6
                       sess->decr_ctx.mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.active == TRUE) {
Packit 8681c6
        active_ops++;
Packit 8681c6
        if (op_data != NULL) {
Packit 8681c6
            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
            return CKR_STATE_UNSAVEABLE;
Packit 8681c6
        }
Packit 8681c6
        op_data_len = sizeof(OP_STATE_DATA) +
Packit 8681c6
            sizeof(DIGEST_CONTEXT) +
Packit 8681c6
            sess->digest_ctx.context_len + sess->digest_ctx.mech.ulParameterLen;
Packit 8681c6
Packit 8681c6
        if (length_only == FALSE) {
Packit 8681c6
            op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
            op_data->data_len = op_data_len - sizeof(OP_STATE_DATA);
Packit 8681c6
            op_data->session_state = sess->session_info.state;
Packit 8681c6
            op_data->active_operation = STATE_DIGEST;
Packit 8681c6
Packit 8681c6
            offset = sizeof(OP_STATE_DATA);
Packit 8681c6
Packit 8681c6
            memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                   &sess->digest_ctx, sizeof(DIGEST_CONTEXT));
Packit 8681c6
Packit 8681c6
            offset += sizeof(DIGEST_CONTEXT);
Packit 8681c6
Packit 8681c6
            if (sess->digest_ctx.context_len != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->digest_ctx.context, sess->digest_ctx.context_len);
Packit 8681c6
Packit 8681c6
                offset += sess->digest_ctx.context_len;
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (sess->digest_ctx.mech.ulParameterLen != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->digest_ctx.mech.pParameter,
Packit 8681c6
                       sess->digest_ctx.mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.active == TRUE) {
Packit 8681c6
        active_ops++;
Packit 8681c6
        if (op_data != NULL) {
Packit 8681c6
            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
            return CKR_STATE_UNSAVEABLE;
Packit 8681c6
        }
Packit 8681c6
        op_data_len = sizeof(OP_STATE_DATA) +
Packit 8681c6
            sizeof(SIGN_VERIFY_CONTEXT) +
Packit 8681c6
            sess->sign_ctx.context_len + sess->sign_ctx.mech.ulParameterLen;
Packit 8681c6
Packit 8681c6
        if (length_only == FALSE) {
Packit 8681c6
            op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
            op_data->data_len = op_data_len - sizeof(OP_STATE_DATA);
Packit 8681c6
            op_data->session_state = sess->session_info.state;
Packit 8681c6
            op_data->active_operation = STATE_SIGN;
Packit 8681c6
Packit 8681c6
            offset = sizeof(OP_STATE_DATA);
Packit 8681c6
Packit 8681c6
            memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                   &sess->sign_ctx, sizeof(SIGN_VERIFY_CONTEXT));
Packit 8681c6
Packit 8681c6
            offset += sizeof(SIGN_VERIFY_CONTEXT);
Packit 8681c6
Packit 8681c6
            if (sess->sign_ctx.context_len != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->sign_ctx.context, sess->sign_ctx.context_len);
Packit 8681c6
Packit 8681c6
                offset += sess->sign_ctx.context_len;
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (sess->sign_ctx.mech.ulParameterLen != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->sign_ctx.mech.pParameter,
Packit 8681c6
                       sess->sign_ctx.mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.active == TRUE) {
Packit 8681c6
        active_ops++;
Packit 8681c6
        if (op_data != NULL) {
Packit 8681c6
            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
            return CKR_STATE_UNSAVEABLE;
Packit 8681c6
        }
Packit 8681c6
        op_data_len = sizeof(OP_STATE_DATA) +
Packit 8681c6
            sizeof(SIGN_VERIFY_CONTEXT) +
Packit 8681c6
            sess->verify_ctx.context_len + sess->verify_ctx.mech.ulParameterLen;
Packit 8681c6
Packit 8681c6
        if (length_only == FALSE) {
Packit 8681c6
            op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
            op_data->data_len = op_data_len - sizeof(OP_STATE_DATA);
Packit 8681c6
            op_data->session_state = sess->session_info.state;
Packit 8681c6
            op_data->active_operation = STATE_SIGN;
Packit 8681c6
Packit 8681c6
            offset = sizeof(OP_STATE_DATA);
Packit 8681c6
Packit 8681c6
            memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                   &sess->verify_ctx, sizeof(SIGN_VERIFY_CONTEXT));
Packit 8681c6
Packit 8681c6
            offset += sizeof(SIGN_VERIFY_CONTEXT);
Packit 8681c6
Packit 8681c6
            if (sess->verify_ctx.context_len != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->verify_ctx.context, sess->verify_ctx.context_len);
Packit 8681c6
Packit 8681c6
                offset += sess->verify_ctx.context_len;
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (sess->verify_ctx.mech.ulParameterLen != 0) {
Packit 8681c6
                memcpy((CK_BYTE *) op_data + offset,
Packit 8681c6
                       sess->verify_ctx.mech.pParameter,
Packit 8681c6
                       sess->verify_ctx.mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    if (!active_ops) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
Packit 8681c6
        return CKR_OPERATION_NOT_INITIALIZED;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    *data_len = op_data_len;
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
//
Packit 8681c6
//
Packit 8681c6
CK_RV session_mgr_set_op_state(SESSION *sess,
Packit 8681c6
                               CK_OBJECT_HANDLE encr_key,
Packit 8681c6
                               CK_OBJECT_HANDLE auth_key,
Packit 8681c6
                               CK_BYTE *data, CK_ULONG data_len)
Packit 8681c6
{
Packit 8681c6
    OP_STATE_DATA *op_data = NULL;
Packit 8681c6
    CK_BYTE *mech_param = NULL;
Packit 8681c6
    CK_BYTE *context = NULL;
Packit 8681c6
    CK_BYTE *ptr1 = NULL;
Packit 8681c6
    CK_BYTE *ptr2 = NULL;
Packit 8681c6
    CK_BYTE *ptr3 = NULL;
Packit 8681c6
    CK_ULONG len;
Packit 8681c6
Packit 8681c6
    UNUSED(data_len);
Packit 8681c6
Packit 8681c6
    if (!sess || !data) {
Packit 8681c6
        TRACE_ERROR("%s received bad argument(s)\n", __func__);
Packit 8681c6
        return CKR_FUNCTION_FAILED;
Packit 8681c6
    }
Packit 8681c6
    op_data = (OP_STATE_DATA *) data;
Packit 8681c6
Packit 8681c6
    // make sure the session states are compatible
Packit 8681c6
    //
Packit 8681c6
    if (sess->session_info.state != op_data->session_state) {
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID));
Packit 8681c6
        return CKR_SAVED_STATE_INVALID;
Packit 8681c6
    }
Packit 8681c6
    // validate the new state information.  don't touch the session
Packit 8681c6
    // until the new state is valid.
Packit 8681c6
    //
Packit 8681c6
    switch (op_data->active_operation) {
Packit 8681c6
    case STATE_ENCR:
Packit 8681c6
    case STATE_DECR:
Packit 8681c6
        {
Packit 8681c6
            ENCR_DECR_CONTEXT *ctx =
Packit 8681c6
                (ENCR_DECR_CONTEXT *) (data + sizeof(OP_STATE_DATA));
Packit 8681c6
Packit 8681c6
            len =
Packit 8681c6
                sizeof(ENCR_DECR_CONTEXT) + ctx->context_len +
Packit 8681c6
                ctx->mech.ulParameterLen;
Packit 8681c6
            if (len != op_data->data_len) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID));
Packit 8681c6
                return CKR_SAVED_STATE_INVALID;
Packit 8681c6
            }
Packit 8681c6
            if (auth_key != 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED));
Packit 8681c6
                return CKR_KEY_NOT_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            if (encr_key == 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NEEDED));
Packit 8681c6
                return CKR_KEY_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            ptr1 = (CK_BYTE *) ctx;
Packit 8681c6
            ptr2 = ptr1 + sizeof(ENCR_DECR_CONTEXT);
Packit 8681c6
            ptr3 = ptr2 + ctx->context_len;
Packit 8681c6
Packit 8681c6
            if (ctx->context_len) {
Packit 8681c6
                context = (CK_BYTE *) malloc(ctx->context_len);
Packit 8681c6
                if (!context) {
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(context, ptr2, ctx->context_len);
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (ctx->mech.ulParameterLen) {
Packit 8681c6
                mech_param = (CK_BYTE *) malloc(ctx->mech.ulParameterLen);
Packit 8681c6
                if (!mech_param) {
Packit 8681c6
                    if (context)
Packit 8681c6
                        free(context);
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(mech_param, ptr3, ctx->mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
        break;
Packit 8681c6
    case STATE_SIGN:
Packit 8681c6
    case STATE_VERIFY:
Packit 8681c6
        {
Packit 8681c6
            SIGN_VERIFY_CONTEXT *ctx =
Packit 8681c6
                (SIGN_VERIFY_CONTEXT *) (data + sizeof(OP_STATE_DATA));
Packit 8681c6
Packit 8681c6
            len =
Packit 8681c6
                sizeof(SIGN_VERIFY_CONTEXT) + ctx->context_len +
Packit 8681c6
                ctx->mech.ulParameterLen;
Packit 8681c6
            if (len != op_data->data_len) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID));
Packit 8681c6
                return CKR_SAVED_STATE_INVALID;
Packit 8681c6
            }
Packit 8681c6
            if (auth_key == 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NEEDED));
Packit 8681c6
                return CKR_KEY_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            if (encr_key != 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED));
Packit 8681c6
                return CKR_KEY_NOT_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            ptr1 = (CK_BYTE *) ctx;
Packit 8681c6
            ptr2 = ptr1 + sizeof(SIGN_VERIFY_CONTEXT);
Packit 8681c6
            ptr3 = ptr2 + ctx->context_len;
Packit 8681c6
Packit 8681c6
            if (ctx->context_len) {
Packit 8681c6
                context = (CK_BYTE *) malloc(ctx->context_len);
Packit 8681c6
                if (!context) {
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(context, ptr2, ctx->context_len);
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (ctx->mech.ulParameterLen) {
Packit 8681c6
                mech_param = (CK_BYTE *) malloc(ctx->mech.ulParameterLen);
Packit 8681c6
                if (!mech_param) {
Packit 8681c6
                    if (context)
Packit 8681c6
                        free(context);
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(mech_param, ptr3, ctx->mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
        break;
Packit 8681c6
    case STATE_DIGEST:
Packit 8681c6
        {
Packit 8681c6
            DIGEST_CONTEXT *ctx =
Packit 8681c6
                (DIGEST_CONTEXT *) (data + sizeof(OP_STATE_DATA));
Packit 8681c6
Packit 8681c6
            len =
Packit 8681c6
                sizeof(DIGEST_CONTEXT) + ctx->context_len +
Packit 8681c6
                ctx->mech.ulParameterLen;
Packit 8681c6
            if (len != op_data->data_len) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID));
Packit 8681c6
                return CKR_SAVED_STATE_INVALID;
Packit 8681c6
            }
Packit 8681c6
            if (auth_key != 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED));
Packit 8681c6
                return CKR_KEY_NOT_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            if (encr_key != 0) {
Packit 8681c6
                TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED));
Packit 8681c6
                return CKR_KEY_NOT_NEEDED;
Packit 8681c6
            }
Packit 8681c6
            ptr1 = (CK_BYTE *) ctx;
Packit 8681c6
            ptr2 = ptr1 + sizeof(DIGEST_CONTEXT);
Packit 8681c6
            ptr3 = ptr2 + ctx->context_len;
Packit 8681c6
Packit 8681c6
            if (ctx->context_len) {
Packit 8681c6
                context = (CK_BYTE *) malloc(ctx->context_len);
Packit 8681c6
                if (!context) {
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(context, ptr2, ctx->context_len);
Packit 8681c6
            }
Packit 8681c6
Packit 8681c6
            if (ctx->mech.ulParameterLen) {
Packit 8681c6
                mech_param = (CK_BYTE *) malloc(ctx->mech.ulParameterLen);
Packit 8681c6
                if (!mech_param) {
Packit 8681c6
                    if (context)
Packit 8681c6
                        free(context);
Packit 8681c6
                    TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
Packit 8681c6
                    return CKR_HOST_MEMORY;
Packit 8681c6
                }
Packit 8681c6
                memcpy(mech_param, ptr3, ctx->mech.ulParameterLen);
Packit 8681c6
            }
Packit 8681c6
        }
Packit 8681c6
        break;
Packit 8681c6
    default:
Packit 8681c6
        TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID));
Packit 8681c6
        return CKR_SAVED_STATE_INVALID;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
Packit 8681c6
    // state information looks okay.  cleanup the current session state, first
Packit 8681c6
    //
Packit 8681c6
    if (sess->encr_ctx.active)
Packit 8681c6
        encr_mgr_cleanup(&sess->encr_ctx);
Packit 8681c6
Packit 8681c6
    if (sess->decr_ctx.active)
Packit 8681c6
        decr_mgr_cleanup(&sess->decr_ctx);
Packit 8681c6
Packit 8681c6
    if (sess->digest_ctx.active)
Packit 8681c6
        digest_mgr_cleanup(&sess->digest_ctx);
Packit 8681c6
Packit 8681c6
    if (sess->sign_ctx.active)
Packit 8681c6
        sign_mgr_cleanup(&sess->sign_ctx);
Packit 8681c6
Packit 8681c6
    if (sess->verify_ctx.active)
Packit 8681c6
        verify_mgr_cleanup(&sess->verify_ctx);
Packit 8681c6
Packit 8681c6
Packit 8681c6
    // copy the new state information
Packit 8681c6
    //
Packit 8681c6
    switch (op_data->active_operation) {
Packit 8681c6
    case STATE_ENCR:
Packit 8681c6
        memcpy(&sess->encr_ctx, ptr1, sizeof(ENCR_DECR_CONTEXT));
Packit 8681c6
Packit 8681c6
        sess->encr_ctx.key = encr_key;
Packit 8681c6
        sess->encr_ctx.context = context;
Packit 8681c6
        sess->encr_ctx.mech.pParameter = mech_param;
Packit 8681c6
        break;
Packit 8681c6
    case STATE_DECR:
Packit 8681c6
        memcpy(&sess->decr_ctx, ptr1, sizeof(ENCR_DECR_CONTEXT));
Packit 8681c6
Packit 8681c6
        sess->decr_ctx.key = encr_key;
Packit 8681c6
        sess->decr_ctx.context = context;
Packit 8681c6
        sess->decr_ctx.mech.pParameter = mech_param;
Packit 8681c6
        break;
Packit 8681c6
    case STATE_SIGN:
Packit 8681c6
        memcpy(&sess->sign_ctx, ptr1, sizeof(SIGN_VERIFY_CONTEXT));
Packit 8681c6
Packit 8681c6
        sess->sign_ctx.key = auth_key;
Packit 8681c6
        sess->sign_ctx.context = context;
Packit 8681c6
        sess->sign_ctx.mech.pParameter = mech_param;
Packit 8681c6
        break;
Packit 8681c6
    case STATE_VERIFY:
Packit 8681c6
        memcpy(&sess->verify_ctx, ptr1, sizeof(SIGN_VERIFY_CONTEXT));
Packit 8681c6
Packit 8681c6
        sess->verify_ctx.key = auth_key;
Packit 8681c6
        sess->verify_ctx.context = context;
Packit 8681c6
        sess->verify_ctx.mech.pParameter = mech_param;
Packit 8681c6
        break;
Packit 8681c6
    case STATE_DIGEST:
Packit 8681c6
        memcpy(&sess->digest_ctx, ptr1, sizeof(DIGEST_CONTEXT));
Packit 8681c6
Packit 8681c6
        sess->digest_ctx.context = context;
Packit 8681c6
        sess->digest_ctx.mech.pParameter = mech_param;
Packit 8681c6
        break;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// Return TRUE if the session we're in has its PIN expired.
Packit 8681c6
CK_BBOOL pin_expired(CK_SESSION_INFO *si, CK_FLAGS flags)
Packit 8681c6
{
Packit 8681c6
    // If this is an SO session
Packit 8681c6
    if ((flags & CKF_SO_PIN_TO_BE_CHANGED) &&
Packit 8681c6
        (si->state == CKS_RW_SO_FUNCTIONS))
Packit 8681c6
        return TRUE;
Packit 8681c6
Packit 8681c6
    // Else we're a User session
Packit 8681c6
    return ((flags & CKF_USER_PIN_TO_BE_CHANGED) &&
Packit 8681c6
            ((si->state == CKS_RO_USER_FUNCTIONS) ||
Packit 8681c6
             (si->state == CKS_RW_USER_FUNCTIONS)));
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// Return TRUE if the session we're in has its PIN locked.
Packit 8681c6
CK_BBOOL pin_locked(CK_SESSION_INFO *si, CK_FLAGS flags)
Packit 8681c6
{
Packit 8681c6
    // If this is an SO session
Packit 8681c6
    if ((flags & CKF_SO_PIN_LOCKED) && (si->state == CKS_RW_SO_FUNCTIONS))
Packit 8681c6
        return TRUE;
Packit 8681c6
Packit 8681c6
    // Else we're a User session
Packit 8681c6
    return ((flags & CKF_USER_PIN_LOCKED) &&
Packit 8681c6
            ((si->state == CKS_RO_USER_FUNCTIONS) ||
Packit 8681c6
             (si->state == CKS_RW_USER_FUNCTIONS)));
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
// Increment the login flags after an incorrect password
Packit 8681c6
// has been passed to C_Login. New for v2.11. - KEY
Packit 8681c6
void set_login_flags(CK_USER_TYPE userType, CK_FLAGS_32 *flags)
Packit 8681c6
{
Packit 8681c6
    if (userType == CKU_USER) {
Packit 8681c6
        if (*flags & CKF_USER_PIN_FINAL_TRY) {
Packit 8681c6
            *flags |= CKF_USER_PIN_LOCKED;
Packit 8681c6
            *flags &= ~(CKF_USER_PIN_FINAL_TRY);
Packit 8681c6
        } else if (*flags & CKF_USER_PIN_COUNT_LOW) {
Packit 8681c6
            *flags |= CKF_USER_PIN_FINAL_TRY;
Packit 8681c6
            *flags &= ~(CKF_USER_PIN_COUNT_LOW);
Packit 8681c6
        } else {
Packit 8681c6
            *flags |= CKF_USER_PIN_COUNT_LOW;
Packit 8681c6
        }
Packit 8681c6
    } else {
Packit 8681c6
        if (*flags & CKF_SO_PIN_FINAL_TRY) {
Packit 8681c6
            *flags |= CKF_SO_PIN_LOCKED;
Packit 8681c6
            *flags &= ~(CKF_SO_PIN_FINAL_TRY);
Packit 8681c6
        } else if (*flags & CKF_SO_PIN_COUNT_LOW) {
Packit 8681c6
            *flags |= CKF_SO_PIN_FINAL_TRY;
Packit 8681c6
            *flags &= ~(CKF_SO_PIN_COUNT_LOW);
Packit 8681c6
        } else {
Packit 8681c6
            *flags |= CKF_SO_PIN_COUNT_LOW;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
}