Blame usr/sbin/pkcsslotd/slotmgr.c

Packit 8681c6
/*
Packit 8681c6
 * COPYRIGHT (c) International Business Machines Corp. 2001-2017
Packit 8681c6
 *
Packit 8681c6
 * This program is provided under the terms of the Common Public License,
Packit 8681c6
 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
Packit 8681c6
 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
Packit 8681c6
 * found in the file LICENSE file or at
Packit 8681c6
 * https://opensource.org/licenses/cpl1.0.php
Packit 8681c6
 */
Packit 8681c6
Packit 8681c6
#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 */