Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
/*
** dbtest.c
**
** QA test for cert and key databases, especially to open
** database readonly (NSS_INIT_READONLY) and force initializations
** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
**
*/
#include <stdio.h>
#include <string.h>
#if defined(WIN32)
#include "fcntl.h"
#include "io.h"
#endif
#include "secutil.h"
#include "pk11pub.h"
#if defined(XP_UNIX)
#include <unistd.h>
#endif
#include "nspr.h"
#include "prtypes.h"
#include "certdb.h"
#include "nss.h"
#include "../modutil/modutil.h"
#include "plgetopt.h"
static char *progName;
char *dbDir = NULL;
static char *dbName[] = { "secmod.db", "cert8.db", "key3.db" };
static char *dbprefix = "";
static char *secmodName = "secmod.db";
static char *userPassword = "";
PRBool verbose;
static char *
getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
{
int *success = (int *)arg;
if (retry) {
*success = 0;
return NULL;
}
*success = 1;
return PORT_Strdup(userPassword);
}
static void
Usage()
{
printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n",
progName);
printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
printf("%-20s Continue to force initializations even if the\n", "-f");
printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
printf("%-20s Try to initialize the database\n", "-i");
printf("%-20s Supply a password with which to initialize the db\n", "-p");
printf("%-20s Directory with cert database (default is .\n",
"-d certdir");
exit(1);
}
int
main(int argc, char **argv)
{
PLOptState *optstate;
PLOptStatus optstatus;
PRUint32 flags = 0;
Error ret;
SECStatus rv;
char *dbString = NULL;
PRBool doInitTest = PR_FALSE;
int i;
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
progName = progName ? progName + 1 : argv[0];
optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
case 'h':
default:
Usage();
break;
case 'r':
flags |= NSS_INIT_READONLY;
break;
case 'f':
flags |= NSS_INIT_FORCEOPEN;
break;
case 'i':
doInitTest = PR_TRUE;
break;
case 'p':
userPassword = PORT_Strdup(optstate->value);
break;
case 'd':
dbDir = PORT_Strdup(optstate->value);
break;
}
}
PL_DestroyOptState(optstate);
if (optstatus == PL_OPT_BAD)
Usage();
if (dbDir) {
char *tmp = dbDir;
dbDir = SECU_ConfigDirectory(tmp);
PORT_Free(tmp);
} else {
/* Look in $SSL_DIR */
dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir());
}
PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
if (dbDir[0] == '\0') {
PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
ret = DIR_DOESNT_EXIST_ERR;
goto loser;
}
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
/* get the status of the directory and databases and output message */
if (PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
} else if (PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
} else {
if (!(flags & NSS_INIT_READONLY) &&
PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
}
if (!doInitTest) {
for (i = 0; i < 3; i++) {
dbString = PR_smprintf("%s/%s", dbDir, dbName[i]);
PR_fprintf(PR_STDOUT, "database checked is %s\n", dbString);
if (PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
dbString);
} else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
dbString);
} else if (!(flags & NSS_INIT_READONLY) &&
PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
dbString);
}
PR_smprintf_free(dbString);
}
}
}
rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
secmodName, flags);
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
ret = NSS_INITIALIZE_FAILED_ERR;
} else {
ret = SUCCESS;
if (doInitTest) {
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
int passwordSuccess = 0;
int type = CKM_DES3_CBC;
SECItem keyid = { 0, NULL, 0 };
unsigned char keyIdData[] = { 0xff, 0xfe };
PK11SymKey *key = NULL;
keyid.data = keyIdData;
keyid.len = sizeof(keyIdData);
PK11_SetPasswordFunc(getPassword);
rv = PK11_InitPin(slot, (char *)NULL, userPassword);
if (rv != SECSuccess) {
PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
SECU_Strerror(PORT_GetError()));
ret = CHANGEPW_FAILED_ERR;
}
if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
ret = AUTHENTICATION_FAILED_ERR;
}
/* generate a symetric key */
key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
PR_TRUE, &passwordSuccess);
if (!key) {
PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
SECU_Strerror(PORT_GetError()));
exit(UNSPECIFIED_ERR);
}
PK11_FreeSymKey(key);
PK11_Logout(slot);
PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
if (*userPassword && !passwordSuccess) {
PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
ret = AUTHENTICATION_FAILED_ERR;
}
key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
if (!key) {
PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
SECU_Strerror(PORT_GetError()));
ret = UNSPECIFIED_ERR;
} else {
PK11_FreeSymKey(key);
}
PK11_FreeSlot(slot);
}
if (NSS_Shutdown() != SECSuccess) {
PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
SECU_Strerror(PORT_GetError()));
exit(1);
}
}
loser:
return ret;
}