/*
 * NSS utility functions
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "lowkeyi.h"
#include "pcert.h"
#include "keydbi.h"
#include "lgdb.h"
#include "secoid.h"
#include "prenv.h"
#include "softkver.h"

/* Library identity and versioning */

#if defined(DEBUG)
#define _DEBUG_STRING " (debug)"
#else
#define _DEBUG_STRING ""
#endif

/*
 * Version information
 */
const char __nss_dbm_version[] = "Version: NSS " SOFTOKEN_VERSION _DEBUG_STRING;

typedef struct LGPrivateStr {
    NSSLOWCERTCertDBHandle *certDB;
    NSSLOWKEYDBHandle *keyDB;
    PRLock *dbLock;
    PLHashTable *hashTable;
} LGPrivate;

static char *
lg_certdb_name_cb(void *arg, int dbVersion)
{
    const char *configdir = (const char *)arg;
    const char *dbver;
    char *smpname = NULL;
    char *dbname = NULL;

    switch (dbVersion) {
        case 8:
            dbver = "8";
            break;
        case 7:
            dbver = "7";
            break;
        case 6:
            dbver = "6";
            break;
        case 5:
            dbver = "5";
            break;
        case 4:
        default:
            dbver = "";
            break;
    }

    /* make sure we return something allocated with PORT_ so we have properly
     * matched frees at the end */
    smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
    if (smpname) {
        dbname = PORT_Strdup(smpname);
        PR_smprintf_free(smpname);
    }
    return dbname;
}

static char *
lg_keydb_name_cb(void *arg, int dbVersion)
{
    const char *configdir = (const char *)arg;
    const char *dbver;
    char *smpname = NULL;
    char *dbname = NULL;

    switch (dbVersion) {
        case 4:
            dbver = "4";
            break;
        case 3:
            dbver = "3";
            break;
        case 1:
            dbver = "1";
            break;
        case 2:
        default:
            dbver = "";
            break;
    }

    smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
    if (smpname) {
        dbname = PORT_Strdup(smpname);
        PR_smprintf_free(smpname);
    }
    return dbname;
}

const char *
lg_EvaluateConfigDir(const char *configdir, char **appName)
{
    if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS) - 1) == 0) {
        char *cdir;

        *appName = PORT_Strdup(configdir + sizeof(MULTIACCESS) - 1);
        if (*appName == NULL) {
            return configdir;
        }
        cdir = *appName;
        while (*cdir && *cdir != ':') {
            cdir++;
        }
        if (*cdir == ':') {
            *cdir = 0;
            cdir++;
        }
        configdir = cdir;
    }
    return configdir;
}

static int rdbmapflags(int flags);
static rdbfunc lg_rdbfunc = NULL;
static rdbstatusfunc lg_rdbstatusfunc = NULL;

/* NOTE: SHLIB_SUFFIX is defined on the command line */
#define RDBLIB SHLIB_PREFIX "rdb." SHLIB_SUFFIX

DB *
rdbopen(const char *appName, const char *prefix,
        const char *type, int flags, int *status)
{
    PRLibrary *lib;
    DB *db;
    char *disableUnload = NULL;

    if (lg_rdbfunc) {
        db = (*lg_rdbfunc)(appName, prefix, type, rdbmapflags(flags));
        if (!db && status && lg_rdbstatusfunc) {
            *status = (*lg_rdbstatusfunc)();
        }
        return db;
    }

    /*
     * try to open the library.
     */
    lib = PR_LoadLibrary(RDBLIB);

    if (!lib) {
        return NULL;
    }

    /* get the entry points */
    lg_rdbstatusfunc = (rdbstatusfunc)PR_FindSymbol(lib, "rdbstatus");
    lg_rdbfunc = (rdbfunc)PR_FindSymbol(lib, "rdbopen");
    if (lg_rdbfunc) {
        db = (*lg_rdbfunc)(appName, prefix, type, rdbmapflags(flags));
        if (!db && status && lg_rdbstatusfunc) {
            *status = (*lg_rdbstatusfunc)();
        }
        return db;
    }

    /* couldn't find the entry point, unload the library and fail */
    disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
    if (!disableUnload) {
        PR_UnloadLibrary(lib);
    }
    return NULL;
}

/*
 * the following data structures are from rdb.h.
 */
struct RDBStr {
    DB db;
    int (*xactstart)(DB *db);
    int (*xactdone)(DB *db, PRBool abort);
    int version;
    int (*dbinitcomplete)(DB *db);
};

#define DB_RDB ((DBTYPE)0xff)
#define RDB_RDONLY 1
#define RDB_RDWR 2
#define RDB_CREATE 4

static int
rdbmapflags(int flags)
{
    switch (flags) {
        case NO_RDONLY:
            return RDB_RDONLY;
        case NO_RDWR:
            return RDB_RDWR;
        case NO_CREATE:
            return RDB_CREATE;
        default:
            break;
    }
    return 0;
}

PRBool
db_IsRDB(DB *db)
{
    return (PRBool)db->type == DB_RDB;
}

int
db_BeginTransaction(DB *db)
{
    struct RDBStr *rdb = (struct RDBStr *)db;
    if (db->type != DB_RDB) {
        return 0;
    }

    return rdb->xactstart(db);
}

int
db_FinishTransaction(DB *db, PRBool abort)
{
    struct RDBStr *rdb = (struct RDBStr *)db;
    if (db->type != DB_RDB) {
        return 0;
    }

    return rdb->xactdone(db, abort);
}

static DB *
lg_getRawDB(SDB *sdb)
{
    NSSLOWCERTCertDBHandle *certDB;
    NSSLOWKEYDBHandle *keyDB;

    certDB = lg_getCertDB(sdb);
    if (certDB) {
        return certDB->permCertDB;
    }
    keyDB = lg_getKeyDB(sdb);
    if (keyDB) {
        return keyDB->db;
    }
    return NULL;
}

CK_RV
lg_Begin(SDB *sdb)
{
    DB *db = lg_getRawDB(sdb);
    int ret;

    if (db == NULL) {
        return CKR_GENERAL_ERROR; /* shouldn't happen */
    }
    ret = db_BeginTransaction(db);
    if (ret != 0) {
        return CKR_GENERAL_ERROR; /* could happen */
    }
    return CKR_OK;
}

CK_RV
lg_Commit(SDB *sdb)
{
    DB *db = lg_getRawDB(sdb);
    int ret;

    if (db == NULL) {
        return CKR_GENERAL_ERROR; /* shouldn't happen */
    }
    ret = db_FinishTransaction(db, PR_FALSE);
    if (ret != 0) {
        return CKR_GENERAL_ERROR; /* could happen */
    }
    return CKR_OK;
}

CK_RV
lg_Abort(SDB *sdb)
{
    DB *db = lg_getRawDB(sdb);
    int ret;

    if (db == NULL) {
        return CKR_GENERAL_ERROR; /* shouldn't happen */
    }
    ret = db_FinishTransaction(db, PR_TRUE);
    if (ret != 0) {
        return CKR_GENERAL_ERROR; /* could happen */
    }
    return CKR_OK;
}

int
db_InitComplete(DB *db)
{
    struct RDBStr *rdb = (struct RDBStr *)db;
    if (db->type != DB_RDB) {
        return 0;
    }
    /* we should have added a version number to the RDBS structure. Since we
     * didn't, we detect that we have and 'extended' structure if the rdbstatus
     * func exists */
    if (!lg_rdbstatusfunc) {
        return 0;
    }

    return rdb->dbinitcomplete(db);
}

SECStatus
db_Copy(DB *dest, DB *src)
{
    int ret;
    DBT key, data;
    ret = (*src->seq)(src, &key, &data, R_FIRST);
    if (ret) {
        return SECSuccess;
    }

    do {
        (void)(*dest->put)(dest, &key, &data, R_NOOVERWRITE);
    } while ((*src->seq)(src, &key, &data, R_NEXT) == 0);
    (void)(*dest->sync)(dest, 0);

    return SECSuccess;
}

static CK_RV
lg_OpenCertDB(const char *configdir, const char *prefix, PRBool readOnly,
              NSSLOWCERTCertDBHandle **certdbPtr)
{
    NSSLOWCERTCertDBHandle *certdb = NULL;
    CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
    SECStatus rv;
    char *name = NULL;
    char *appName = NULL;

    if (prefix == NULL) {
        prefix = "";
    }

    configdir = lg_EvaluateConfigDir(configdir, &appName);

    name = PR_smprintf("%s" PATH_SEPARATOR "%s", configdir, prefix);
    if (name == NULL)
        goto loser;

    certdb = (NSSLOWCERTCertDBHandle *)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
    if (certdb == NULL)
        goto loser;

    certdb->ref = 1;
    /* fix when we get the DB in */
    rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
                               lg_certdb_name_cb, (void *)name, PR_FALSE);
    if (rv == SECSuccess) {
        crv = CKR_OK;
        *certdbPtr = certdb;
        certdb = NULL;
    }
loser:
    if (certdb)
        PR_Free(certdb);
    if (name)
        PR_smprintf_free(name);
    if (appName)
        PORT_Free(appName);
    return crv;
}

static CK_RV
lg_OpenKeyDB(const char *configdir, const char *prefix, PRBool readOnly,
             NSSLOWKEYDBHandle **keydbPtr)
{
    NSSLOWKEYDBHandle *keydb;
    char *name = NULL;
    char *appName = NULL;

    if (prefix == NULL) {
        prefix = "";
    }
    configdir = lg_EvaluateConfigDir(configdir, &appName);

    name = PR_smprintf("%s" PATH_SEPARATOR "%s", configdir, prefix);
    if (name == NULL)
        return CKR_HOST_MEMORY;
    keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
                                lg_keydb_name_cb, (void *)name);
    PR_smprintf_free(name);
    if (appName)
        PORT_Free(appName);
    if (keydb == NULL)
        return CKR_NETSCAPE_KEYDB_FAILED;
    *keydbPtr = keydb;

    return CKR_OK;
}

/*
 * Accessors for the private parts of the sdb structure.
 */
void
lg_DBLock(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
    SKIP_AFTER_FORK(PR_Lock(lgdb_p->dbLock));
}

void
lg_DBUnlock(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
    SKIP_AFTER_FORK(PR_Unlock(lgdb_p->dbLock));
}

PLHashTable *
lg_GetHashTable(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
    return lgdb_p->hashTable;
}

NSSLOWCERTCertDBHandle *
lg_getCertDB(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;

    return lgdb_p->certDB;
}

NSSLOWKEYDBHandle *
lg_getKeyDB(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;

    return lgdb_p->keyDB;
}

PRBool lg_parentForkedAfterC_Initialize;

void
lg_SetForkState(PRBool forked)
{
    lg_parentForkedAfterC_Initialize = forked;
}

CK_RV
lg_Close(SDB *sdb)
{
    LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
    lg_ClearTokenKeyHashTable(sdb);
    if (lgdb_p) {
        if (lgdb_p->certDB) {
            nsslowcert_ClosePermCertDB(lgdb_p->certDB);
        } else if (lgdb_p->keyDB) {
            nsslowkey_CloseKeyDB(lgdb_p->keyDB);
        }
        if (lgdb_p->dbLock) {
            SKIP_AFTER_FORK(PR_DestroyLock(lgdb_p->dbLock));
        }
        if (lgdb_p->hashTable) {
            PL_HashTableDestroy(lgdb_p->hashTable);
        }
        PORT_Free(lgdb_p);
    }
    PORT_Free(sdb);
    return CKR_OK;
}

static PLHashNumber
lg_HashNumber(const void *key)
{
    return (PLHashNumber)((char *)key - (char *)NULL);
}

/*
 * helper function to wrap a NSSLOWCERTCertDBHandle or a NSSLOWKEYDBHandle
 * with and sdb structure.
 */
CK_RV
lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
        NSSLOWKEYDBHandle *keydbPtr)
{
    SDB *sdb = NULL;
    LGPrivate *lgdb_p = NULL;
    CK_RV error = CKR_HOST_MEMORY;

    *pSdb = NULL;
    sdb = (SDB *)PORT_Alloc(sizeof(SDB));
    if (sdb == NULL) {
        goto loser;
    }
    lgdb_p = (LGPrivate *)PORT_Alloc(sizeof(LGPrivate));
    if (lgdb_p == NULL) {
        goto loser;
    }
    /* invariant fields */
    lgdb_p->certDB = certdbPtr;
    lgdb_p->keyDB = keydbPtr;
    lgdb_p->dbLock = PR_NewLock();
    if (lgdb_p->dbLock == NULL) {
        goto loser;
    }
    lgdb_p->hashTable = PL_NewHashTable(64, lg_HashNumber, PL_CompareValues,
                                        SECITEM_HashCompare, NULL, 0);
    if (lgdb_p->hashTable == NULL) {
        goto loser;
    }

    sdb->private = lgdb_p;
    sdb->version = 0;
    sdb->sdb_flags = flags;
    sdb->app_private = NULL;
    sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
    sdb->sdb_FindObjects = lg_FindObjects;
    sdb->sdb_FindObjectsFinal = lg_FindObjectsFinal;
    sdb->sdb_GetAttributeValue = lg_GetAttributeValue;
    sdb->sdb_SetAttributeValue = lg_SetAttributeValue;
    sdb->sdb_CreateObject = lg_CreateObject;
    sdb->sdb_DestroyObject = lg_DestroyObject;
    sdb->sdb_GetMetaData = lg_GetMetaData;
    sdb->sdb_PutMetaData = lg_PutMetaData;
    sdb->sdb_Begin = lg_Begin;
    sdb->sdb_Commit = lg_Commit;
    sdb->sdb_Abort = lg_Abort;
    sdb->sdb_Reset = lg_Reset;
    sdb->sdb_Close = lg_Close;
    sdb->sdb_SetForkState = lg_SetForkState;

    *pSdb = sdb;
    return CKR_OK;

loser:
    if (sdb) {
        PORT_Free(sdb);
    }
    if (lgdb_p) {
        if (lgdb_p->dbLock) {
            PR_DestroyLock(lgdb_p->dbLock);
        }
        if (lgdb_p->hashTable) {
            PL_HashTableDestroy(lgdb_p->hashTable);
        }
        PORT_Free(lgdb_p);
    }
    return error;
}

/*
 * OK there are now lots of options here, lets go through them all:
 *
 * configdir - base directory where all the cert, key, and module datbases live.
 * certPrefix - prefix added to the beginning of the cert database example: "
 *              "https-server1-"
 * keyPrefix - prefix added to the beginning of the key database example: "
 *             "https-server1-"
 * secmodName - name of the security module database (usually "secmod.db").
 * readOnly - Boolean: true if the databases are to be openned read only.
 * nocertdb - Don't open the cert DB and key DB's, just initialize the
 *            Volatile certdb.
 * nomoddb - Don't open the security module DB, just initialize the
 *           PKCS #11 module.
 * forceOpen - Continue to force initializations even if the databases cannot
 *             be opened.
 */
CK_RV
legacy_Open(const char *configdir, const char *certPrefix,
            const char *keyPrefix, int certVersion, int keyVersion,
            int flags, SDB **certDB, SDB **keyDB)
{
    CK_RV crv = CKR_OK;
    SECStatus rv;
    PRBool readOnly = ((flags & 0x7) == SDB_RDONLY) ? PR_TRUE : PR_FALSE;

#define NSS_VERSION_VARIABLE __nss_dbm_version
#include "verref.h"

#ifndef NSS_FIPS_DISABLED
    if (flags & SDB_FIPS) {
        /* We shouldn't get here when FIPS is not enabled on the database. But
         * we also don't care when this NSS build doesn't support FIPS. */
        if (!lg_FIPSEntryOK()) {
            return CKR_DEVICE_ERROR;
        }
    }
#endif

    rv = SECOID_Init();
    if (SECSuccess != rv) {
        return CKR_DEVICE_ERROR;
    }
    nsslowcert_InitLocks();

    if (keyDB)
        *keyDB = NULL;
    if (certDB)
        *certDB = NULL;

    if (certDB) {
        NSSLOWCERTCertDBHandle *certdbPtr = NULL;

        crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr);
        if (crv != CKR_OK) {
            goto loser;
        }
        crv = lg_init(certDB, flags, certdbPtr, NULL);
        if (crv != CKR_OK) {
            nsslowcert_ClosePermCertDB(certdbPtr);
            goto loser;
        }
    }
    if (keyDB) {
        NSSLOWKEYDBHandle *keydbPtr;

        crv = lg_OpenKeyDB(configdir, keyPrefix, readOnly, &keydbPtr);
        if (crv != CKR_OK) {
            goto loser;
        }
        crv = lg_init(keyDB, flags, NULL, keydbPtr);
        if (crv != CKR_OK) {
            nsslowkey_CloseKeyDB(keydbPtr);
            goto loser;
        }
        if (certDB && *certDB) {
            LGPrivate *lgdb_p = (LGPrivate *)(*certDB)->private;
            lgdb_p->keyDB = keydbPtr;
        }
    }

loser:
    if (crv != CKR_OK) {
        if (keyDB && *keyDB) {
            lg_Close(*keyDB);
            *keyDB = NULL;
        }
        if (certDB && *certDB) {
            lg_Close(*certDB);
            *certDB = NULL;
        }
    }
    return crv;
}

CK_RV
legacy_Shutdown(PRBool forked)
{
    lg_SetForkState(forked);
    nsslowcert_DestroyFreeLists();
    nsslowcert_DestroyGlobalLocks();
    SECOID_Shutdown();
    lg_SetForkState(PR_FALSE);
    return CKR_OK;
}
