Initialize NSS database - sample 2¶
NSS sample code 2: initialize the NSS database.¶
The NSS sample code below demonstrates how to initialize the NSS database.
/*
* Print a usage message and exit
*/
static void
Usage(const char *progName)
{
fprintf(stderr, "\nUsage: %s -d [-p ]"
" [-f ]\n\n",
progName);
fprintf(stderr, "%-15s Specify a DB directory path\n\n",
"-d ");
fprintf(stderr, "%-15s Specify a plaintext password\n\n",
"-p ");
fprintf(stderr, "%-15s Specify a password file\n\n",
"-f ");
exit(-1);
}
/*
* InitSlotPassword
*/
char *
InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
{
FILE *input;
FILE *output;
char *p0 = NULL;
char *p1 = NULL;
secuPWData *pwdata = (secuPWData *) arg;
if (pwdata->source == PW_FROMFILE) {
return FilePasswd(slot, retry, pwdata->data);
}
if (pwdata->source == PW_PLAINTEXT) {
return PL_strdup(pwdata->data);
}
/* open terminal */
input = fopen("/dev/tty", "r");
if (input == NULL) {
PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
return NULL;
}
/* we have no password, so initialize database with one */
PR_fprintf(PR_STDERR,
"Enter a password which will be used to encrypt your keys.\n"
"The password should be at least 8 characters long,\n"
"and should contain at least one non-alphabetic character.\n\n");
output = fopen("/dev/tty", "w");
if (output == NULL) {
PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
return NULL;
}
for (;;) {
if (p0)
PORT_Free(p0);
p0 = GetPassword(input, output, "Enter new password: ",
CheckPassword);
if (p1)
PORT_Free(p1);
p1 = GetPassword(input, output, "Re-enter password: ",
CheckPassword);
if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
break;
}
PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
}
/* clear out the duplicate password string */
if (p1) {
PORT_Memset(p1, 0, PORT_Strlen(p1));
PORT_Free(p1);
}
fclose(input);
fclose(output);
return p0;
}
/*
* ChangePW
*/
SECStatus
ChangePW(PK11SlotInfo *slot, char *oldPass, char *newPass,
char *oldPwFile, char *newPwFile)
{
SECStatus rv;
secuPWData pwdata;
secuPWData newpwdata;
char *oldpw = NULL;
char *newpw = NULL;
if (oldPass) {
pwdata.source = PW_PLAINTEXT;
pwdata.data = oldPass;
} else if (oldPwFile) {
pwdata.source = PW_FROMFILE;
pwdata.data = oldPwFile;
} else {
pwdata.source = PW_NONE;
pwdata.data = NULL;
}
if (newPass) {
newpwdata.source = PW_PLAINTEXT;
newpwdata.data = newPass;
} else if (newPwFile) {
newpwdata.source = PW_FROMFILE;
newpwdata.data = NULL;
} else {
newpwdata.source = PW_NONE;
newpwdata.data = NULL;
}
if (PK11_NeedUserInit(slot)) {
newpw = InitSlotPassword(slot, PR_FALSE, &pwdata);
rv = PK11_InitPin(slot, (char*)NULL, newpw);
if (rv == SECSuccess) {
PR_fprintf(PR_STDERR, "PK11_InitPin failed.\n");
return SECFailure;
}
}
else {
for (;;) {
oldpw = GetModulePassword(slot, PR_FALSE, &pwdata);
if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
if (pwdata.source == PW_NONE) {
PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
} else {
PR_fprintf(PR_STDERR, "Invalid password.\n");
PORT_Memset(oldpw, 0, PL_strlen(oldpw));
PORT_Free(oldpw);
return SECFailure;
}
} else {
break;
}
PORT_Free(oldpw);
}
newpw = InitSlotPassword(slot, PR_FALSE, &newpwdata);
if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
PR_fprintf(PR_STDERR, "Failed to change password.\n");
return SECFailure;
}
PORT_Memset(oldpw, 0, PL_strlen(oldpw));
PORT_Free(oldpw);
PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
}
PORT_Memset(newpw, 0, PL_strlen(newpw));
PORT_Free(newpw);
return SECSuccess;
}
/*
* This example illustrates initialization of the NSS database.
* It creates an nss configuration directory with empty databases
* and initializes the databases. It also illustrates techniques for
* password handling.
*/
int main(int argc, char **argv)
{
PLOptState *optstate;
PLOptStatus status;
SECStatus rv;
SECStatus rvShutdown;
char *slotname = "internal";
PK11SlotInfo *slot = NULL;
char *dbdir = NULL;
char *plainPass = NULL;
char *pwFile = NULL;
char * progName = strrchr(argv[0], '/');
progName = progName ? progName + 1 : argv[0];
/* Parse command line arguments */
optstate = PL_CreateOptState(argc, argv, "d:p:q:f:g:");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
case 'd':
dbdir = strdup(optstate->value);
break;
case 'p':
plainPass = strdup(optstate->value);
break;
case 'f':
pwFile = strdup(optstate->value);
break;
default:
Usage(progName);
break;
}
}
PL_DestroyOptState(optstate);
if (!dbdir)
Usage(progName);
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
/* Create the database */
rv = NSS_InitReadWrite(dbdir);
if (rv != SECSuccess) {
PR_fprintf(PR_STDERR, "NSS_Initialize Failed");
PR_Cleanup();
exit(rv);
}
if (PL_strcmp(slotname, "internal") == 0)
slot = PK11_GetInternalKeySlot();
/* If creating new database, initialize the password. */
rv = ChangePW(slot, plainPass, 0, pwFile, 0);
if (rv != SECSuccess) {
PR_fprintf(PR_STDERR, "Failed to change password\n");
}
if (slot) {
PK11_FreeSlot(slot);
}
rvShutdown = NSS_Shutdown();
if (rvShutdown != SECSuccess) {
PR_fprintf(PR_STDERR, "Failed : NSS_Shutdown()\n");
rv = SECFailure;
}
PR_Cleanup();
return rv;
}