|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <unistd.h>
|
|
Packit |
8681c6 |
#include <errno.h>
|
|
Packit |
8681c6 |
#include <sys/types.h>
|
|
Packit |
8681c6 |
#include <sys/stat.h>
|
|
Packit |
8681c6 |
#include <grp.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <openssl/evp.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "log.h"
|
|
Packit |
8681c6 |
#include "slotmgr.h"
|
|
Packit |
8681c6 |
#include "pkcsslotd.h"
|
|
Packit |
8681c6 |
#include "parser.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define OBJ_DIR "TOK_OBJ"
|
|
Packit |
8681c6 |
#define MD5_HASH_SIZE 16
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
typedef char md5_hash_entry[MD5_HASH_SIZE];
|
|
Packit |
8681c6 |
md5_hash_entry tokname_hash_table[NUMBER_SLOTS_MANAGED];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
Slot_Mgr_Shr_t *shmp; // pointer to the shared memory region.
|
|
Packit |
8681c6 |
int shmid;
|
|
Packit |
8681c6 |
key_t tok;
|
|
Packit |
8681c6 |
Slot_Info_t_64 sinfo[NUMBER_SLOTS_MANAGED];
|
|
Packit |
8681c6 |
unsigned int NumberSlotsInDB = 0;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
Slot_Info_t_64 *psinfo;
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
int socketfd;
|
|
Packit |
8681c6 |
Slot_Mgr_Socket_t socketData;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
struct dircheckinfo_s {
|
|
Packit |
8681c6 |
const char *dir;
|
|
Packit |
8681c6 |
int mode;
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
struct parse_data {
|
|
Packit Service |
8aa27d |
Slot_Info_t_64 sinfo_struct;
|
|
Packit Service |
8aa27d |
unsigned long int index;
|
|
Packit Service |
8aa27d |
char errbuf[256];
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
We make main() able to modify Daemon so that we can
|
|
Packit |
8681c6 |
daemonize or not based on a command-line argument
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
extern BOOL Daemon;
|
|
Packit |
8681c6 |
extern BOOL IveDaemonized;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
void DumpSharedMemory(void)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
u_int32 *p;
|
|
Packit Service |
8aa27d |
char buf[4 * 8 + 4];
|
|
Packit |
8681c6 |
u_int32 i;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
p = (u_int32 *) shmp;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < 15; i++) {
|
|
Packit Service |
8aa27d |
sprintf(buf, "%08X %08X %08X %08X", p[0 + (i * 4)], p[1 + (i * 4)],
|
|
Packit |
8681c6 |
p[2 + (i * 4)], p[3 + (i * 4)]);
|
|
Packit Service |
8aa27d |
LogLog(buf);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int compute_hash(int hash_type, int buf_size, char *buf, char *digest)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
EVP_MD_CTX *md_ctx = NULL;
|
|
Packit |
8681c6 |
unsigned int result_size;
|
|
Packit |
8681c6 |
int rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
md_ctx = EVP_MD_CTX_create();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (hash_type) {
|
|
Packit |
8681c6 |
case HASH_SHA1:
|
|
Packit |
8681c6 |
rc = EVP_DigestInit(md_ctx, EVP_sha1());
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case HASH_MD5:
|
|
Packit |
8681c6 |
rc = EVP_DigestInit(md_ctx, EVP_md5());
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
EVP_MD_CTX_destroy(md_ctx);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
fprintf(stderr, "EVP_DigestInit() failed: rc = %d\n", rc);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = EVP_DigestUpdate(md_ctx, buf, buf_size);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
fprintf(stderr, "EVP_DigestUpdate() failed: rc = %d\n", rc);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
result_size = EVP_MD_CTX_size(md_ctx);
|
|
Packit |
8681c6 |
rc = EVP_DigestFinal(md_ctx, (unsigned char *) digest, &result_size);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
fprintf(stderr, "EVP_DigestFinal() failed: rc = %d\n", rc);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
EVP_MD_CTX_destroy(md_ctx);
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/** This function does basic sanity checks to make sure the
|
|
Packit |
8681c6 |
* eco system is in place for opencryptoki to run properly.
|
|
Packit |
8681c6 |
**/
|
|
Packit |
8681c6 |
void run_sanity_checks()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int i, ec, uid = -1;
|
|
Packit |
8681c6 |
struct group *grp = NULL;
|
|
Packit |
8681c6 |
struct stat sbuf;
|
|
Packit |
8681c6 |
struct dircheckinfo_s dircheck[] = {
|
|
Packit |
8681c6 |
//drwxrwx---
|
|
Packit |
8681c6 |
{LOCKDIR_PATH, S_IRWXU | S_IRWXG},
|
|
Packit |
8681c6 |
{OCK_LOGDIR, S_IRWXU | S_IRWXG},
|
|
Packit |
8681c6 |
{NULL, 0},
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* first check that our effective user id is root */
|
|
Packit |
8681c6 |
uid = (int) geteuid();
|
|
Packit |
8681c6 |
if (uid != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "This daemon needs root privilegies, "
|
|
Packit |
8681c6 |
"but the effective user id is not 'root'.\n");
|
|
Packit |
8681c6 |
exit(1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* check that the pkcs11 group exists */
|
|
Packit |
8681c6 |
grp = getgrnam("pkcs11");
|
|
Packit |
8681c6 |
if (!grp) {
|
|
Packit |
8681c6 |
fprintf(stderr, "There is no 'pkcs11' group on this system.\n");
|
|
Packit |
8681c6 |
exit(1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* check effective group id */
|
|
Packit |
8681c6 |
uid = (int) getegid();
|
|
Packit |
8681c6 |
if (uid != 0 && uid != (int) grp->gr_gid) {
|
|
Packit |
8681c6 |
fprintf(stderr, "This daemon should have an effective group id of "
|
|
Packit |
8681c6 |
"'root' or 'pkcs11'.\n");
|
|
Packit |
8681c6 |
exit(1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Create base lock and log directory here. API..Lock file is
|
|
Packit |
8681c6 |
* accessed from the daemon in CreateXProcLock() in mutex.c.*/
|
|
Packit |
8681c6 |
for (i = 0; dircheck[i].dir != NULL; i++) {
|
|
Packit |
8681c6 |
ec = stat(dircheck[i].dir, &sbuf);
|
|
Packit |
8681c6 |
if (ec != 0 && errno == ENOENT) {
|
|
Packit |
8681c6 |
/* dir does not exist, try to create it */
|
|
Packit |
8681c6 |
ec = mkdir(dircheck[i].dir, dircheck[i].mode);
|
|
Packit |
8681c6 |
if (ec != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Directory %s missing\n", dircheck[i].dir);
|
|
Packit |
8681c6 |
exit(2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
/* set ownership to root, and pkcs11 group */
|
|
Packit |
8681c6 |
if (chown(dircheck[i].dir, geteuid(), grp->gr_gid) != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Failed to set owner:group ownership on %s directory",
|
|
Packit |
8681c6 |
dircheck[i].dir);
|
|
Packit |
8681c6 |
exit(1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
/* mkdir does not set group permission right, so
|
|
Packit |
8681c6 |
* trying explictly here again */
|
|
Packit |
8681c6 |
if (chmod(dircheck[i].dir, dircheck[i].mode) != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Failed to change permissions on %s directory",
|
|
Packit |
8681c6 |
dircheck[i].dir);
|
|
Packit |
8681c6 |
exit(1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* check if token directory is available, if not flag an error.
|
|
Packit |
8681c6 |
* We do not create token directories here as admin should
|
|
Packit |
8681c6 |
* configure and decide which tokens to expose to opencryptoki
|
|
Packit |
8681c6 |
* outside of opencryptoki and pkcsslotd */
|
|
Packit |
8681c6 |
ec = stat(CONFIG_PATH, &sbuf);
|
|
Packit |
8681c6 |
if (ec != 0 && errno == ENOENT) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Token directories missing\n");
|
|
Packit |
8681c6 |
exit(2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int is_duplicate(md5_hash_entry hash, md5_hash_entry *hash_table)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int i;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 0; i < NUMBER_SLOTS_MANAGED; i++) {
|
|
Packit |
8681c6 |
if (memcmp(hash_table[i], hash, sizeof(md5_hash_entry)) == 0)
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int chk_create_tokdir(Slot_Info_t_64 *psinfo)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
struct stat sbuf;
|
|
Packit |
8681c6 |
char tokendir[PATH_MAX];
|
|
Packit |
8681c6 |
struct group *grp;
|
|
Packit |
8681c6 |
gid_t grpid;
|
|
Packit |
8681c6 |
int uid, rc;
|
|
Packit |
8681c6 |
mode_t proc_umask;
|
|
Packit |
8681c6 |
char *tokdir = psinfo->tokname;
|
|
Packit |
8681c6 |
char token_md5_hash[MD5_HASH_SIZE];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* skip if no dedicated token directory is required */
|
|
Packit |
8681c6 |
if (!tokdir || strlen(tokdir) == 0)
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
/* Check if the path length fits in the max path length
|
|
Packit Service |
8aa27d |
(include 2 * / and 0)
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
if (strlen(CONFIG_PATH) + strlen(tokdir) + strlen(OBJ_DIR) + 3 > PATH_MAX) {
|
|
Packit Service |
8aa27d |
fprintf(stderr, "Path name for token object directory too long!\n");
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
proc_umask = umask(0);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get 'PKCS11' group id */
|
|
Packit |
8681c6 |
uid = (int) geteuid();
|
|
Packit |
8681c6 |
grp = getgrnam("pkcs11");
|
|
Packit |
8681c6 |
if (!grp) {
|
|
Packit |
8681c6 |
fprintf(stderr, "PKCS11 group does not exist [errno=%d].\n", errno);
|
|
Packit |
8681c6 |
return errno;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
grpid = grp->gr_gid;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* calculate md5 hash from token name */
|
|
Packit |
8681c6 |
rc = compute_md5(tokdir, strlen(tokdir), token_md5_hash);
|
|
Packit |
8681c6 |
if (rc) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Error calculating MD5 of token name!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
/* check for duplicate token names */
|
|
Packit |
8681c6 |
if (is_duplicate(token_md5_hash, tokname_hash_table)) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Duplicate token name '%s'!\n", tokdir);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* add entry into hash table */
|
|
Packit |
8681c6 |
memcpy(tokname_hash_table[psinfo->slot_number], token_md5_hash,
|
|
Packit |
8681c6 |
MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Create token specific directory */
|
|
Packit Service |
8aa27d |
/* sprintf checked above */
|
|
Packit |
8681c6 |
sprintf(tokendir, "%s/%s", CONFIG_PATH, tokdir);
|
|
Packit |
8681c6 |
rc = stat(tokendir, &sbuf);
|
|
Packit |
8681c6 |
if (rc != 0 && errno == ENOENT) {
|
|
Packit |
8681c6 |
/* directory does not exist, create it */
|
|
Packit |
8681c6 |
rc = mkdir(tokendir, S_IRWXU | S_IRWXG);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Creating directory '%s' failed [errno=%d].\n",
|
|
Packit |
8681c6 |
tokendir, errno);
|
|
Packit |
8681c6 |
umask(proc_umask);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = chown(tokendir, uid, grpid);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Could not set PKCS11 group permission [errno=%d].\n",
|
|
Packit |
8681c6 |
errno);
|
|
Packit |
8681c6 |
umask(proc_umask);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Create TOK_OBJ directory */
|
|
Packit Service |
8aa27d |
/* sprintf checked above */
|
|
Packit |
8681c6 |
sprintf(tokendir, "%s/%s/%s", CONFIG_PATH, tokdir, OBJ_DIR);
|
|
Packit |
8681c6 |
rc = stat(tokendir, &sbuf);
|
|
Packit |
8681c6 |
if (rc != 0 && errno == ENOENT) {
|
|
Packit |
8681c6 |
/* directory does not exist, create it */
|
|
Packit |
8681c6 |
rc = mkdir(tokendir, S_IRWXU | S_IRWXG);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Creating directory '%s' failed [errno=%d].\n",
|
|
Packit |
8681c6 |
tokendir, errno);
|
|
Packit |
8681c6 |
umask(proc_umask);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = chown(tokendir, uid, grpid);
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Could not set PKCS11 group permission [errno=%d].\n",
|
|
Packit |
8681c6 |
errno);
|
|
Packit |
8681c6 |
umask(proc_umask);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
umask(proc_umask);
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int create_pid_file(pid_t pid)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *pidfile;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
pidfile = fopen(PID_FILE_PATH, "w");
|
|
Packit |
8681c6 |
if (!pidfile) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Could not create pid file '%s' [errno=%d].\n",
|
|
Packit |
8681c6 |
PID_FILE_PATH, errno);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fprintf(pidfile, "%d\n", (int) pid);
|
|
Packit |
8681c6 |
fflush(pidfile);
|
|
Packit |
8681c6 |
fclose(pidfile);
|
|
Packit |
8681c6 |
InfoLog("PID File created");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
/*************************
|
|
Packit Service |
8aa27d |
* Parser callouts
|
|
Packit Service |
8aa27d |
************************/
|
|
Packit Service |
8aa27d |
static int slotmgr_begin_slot(void *private, int slot, int nl_before_slot)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parse_data *d = (struct parse_data *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
UNUSED(nl_before_slot);
|
|
Packit Service |
8aa27d |
memset(&d->sinfo_struct, 0, sizeof(d->sinfo_struct));
|
|
Packit Service |
8aa27d |
if (slot >= NUMBER_SLOTS_MANAGED) {
|
|
Packit Service |
8aa27d |
snprintf(d->errbuf, sizeof(d->errbuf),
|
|
Packit Service |
8aa27d |
"Slot number %d unsupported! Slot number has to be less than %d!",
|
|
Packit Service |
8aa27d |
slot, NUMBER_SLOTS_MANAGED);
|
|
Packit Service |
8aa27d |
return 1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
d->sinfo_struct.slot_number = slot;
|
|
Packit Service |
8aa27d |
d->index = slot;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int slotmgr_end_slot(void *private)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parse_data *d = (struct parse_data *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* set some defaults if user hasn't set these. */
|
|
Packit Service |
8aa27d |
if (!d->sinfo_struct.pk_slot.slotDescription[0]) {
|
|
Packit Service |
8aa27d |
memset(&d->sinfo_struct.pk_slot.slotDescription[0], ' ',
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.pk_slot.slotDescription));
|
|
Packit Service |
8aa27d |
memcpy(&d->sinfo_struct.pk_slot.slotDescription[0],
|
|
Packit Service |
8aa27d |
DEF_SLOTDESC, strlen(DEF_SLOTDESC));
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (!d->sinfo_struct.pk_slot.manufacturerID[0]) {
|
|
Packit Service |
8aa27d |
memset(&d->sinfo_struct.pk_slot.manufacturerID[0], ' ',
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.pk_slot.manufacturerID));
|
|
Packit Service |
8aa27d |
memcpy(&d->sinfo_struct.pk_slot.manufacturerID[0],
|
|
Packit Service |
8aa27d |
DEF_MANUFID, strlen(DEF_MANUFID));
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
memcpy(&(sinfo[d->index]), &d->sinfo_struct, sizeof(d->sinfo_struct));
|
|
Packit Service |
8aa27d |
NumberSlotsInDB++;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int do_str(struct parse_data *d, char *slotinfo, size_t size,
|
|
Packit Service |
8aa27d |
int tok, const char *val, char padding)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (strlen(val) > size) {
|
|
Packit Service |
8aa27d |
snprintf(d->errbuf, sizeof(d->errbuf), "%s has too many characters\n",
|
|
Packit Service |
8aa27d |
keyword_token_to_str(tok));
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
memset(slotinfo, padding, size);
|
|
Packit Service |
8aa27d |
memcpy(slotinfo, val, strlen(val));
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int do_vers(struct parse_data *d,
|
|
Packit Service |
8aa27d |
CK_VERSION *slotinfo, int kw, const char *val)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char *dot;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (!val || !*val) {
|
|
Packit Service |
8aa27d |
snprintf(d->errbuf, sizeof(d->errbuf), "%s has no value\n",
|
|
Packit Service |
8aa27d |
keyword_token_to_str(kw));
|
|
Packit Service |
8aa27d |
return -1 ;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
dot = strchr(val, '.');
|
|
Packit Service |
8aa27d |
slotinfo->major = strtol(val, NULL, 10);
|
|
Packit Service |
8aa27d |
slotinfo->minor = dot ? strtol(dot + 1, NULL, 10) : 0;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int slotmgr_key_str(void *private, int tok, const char *val)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parse_data *d = (struct parse_data *)private;
|
|
Packit Service |
8aa27d |
int res = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
switch (tok) {
|
|
Packit Service |
8aa27d |
case KW_STDLL:
|
|
Packit Service |
8aa27d |
if (do_str(d, (char *)&d->sinfo_struct.dll_location,
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.dll_location), tok, val, 0)) {
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
d->sinfo_struct.present = TRUE;
|
|
Packit Service |
8aa27d |
d->sinfo_struct.pk_slot.flags |= (CKF_TOKEN_PRESENT);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_SLOTDESC:
|
|
Packit Service |
8aa27d |
if (do_str(d, (char *)d->sinfo_struct.pk_slot.slotDescription,
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.pk_slot.slotDescription), tok, val, ' '))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_MANUFID:
|
|
Packit Service |
8aa27d |
if (do_str(d, (char *)d->sinfo_struct.pk_slot.manufacturerID,
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.pk_slot.manufacturerID), tok, val, ' '))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_CONFNAME:
|
|
Packit Service |
8aa27d |
if (do_str(d, (char *)d->sinfo_struct.confname,
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.confname), tok, val, 0))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_TOKNAME:
|
|
Packit Service |
8aa27d |
if (do_str(d, (char *)d->sinfo_struct.pk_slot.slotDescription,
|
|
Packit Service |
8aa27d |
sizeof(d->sinfo_struct.pk_slot.slotDescription), tok, val, ' '))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_HWVERSION:
|
|
Packit Service |
8aa27d |
if (do_vers(d, &d->sinfo_struct.pk_slot.hardwareVersion, tok, val))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case KW_FWVERSION:
|
|
Packit Service |
8aa27d |
if (do_vers(d, &d->sinfo_struct.pk_slot.firmwareVersion, tok, val))
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
snprintf(d->errbuf, sizeof(d->errbuf),
|
|
Packit Service |
8aa27d |
"Unknown string-valued keyword detected: \"%s\"",
|
|
Packit Service |
8aa27d |
keyword_token_to_str(tok));
|
|
Packit Service |
8aa27d |
res = 1;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return res;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int slotmgr_key_vers(void *private, int tok, unsigned int vers)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parse_data *d = (struct parse_data *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (tok == KW_TOKVERSION) {
|
|
Packit Service |
8aa27d |
d->sinfo_struct.version = vers;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
snprintf(d->errbuf, sizeof(d->errbuf),
|
|
Packit Service |
8aa27d |
"Unkown version-valued keyword detected: \"%s\"",
|
|
Packit Service |
8aa27d |
keyword_token_to_str(tok));
|
|
Packit Service |
8aa27d |
return 1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static void slotmgr_parseerror(void *private, int line, const char *parsermsg)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parse_data *d = (struct parse_data *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ErrLog("Error parsing config file: line %d: %s\n",
|
|
Packit Service |
8aa27d |
line, parsermsg ? parsermsg : d->errbuf);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static struct parsefuncs slotmgr_parsefuncs = {
|
|
Packit Service |
8aa27d |
.begin_slot = slotmgr_begin_slot,
|
|
Packit Service |
8aa27d |
.end_slot = slotmgr_end_slot,
|
|
Packit Service |
8aa27d |
.key_str = slotmgr_key_str,
|
|
Packit Service |
8aa27d |
.key_vers = slotmgr_key_vers,
|
|
Packit Service |
8aa27d |
.parseerror = slotmgr_parseerror
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
/*****************************************
|
|
Packit |
8681c6 |
* main() -
|
|
Packit |
8681c6 |
* You know what main does.
|
|
Packit |
8681c6 |
* Comment block for ease of spotting
|
|
Packit |
8681c6 |
* it when paging through file
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
*****************************************/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int main(int argc, char *argv[], char *envp[])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int ret, i;
|
|
Packit Service |
8aa27d |
struct parse_data parsedata;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**********************************/
|
|
Packit |
8681c6 |
/* Read in command-line arguments */
|
|
Packit |
8681c6 |
/**********************************/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* FIXME: Argument for daemonizing or not */
|
|
Packit |
8681c6 |
/* FIXME: Argument for debug level */
|
|
Packit |
8681c6 |
/* FIXME: Arguments affecting the log files, whether to use syslog, etc.
|
|
Packit |
8681c6 |
* (Read conf file?) */
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
UNUSED(argc);
|
|
Packit |
8681c6 |
UNUSED(argv);
|
|
Packit |
8681c6 |
UNUSED(envp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Do some basic sanity checks */
|
|
Packit |
8681c6 |
run_sanity_checks();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Report our debug level */
|
|
Packit |
8681c6 |
if (GetDebugLevel() > DEBUG_NONE) {
|
|
Packit |
8681c6 |
DbgLog(GetDebugLevel(),
|
|
Packit |
8681c6 |
"Starting with debugging messages logged at level %d "
|
|
Packit |
8681c6 |
"(%d = No messages; %d = few; %d = more, etc.)",
|
|
Packit |
8681c6 |
GetDebugLevel(), DEBUG_NONE, DEBUG_LEVEL0, DEBUG_LEVEL1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
ret = load_and_parse(OCK_CONFIG, &slotmgr_parsefuncs, &parsedata);
|
|
Packit |
8681c6 |
if (ret != 0) {
|
|
Packit |
8681c6 |
ErrLog("Failed to read config file.\n");
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
DbgLog(DL0, "Parse config file succeeded.\n");
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Allocate and Attach the shared memory region */
|
|
Packit |
8681c6 |
if (!CreateSharedMemory()) {
|
|
Packit |
8681c6 |
/* CreateSharedMemory() does it's own error logging */
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
DbgLog(DL0, "SHMID %d token %#X \n", shmid, tok);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Now that we've created the shared memory segment, we attach to it */
|
|
Packit |
8681c6 |
if (!AttachToSharedMemory()) {
|
|
Packit |
8681c6 |
/* AttachToSharedMemory() does it's own error logging */
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 2;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Initialize the global shared memory mutex (and the attribute
|
|
Packit |
8681c6 |
* used to create the per-process mutexes */
|
|
Packit |
8681c6 |
if (!InitializeMutexes()) {
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 3;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Get the global shared memory mutex */
|
|
Packit |
8681c6 |
if (!XProcLock())
|
|
Packit |
8681c6 |
return 4;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Populate the Shared Memory Region */
|
|
Packit |
8681c6 |
if (!InitSharedMemory(shmp)) {
|
|
Packit |
8681c6 |
XProcUnLock();
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 4;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Release the global shared memory mutex */
|
|
Packit |
8681c6 |
if (!XProcUnLock())
|
|
Packit |
8681c6 |
return 4;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if ((socketfd = CreateListenerSocket()) < 0) {
|
|
Packit |
8681c6 |
DestroyMutexes();
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 5;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!InitSocketData(&socketData)) {
|
|
Packit |
8681c6 |
DetachSocketListener(socketfd);
|
|
Packit |
8681c6 |
DestroyMutexes();
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 6;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Create customized token directories */
|
|
Packit |
8681c6 |
psinfo = &socketData.slot_info[0];
|
|
Packit |
8681c6 |
for (i = 0; i < NUMBER_SLOTS_MANAGED; i++, psinfo++) {
|
|
Packit |
8681c6 |
ret = chk_create_tokdir(psinfo);
|
|
Packit |
8681c6 |
if (ret)
|
|
Packit |
8681c6 |
return EACCES;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* Become a Daemon, if called for
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
if (Daemon) {
|
|
Packit |
8681c6 |
pid_t pid;
|
|
Packit |
8681c6 |
if ((pid = fork()) < 0) {
|
|
Packit |
8681c6 |
DetachSocketListener(socketfd);
|
|
Packit |
8681c6 |
DestroyMutexes();
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 7;
|
|
Packit |
8681c6 |
} else if (pid != 0) {
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* This is the parent
|
|
Packit |
8681c6 |
* Create the pid file for the client as systemd wants to
|
|
Packit |
8681c6 |
* see the pid file a soon as the parent terminates.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
create_pid_file(pid);
|
|
Packit |
8681c6 |
/* now terminate the parent */
|
|
Packit |
8681c6 |
exit(0);
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* This is the child */
|
|
Packit |
8681c6 |
setsid(); // Session leader
|
|
Packit |
8681c6 |
#ifndef DEV
|
|
Packit |
8681c6 |
fclose(stderr);
|
|
Packit |
8681c6 |
fclose(stdout);
|
|
Packit |
8681c6 |
fclose(stdin);
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
#ifdef DEV
|
|
Packit |
8681c6 |
// Log only on development builds
|
|
Packit |
8681c6 |
LogLog("Not becoming a daemon...\n");
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*****************************************
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* Register Signal Handlers
|
|
Packit |
8681c6 |
* Daemon probably should ignore ALL signals possible, since termination
|
|
Packit |
8681c6 |
* while active is a bad thing... however one could check for
|
|
Packit |
8681c6 |
* any processes active in the shared memory, and destroy the shm if
|
|
Packit |
8681c6 |
* the process wishes to terminate.
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
*****************************************/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* We have to set up the signal handlers after we daemonize because
|
|
Packit |
8681c6 |
* the daemonization process redefines our handler for (at least) SIGTERM
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
if (!SetupSignalHandlers()) {
|
|
Packit |
8681c6 |
DetachSocketListener(socketfd);
|
|
Packit |
8681c6 |
DestroyMutexes();
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 8;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* ultimatly we will create a couple of threads which monitor the slot db
|
|
Packit |
8681c6 |
* and handle the insertion and removal of tokens from the slot.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* For Testing the Garbage collection routines */
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* shmp->proc_table[3].inuse = TRUE;
|
|
Packit |
8681c6 |
* shmp->proc_table[3].proc_id = 24328;
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#if !defined(NOGARBAGE)
|
|
Packit |
8681c6 |
printf("Start garbage \n");
|
|
Packit |
8681c6 |
/* start garbage collection thread */
|
|
Packit |
8681c6 |
if (!StartGCThread(shmp)) {
|
|
Packit |
8681c6 |
DetachSocketListener(socketfd);
|
|
Packit |
8681c6 |
DestroyMutexes();
|
|
Packit |
8681c6 |
DetachFromSharedMemory();
|
|
Packit |
8681c6 |
DestroySharedMemory();
|
|
Packit |
8681c6 |
return 9;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* We've fully become a daemon.
|
|
Packit |
8681c6 |
* In not-daemon mode the pid file hasn't been created jet,
|
|
Packit |
8681c6 |
* so let's do this now.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
if (!Daemon)
|
|
Packit |
8681c6 |
create_pid_file(getpid());
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (1) {
|
|
Packit |
8681c6 |
#if !(THREADED) && !(NOGARBAGE)
|
|
Packit |
8681c6 |
CheckForGarbage(shmp);
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
SocketConnectionHandler(socketfd, 10);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*************************************************************
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* Here we need to actualy go through the processes and verify that thye
|
|
Packit |
8681c6 |
* still exist. If not, then they terminated with out properly calling
|
|
Packit |
8681c6 |
* C_Finalize and therefore need to be removed from the system.
|
|
Packit |
8681c6 |
* Look for a system routine to determine if the shared memory is held by
|
|
Packit |
8681c6 |
* the process to further verify that the proper processes are in the
|
|
Packit |
8681c6 |
* table.
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
**************************************************************/
|
|
Packit |
8681c6 |
} /* end main */
|