obj_mgr.c revision 47e946e784719ae402ace34695f67b0e6e76ae5c
/*
* Common Public License Version 0.5
*
* THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF
* THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE,
* REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
*
* 1. DEFINITIONS
*
* "Contribution" means:
* a) in the case of the initial Contributor, the
* initial code and documentation distributed under
* this Agreement, and
*
* b) in the case of each subsequent Contributor:
* i) changes to the Program, and
* ii) additions to the Program;
*
* where such changes and/or additions to the Program
* originate from and are distributed by that
* particular Contributor. A Contribution 'originates'
* from a Contributor if it was added to the Program
* by such Contributor itself or anyone acting on such
* Contributor's behalf. Contributions do not include
* additions to the Program which: (i) are separate
* modules of software distributed in conjunction with
* the Program under their own license agreement, and
* (ii) are not derivative works of the Program.
*
*
* "Contributor" means any person or entity that distributes
* the Program.
*
* "Licensed Patents " mean patent claims licensable by a
* Contributor which are necessarily infringed by the use or
* sale of its Contribution alone or when combined with the
* Program.
*
* "Program" means the Contributions distributed in
* accordance with this Agreement.
*
* "Recipient" means anyone who receives the Program under
* this Agreement, including all Contributors.
*
* 2. GRANT OF RIGHTS
*
* a) Subject to the terms of this Agreement, each
* Contributor hereby grants Recipient a
* no - exclusive, worldwide, royalt - free copyright
* license to reproduce, prepare derivative works of,
* publicly display, publicly perform, distribute and
* sublicense the Contribution of such Contributor, if
* any, and such derivative works, in source code and
* object code form.
*
* b) Subject to the terms of this Agreement, each
* Contributor hereby grants Recipient a
* no - exclusive, worldwide, royalt - free patent
* license under Licensed Patents to make, use, sell,
* offer to sell, import and otherwise transfer the
* Contribution of such Contributor, if any, in source
* code and object code form. This patent license
* shall apply to the combination of the Contribution
* and the Program if, at the time the Contribution is
* added by the Contributor, such addition of the
* Contribution causes such combination to be covered
* by the Licensed Patents. The patent license shall
* not apply to any other combinations which include
* the Contribution. No hardware per se is licensed
* hereunder.
*
* c) Recipient understands that although each
* Contributor grants the licenses to its
* Contributions set forth herein, no assurances are
* provided by any Contributor that the Program does
* not infringe the patent or other intellectual
* property rights of any other entity. Each
* Contributor disclaims any liability to Recipient
* for claims brought by any other entity based on
* infringement of intellectual property rights or
* otherwise. As a condition to exercising the rights
* and licenses granted hereunder, each Recipient
* hereby assumes sole responsibility to secure any
* other intellectual property rights needed, if any.
*
* For example, if a third party patent license is
* required to allow Recipient to distribute the
* Program, it is Recipient's responsibility to
* acquire that license before distributing the
* Program.
*
* d) Each Contributor represents that to its
* knowledge it has sufficient copyright rights in its
* Contribution, if any, to grant the copyright
* license set forth in this Agreement.
*
* 3. REQUIREMENTS
*
* A Contributor may choose to distribute the Program in
* object code form under its own license agreement, provided
* that:
* a) it complies with the terms and conditions of
* this Agreement; and
*
* b) its license agreement:
* i) effectively disclaims on behalf of all
* Contributors all warranties and conditions, express
* and implied, including warranties or conditions of
* title and no - infringement, and implied warranties
* or conditions of merchantability and fitness for a
* particular purpose;
*
* ii) effectively excludes on behalf of all
* Contributors all liability for damages, including
* direct, indirect, special, incidental and
* consequential damages, such as lost profits;
*
* iii) states that any provisions which differ from
* this Agreement are offered by that Contributor
* alone and not by any other party; and
*
* iv) states that source code for the Program is
* available from such Contributor, and informs
* licensees how to obtain it in a reasonable manner
* on or through a medium customarily used for
* software exchange.
*
* When the Program is made available in source code form:
* a) it must be made available under this Agreement;
* and
* b) a copy of this Agreement must be included with
* each copy of the Program.
*
* Contributors may not remove or alter any copyright notices
* contained within the Program.
*
* Each Contributor must identify itself as the originator of
* its Contribution, if any, in a manner that reasonably
* allows subsequent Recipients to identify the originator of
* the Contribution.
*
*
* 4. COMMERCIAL DISTRIBUTION
*
* Commercial distributors of software may accept certain
* responsibilities with respect to end users, business
* partners and the like. While this license is intended to
* facilitate the commercial use of the Program, the
* Contributor who includes the Program in a commercial
* product offering should do so in a manner which does not
* create potential liability for other Contributors.
* Therefore, if a Contributor includes the Program in a
* commercial product offering, such Contributor ("Commercial
* Contributor") hereby agrees to defend and indemnify every
* other Contributor ("Indemnified Contributor") against any
* losses, damages and costs (collectively "Losses") arising
* from claims, lawsuits and other legal actions brought by a
* third party against the Indemnified Contributor to the
* extent caused by the acts or omissions of such Commercial
* Contributor in connection with its distribution of the
* Program in a commercial product offering. The obligations
* in this section do not apply to any claims or Losses
* relating to any actual or alleged intellectual property
* infringement. In order to qualify, an Indemnified
* Contributor must: a) promptly notify the Commercial
* Contributor in writing of such claim, and b) allow the
* Commercial Contributor to control, and cooperate with the
* Commercial Contributor in, the defense and any related
* settlement negotiations. The Indemnified Contributor may
* participate in any such claim at its own expense.
*
*
* For example, a Contributor might include the Program in a
* commercial product offering, Product X. That Contributor
* is then a Commercial Contributor. If that Commercial
* Contributor then makes performance claims, or offers
* warranties related to Product X, those performance claims
* and warranties are such Commercial Contributor's
* responsibility alone. Under this section, the Commercial
* Contributor would have to defend claims against the other
* Contributors related to those performance claims and
* warranties, and if a court requires any other Contributor
* to pay any damages as a result, the Commercial Contributor
* must pay those damages.
*
*
* 5. NO WARRANTY
*
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE
* PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
* IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
* CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
* responsible for determining the appropriateness of using
* and distributing the Program and assumes all risks
* associated with its exercise of rights under this
* Agreement, including but not limited to the risks and
* costs of program errors, compliance with applicable laws,
* damage to or loss of data, programs or equipment, and
* unavailability or interruption of operations.
*
* 6. DISCLAIMER OF LIABILITY
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER
* RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
* LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE
* OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* 7. GENERAL
*
* If any provision of this Agreement is invalid or
* unenforceable under applicable law, it shall not affect
* the validity or enforceability of the remainder of the
* terms of this Agreement, and without further action by the
* parties hereto, such provision shall be reformed to the
* minimum extent necessary to make such provision valid and
* enforceable.
*
*
* If Recipient institutes patent litigation against a
* Contributor with respect to a patent applicable to
* software (including a cros - claim or counterclaim in a
* lawsuit), then any patent licenses granted by that
* Contributor to such Recipient under this Agreement shall
* terminate as of the date such litigation is filed. In
* addition, If Recipient institutes patent litigation
* against any entity (including a cros - claim or
* counterclaim in a lawsuit) alleging that the Program
* itself (excluding combinations of the Program with other
* software or hardware) infringes such Recipient's
* patent(s), then such Recipient's rights granted under
* Section 2(b) shall terminate as of the date such
* litigation is filed.
*
* All Recipient's rights under this Agreement shall
* terminate if it fails to comply with any of the material
* terms or conditions of this Agreement and does not cure
* such failure in a reasonable period of time after becoming
* aware of such noncompliance. If all Recipient's rights
* under this Agreement terminate, Recipient agrees to cease
* use and distribution of the Program as soon as reasonably
* practicable. However, Recipient's obligations under this
* Agreement and any licenses granted by Recipient relating
* to the Program shall continue and survive.
*
* Everyone is permitted to copy and distribute copies of
* this Agreement, but in order to avoid inconsistency the
* Agreement is copyrighted and may only be modified in the
* following manner. The Agreement Steward reserves the right
* to publish new versions (including revisions) of this
* Agreement from time to time. No one other than the
* Agreement Steward has the right to modify this Agreement.
*
* IBM is the initial Agreement Steward. IBM may assign the
* responsibility to serve as the Agreement Steward to a
* suitable separate entity. Each new version of the
* Agreement will be given a distinguishing version number.
* The Program (including Contributions) may always be
* distributed subject to the version of the Agreement under
* which it was received. In addition, after a new version of
* the Agreement is published, Contributor may elect to
* distribute the Program (including its Contributions) under
* the new version. Except as expressly stated in Sections
* 2(a) and 2(b) above, Recipient receives no rights or
* licenses to the intellectual property of any Contributor
* under this Agreement, whether expressly, by implication,
* estoppel or otherwise. All rights in the Program not
* expressly granted under this Agreement are reserved.
*
*
* This Agreement is governed by the laws of the State of New
* York and the intellectual property laws of the United
* States of America. No party to this Agreement will bring a
* legal action under this Agreement more than one year after
* the cause of action arose. Each party waives its rights to
* a jury trial in any resulting litigation.
*
*
*
* (C) COPYRIGHT International Business Machines Corp. 2001, 2002
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include "tpmtok_int.h"
pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER;
static CK_RV
object_mgr_search_shm_for_obj(TOK_OBJ_ENTRY *,
CK_ULONG, CK_ULONG, OBJECT *, CK_ULONG *);
static CK_RV object_mgr_update_from_shm(TSS_HCONTEXT);
static CK_RV object_mgr_check_shm(TSS_HCONTEXT, OBJECT *);
CK_RV
object_mgr_add(SESSION * sess,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE * handle)
{
OBJECT * o = NULL;
CK_BBOOL priv_obj, sess_obj;
CK_RV rc;
if (! sess || ! pTemplate || ! handle) {
return (CKR_FUNCTION_FAILED);
}
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_create(pTemplate, ulCount, &o);
if (rc != CKR_OK) {
goto done;
}
// check whether session has permissions to create the object, etc
//
// Object R/O R/W R/O R/W R/W
// Type Public Public User User SO
// -------------------------------------------------------------
// Public session R/W R/W R/W R/W R/W
// Private session R/W R/W
// Public token R/O R/W R/O R/W R/W
// Private token R/O R/W
//
sess_obj = object_is_session_object(o);
priv_obj = object_is_private(o);
if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
if (! sess_obj) {
rc = CKR_SESSION_READ_ONLY;
goto done;
}
}
if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) {
if (! sess_obj) {
rc = CKR_SESSION_READ_ONLY;
goto done;
}
}
if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
}
if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
}
// okay, object is created and the session permissions look okay.
// add the object to the appropriate list and assign an object handle
//
if (sess_obj) {
o->session = sess;
(void) memset(o->name, 0x00, sizeof (CK_BYTE) * 8);
sess_obj_list = dlist_add_as_first(sess_obj_list, o);
} else {
CK_BYTE current[8];
CK_BYTE next[8];
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
} else {
if (priv_obj) {
if (global_shm->num_priv_tok_obj >=
MAX_TOK_OBJS) {
rc = CKR_HOST_MEMORY;
(void) XProcUnLock(xproclock);
goto done;
}
} else {
if (global_shm->num_publ_tok_obj >=
MAX_TOK_OBJS) {
rc = CKR_HOST_MEMORY;
(void) XProcUnLock(xproclock);
goto done;
}
}
(void) memcpy(current,
&nv_token_data->next_token_object_name, 8);
o->session = NULL;
(void) memcpy(&o->name, current, 8);
(void) compute_next_token_obj_name(current, next);
(void) memcpy(&nv_token_data->next_token_object_name,
next, 8);
rc = save_token_object(sess->hContext, o);
if (rc != CKR_OK) {
(void) XProcUnLock(xproclock);
goto done;
}
(void) object_mgr_add_to_shm(o);
(void) XProcUnLock(xproclock);
(void) save_token_data(nv_token_data);
}
if (priv_obj)
priv_token_obj_list =
dlist_add_as_last(priv_token_obj_list, o);
else
publ_token_obj_list =
dlist_add_as_last(publ_token_obj_list, o);
}
rc = object_mgr_add_to_map(sess, o, handle);
if (rc != CKR_OK) {
DL_NODE *node = NULL;
if (sess_obj) {
node = dlist_find(sess_obj_list, o);
if (node)
sess_obj_list =
dlist_remove_node(sess_obj_list, node);
} else {
(void) delete_token_object(o);
if (priv_obj) {
node = dlist_find(priv_token_obj_list, o);
if (node)
priv_token_obj_list =
dlist_remove_node(
priv_token_obj_list, node);
} else {
node = dlist_find(publ_token_obj_list, o);
if (node)
publ_token_obj_list =
dlist_remove_node(
publ_token_obj_list, node);
}
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
}
(void) object_mgr_del_from_shm(o);
(void) XProcUnLock(xproclock);
}
}
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
if ((rc != CKR_OK) && (o != NULL))
(void) object_free(o);
return (rc);
}
CK_RV
object_mgr_add_to_map(SESSION * sess,
OBJECT * obj,
CK_OBJECT_HANDLE * handle) {
OBJECT_MAP *map_node = NULL;
if (! sess || ! obj || ! handle) {
return (CKR_FUNCTION_FAILED);
}
map_node = (OBJECT_MAP *)malloc(sizeof (OBJECT_MAP));
if (! map_node) {
return (CKR_HOST_MEMORY);
}
map_node->handle = next_object_handle++;
map_node->session = sess;
map_node->ptr = obj;
if (obj->session != NULL)
map_node->is_session_obj = TRUE;
else
map_node->is_session_obj = FALSE;
// add the new map entry to the list
if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
object_map = dlist_add_as_first(object_map, map_node);
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
*handle = map_node->handle;
return (CKR_OK);
}
// object_mgr_copy()
//
// algorithm:
// 1) find the old object
// 2) get the template from the old object
// 3) merge in the new object's template
// 4) perform class - specific sanity checks
//
CK_RV
object_mgr_copy(SESSION * sess,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE old_handle,
CK_OBJECT_HANDLE * new_handle)
{
OBJECT *old_obj = NULL;
OBJECT *new_obj = NULL;
CK_BBOOL priv_obj;
CK_BBOOL sess_obj;
CK_RV rc;
if (! sess || ! pTemplate || ! new_handle) {
return (CKR_FUNCTION_FAILED);
}
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_mgr_find_in_map1(sess->hContext, old_handle, &old_obj);
if (rc != CKR_OK) {
goto done;
}
rc = object_copy(pTemplate, ulCount, old_obj, &new_obj);
if (rc != CKR_OK) {
goto done;
}
sess_obj = object_is_session_object(new_obj);
priv_obj = object_is_private(new_obj);
if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
if (! sess_obj) {
rc = CKR_SESSION_READ_ONLY;
goto done;
}
}
if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) {
if (! sess_obj) {
rc = CKR_SESSION_READ_ONLY;
goto done;
}
}
if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
}
if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
if (priv_obj) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
}
if (sess_obj) {
new_obj->session = sess;
(void) memset(&new_obj->name, 0x00, sizeof (CK_BYTE) * 8);
sess_obj_list = dlist_add_as_first(sess_obj_list, new_obj);
} else {
CK_BYTE current[8];
CK_BYTE next[8];
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
} else {
if (priv_obj) {
if (global_shm->num_priv_tok_obj >=
MAX_TOK_OBJS) {
(void) XProcUnLock(xproclock);
rc = CKR_HOST_MEMORY;
goto done;
}
} else {
if (global_shm->num_publ_tok_obj >=
MAX_TOK_OBJS) {
(void) XProcUnLock(xproclock);
rc = CKR_HOST_MEMORY;
goto done;
}
}
(void) memcpy(current,
&nv_token_data->next_token_object_name, 8);
new_obj->session = NULL;
(void) memcpy(&new_obj->name, current, 8);
(void) compute_next_token_obj_name(current, next);
(void) memcpy(&nv_token_data->next_token_object_name,
next, 8);
rc = save_token_object(sess->hContext, new_obj);
if (rc != CKR_OK) {
(void) XProcUnLock(xproclock);
goto done;
}
(void) object_mgr_add_to_shm(new_obj);
(void) XProcUnLock(xproclock);
(void) save_token_data(nv_token_data);
}
if (priv_obj)
priv_token_obj_list = dlist_add_as_last(
priv_token_obj_list, new_obj);
else
publ_token_obj_list = dlist_add_as_last(
publ_token_obj_list, new_obj);
}
rc = object_mgr_add_to_map(sess, new_obj, new_handle);
if (rc != CKR_OK) {
DL_NODE *node = NULL;
if (sess_obj) {
node = dlist_find(sess_obj_list, new_obj);
if (node)
sess_obj_list = dlist_remove_node(
sess_obj_list, node);
} else {
(void) delete_token_object(new_obj);
if (priv_obj) {
node = dlist_find(priv_token_obj_list, new_obj);
if (node)
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
} else {
node = dlist_find(publ_token_obj_list, new_obj);
if (node)
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
}
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
}
(void) object_mgr_del_from_shm(new_obj);
(void) XProcUnLock(xproclock);
}
}
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
if ((rc != CKR_OK) && (new_obj != NULL))
(void) object_free(new_obj);
return (rc);
}
//
// determines whether the session is allowed to create an object. creates
// the object but doesn't add the object to any object lists or to the
// process' object map.
//
CK_RV
object_mgr_create_skel(SESSION * sess,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount,
CK_ULONG mode,
CK_ULONG obj_type,
CK_ULONG sub_class,
OBJECT ** obj)
{
OBJECT *o = NULL;
CK_RV rc;
CK_BBOOL priv_obj;
CK_BBOOL sess_obj;
if (! sess || ! obj) {
return (CKR_FUNCTION_FAILED);
}
if (! pTemplate && (ulCount != 0)) {
return (CKR_FUNCTION_FAILED);
}
rc = object_create_skel(pTemplate, ulCount,
mode, obj_type, sub_class, &o);
if (rc != CKR_OK) {
return (rc);
}
sess_obj = object_is_session_object(o);
priv_obj = object_is_private(o);
if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) {
if (priv_obj) {
(void) object_free(o);
return (CKR_USER_NOT_LOGGED_IN);
}
if (! sess_obj) {
(void) object_free(o);
return (CKR_SESSION_READ_ONLY);
}
}
if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) {
if (! sess_obj) {
(void) object_free(o);
return (CKR_SESSION_READ_ONLY);
}
}
if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
if (priv_obj) {
(void) object_free(o);
return (CKR_USER_NOT_LOGGED_IN);
}
}
if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
if (priv_obj) {
(void) object_free(o);
return (CKR_USER_NOT_LOGGED_IN);
}
}
*obj = o;
return (CKR_OK);
}
CK_RV
object_mgr_create_final(SESSION * sess,
OBJECT * obj,
CK_OBJECT_HANDLE * handle)
{
CK_BBOOL sess_obj;
CK_BBOOL priv_obj;
CK_RV rc;
if (!sess || !obj || !handle)
return (CKR_FUNCTION_FAILED);
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
sess_obj = object_is_session_object(obj);
priv_obj = object_is_private(obj);
if (sess_obj) {
obj->session = sess;
(void) memset(obj->name, 0x0, sizeof (CK_BYTE) * 8);
sess_obj_list = dlist_add_as_first(sess_obj_list, obj);
} else {
CK_BYTE current[8];
CK_BYTE next[8];
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
} else {
if (priv_obj) {
if (global_shm->num_priv_tok_obj >=
MAX_TOK_OBJS) {
(void) XProcUnLock(xproclock);
rc = CKR_HOST_MEMORY;
goto done;
}
} else {
if (global_shm->num_publ_tok_obj >=
MAX_TOK_OBJS) {
(void) XProcUnLock(xproclock);
rc = CKR_HOST_MEMORY;
goto done;
}
}
(void) memcpy(current,
&nv_token_data->next_token_object_name, 8);
obj->session = NULL;
(void) memcpy(&obj->name, current, 8);
(void) compute_next_token_obj_name(current, next);
(void) memcpy(&nv_token_data->next_token_object_name,
next, 8);
rc = save_token_object(sess->hContext, obj);
if (rc != CKR_OK) {
(void) XProcUnLock(xproclock);
goto done;
}
(void) object_mgr_add_to_shm(obj);
(void) XProcUnLock(xproclock);
(void) save_token_data(nv_token_data);
}
if (priv_obj)
priv_token_obj_list = dlist_add_as_last(
priv_token_obj_list, obj);
else
publ_token_obj_list = dlist_add_as_last(
publ_token_obj_list, obj);
}
rc = object_mgr_add_to_map(sess, obj, handle);
if (rc != CKR_OK) {
DL_NODE *node = NULL;
if (sess_obj) {
node = dlist_find(sess_obj_list, obj);
if (node)
sess_obj_list = dlist_remove_node(
sess_obj_list, node);
} else {
(void) delete_token_object(obj);
if (priv_obj) {
node = dlist_find(priv_token_obj_list, obj);
if (node)
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
} else {
node = dlist_find(publ_token_obj_list, obj);
if (node)
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
}
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
}
(void) object_mgr_del_from_shm(obj);
(void) XProcUnLock(xproclock);
}
}
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
return (rc);
}
CK_RV
object_mgr_destroy_object(SESSION * sess,
CK_OBJECT_HANDLE handle)
{
OBJECT * obj = NULL;
CK_BBOOL sess_obj;
CK_BBOOL priv_obj;
CK_RV rc;
if (! sess)
return (CKR_FUNCTION_FAILED);
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_mgr_find_in_map1(sess->hContext, handle, &obj);
if (rc != CKR_OK) {
goto done;
}
sess_obj = object_is_session_object(obj);
priv_obj = object_is_private(obj);
if (sess_obj) {
DL_NODE *node;
node = dlist_find(sess_obj_list, obj);
if (node) {
(void) object_mgr_remove_from_map(handle);
(void) object_free(obj);
sess_obj_list = dlist_remove_node(
sess_obj_list, node);
rc = CKR_OK;
goto done;
}
} else {
DL_NODE *node = NULL;
(void) delete_token_object(obj);
if (priv_obj)
node = dlist_find(priv_token_obj_list, obj);
else
node = dlist_find(publ_token_obj_list, obj);
if (node) {
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto done;
}
(void) object_mgr_del_from_shm(obj);
(void) XProcUnLock(xproclock);
(void) object_mgr_remove_from_map(handle);
(void) object_free(obj);
if (priv_obj)
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
else
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
rc = CKR_OK;
goto done;
}
}
rc = CKR_FUNCTION_FAILED;
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
return (rc);
}
CK_RV
object_mgr_destroy_token_objects(TSS_HCONTEXT hContext)
{
CK_BBOOL locked2 = FALSE;
CK_RV rc;
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
while (publ_token_obj_list) {
OBJECT *obj = (OBJECT *)publ_token_obj_list->data;
CK_OBJECT_HANDLE handle;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) delete_token_object(obj);
(void) object_free(obj);
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, publ_token_obj_list);
}
while (priv_token_obj_list) {
OBJECT *obj = (OBJECT *)priv_token_obj_list->data;
CK_OBJECT_HANDLE handle;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) delete_token_object(obj);
(void) object_free(obj);
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, priv_token_obj_list);
}
// now we want to purge the token object list in shared memory
//
rc = XProcLock(xproclock);
if (rc == CKR_OK) {
locked2 = TRUE;
global_shm->num_priv_tok_obj = 0;
global_shm->num_publ_tok_obj = 0;
(void) memset(&global_shm->publ_tok_objs, 0x0,
MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY));
(void) memset(&global_shm->priv_tok_objs, 0x0,
MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY));
}
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
if (locked2 == TRUE) (void) XProcUnLock(xproclock);
return (rc);
}
//
// Locates the specified object in the map
// without going and checking for cache update
//
CK_RV
object_mgr_find_in_map_nocache(CK_OBJECT_HANDLE handle,
OBJECT ** ptr) {
DL_NODE * node = NULL;
OBJECT * obj = NULL;
if (! ptr) {
return (CKR_FUNCTION_FAILED);
}
if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->handle == handle) {
obj = map->ptr;
break;
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
if (obj == NULL || node == NULL) {
return (CKR_OBJECT_HANDLE_INVALID);
}
if (object_is_session_object(obj) == TRUE) {
*ptr = obj;
return (CKR_OK);
}
*ptr = obj;
return (CKR_OK);
}
CK_RV
object_mgr_find_in_map1(
TSS_HCONTEXT hContext,
CK_OBJECT_HANDLE handle,
OBJECT ** ptr)
{
DL_NODE * node = NULL;
OBJECT * obj = NULL;
if (! ptr) {
return (CKR_FUNCTION_FAILED);
}
if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->handle == handle) {
obj = map->ptr;
break;
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
if (obj == NULL || node == NULL) {
return (CKR_OBJECT_HANDLE_INVALID);
}
if (object_is_session_object(obj) == TRUE) {
*ptr = obj;
return (CKR_OK);
}
(void) object_mgr_check_shm(hContext, obj);
*ptr = obj;
return (CKR_OK);
}
CK_RV
object_mgr_find_in_map2(
TSS_HCONTEXT hContext,
OBJECT * obj,
CK_OBJECT_HANDLE * handle)
{
DL_NODE * node = NULL;
CK_OBJECT_HANDLE h = (CK_OBJECT_HANDLE)NULL;
if (! obj || ! handle) {
return (CKR_FUNCTION_FAILED);
}
if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->ptr == obj) {
h = map->handle;
break;
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
if (node == NULL) {
return (CKR_OBJECT_HANDLE_INVALID);
}
if (object_is_session_object(obj) == TRUE) {
*handle = h;
return (CKR_OK);
}
(void) object_mgr_check_shm(hContext, obj);
*handle = h;
return (CKR_OK);
}
CK_RV
object_mgr_find_init(SESSION * sess,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount)
{
if (! sess) {
return (CKR_FUNCTION_FAILED);
}
if (sess->find_active != FALSE) {
return (CKR_OPERATION_ACTIVE);
}
// initialize the found object list. if it doesn't exist, allocate
// a list big enough for 10 handles. we'll reallocate if we need more
//
if (sess->find_list != NULL) {
(void) memset(sess->find_list, 0x0,
sess->find_len * sizeof (CK_OBJECT_HANDLE));
} else {
sess->find_list = (CK_OBJECT_HANDLE *)malloc(
10 * sizeof (CK_OBJECT_HANDLE));
if (! sess->find_list) {
return (CKR_HOST_MEMORY);
} else {
(void) memset(sess->find_list, 0x0,
10 * sizeof (CK_OBJECT_HANDLE));
sess->find_len = 10;
}
}
sess->find_count = 0;
sess->find_idx = 0;
// --- need to grab the object lock here
if (pthread_mutex_lock(&obj_list_mutex))
return (CKR_FUNCTION_FAILED);
(void) object_mgr_update_from_shm(sess->hContext);
// which objects can be return (ed:
//
// Public Session: public session objects, public token objects
// User Session: all session objects, all token objects
// SO session: public session objects, public token objects
//
switch (sess->session_info.state) {
case CKS_RO_PUBLIC_SESSION:
case CKS_RW_PUBLIC_SESSION:
case CKS_RW_SO_FUNCTIONS:
(void) object_mgr_find_build_list(sess, pTemplate,
ulCount, publ_token_obj_list, TRUE);
(void) object_mgr_find_build_list(sess, pTemplate,
ulCount, sess_obj_list, TRUE);
break;
case CKS_RO_USER_FUNCTIONS:
case CKS_RW_USER_FUNCTIONS:
(void) object_mgr_find_build_list(sess, pTemplate,
ulCount, priv_token_obj_list, FALSE);
(void) object_mgr_find_build_list(sess, pTemplate,
ulCount, publ_token_obj_list, FALSE);
(void) object_mgr_find_build_list(sess, pTemplate,
ulCount, sess_obj_list, FALSE);
break;
}
(void) pthread_mutex_unlock(&obj_list_mutex);
sess->find_active = TRUE;
return (CKR_OK);
}
CK_RV
object_mgr_find_build_list(SESSION * sess,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount,
DL_NODE * obj_list,
CK_BBOOL public_only)
{
OBJECT * obj = NULL;
DL_NODE * node = NULL;
CK_OBJECT_HANDLE handle;
CK_BBOOL is_priv;
CK_BBOOL match;
CK_BBOOL hw_feature = FALSE;
CK_BBOOL hidden_object = FALSE;
CK_RV rc;
CK_ATTRIBUTE * attr;
unsigned int i;
if (! sess) {
return (CKR_FUNCTION_FAILED);
}
if (! obj_list)
return (CKR_OK);
// PKCS#11 v2.11 (pg. 79): "When searching using C_FindObjectsInit
// and C_FindObjects, hardware feature objects are not returned
// unless the CKA_CLASS attribute in the template has the value
// CKO_HW_FEATURE." So, we check for CKO_HW_FEATURE and if its set,
// we'll find these objects below. - KEY
for (i = 0; i < ulCount; i++) {
if (pTemplate[i].type == CKA_CLASS) {
if (*(CK_ULONG *)pTemplate[i].pValue ==
CKO_HW_FEATURE) {
hw_feature = TRUE;
break;
}
}
if (pTemplate[i].type == CKA_HIDDEN) {
if (*(CK_BBOOL *)pTemplate[i].pValue == TRUE) {
hidden_object = TRUE;
break;
}
}
}
node = obj_list;
while (node) {
match = FALSE;
obj = (OBJECT *)node->data;
is_priv = object_is_private(obj);
if ((is_priv == FALSE) || (public_only == FALSE)) {
if (pTemplate == NULL || ulCount == 0)
match = TRUE;
else
match = template_compare(pTemplate,
ulCount, obj->template);
}
if (match) {
rc = object_mgr_find_in_map2(sess->hContext, obj,
&handle);
if (rc != CKR_OK) {
rc = object_mgr_add_to_map(sess, obj, &handle);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
}
if (rc == CKR_OK) {
if ((hw_feature == FALSE) &&
(template_attribute_find(obj->template,
CKA_CLASS, &attr) == TRUE)) {
if (*(CK_OBJECT_CLASS *)attr->pValue ==
CKO_HW_FEATURE)
goto next_loop;
}
if ((hidden_object == FALSE) &&
(template_attribute_find(obj->template,
CKA_HIDDEN, &attr) == TRUE)) {
if (*(CK_BBOOL *)attr->pValue == TRUE)
goto next_loop;
}
sess->find_list[ sess->find_count ] = handle;
sess->find_count++;
if (sess->find_count >= sess->find_len) {
sess->find_len += 15;
sess->find_list =
(CK_OBJECT_HANDLE *)realloc(
sess->find_list, sess->find_len *
sizeof (CK_OBJECT_HANDLE));
if (! sess->find_list) {
return (CKR_HOST_MEMORY);
}
}
}
}
next_loop:
node = node->next;
}
return (CKR_OK);
}
CK_RV
object_mgr_find_final(SESSION *sess)
{
if (! sess) {
return (CKR_FUNCTION_FAILED);
}
if (sess->find_active == FALSE) {
return (CKR_OPERATION_NOT_INITIALIZED);
}
free(sess->find_list);
sess->find_list = NULL;
sess->find_count = 0;
sess->find_idx = 0;
sess->find_active = FALSE;
return (CKR_OK);
}
CK_RV
object_mgr_get_attribute_values(SESSION * sess,
CK_OBJECT_HANDLE handle,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount)
{
OBJECT * obj;
CK_BBOOL priv_obj;
CK_RV rc;
if (! pTemplate) {
return (CKR_FUNCTION_FAILED);
}
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_mgr_find_in_map1(sess->hContext, handle, &obj);
if (rc != CKR_OK) {
goto done;
}
priv_obj = object_is_private(obj);
if (priv_obj == TRUE) {
if (sess->session_info.state == CKS_RO_PUBLIC_SESSION ||
sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
rc = CKR_USER_NOT_LOGGED_IN;
goto done;
}
}
rc = object_get_attribute_values(obj, pTemplate, ulCount);
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
return (rc);
}
CK_RV
object_mgr_get_object_size(
TSS_HCONTEXT hContext,
CK_OBJECT_HANDLE handle,
CK_ULONG * size)
{
OBJECT * obj;
CK_RV rc;
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_mgr_find_in_map1(hContext, handle, &obj);
if (rc != CKR_OK) {
rc = CKR_OBJECT_HANDLE_INVALID;
goto done;
}
*size = object_get_size(obj);
done:
(void) pthread_mutex_unlock(&obj_list_mutex);
return (rc);
}
// object_mgr_invalidate_handle1()
//
// Returns: TRUE if successfully removes the node
// FALSE if cannot remove the node (not found, etc)
//
CK_BBOOL
object_mgr_invalidate_handle1(CK_OBJECT_HANDLE handle)
{
DL_NODE *node = NULL;
if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->handle == handle) {
object_map = dlist_remove_node(object_map, node);
free(map);
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (TRUE);
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (FALSE);
}
// object_mgr_invalidate_handle2()
//
// Returns: TRUE if successfully removes the node
// FALSE if cannot remove the node (not found, etc)
//
CK_BBOOL
object_mgr_invalidate_handle2(OBJECT *obj)
{
DL_NODE *node = NULL;
if (! obj)
return (FALSE);
if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->ptr == obj) {
object_map = dlist_remove_node(object_map, node);
free(map);
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (TRUE);
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (FALSE);
}
// object_mgr_purge_session_objects()
//
// Args: SESSION *
// SESS_OBJ_TYPE: can be ALL, PRIVATE or PUBLIC
//
// Remove all session objects owned by the specified session satisfying
// the 'type' requirements
//
CK_BBOOL
object_mgr_purge_session_objects(SESSION * sess,
SESS_OBJ_TYPE type)
{
DL_NODE *node = NULL;
DL_NODE *next = NULL;
OBJECT *obj = NULL;
CK_BBOOL del;
CK_RV rc;
if (!sess)
return (FALSE);
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (FALSE);
node = sess_obj_list;
while (node) {
obj = (OBJECT *)node->data;
del = FALSE;
if (obj->session == sess) {
if (type == PRIVATE) {
if (object_is_private(obj))
del = TRUE;
} else if (type == PUBLIC) {
if (object_is_public(obj))
del = TRUE;
} else if (type == ALL)
del = TRUE;
}
if (del == TRUE) {
CK_OBJECT_HANDLE handle;
CK_RV rc;
rc = object_mgr_find_in_map2(sess->hContext, obj,
&handle);
if (rc == CKR_OK) {
(void) object_mgr_invalidate_handle1(handle);
(void) object_free(obj);
}
next = node->next;
sess_obj_list = dlist_remove_node(sess_obj_list, node);
node = next;
}
else
node = node->next;
}
(void) pthread_mutex_unlock(&obj_list_mutex);
return (TRUE);
}
//
// This routine cleans up the list of token objects. in general, we don't
// need to do this but when tracing memory leaks, it's best that we free
// everything that we've allocated.
//
CK_BBOOL
object_mgr_purge_token_objects(TSS_HCONTEXT hContext)
{
DL_NODE *node = NULL;
DL_NODE *next = NULL;
OBJECT *obj = NULL;
CK_RV rc;
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (FALSE);
node = publ_token_obj_list;
while (publ_token_obj_list) {
CK_OBJECT_HANDLE handle;
CK_RV rc;
obj = (OBJECT *)node->data;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_invalidate_handle1(handle);
}
(void) object_free(obj);
next = node->next;
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
node = next;
}
node = priv_token_obj_list;
while (priv_token_obj_list) {
CK_OBJECT_HANDLE handle;
CK_RV rc;
obj = (OBJECT *)node->data;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK)
(void) object_mgr_invalidate_handle1(handle);
(void) object_free(obj);
next = node->next;
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
node = next;
}
(void) pthread_mutex_unlock(&obj_list_mutex);
return (TRUE);
}
CK_BBOOL
object_mgr_purge_private_token_objects(TSS_HCONTEXT hContext) {
OBJECT * obj = NULL;
DL_NODE * node = NULL;
DL_NODE * next = NULL;
CK_RV rc;
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (FALSE);
node = priv_token_obj_list;
while (priv_token_obj_list) {
CK_OBJECT_HANDLE handle;
CK_RV rc;
obj = (OBJECT *)node->data;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_invalidate_handle1(handle);
}
(void) object_free(obj);
next = node->next;
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
node = next;
}
(void) pthread_mutex_unlock(&obj_list_mutex);
return (TRUE);
}
CK_RV
object_mgr_remove_from_map(CK_OBJECT_HANDLE handle)
{
DL_NODE *node = NULL;
if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
if (map->handle == handle) {
object_map = dlist_remove_node(object_map, node);
free(map);
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (CKR_OK);
}
node = node->next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (CKR_FUNCTION_FAILED);
}
CK_RV
object_mgr_restore_obj(CK_BYTE *data, OBJECT *oldObj)
{
OBJECT * obj = NULL;
CK_BBOOL priv;
CK_RV rc;
if (! data) {
return (CKR_FUNCTION_FAILED);
}
if (oldObj != NULL) {
obj = oldObj;
rc = object_restore(data, &obj, TRUE);
} else {
rc = object_restore(data, &obj, FALSE);
if (rc == CKR_OK) {
priv = object_is_private(obj);
if (priv)
priv_token_obj_list = dlist_add_as_last(
priv_token_obj_list, obj);
else
publ_token_obj_list = dlist_add_as_last(
publ_token_obj_list, obj);
(void) (void) XProcLock(xproclock);
if (priv) {
if (global_shm->priv_loaded == FALSE) {
if (global_shm->num_priv_tok_obj <
MAX_TOK_OBJS)
(void) object_mgr_add_to_shm(
obj);
else
rc = CKR_HOST_MEMORY;
}
} else {
if (global_shm->publ_loaded == FALSE) {
if (global_shm->num_publ_tok_obj <
MAX_TOK_OBJS)
(void) object_mgr_add_to_shm(
obj);
else
rc = CKR_HOST_MEMORY;
}
}
(void) XProcUnLock(xproclock);
}
}
// make the callers have to have the mutes
// to many grab it now.
return (rc);
}
CK_RV
object_mgr_set_attribute_values(SESSION * sess,
CK_OBJECT_HANDLE handle,
CK_ATTRIBUTE * pTemplate,
CK_ULONG ulCount)
{
OBJECT * obj;
CK_BBOOL sess_obj, priv_obj;
CK_BBOOL modifiable;
CK_RV rc;
if (! pTemplate) {
return (CKR_FUNCTION_FAILED);
}
rc = pthread_mutex_lock(&obj_list_mutex);
if (rc != CKR_OK)
return (CKR_FUNCTION_FAILED);
rc = object_mgr_find_in_map1(sess->hContext, handle, &obj);
if (rc != CKR_OK) {
(void) pthread_mutex_unlock(&obj_list_mutex);
return (CKR_OBJECT_HANDLE_INVALID);
}
(void) pthread_mutex_unlock(&obj_list_mutex);
modifiable = object_is_modifiable(obj);
sess_obj = object_is_session_object(obj);
priv_obj = object_is_private(obj);
if (! modifiable) {
return (CKR_ATTRIBUTE_READ_ONLY);
}
if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) {
if (priv_obj) {
return (CKR_USER_NOT_LOGGED_IN);
}
if (! sess_obj) {
return (CKR_SESSION_READ_ONLY);
}
}
if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) {
if (! sess_obj) {
return (CKR_SESSION_READ_ONLY);
}
}
if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
if (priv_obj) {
return (CKR_USER_NOT_LOGGED_IN);
}
}
if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
if (priv_obj) {
return (CKR_USER_NOT_LOGGED_IN);
}
}
rc = object_set_attribute_values(obj, pTemplate, ulCount);
if (rc != CKR_OK) {
return (rc);
}
if (! sess_obj) {
TOK_OBJ_ENTRY *entry = NULL;
CK_ULONG index;
obj->count_lo++;
if (obj->count_lo == 0)
obj->count_hi++;
rc = save_token_object(sess->hContext, obj);
if (rc != CKR_OK)
return (rc);
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
return (rc);
}
if (priv_obj) {
rc = object_mgr_search_shm_for_obj(
global_shm->priv_tok_objs,
0, global_shm->num_priv_tok_obj - 1,
obj, &index);
if (rc != CKR_OK) {
(void) XProcUnLock(xproclock);
return (rc);
}
entry = &global_shm->priv_tok_objs[index];
} else {
rc = object_mgr_search_shm_for_obj(
global_shm->publ_tok_objs,
0, global_shm->num_publ_tok_obj - 1,
obj, &index);
if (rc != CKR_OK) {
(void) XProcUnLock(xproclock);
return (rc);
}
entry = &global_shm->publ_tok_objs[index];
}
entry->count_lo = obj->count_lo;
entry->count_hi = obj->count_hi;
(void) XProcUnLock(xproclock);
}
return (rc);
}
CK_RV
object_mgr_add_to_shm(OBJECT *obj)
{
TOK_OBJ_ENTRY * entry = NULL;
CK_BBOOL priv;
priv = object_is_private(obj);
if (priv)
entry = &global_shm->priv_tok_objs[
global_shm->num_priv_tok_obj];
else
entry = &global_shm->publ_tok_objs[
global_shm->num_publ_tok_obj];
entry->deleted = FALSE;
entry->count_lo = 0;
entry->count_hi = 0;
(void) memcpy(entry->name, obj->name, 8);
if (priv) {
global_shm->num_priv_tok_obj++;
} else {
global_shm->num_publ_tok_obj++;
}
return (CKR_OK);
}
CK_RV
object_mgr_del_from_shm(OBJECT *obj)
{
CK_ULONG index, count;
CK_BBOOL priv;
CK_RV rc;
priv = object_is_private(obj);
if (priv) {
rc = object_mgr_search_shm_for_obj(global_shm->priv_tok_objs,
0, global_shm->num_priv_tok_obj - 1, obj, &index);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
global_shm->num_priv_tok_obj--;
if (index > global_shm->num_priv_tok_obj) {
count = index - global_shm->num_priv_tok_obj;
} else {
count = global_shm->num_priv_tok_obj - index;
}
if (count > 0) {
(void) memcpy((char *)&global_shm->priv_tok_objs[index],
(char *)&global_shm->priv_tok_objs[index + 1],
sizeof (TOK_OBJ_ENTRY) * count);
(void) memset((char *)&global_shm->priv_tok_objs[
global_shm->num_priv_tok_obj + 1], 0,
sizeof (TOK_OBJ_ENTRY));
} else {
(void) memset((char *)&global_shm->priv_tok_objs[
global_shm->num_priv_tok_obj], 0,
sizeof (TOK_OBJ_ENTRY));
}
} else {
rc = object_mgr_search_shm_for_obj(global_shm->publ_tok_objs,
0, global_shm->num_publ_tok_obj - 1, obj, &index);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
global_shm->num_publ_tok_obj--;
if (index > global_shm->num_publ_tok_obj) {
count = index - global_shm->num_publ_tok_obj;
} else {
count = global_shm->num_publ_tok_obj - index;
}
if (count > 0) {
(void) memcpy((char *)&global_shm->publ_tok_objs[index],
(char *)&global_shm->publ_tok_objs[index + 1],
sizeof (TOK_OBJ_ENTRY) * count);
(void) memset((char *)&global_shm->publ_tok_objs[
global_shm->num_publ_tok_obj + 1], 0,
sizeof (TOK_OBJ_ENTRY));
} else {
(void) memset((char *)&global_shm->publ_tok_objs[
global_shm->num_publ_tok_obj], 0,
sizeof (TOK_OBJ_ENTRY));
}
}
return (CKR_OK);
}
static CK_RV
object_mgr_check_shm(TSS_HCONTEXT hContext, OBJECT *obj)
{
TOK_OBJ_ENTRY * entry = NULL;
CK_BBOOL priv;
CK_ULONG index;
CK_RV rc;
priv = object_is_private(obj);
if (priv) {
rc = object_mgr_search_shm_for_obj(
global_shm->priv_tok_objs,
0, global_shm->num_priv_tok_obj - 1, obj, &index);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
entry = &global_shm->priv_tok_objs[index];
} else {
rc = object_mgr_search_shm_for_obj(
global_shm->publ_tok_objs,
0, global_shm->num_publ_tok_obj - 1, obj, &index);
if (rc != CKR_OK) {
return (CKR_FUNCTION_FAILED);
}
entry = &global_shm->publ_tok_objs[index];
}
if ((obj->count_hi == entry->count_hi) &&
(obj->count_lo == entry->count_lo))
return (CKR_OK);
rc = reload_token_object(hContext, obj);
return (rc);
}
/*ARGSUSED*/
static CK_RV
object_mgr_search_shm_for_obj(
TOK_OBJ_ENTRY *obj_list,
CK_ULONG lo,
CK_ULONG hi,
OBJECT *obj,
CK_ULONG *index)
{
CK_ULONG idx;
if (obj->index == 0) {
for (idx = lo; idx <= hi; idx++) {
if (memcmp(obj->name, obj_list[idx].name, 8) == 0) {
*index = idx;
obj->index = idx;
return (CKR_OK);
}
}
} else {
if (memcmp(obj->name, obj_list[obj->index].name, 8) == 0) {
*index = obj->index;
return (CKR_OK);
} else {
for (idx = lo; idx <= hi; idx++) {
if (memcmp(obj->name,
obj_list[idx].name, 8) == 0) {
*index = idx;
obj->index = idx;
return (CKR_OK);
}
}
}
}
return (CKR_FUNCTION_FAILED);
}
static CK_RV
object_mgr_update_publ_tok_obj_from_shm(TSS_HCONTEXT hContext)
{
DL_NODE * node = NULL;
DL_NODE * next = NULL;
TOK_OBJ_ENTRY * te = NULL;
OBJECT * obj = NULL;
CK_OBJECT_HANDLE handle;
CK_ULONG index;
int val;
CK_RV rc;
node = publ_token_obj_list;
index = 0;
while ((node != NULL) && (index < global_shm->num_publ_tok_obj)) {
te = &global_shm->publ_tok_objs[index];
obj = (OBJECT *)node->data;
val = memcmp(obj->name, te->name, 8);
// 3 cases:
// 1) object in local list but not in the global list,
// need to remove from local list
// 2) object in both lists, need to compare counters
// and update as needed
// 3) object in global list but not in the local list,
// need to add the object here.
//
if (val < 0) {
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) object_free(obj);
next = node->next;
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
} else if (val == 0) {
if ((te->count_hi != obj->count_hi) ||
(te->count_lo != obj->count_lo)) {
(void) reload_token_object(hContext, obj);
obj->count_hi = te->count_hi;
obj->count_lo = te->count_lo;
}
next = node->next;
index++;
} else {
DL_NODE *new_node = NULL;
OBJECT *new_obj = NULL;
new_obj = (OBJECT *)malloc(sizeof (OBJECT));
(void) memset(new_obj, 0x0, sizeof (OBJECT));
(void) memcpy(new_obj->name, te->name, 8);
(void) reload_token_object(hContext, new_obj);
new_node = (DL_NODE *)malloc(sizeof (DL_NODE));
new_node->data = new_obj;
new_node->next = node->next;
node->next = new_node;
new_node->prev = node;
next = new_node->next;
index++;
}
node = next;
}
if ((node == NULL) && (index < global_shm->num_publ_tok_obj)) {
OBJECT *new_obj = NULL;
unsigned int i;
for (i = index; i < global_shm->num_publ_tok_obj; i++) {
new_obj = (OBJECT *)malloc(sizeof (OBJECT));
(void) memset(new_obj, 0x0, sizeof (OBJECT));
te = &global_shm->publ_tok_objs[index];
(void) memcpy(new_obj->name, te->name, 8);
(void) reload_token_object(hContext, new_obj);
publ_token_obj_list = dlist_add_as_last(
publ_token_obj_list, new_obj);
}
} else if ((node != NULL) && (index >= global_shm->num_publ_tok_obj)) {
while (node) {
obj = (OBJECT *)node->data;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) object_free(obj);
next = node->next;
publ_token_obj_list = dlist_remove_node(
publ_token_obj_list, node);
node = next;
}
}
return (CKR_OK);
}
static CK_RV
object_mgr_update_priv_tok_obj_from_shm(TSS_HCONTEXT hContext)
{
DL_NODE * node = NULL;
DL_NODE * next = NULL;
TOK_OBJ_ENTRY * te = NULL;
OBJECT * obj = NULL;
CK_OBJECT_HANDLE handle;
CK_ULONG index;
int val;
CK_RV rc;
node = priv_token_obj_list;
index = 0;
if (! (global_login_state == CKS_RW_USER_FUNCTIONS ||
global_login_state == CKS_RO_USER_FUNCTIONS)) {
return (CKR_OK);
}
while ((node != NULL) && (index < global_shm->num_priv_tok_obj)) {
te = &global_shm->priv_tok_objs[index];
obj = (OBJECT *)node->data;
val = memcmp(obj->name, te->name, 8);
if (val < 0) {
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) object_free(obj);
next = node->next;
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
} else if (val == 0) {
if ((te->count_hi != obj->count_hi) ||
(te->count_lo != obj->count_lo)) {
(void) reload_token_object(hContext, obj);
obj->count_hi = te->count_hi;
obj->count_lo = te->count_lo;
}
next = node->next;
index++;
} else {
DL_NODE *new_node = NULL;
OBJECT *new_obj = NULL;
new_obj = (OBJECT *)malloc(sizeof (OBJECT));
(void) memset(new_obj, 0x0, sizeof (OBJECT));
(void) memcpy(new_obj->name, te->name, 8);
(void) reload_token_object(hContext, new_obj);
new_node = (DL_NODE *)malloc(sizeof (DL_NODE));
new_node->data = new_obj;
new_node->next = node->next;
node->next = new_node;
new_node->prev = node;
next = new_node->next;
index++;
}
node = next;
}
if ((node == NULL) && (index < global_shm->num_priv_tok_obj)) {
OBJECT *new_obj = NULL;
unsigned int i;
for (i = index; i < global_shm->num_priv_tok_obj; i++) {
new_obj = (OBJECT *)malloc(sizeof (OBJECT));
(void) memset(new_obj, 0x0, sizeof (OBJECT));
te = &global_shm->priv_tok_objs[index];
(void) memcpy(new_obj->name, te->name, 8);
(void) reload_token_object(hContext, new_obj);
priv_token_obj_list = dlist_add_as_last(
priv_token_obj_list, new_obj);
}
} else if ((node != NULL) && (index >= global_shm->num_priv_tok_obj)) {
while (node) {
obj = (OBJECT *)node->data;
rc = object_mgr_find_in_map2(hContext, obj, &handle);
if (rc == CKR_OK) {
(void) object_mgr_remove_from_map(handle);
}
(void) object_free(obj);
next = node->next;
priv_token_obj_list = dlist_remove_node(
priv_token_obj_list, node);
node = next;
}
}
return (CKR_OK);
}
static CK_RV
object_mgr_update_from_shm(TSS_HCONTEXT hContext)
{
(void) object_mgr_update_publ_tok_obj_from_shm(hContext);
(void) object_mgr_update_priv_tok_obj_from_shm(hContext);
return (CKR_OK);
}
/*ARGSUSED*/
CK_BBOOL
object_mgr_purge_map(
SESSION *sess,
SESS_OBJ_TYPE type)
{
DL_NODE *node = NULL;
DL_NODE *next = NULL;
if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) {
return (CKR_FUNCTION_FAILED);
}
node = object_map;
while (node) {
OBJECT_MAP *map = (OBJECT_MAP *)node->data;
OBJECT *obj = (OBJECT *)map->ptr;
next = node->next;
if (type == PRIVATE) {
if (object_is_private(obj)) {
object_map = dlist_remove_node(
object_map, node);
free(map);
}
}
if (type == PUBLIC) {
if (object_is_public(obj)) {
object_map = dlist_remove_node(
object_map, node);
free(map);
}
}
node = next;
}
(void) pthread_rwlock_unlock(&obj_list_rw_mutex);
return (TRUE);
}