From dfc53371656a6dafa7366b4bd265d5d0c642f088575e229e3f3a314a5f5805f8 Mon Sep 17 00:00:00 2001 From: Mark Post Date: Mon, 13 Jun 2016 20:42:21 +0000 Subject: [PATCH] - Added ocki-3.5-sanity-checking.patch (bsc#983496). - Added %dir entry for %{_localstatedir}/log/opencryptoki/ (bsc#983990) OBS-URL: https://build.opensuse.org/package/show/security/openCryptoki?expand=0&rev=35 --- ocki-3.5-sanity-checking.patch | 674 +++++++++++++++++++++++++++++++++ openCryptoki.changes | 7 + openCryptoki.spec | 3 + 3 files changed, 684 insertions(+) create mode 100644 ocki-3.5-sanity-checking.patch diff --git a/ocki-3.5-sanity-checking.patch b/ocki-3.5-sanity-checking.patch new file mode 100644 index 0000000..7b34d59 --- /dev/null +++ b/ocki-3.5-sanity-checking.patch @@ -0,0 +1,674 @@ +1) Create lock and log directories from pkcsslotd when they are not available on the system. +2) The patch also does basic sanity checks of asserting the presence of pkcs11 group, euid, gid of the process running pkcsslotd. +3) The patch also checks if token directories are available on the system. +4) The token lock sub-directories are created from opencryptoki while the token is configured via pkcsconf or when the first call to the token is made via C_Initialize. +Signed-off-by: Vineetha Pai +Signed-off-by: Harald Freudenberger + +--- a/usr/lib/pkcs11/common/utility.c ++++ b/usr/lib/pkcs11/common/utility.c +@@ -557,9 +557,11 @@ + CK_RV CreateXProcLock(void) + { + CK_BYTE lockfile[PATH_MAX]; ++ CK_BYTE lockdir[PATH_MAX]; + struct group *grp; + struct stat statbuf; + mode_t mode = (S_IRUSR | S_IRGRP); ++ int ret = -1; + + if (spinxplfd == -1) { + +@@ -571,9 +573,42 @@ + return CKR_FUNCTION_FAILED; + } + ++ /** create lock subdir for each token if it doesn't exist. ++ * The root directory should be created in slotmgr daemon **/ ++ sprintf(lockdir, "%s/%s", LOCKDIR_PATH, SUB_DIR); ++ ++ ret = stat(lockdir, &statbuf); ++ if (ret != 0 && errno == ENOENT) { ++ /* dir does not exist, try to create it */ ++ ret = mkdir(lockdir, S_IRWXU|S_IRWXG); ++ if (ret != 0) { ++ OCK_SYSLOG(LOG_ERR, ++ "Directory(%s) missing: %s\n", ++ lockdir, ++ strerror(errno)); ++ goto err; ++ } ++ grp = getgrnam("pkcs11"); ++ /* set ownership to euid, and pkcs11 group */ ++ if (chown(lockdir, geteuid(), grp->gr_gid) != 0) { ++ fprintf(stderr, "Failed to set owner:group \ ++ ownership\ ++ on %s directory", lockdir); ++ goto err; ++ } ++ /* mkdir does not set group permission right, so ++ ** trying explictly here again */ ++ if (chmod(lockdir, S_IRWXU|S_IRWXG) != 0){ ++ fprintf(stderr, "Failed to change \ ++ permissions\ ++ on %s directory", lockdir); ++ goto err; ++ } ++ } ++ + /* create user lock file */ + sprintf(lockfile, "%s/%s/LCK..%s", +- LOCKDIR_PATH, SUB_DIR, SUB_DIR); ++ LOCKDIR_PATH, SUB_DIR, SUB_DIR); + + if (stat(lockfile, &statbuf) == 0) + spinxplfd = open(lockfile, O_RDONLY, mode); +@@ -583,30 +618,30 @@ + /* umask may prevent correct mode,so set it. */ + if (fchmod(spinxplfd, mode) == -1) { + OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n", +- lockfile, strerror(errno)); ++ lockfile, strerror(errno)); + goto err; + } + + grp = getgrnam("pkcs11"); + if (grp != NULL) { + if (fchown(spinxplfd, -1, grp->gr_gid) +- == -1) { ++ == -1) { + OCK_SYSLOG(LOG_ERR, +- "fchown(%s): %s\n", +- lockfile, +- strerror(errno)); ++ "fchown(%s): %s\n", ++ lockfile, ++ strerror(errno)); + goto err; + } + } else { + OCK_SYSLOG(LOG_ERR, "getgrnam(): %s\n", +- strerror(errno)); ++ strerror(errno)); + goto err; + } + } + } + if (spinxplfd == -1) { + OCK_SYSLOG(LOG_ERR, "open(%s): %s\n", +- lockfile, strerror(errno)); ++ lockfile, strerror(errno)); + return CKR_FUNCTION_FAILED; + } + } +--- a/usr/sbin/pkcsslotd/slotmgr.c ++++ b/usr/sbin/pkcsslotd/slotmgr.c +@@ -8,10 +8,10 @@ + + 1. DEFINITIONS + +- "Contribution" means: ++ "Contribution" means: + a) in the case of the initial Contributor, the + initial code and documentation distributed under +- this Agreement, and ++ this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and +@@ -35,7 +35,7 @@ + "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. + + "Program" means the Contributions distributed in + accordance with this Agreement. +@@ -130,7 +130,7 @@ + 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. ++ each copy of the Program. + + Contributors may not remove or alter any copyright notices + contained within the Program. +@@ -138,7 +138,7 @@ + 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. ++ the Contribution. + + + 4. COMMERCIAL DISTRIBUTION +@@ -199,7 +199,7 @@ + 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. ++ unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER +@@ -248,7 +248,7 @@ + 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. ++ 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 +@@ -280,7 +280,7 @@ + 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. ++ a jury trial in any resulting litigation. + + + +@@ -294,6 +294,8 @@ + #include + #include + #include ++#include ++#include + + #include "log.h" + #include "slotmgr.h" +@@ -309,8 +311,13 @@ + int socketfd; + Slot_Mgr_Socket_t socketData; + +-/* +- We make main() able to modify Daemon so that we can ++struct dircheckinfo_s { ++ const char *dir; ++ int mode; ++}; ++ ++/* ++ We make main() able to modify Daemon so that we can + daemonize or not based on a command-line argument + */ + extern BOOL Daemon; +@@ -322,14 +329,91 @@ + u_int32 *p; + char Buf[PATH_MAX]; + u_int32 i; +- ++ + p = (u_int32 *) shmp; +- ++ + for ( i = 0; i < 15; i++ ) { + sprintf(Buf, "%08X %08X %08X %08X", p[0+(i*4)], p[1+(i*4)], p[2+(i*4)], p[3+(i*4)]); + LogLog(Buf); + } + return; ++} ++ ++/** This function does basic sanity checks to make sure the ++ * eco system is in place for opencryptoki to run properly. ++ **/ ++void run_sanity_checks() ++{ ++ int i, ec, uid = -1; ++ struct group *grp = NULL; ++ struct stat sbuf; ++ struct dircheckinfo_s dircheck[] = { ++ //drwxrwx--- ++ {LOCKDIR_PATH, S_IRWXU|S_IRWXG}, ++ {OCK_LOGDIR, S_IRWXU|S_IRWXG}, ++ {NULL, 0}, ++ }; ++ ++ /* first check that our effective user id is root */ ++ uid = (int) geteuid(); ++ if (uid != 0) { ++ fprintf(stderr, "This daemon needs root privilegies, but the effective user id is not 'root'.\n"); ++ exit(1); ++ } ++ ++ /* check that the pkcs11 group exists */ ++ grp = getgrnam("pkcs11"); ++ if (!grp) { ++ fprintf(stderr, "There is no 'pkcs11' group on this system.\n"); ++ exit(1); ++ } ++ ++ /* check effective group id */ ++ uid = (int) getegid(); ++ if (uid != 0 && uid != (int) grp->gr_gid) { ++ fprintf(stderr, "This daemon should have an effective group id of 'root' or 'pkcs11'.\n"); ++ exit(1); ++ } ++ ++ /* Create base lock and log directory here. API..Lock file is ++ * accessed from the daemon in CreateXProcLock() in mutex.c.*/ ++ for (i=0; dircheck[i].dir != NULL; i++) { ++ ec = stat(dircheck[i].dir, &sbuf); ++ if (ec != 0 && errno == ENOENT) { ++ /* dir does not exist, try to create it */ ++ ec = mkdir(dircheck[i].dir, dircheck[i].mode); ++ if (ec != 0) { ++ fprintf(stderr, "Directory %s missing\n", ++ dircheck[i].dir); ++ exit(2); ++ } ++ /* set ownership to root, and pkcs11 group */ ++ if (chown(dircheck[i].dir, geteuid(), grp->gr_gid) != 0) { ++ fprintf(stderr, "Failed to set owner:group \ ++ ownership\ ++ on %s directory", dircheck[i].dir); ++ exit(1); ++ } ++ /* mkdir does not set group permission right, so ++ * trying explictly here again */ ++ if (chmod(dircheck[i].dir, dircheck[i].mode) != 0){ ++ fprintf(stderr, "Failed to change \ ++ permissions\ ++ on %s directory", dircheck[i].dir); ++ exit(1); ++ } ++ } ++ } ++ ++ /** check if token directory is available, if not flag an error. ++ * We do not create token directories here as admin should ++ * configure and decide which tokens to expose to opencryptoki ++ * outside of opencryptoki and pkcsslotd */ ++ ec = stat(CONFIG_PATH, &sbuf); ++ if (ec != 0 && errno == ENOENT) { ++ fprintf(stderr, "Token directories missing\n"); ++ exit(2); ++ } + } + + /***************************************** +@@ -341,205 +425,191 @@ + *****************************************/ + + int main ( int argc, char *argv[], char *envp[]) { +- int ret; +- +- /**********************************/ +- /* Read in command-line arguments */ +- /**********************************/ +- +- /* FIXME: Argument for daemonizing or not */ +- /* FIXME: Argument for debug level */ +- /* FIXME: Arguments affecting the log files, whether to use syslog, etc. (Read conf file?) */ +- +- +- /* Report our debug level */ +- if ( GetDebugLevel() > DEBUG_NONE) { +- +- DbgLog(GetDebugLevel(), "Starting with debugging messages logged at level %d (%d = No messages; %d = few; %d = more, etc.)", +- GetDebugLevel(), DEBUG_NONE, DEBUG_LEVEL0, DEBUG_LEVEL1); +- +- } +- +- +- /* Save our startup directory */ +- SaveStartupDirectory( argv[0] ); +- +- ret = load_and_parse(OCK_CONFIG); +- if (ret != 0) { +- ErrLog("Failed to read config file.\n"); +- return 1; +- } else +- DbgLog (DL0, "Parse config file succeeded.\n"); +- +- /* Allocate and Attach the shared memory region */ +- if ( ! CreateSharedMemory() ) { +- /* CreateSharedMemory() does it's own error logging */ +- return 1; +- } +- +- DbgLog(DL0,"SHMID %d token %#X \n", shmid, tok); +- +- /* Now that we've created the shared memory segment, we attach to it */ +- if ( ! AttachToSharedMemory() ) { +- /* AttachToSharedMemory() does it's own error logging */ +- DestroySharedMemory(); +- return 2; +- } +- +- /* Initialize the global shared memory mutex (and the attribute used to create the per-process mutexes */ +- if ( ! InitializeMutexes() ) { +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 3; +- } +- +- /* Get the global shared memory mutex */ +- +- XProcLock(); +- +- /* Populate the Shared Memory Region */ +- if ( ! InitSharedMemory(shmp) ) { +- +- XProcUnLock(); +- +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 4; +- } +- +- /* Release the global shared memory mutex */ +- XProcUnLock(); +- +- if ((socketfd = CreateListenerSocket()) < 0) { +- DestroyMutexes(); +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 5; +- } +- +- if (!InitSocketData(&socketData)) { +- DetachSocketListener(socketfd); +- DestroyMutexes(); +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 6; +- } +- +- /* +- * Become a Daemon, if called for +- */ +- if ( Daemon ) { +- pid_t pid; +- if ( (pid = fork()) < 0 ){ +- DetachSocketListener(socketfd); +- DestroyMutexes(); +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 7; +- } else { +- if ( pid != 0) { +- exit(0); // Terminate the parent +- } else { +- +- setsid(); // Session leader ++ int ret; ++ ++ /**********************************/ ++ /* Read in command-line arguments */ ++ /**********************************/ ++ ++ /* FIXME: Argument for daemonizing or not */ ++ /* FIXME: Argument for debug level */ ++ /* FIXME: Arguments affecting the log files, whether to use syslog, etc. (Read conf file?) */ ++ ++ /* Do some basic sanity checks */ ++ run_sanity_checks(); ++ ++ /* Report our debug level */ ++ if ( GetDebugLevel() > DEBUG_NONE) { ++ DbgLog(GetDebugLevel(), "Starting with debugging messages logged at \ ++ level %d (%d = No messages; %d = few; %d = more, etc.)", ++ GetDebugLevel(), DEBUG_NONE, DEBUG_LEVEL0, DEBUG_LEVEL1); ++ } ++ ++ /* Save our startup directory */ ++ SaveStartupDirectory( argv[0] ); ++ ++ ret = load_and_parse(OCK_CONFIG); ++ if (ret != 0) { ++ ErrLog("Failed to read config file.\n"); ++ return 1; ++ } else ++ DbgLog (DL0, "Parse config file succeeded.\n"); ++ ++ /* Allocate and Attach the shared memory region */ ++ if ( ! CreateSharedMemory() ) { ++ /* CreateSharedMemory() does it's own error logging */ ++ return 1; ++ } ++ ++ DbgLog(DL0,"SHMID %d token %#X \n", shmid, tok); ++ ++ /* Now that we've created the shared memory segment, we attach to it */ ++ if ( ! AttachToSharedMemory() ) { ++ /* AttachToSharedMemory() does it's own error logging */ ++ DestroySharedMemory(); ++ return 2; ++ } ++ ++ /* Initialize the global shared memory mutex (and the attribute ++ * used to create the per-process mutexes */ ++ if ( ! InitializeMutexes() ) { ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 3; ++ } ++ ++ /* Get the global shared memory mutex */ ++ XProcLock(); ++ ++ /* Populate the Shared Memory Region */ ++ if ( ! InitSharedMemory(shmp) ) { ++ ++ XProcUnLock(); ++ ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 4; ++ } ++ ++ /* Release the global shared memory mutex */ ++ XProcUnLock(); ++ ++ if ((socketfd = CreateListenerSocket()) < 0) { ++ DestroyMutexes(); ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 5; ++ } ++ ++ if (!InitSocketData(&socketData)) { ++ DetachSocketListener(socketfd); ++ DestroyMutexes(); ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 6; ++ } ++ ++ /* ++ * Become a Daemon, if called for ++ */ ++ if ( Daemon ) { ++ pid_t pid; ++ if ( (pid = fork()) < 0 ){ ++ DetachSocketListener(socketfd); ++ DestroyMutexes(); ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 7; ++ } else { ++ if ( pid != 0) { ++ exit(0); // Terminate the parent ++ } else { ++ ++ setsid(); // Session leader + #ifndef DEV +- fclose(stderr); +- fclose(stdout); +- fclose(stdin); ++ fclose(stderr); ++ fclose(stdout); ++ fclose(stdin); + #endif +- +- } +- } +- +- +- } else { +- ++ } ++ } ++ } else { + #ifdef DEV +- // Log only on development builds +- LogLog("Not becoming a daemon...\n"); ++ // Log only on development builds ++ LogLog("Not becoming a daemon...\n"); + #endif +- +- } +- +- +- /***************************************** +- * +- * Register Signal Handlers +- * Daemon probably should ignore ALL signals possible, since termination +- * while active is a bad thing... however one could check for +- * any processes active in the shared memory, and destroy the shm if +- * the process wishes to terminate. +- * +- *****************************************/ +- +- /* +- * We have to set up the signal handlers after we daemonize because +- * the daemonization process redefines our handler for (at least) SIGTERM +- */ +- +- if ( ! SetupSignalHandlers() ) { +- DetachSocketListener(socketfd); +- DestroyMutexes(); +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 8; +- } +- +- +- +- +- /* ultimatly we will create a couple of threads which monitor the slot db +- and handle the insertion and removal of tokens from the slot. +- */ +- +- /* For Testing the Garbage collection routines */ +- /* +- shmp->proc_table[3].inuse = TRUE; +- shmp->proc_table[3].proc_id = 24328; +- */ ++ } ++ ++ /***************************************** ++ * ++ * Register Signal Handlers ++ * Daemon probably should ignore ALL signals possible, since termination ++ * while active is a bad thing... however one could check for ++ * any processes active in the shared memory, and destroy the shm if ++ * the process wishes to terminate. ++ * ++ *****************************************/ ++ ++ /* ++ * We have to set up the signal handlers after we daemonize because ++ * the daemonization process redefines our handler for (at least) SIGTERM ++ */ ++ if ( ! SetupSignalHandlers() ) { ++ DetachSocketListener(socketfd); ++ DestroyMutexes(); ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 8; ++ } ++ ++ /* ultimatly we will create a couple of threads which monitor the slot db ++ and handle the insertion and removal of tokens from the slot. ++ */ ++ ++ /* For Testing the Garbage collection routines */ ++ /* ++ shmp->proc_table[3].inuse = TRUE; ++ shmp->proc_table[3].proc_id = 24328; ++ */ + + #if !defined(NOGARBAGE) +-printf("Start garbage \n"); +- /* start garbage collection thread */ +- if ( ! StartGCThread(shmp) ) { +- DetachSocketListener(socketfd); +- DestroyMutexes(); +- DetachFromSharedMemory(); +- DestroySharedMemory(); +- return 9; +- } ++ printf("Start garbage \n"); ++ /* start garbage collection thread */ ++ if ( ! StartGCThread(shmp) ) { ++ DetachSocketListener(socketfd); ++ DestroyMutexes(); ++ DetachFromSharedMemory(); ++ DestroySharedMemory(); ++ return 9; ++ } + #endif + +- // We've fully become a daemon. Now create the PID file +- { +- FILE *pidfile; +- +- pidfile = fopen(PID_FILE_PATH,"w"); +- if (pidfile) { +- fprintf(pidfile,"%d",getpid()); +- fclose(pidfile); +- } +- } +- +- while (1) { ++ // We've fully become a daemon. Now create the PID file ++ { ++ FILE *pidfile; ++ ++ pidfile = fopen(PID_FILE_PATH,"w"); ++ if (pidfile) { ++ fprintf(pidfile,"%d",getpid()); ++ fclose(pidfile); ++ } ++ } ++ ++ while (1) { + #if !(THREADED) && !(NOGARBAGE) +- CheckForGarbage(shmp); ++ CheckForGarbage(shmp); + #endif +- +- SocketConnectionHandler(socketfd, 10); +- +- } +- +- +- /************************************************************* +- * +- * Here we need to actualy go through the processes and verify that thye +- * still exist. If not, then they terminated with out properly calling +- * C_Finalize and therefore need to be removed from the system. +- * Look for a system routine to determine if the shared memory is held by +- * the process to further verify that the proper processes are in the +- * table. +- * +- *************************************************************/ +- ++ SocketConnectionHandler(socketfd, 10); ++ } ++ ++ /************************************************************* ++ * ++ * Here we need to actualy go through the processes and verify that thye ++ * still exist. If not, then they terminated with out properly calling ++ * C_Finalize and therefore need to be removed from the system. ++ * Look for a system routine to determine if the shared memory is held by ++ * the process to further verify that the proper processes are in the ++ * table. ++ * ++ *************************************************************/ + } /* end main */ diff --git a/openCryptoki.changes b/openCryptoki.changes index 408d6a2..cc8a863 100644 --- a/openCryptoki.changes +++ b/openCryptoki.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Mon Jun 13 20:17:04 UTC 2016 - mpost@suse.com + +- Added ocki-3.5-sanity-checking.patch (bsc#983496). +- Added %dir entry for %{_localstatedir}/log/opencryptoki/ + (bsc#983990) + ------------------------------------------------------------------- Wed May 25 21:23:29 UTC 2016 - mpost@suse.com diff --git a/openCryptoki.spec b/openCryptoki.spec index 11a3720..22ed898 100644 --- a/openCryptoki.spec +++ b/openCryptoki.spec @@ -63,6 +63,7 @@ Source3: openCryptoki-tmp.conf # Patch 1 is needed because group pkcs11 doesn't exist in the build environment # and because we don't want(?) various file and directory permissions to be 0700. Patch1: ocki-3.1-remove-make-install-chgrp.patch +Patch2: ocki-3.5-sanity-checking.patch Url: https://sourceforge.net/projects/opencryptoki/ BuildRoot: %{_tmppath}/%{name}-%{version}-build PreReq: /usr/sbin/groupadd /usr/bin/id /usr/sbin/usermod /bin/sed @@ -141,6 +142,7 @@ Cryptographic Accelerator (FC 4960 on pSeries). %prep %setup -q -n %{oc_cvs_tag} %patch1 -p1 +%patch2 -p1 cp %{SOURCE2} . %build @@ -289,6 +291,7 @@ ln -sf %{_libdir}/opencryptoki/libopencryptoki.so /usr/lib/pkcs11/PKCS11_API.so6 %dir %attr(770,root,pkcs11) %{_localstatedir}/lib/opencryptoki/lite %dir %attr(770,root,pkcs11) %{_localstatedir}/lib/opencryptoki/lite/TOK_OBJ %endif +%dir %attr(770,root,pkcs11) %{_localstatedir}/log/opencryptoki/ %{_mandir}/man*/* %files devel