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; }