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