From 8a63b3b17d34718d0f8c7525f93b5eb3c623076a Mon Sep 17 00:00:00 2001
From: Joy Latten <jmlatten@users.sourceforge.net>
Date: Thu, 12 Apr 2012 16:55:06 -0500
Subject: [PATCH] lock per token to access shared memory; tpm per user; api and pkcsslotd
 acquire same lock to access shared memory.
 locks moved to $prefix/var/lock/opencryptoki.

Signed-off-by: Joy Latten <jmlatten@users.sourceforge.net>
---
 FAQ                                   |    2 
 configure.in                          |    8 +-
 usr/Makefile.am                       |    5 +
 usr/include/pkcs11/slotmgr.h          |    2 
 usr/lib/pkcs11/api/api_interface.c    |    8 ++
 usr/lib/pkcs11/api/apiproto.h         |    5 -
 usr/lib/pkcs11/api/apiutil.c          |   50 +++++++++++-----
 usr/lib/pkcs11/cca_stdll/defs.h       |    4 +
 usr/lib/pkcs11/cca_stdll/h_extern.h   |    1 
 usr/lib/pkcs11/cca_stdll/loadsave.c   |    2 
 usr/lib/pkcs11/cca_stdll/new_host.c   |   14 ++--
 usr/lib/pkcs11/cca_stdll/tokenlocal.h |    1 
 usr/lib/pkcs11/cca_stdll/utility.c    |  100 ++++++++++++++++++++++++++------
 usr/lib/pkcs11/common/h_extern.h      |    3 
 usr/lib/pkcs11/common/loadsave.c      |    2 
 usr/lib/pkcs11/common/new_host.c      |   13 ++--
 usr/lib/pkcs11/common/utility.c       |   93 +++++++++++++++++++++++++----
 usr/lib/pkcs11/tpm_stdll/h_extern.h   |    1 
 usr/lib/pkcs11/tpm_stdll/new_host.c   |   12 ++-
 usr/lib/pkcs11/tpm_stdll/utility.c    |  106 ++++++++++++++++++++++++++++------
 usr/sbin/pkcs_slot/Makefile.am        |    1 
 usr/sbin/pkcs_slot/pkcs_slot.in       |   48 +++++++++++++++
 usr/sbin/pkcsslotd/mutex.c            |   63 +++++++++++++++++---
 23 files changed, 447 insertions(+), 97 deletions(-)

--- a/FAQ
+++ b/FAQ
@@ -40,7 +40,7 @@
  4. Q. How can I get the complete debug logs from openCryptoki?
 
     A. In the opencryptoki version 2.4 release, if opencryptoki has been compiled 
-       with debugging enabled (configure --enable-debugging), then debug
+       with debugging enabled (configure --enable-debug), then debug
        messages are logged to the file specified with OPENCRYPTOKI_DEBUG_FILE
        environment variable. If this environment variable is not set, then  
        opencryptoki debug messages are not logged. 
--- a/configure.in
+++ b/configure.in
@@ -36,6 +36,11 @@ AC_PATH_PROG([CHGRP], [chgrp], [/bin/chg
 AC_PROG_SED
 AC_PROG_MKDIR_P
 
+dnl Define custom variables
+
+lockdir=$localstatedir/lock/opencryptoki
+AC_SUBST(lockdir)
+
 dnl ---
 dnl --- Check all --enable/--disable-features
 dnl ---
@@ -621,10 +626,9 @@ else
 fi
 AM_CONDITIONAL([ENABLE_PKCSCCA_MIGRATE], [test "x$enable_pkcscca_migrate" = "xyes"])
 
-
 CFLAGS="$CFLAGS -DPKCS64 -D_XOPEN_SOURCE=500"
 
-CFLAGS+=' -DCONFIG_PATH=\"$(localstatedir)/lib/opencryptoki\" -DSBIN_PATH=\"$(sbindir)\" -DLIB_PATH=\"$(libdir)\"'
+CFLAGS+=' -DCONFIG_PATH=\"$(localstatedir)/lib/opencryptoki\" -DSBIN_PATH=\"$(sbindir)\" -DLIB_PATH=\"$(libdir)\" -DLOCKDIR_PATH=\"$(lockdir)\"'
 
 # At this point, CFLAGS is set to something sensible
 AC_PROG_CC
--- a/usr/Makefile.am
+++ b/usr/Makefile.am
@@ -3,3 +3,8 @@ DAEMONDIRS = include sbin
 endif
 
 SUBDIRS = lib $(DAEMONDIRS)
+
+install-data-hook:
+	$(MKDIR_P) $(lockdir)
+	$(CHGRP) pkcs11 $(lockdir)
+	$(CHMOD) 0770 $(lockdir)
--- a/usr/include/pkcs11/slotmgr.h
+++ b/usr/include/pkcs11/slotmgr.h
@@ -313,7 +313,7 @@
 #define _SLOTMGR_H
 
 #define TOK_PATH  SBIN_PATH "/pkcsslotd"
-#define  OCK_API_LOCK_FILE  "/var/lock/LCK..opencryptoki"
+#define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock"
 
 #define PID_FILE_PATH "/var/run/pkcsslotd.pid"
 
--- a/usr/lib/pkcs11/api/api_interface.c
+++ b/usr/lib/pkcs11/api/api_interface.c
@@ -3145,6 +3145,14 @@ C_Initialize ( CK_VOID_PTR pVoid )
          ;
       }
 
+      // Create the shared memory lock.
+      if (CreateXProcLock() != CKR_OK) {
+	 free((void *)Anchor);
+	 Anchor = NULL;
+	 OCK_LOG_ERR(ERR_PROCESS_LOCK);
+	 return CKR_FUNCTION_FAILED;
+      }
+
       //Zero out API_Proc_Struct
       //Map Shared Memory Region
       //if ( Shared Memory Mapped not Successful )
--- a/usr/lib/pkcs11/api/apiproto.h
+++ b/usr/lib/pkcs11/api/apiproto.h
@@ -318,8 +318,9 @@ void API_UnRegister();
 int DL_Load_and_Init(API_Slot_t *,CK_SLOT_ID);
 
 
-int XProcLock(void);
-int XProcUnLock(void);
+CK_RV CreateXProcLock(void);
+CK_RV XProcLock(void);
+CK_RV XProcUnLock(void);
 
 void _init(void);
 void get_sess_count(CK_SLOT_ID, CK_ULONG *);
--- a/usr/lib/pkcs11/api/apiutil.c
+++ b/usr/lib/pkcs11/api/apiutil.c
@@ -323,6 +323,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/file.h>
+
 static int xplfd=-1;
 
 #include <libgen.h>
@@ -335,26 +336,49 @@ extern  API_Proc_Struct_t  *Anchor;
 #include <stdarg.h>
 
 
-int
+CK_RV
+CreateXProcLock(void)
+{
+	struct stat statbuf;
+
+	if (xplfd == -1 ) {
+
+		/* The slot mgr daemon should have already created lock,
+		 * so just open it so we can get a lock...
+		 */
+		if (stat(OCK_API_LOCK_FILE, &statbuf) == 0)
+			xplfd = open(OCK_API_LOCK_FILE, O_RDONLY);
+
+		if (xplfd == -1) {
+			OCK_SYSLOG(LOG_ERR, "Could not open %s\n",
+				   OCK_API_LOCK_FILE);
+			return CKR_FUNCTION_FAILED;
+		}
+	}
+
+	return CKR_OK;
+}
+
+CK_RV
 XProcLock(void)
 {
-   if (xplfd == -1 ) {
-        xplfd = open(OCK_API_LOCK_FILE,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-	if (xplfd == -1)
-	    OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
-                          OCK_API_LOCK_FILE, strerror(errno));
-   }
-   if (xplfd != -1)
-	flock(xplfd,LOCK_EX);
+	if (xplfd != -1)
+		flock(xplfd, LOCK_EX);
+	else 
+		OCK_LOG_DEBUG("No file descriptor to lock with.\n");
 
-   return CKR_OK;
+	return CKR_OK;
 }
 
-int 
+CK_RV
 XProcUnLock(void)
 {
-   flock(xplfd,LOCK_UN);
-   return CKR_OK;
+	if (xplfd != -1)
+		flock(xplfd,LOCK_UN);
+	else
+		OCK_LOG_DEBUG("No file descriptor to unlock with.\n");
+
+	return CKR_OK;
 }
 
 unsigned long
--- a/usr/lib/pkcs11/cca_stdll/defs.h
+++ b/usr/lib/pkcs11/cca_stdll/defs.h
@@ -109,6 +109,10 @@ enum {
 #define SHA384_HASH_SIZE	48
 #define SHA512_HASH_SIZE	64
 
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
 typedef struct _sha1_ctx {
    unsigned char hash[SHA1_HASH_SIZE+1];
    unsigned int hash_len, tail_len;
--- a/usr/lib/pkcs11/cca_stdll/h_extern.h
+++ b/usr/lib/pkcs11/cca_stdll/h_extern.h
@@ -2173,5 +2173,4 @@ void dump_shm(const char *);
 CK_RV sw_des3_cbc(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *,
 		  CK_BYTE  *, CK_BYTE *, CK_BYTE);
 
-#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
 #endif
--- a/usr/lib/pkcs11/cca_stdll/loadsave.c
+++ b/usr/lib/pkcs11/cca_stdll/loadsave.c
@@ -42,8 +42,6 @@
 #include "tok_spec_struct.h"
 #include "pkcs32.h"
 
-#include "../api/apiproto.h"
-
 void
 set_perm(int file)
 {
--- a/usr/lib/pkcs11/cca_stdll/new_host.c
+++ b/usr/lib/pkcs11/cca_stdll/new_host.c
@@ -103,13 +103,12 @@ st_Initialized()
 	return TRUE;
 }
 
-extern int spinxplfd;
-
 void
 Fork_Initializer(void)
 {
 
-	spinxplfd = -1;
+	// Initialize spinlock.
+	XProcLock_Init();
 
 	// Force logout.  This cleans out the private session and list
 	// and cleans out the private object map
@@ -335,6 +334,12 @@ ST_Initialize(void **FunctionList,
 	MY_CreateMutex( &sess_list_mutex );
 	MY_CreateMutex( &login_mutex     );
 
+	/* Create lockfile */
+	if (CreateXProcLock() != CKR_OK) {
+		OCK_LOG_ERR(ERR_PROCESS_LOCK);
+		goto done;
+	}
+
 	init_data_store((char *)PK_DIR);
 
 
@@ -423,8 +428,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 	object_mgr_purge_token_objects();
 	detach_shm();
 	// close spin lock file
-	if (spinxplfd != -1)
-	  close(spinxplfd);
+	CloseXProcLock();
 	if ( token_specific.t_final != NULL) {
 		token_specific.t_final();
 	}
--- a/usr/lib/pkcs11/cca_stdll/tokenlocal.h
+++ b/usr/lib/pkcs11/cca_stdll/tokenlocal.h
@@ -18,7 +18,6 @@
 #define PK_DIR      PK_LITE_DIR
 #define SUB_DIR     token_specific.token_subdir
 
-
 #define DBGTAG  token_specific.token_debug_tag
 
 #endif
--- a/usr/lib/pkcs11/cca_stdll/utility.c
+++ b/usr/lib/pkcs11/cca_stdll/utility.c
@@ -21,6 +21,7 @@
 #include <sys/shm.h>
 #include <errno.h>
 #include <pwd.h>
+#include <grp.h>
 
 #include "cca_stdll.h"
 
@@ -32,8 +33,7 @@
 #include "pkcs32.h"
 
 #include <sys/file.h>
-
-
+#include <syslog.h>
 
 // Function:  dlist_add_as_first()
 //
@@ -312,36 +312,100 @@ _UnlockMutex( MUTEX *mutex )
 
 }
 
-int spinxplfd=-1;
+static int spinxplfd=-1;
 
 CK_RV
-XProcLock(void)
+CreateXProcLock(void)
 {
+	CK_BYTE lockfile[PATH_MAX];
+	struct group *grp;
+	struct stat statbuf;
+	mode_t mode = (S_IRUSR|S_IRGRP);
+
+	/* see if it exists */
+	if (spinxplfd == -1) {
+
+		/* create user lock file */
+		sprintf(lockfile, "%s/%s/LCK..%s",
+			LOCKDIR_PATH, SUB_DIR, SUB_DIR);
+
+		if (stat(lockfile, &statbuf) == 0)
+			spinxplfd = open(lockfile, O_RDONLY, mode);
+		else {
+			spinxplfd = open(lockfile, O_CREAT|O_RDONLY, mode);
+			if (spinxplfd != -1) {
+				/* umask may prevent correct mode, set it */
+				if (fchmod(spinxplfd, mode) == -1) {
+					OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n",
+						   lockfile, strerror(errno));
+					goto err;
+				}
+
+				grp = getgrnam("pkcs11");
+				if (grp != NULL) {
+					if (fchown(spinxplfd, -1, grp->gr_gid) == -1) {
+						OCK_SYSLOG(LOG_ERR,
+							   "fchown(%s): %s\n",
+						      lockfile,strerror(errno));
+						goto err;
+					}
+				} else {
+					OCK_SYSLOG(LOG_ERR, "getgrnam(): %s\n",
+						   strerror(errno));
+					goto err;
+				}
+			}
+		}
+
+		if (spinxplfd == -1) {
+			OCK_SYSLOG(LOG_ERR, "open(%s): %s\n",
+				   lockfile, strerror(errno));
+			return CKR_FUNCTION_FAILED;
+		}
+	}
+
+	return CKR_OK;
+
+err:
+	if (spinxplfd != -1)
+		close(spinxplfd);
+	return CKR_FUNCTION_FAILED;
+}
 
-   /* see if it exists */
-   if (spinxplfd == -1) {
-       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
-                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
-       if (spinxplfd == -1)
-          OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
-                        OCK_STDLL_LOCK_FILE, strerror(errno));
-   }
+void
+CloseXProcLock(void)
+{
+	if (spinxplfd != -1)
+		close(spinxplfd);
+}
 
-   if (spinxplfd != -1)
-      flock(spinxplfd,LOCK_EX);
+CK_RV
+XProcLock(void)
+{
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_EX);
+	else
+		OCK_LOG_DEBUG("No file descriptor to lock with.\n");
 
-   return CKR_OK;
+	return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-   if (spinxplfd != -1)
-      flock(spinxplfd,LOCK_UN);
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_UN);
+	else
+		OCK_LOG_DEBUG("No file descriptor to unlock with.\n");
 
-   return CKR_OK;
+	return CKR_OK;
 }
 
+void
+XProcLock_Init(void)
+{
+	spinxplfd = -1;
+}
 
 //
 //
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -2474,7 +2474,4 @@ void dump_shm(const char *);
  * Used for objects internal to a token for management of that token */
 #define CKA_HIDDEN              CKA_VENDOR_DEFINED + 0x01000000
 
-
-#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
-
 #endif
--- a/usr/lib/pkcs11/common/loadsave.c
+++ b/usr/lib/pkcs11/common/loadsave.c
@@ -319,7 +319,7 @@
 #include "tok_spec_struct.h"
 #include "pkcs32.h"
 
-#include "../api/apiproto.h"
+/* #include "../api/apiproto.h" */
 
 void
 set_perm(int file)
--- a/usr/lib/pkcs11/common/new_host.c
+++ b/usr/lib/pkcs11/common/new_host.c
@@ -384,13 +384,12 @@ st_Initialized()
 	return TRUE;
 }
 
-extern int spinxplfd;
-
 void
 Fork_Initializer(void)
 {
 
-	spinxplfd = -1;
+	// Initialize spinlock.
+	XProcLock_Init();
 
 	// Force logout.  This cleans out the private session and list
 	// and cleans out the private object map
@@ -618,6 +617,11 @@ ST_Initialize(void **FunctionList,
 	MY_CreateMutex( &sess_list_mutex );
 	MY_CreateMutex( &login_mutex     );
 
+	/* Create lockfile */
+	if (CreateXProcLock() != CKR_OK) {
+		OCK_LOG_ERR(ERR_PROCESS_LOCK);
+		goto done;
+	}
 
 	init_data_store((char *)PK_DIR);
 
@@ -705,8 +709,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 	object_mgr_purge_token_objects();
 	detach_shm();
 	// close spin lock file
-	if (spinxplfd != -1)
-	  close(spinxplfd);
+	CloseXProcLock();
 	if ( token_specific.t_final != NULL) {
 		token_specific.t_final();
 	}
--- a/usr/lib/pkcs11/common/utility.c
+++ b/usr/lib/pkcs11/common/utility.c
@@ -301,6 +301,7 @@
 #include <sys/shm.h>
 #include <errno.h>
 #include <pwd.h>
+#include <grp.h>
 
 
 #include "pkcs11types.h"
@@ -311,6 +312,7 @@
 #include "pkcs32.h"
 
 #include <sys/file.h>
+#include <syslog.h>
 
 
 
@@ -592,34 +594,97 @@ _UnlockMutex( MUTEX *mutex )
 }
 
 
-int spinxplfd=-1;
+static int spinxplfd=-1;
 
 CK_RV
-XProcLock(void)
+CreateXProcLock(void)
 {
-   if (spinxplfd == -1) {
-       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
-                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
-      if (spinxplfd == -1)
-          OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
-                        OCK_STDLL_LOCK_FILE, strerror(errno));
-   }
+	CK_BYTE lockfile[PATH_MAX];
+	struct group *grp;
+	struct stat statbuf;
+	mode_t mode = (S_IRUSR|S_IRGRP);
+
+	if (spinxplfd == -1) {
+
+		/* create user lock file */
+		sprintf(lockfile, "%s/%s/LCK..%s",
+			LOCKDIR_PATH, SUB_DIR, SUB_DIR);
+
+		if (stat(lockfile, &statbuf) == 0)
+			spinxplfd = open(lockfile, O_RDONLY, mode);
+		else {
+			spinxplfd = open(lockfile, O_CREAT|O_RDONLY, mode);
+			if (spinxplfd != -1) {
+				/* umask may prevent correct mode,so set it. */
+				if (fchmod(spinxplfd, mode) == -1) {
+					OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n",
+						   lockfile, strerror(errno));
+					goto err;
+				}
+
+				grp = getgrnam("pkcs11");
+				if (grp != NULL) {
+					if (fchown(spinxplfd, -1, grp->gr_gid) == -1) {
+						OCK_SYSLOG(LOG_ERR,
+						     "fchown(%s): %s\n",
+						     lockfile,strerror(errno));
+						goto err;
+					}
+				} else {
+					OCK_SYSLOG(LOG_ERR, "getgrnam(): %s\n",							   strerror(errno));
+					goto err;
+				}
+			}
+		}
+		if (spinxplfd == -1) {
+			OCK_SYSLOG(LOG_ERR, "open(%s): %s\n",
+				   lockfile,strerror(errno));
+			return CKR_FUNCTION_FAILED;
+		}
+	}
+
+	return CKR_OK;
+
+err:
+	if (spinxplfd != -1)
+		close(spinxplfd);
+	return CKR_FUNCTION_FAILED;
+}
 
-   if (spinxplfd != -1)
-       flock(spinxplfd,LOCK_EX);
+void
+CloseXProcLock(void)
+{
+	if (spinxplfd != -1)
+		close(spinxplfd);
+}
 
-   return CKR_OK;
+CK_RV
+XProcLock(void)
+{
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_EX);
+	else
+		OCK_LOG_DEBUG("No file descriptor to lock with.\n");
+
+	return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-   if (spinxplfd != -1)
-        flock(spinxplfd,LOCK_UN);
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_UN);
+	else
+		OCK_LOG_DEBUG("No file descriptor to unlock with.\n");
 
    return CKR_OK;
 }
 
+void
+XProcLock_Init(void)
+{
+	spinxplfd = -1;
+}
 
 //
 //
--- a/usr/lib/pkcs11/tpm_stdll/h_extern.h
+++ b/usr/lib/pkcs11/tpm_stdll/h_extern.h
@@ -2059,5 +2059,4 @@ void dump_shm(const char *);
  * leaf key or the private leaf key */
 #define CKA_ENC_AUTHDATA	CKA_VENDOR_DEFINED + 0x01000001
 
-#define OCK_STDLL_LOCK_FILE	"/var/lock/LCK..opencryptoki_stdll"
 #endif
--- a/usr/lib/pkcs11/tpm_stdll/new_host.c
+++ b/usr/lib/pkcs11/tpm_stdll/new_host.c
@@ -130,7 +130,6 @@ st_Initialized()
 }
 
 
-extern int spinxplfd;
 
 // ----------- SAB XXX XXX
 //
@@ -139,8 +138,9 @@ Fork_Initializer(void)
 {
   //    initialized == FALSE; // Get the initialization to be not true
 
-	spinxplfd = -1;
 
+	  // Initialize spinlock.
+      XProcLock_Init();
 
           // Force logout.  This cleans out the private session and list
           // and cleans out the private object map
@@ -404,6 +404,11 @@ CK_RV ST_Initialize( void **FunctionList
 	MY_CreateMutex( &sess_list_mutex );
 	MY_CreateMutex( &login_mutex     );
 
+	if (CreateXProcLock() != CKR_OK) {
+		OCK_LOG_ERR(ERR_PROCESS_LOCK);
+		goto done;
+	}
+
 	init_data_store((char *)PK_DIR);
 
 
@@ -498,8 +503,7 @@ CK_RV SC_Finalize( CK_SLOT_ID sid )
 
    detach_shm();
    // close spin lock file
-   if (spinxplfd != -1)
-     close(spinxplfd);
+   CloseXProcLock();
    if ( token_specific.t_final != NULL) {
       token_specific.t_final();
    }
--- a/usr/lib/pkcs11/tpm_stdll/utility.c
+++ b/usr/lib/pkcs11/tpm_stdll/utility.c
@@ -34,6 +34,7 @@
 #include <sys/ipc.h>
 #include <errno.h>
 #include <pwd.h>
+#include <grp.h>
 
 
 #include "pkcs11/pkcs11types.h"
@@ -45,6 +46,7 @@
 #include "pkcs32.h"
 
 #include <sys/file.h>
+#include <syslog.h>
 
 
 
@@ -329,35 +331,107 @@ _UnlockMutex( MUTEX *mutex )
 
 }
 
-int spinxplfd=-1;
+static int spinxplfd=-1;
 
 CK_RV
-XProcLock(void)
+CreateXProcLock(void)
+{
+	CK_BYTE lockfile[PATH_MAX];
+	struct passwd *pw = NULL;
+	struct stat statbuf;
+	mode_t mode = (S_IRUSR|S_IWUSR|S_IXUSR);
+
+	/* see if it exists */
+	if (spinxplfd == -1) {
+
+		/* get userid */
+		if ((pw = getpwuid(getuid())) == NULL) {
+			OCK_SYSLOG(LOG_ERR, "getpwuid(): %s\n",strerror(errno));
+			return CKR_FUNCTION_FAILED;
+		}
+
+		/* create user-specific directory */
+		sprintf(lockfile, "%s/%s/%s",
+			LOCKDIR_PATH, SUB_DIR, pw->pw_name);
+		/* see if it exists, otherwise mkdir will fail */
+		if (stat(lockfile, &statbuf) < 0) {
+			if (mkdir(lockfile, mode) == -1) {
+				OCK_SYSLOG(LOG_ERR, "mkdir(%s): %s\n",
+					   lockfile, strerror(errno));
+				return CKR_FUNCTION_FAILED;
+			}
+
+			/* ensure correct perms on user dir */
+			if (chmod(lockfile, mode) == -1) {
+				OCK_SYSLOG(LOG_ERR, "chmod(%s): %s\n",
+					   lockfile, strerror(errno));
+				return CKR_FUNCTION_FAILED;
+			}
+		}
+
+		/* create user lock file */
+		memset(lockfile, 0, PATH_MAX);
+		sprintf(lockfile, "%s/%s/%s/LCK..%s",
+			LOCKDIR_PATH, SUB_DIR, pw->pw_name, SUB_DIR);
+
+		spinxplfd = open(lockfile, O_CREAT|O_RDWR, mode);
+
+		if (spinxplfd == -1) {
+			OCK_SYSLOG(LOG_ERR, "open(%s): %s\n",
+				   lockfile, strerror(errno));
+			return CKR_FUNCTION_FAILED;
+		} else {
+			/* umask may prevent correct mode, so set it. */
+			if (fchmod(spinxplfd, mode) == -1) {
+				OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n",
+					   lockfile, strerror(errno));
+				goto err;
+			}
+		}
+	}
+
+	return CKR_OK;
+
+err:
+	if (spinxplfd != -1)
+		close(spinxplfd);
+	return CKR_FUNCTION_FAILED;
+}
+
+void
+CloseXProcLock(void)
 {
-   /* see if it exists */
-   if (spinxplfd == -1) {
-       spinxplfd = open(OCK_STDLL_LOCK_FILE, O_CREAT|O_RDWR,
-                       S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
-      if (spinxplfd == -1)
-         OCK_LOG_DEBUG("Failed to open lock file,%s: %s\n",
-                        OCK_STDLL_LOCK_FILE, strerror(errno));
-   }
+	if (spinxplfd != -1)
+		close(spinxplfd);
+}
 
-   if (spinxplfd != -1)
-      flock(spinxplfd,LOCK_EX);
+CK_RV
+XProcLock(void)
+{
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_EX);
+	else
+		OCK_LOG_DEBUG("No file descriptor to lock with.\n");
 
-   return CKR_OK;
+	return CKR_OK;
 }
 
 CK_RV
 XProcUnLock(void)
 {
-   if (spinxplfd != -1)
-      flock(spinxplfd,LOCK_UN);
+	if (spinxplfd != -1)
+		flock(spinxplfd, LOCK_UN);
+	else
+		OCK_LOG_DEBUG("No file descriptor to unlock with.\n");
 
-   return CKR_OK;
+	return CKR_OK;
 }
 
+void
+XProcLock_Init(void)
+{
+	spinxplfd = -1;
+}
 
 //
 //
--- a/usr/sbin/pkcs_slot/Makefile.am
+++ b/usr/sbin/pkcs_slot/Makefile.am
@@ -7,6 +7,7 @@ CLEANFILES = pkcs_slot
 pkcs_slot: pkcs_slot.in
 	@SED@ 	-e s!\@libdir\@!"@libdir@"!g			\
 		-e s!\@localstatedir\@!"@localstatedir@"!g	\
+		-e s!\@lockdir\@!"@lockdir@"!g	\
 		-e s!\@MKDIR_P\@!"@MKDIR_P@"!g			\
 		-e s!\@CHGRP\@!"@CHGRP@"!g			\
 		-e s!\@CHMOD\@!"@CHMOD@"!g < $< > $@-t
--- a/usr/sbin/pkcs_slot/pkcs_slot.in
+++ b/usr/sbin/pkcs_slot/pkcs_slot.in
@@ -306,36 +306,43 @@ SOFT_DIR="@localstatedir@/lib/opencrypto
 SOFT_DLL="@libdir@/opencryptoki/stdll/libpkcs11_sw.so"
 SOFT_DLL_FN="libpkcs11_sw.so"
 SOFT_INIT="ST_Initialize"
+SOFT_LOCK="@lockdir@/swtok"
 
 ICA_DIR="@localstatedir@/lib/opencryptoki/lite"
 ICA_DLL="@libdir@/opencryptoki/stdll/libpkcs11_ica.so"
 ICA_DLL_FN="libpkcs11_ica.so"
 ICA_INIT="ST_Initialize"
+ICA_LOCK="@lockdir@/lite"
 
 BCOM_DIR="@localstatedir@/lib/opencryptoki/bcom"
 BCOM_DLL="@libdir@/opencryptoki/stdll/PKCS11_BC.so"
 BCOM_DLL_FN="PKCS11_BC.so"
 BCOM_INIT="ST_Initialize"
+BCOM_LOCK="@lockdir@/bcom"
 
 AEP_DIR="@localstatedir@/lib/opencryptoki/aep"
 AEP_DLL="@libdir@/opencryptoki/stdll/PKCS11_AEP.so"
 AEP_DLL_FN="PKCS11_AEP.so"
 AEP_INIT="ST_Initialize"
+AEP_LOCK="@lockdir@/aep"
 
 CR_DIR="@localstatedir@/lib/opencryptoki/cr"
 CR_DLL="@libdir@/opencryptoki/stdll/PKCS11_CR.so"
 CR_DLL_FN="PKCS11_CR.so"
 CR_INIT="ST_Initialize"
+CR_LOCK="@lockdir@/cr"
 
 TPM_DIR="@localstatedir@/lib/opencryptoki/tpm"
 TPM_DLL="@libdir@/opencryptoki/stdll/libpkcs11_tpm.so"
 TPM_DLL_FN="libpkcs11_tpm.so"
 TPM_INIT="ST_Initialize"
+TPM_LOCK="@lockdir@/tpm"
 
 CCA_DIR="@localstatedir@/lib/opencryptoki/ccatok"
 CCA_DLL="@libdir@/opencryptoki/stdll/libpkcs11_cca.so"
 CCA_DLL_FN="libpkcs11_cca.so"
 CCA_INIT="ST_Initialize"
+CCA_LOCK="@lockdir@/ccatok"
 
 SYSTEM=`uname -s`
 MANUFACTURER=`uname -rs`
@@ -366,6 +373,13 @@ then
         @CHGRP@ pkcs11 @localstatedir@/lib/opencryptoki
 fi
 
+if [ ! -d @lockdir@ ]
+then
+	@MKDIR_P@ @lockdir@
+	@CHGRP@ pkcs11 @lockdir@
+	@CHMOD@ 0770 @lockdir@
+fi
+
 function create_token_dirs
 {
 	# $1 = the directory to create
@@ -403,10 +417,38 @@ function create_token_dirs
 	fi
 }
 
+
+function create_lock_dir
+{
+	# $1 = the directory to create
+	if test ! -d ${1}; then
+		mkdir ${1}
+		if test $? -ne 0; then
+			echo "Creation of token's lock directory ${1}failed." 1>&2
+			echo "You will need to create ${1} manually." 1>&2
+		fi
+	fi
+
+	# Set group pkcs11 on the lock directory
+	@CHGRP@ pkcs11 ${1}
+	if test $? -ne 0; then
+		echo "Setting group pkcs11 on ${1} failed. You need to" 1>&2
+		echo "do this manually, or this token may not function properly." 1>&2
+	fi
+
+	# Set permissions
+	@CHMOD@ 0770 ${1}
+	if test $? -ne 0; then
+		echo "Setting chmod 0770 on ${1} failed. You need to" 1>&2
+		echo "do this manually, or this token may not function properly." 1>&2
+	fi
+}
+
 # If the depth is "soft" then we are configuring the soft token....
 if [ $DEPTH = "soft" ]
 then
     create_token_dirs ${SOFT_DIR}
+    create_lock_dir ${SOFT_LOCK}
     SYS_SLOT="Soft"
 fi
 
@@ -431,12 +473,14 @@ then
 	    echo "Setting chmod 0770 on ${1} failed. You need to" 1>&2
 	    echo "do this manually, or this token may not function properly." 1>&2
     fi
+    create_lock_dir ${TPM_LOCK}
     SYS_SLOT="TPM"
 fi
 
 if [ $DEPTH = "cca" ]
 then
     create_token_dirs ${CCA_DIR}
+    create_lock_dir ${CCA_LOCK}
     SYS_SLOT="CCA"
 fi
 
@@ -448,24 +492,28 @@ fi
 if [ $DEPTH = "ica" ]
 then
     create_token_dirs ${ICA_DIR}
+    create_lock_dir ${ICA_LOCK}
     SYS_SLOT="ICA"
 fi
 
 if [ $DEPTH = "bcom" ]
 then
     create_token_dirs ${BCOM_DIR}
+    create_lock_dir ${BCOM_LOCK}
     SYS_SLOT="BCOM"
 fi
 
 if [ $DEPTH = "aep" ]
 then
     create_token_dirs ${AEP_DIR}
+    create_lock_dir ${AEP_LOCK}
     SYS_SLOT="AEP"
 fi
 
 if [ $DEPTH = "cr" ]
 then
     create_token_dirs ${CR_DIR}
+    create_lock_dir ${CR_LOCK}
     SYS_SLOT="CRNT"
 fi
 
--- a/usr/sbin/pkcsslotd/mutex.c
+++ b/usr/sbin/pkcsslotd/mutex.c
@@ -297,28 +297,77 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/file.h>
+#include <grp.h>
+
 static int xplfd=-1;
 
 int
 CreateXProcLock(void)
 {
-  
-   xplfd = open (OCK_API_LOCK_FILE,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-   return TRUE;
+	struct group *grp;
+	mode_t mode = (S_IRUSR|S_IRGRP);
+	struct stat statbuf;
+
+	if (xplfd == -1) {
+		if (stat(OCK_API_LOCK_FILE, &statbuf) == 0)
+			xplfd = open(OCK_API_LOCK_FILE, O_RDONLY, mode);
+		else {
+			xplfd = open(OCK_API_LOCK_FILE, O_CREAT|O_RDONLY, mode);
+
+			if (xplfd != -1) {
+				if (fchmod(xplfd, mode) == -1) {
+					DbgLog(DL0,"%s:fchmod(%s):%s\n",
+					       __FUNCTION__, OCK_API_LOCK_FILE,
+					       strerror(errno));
+					goto error;
+				}
+
+				grp = getgrnam("pkcs11");
+				if (grp != NULL) {
+					if (fchown(xplfd,-1,grp->gr_gid) == -1) {
+						DbgLog(DL0,"%s:fchown(%s):%s\n",
+						       __FUNCTION__,
+						       OCK_API_LOCK_FILE,
+						       strerror(errno));
+						goto error;
+					}
+				} else {
+					DbgLog(DL0,"%s:getgrnam():%s\n",
+					       __FUNCTION__, strerror(errno));
+					goto error;
+				}
+			}
+		}
+		if (xplfd == -1) {
+			DbgLog(DL0,"open(%s): %s\n", OCK_API_LOCK_FILE,
+			       strerror(errno));
+			return FALSE;
+		}
+	}
+	return TRUE;
+
+error:
+	if (xplfd != -1)
+		close(xplfd);
+	return FALSE;
 }
 
 int
 XProcLock(void)
 {
-   flock(xplfd,LOCK_EX);
-   return TRUE;
+	if (xplfd != -1)
+		flock(xplfd, LOCK_EX);
+
+	return TRUE;
 }
 
 int
 XProcUnLock(void)
 {
-   flock(xplfd,LOCK_UN);
-   return TRUE;
+	if (xplfd != -1)
+		flock(xplfd, LOCK_UN);
+
+	return TRUE;
 }
 
 /*********************************************************************************
