dbtest.c (7497B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 ** dbtest.c 7 ** 8 ** QA test for cert and key databases, especially to open 9 ** database readonly (NSS_INIT_READONLY) and force initializations 10 ** even if the databases cannot be opened (NSS_INIT_FORCEOPEN) 11 ** 12 */ 13 #include <stdio.h> 14 #include <string.h> 15 16 #if defined(WIN32) 17 #include "fcntl.h" 18 #include "io.h" 19 #endif 20 21 #include "secutil.h" 22 #include "pk11pub.h" 23 24 #if defined(XP_UNIX) 25 #include <unistd.h> 26 #endif 27 28 #include "nspr.h" 29 #include "prtypes.h" 30 #include "certdb.h" 31 #include "nss.h" 32 #include "../modutil/modutil.h" 33 34 #include "plgetopt.h" 35 36 static char *progName; 37 38 char *dbDir = NULL; 39 40 static char *dbName[] = { "secmod.db", "cert8.db", "key3.db" }; 41 static char *dbprefix = ""; 42 static char *secmodName = "secmod.db"; 43 static char *userPassword = ""; 44 PRBool verbose; 45 46 static char * 47 getPassword(PK11SlotInfo *slot, PRBool retry, void *arg) 48 { 49 int *success = (int *)arg; 50 51 if (retry) { 52 *success = 0; 53 return NULL; 54 } 55 56 *success = 1; 57 return PORT_Strdup(userPassword); 58 } 59 60 static void 61 Usage() 62 { 63 printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n", 64 progName); 65 printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r"); 66 printf("%-20s Continue to force initializations even if the\n", "-f"); 67 printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " "); 68 printf("%-20s Try to initialize the database\n", "-i"); 69 printf("%-20s Supply a password with which to initialize the db\n", "-p"); 70 printf("%-20s Directory with cert database (default is .\n", 71 "-d certdir"); 72 exit(1); 73 } 74 75 int 76 main(int argc, char **argv) 77 { 78 PLOptState *optstate; 79 PLOptStatus optstatus; 80 81 PRUint32 flags = 0; 82 Error ret; 83 SECStatus rv; 84 char *dbString = NULL; 85 PRBool doInitTest = PR_FALSE; 86 int i; 87 88 progName = strrchr(argv[0], '/'); 89 if (!progName) 90 progName = strrchr(argv[0], '\\'); 91 progName = progName ? progName + 1 : argv[0]; 92 93 optstate = PL_CreateOptState(argc, argv, "rfip:d:h"); 94 95 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 96 switch (optstate->option) { 97 case 'h': 98 default: 99 Usage(); 100 break; 101 102 case 'r': 103 flags |= NSS_INIT_READONLY; 104 break; 105 106 case 'f': 107 flags |= NSS_INIT_FORCEOPEN; 108 break; 109 110 case 'i': 111 doInitTest = PR_TRUE; 112 break; 113 114 case 'p': 115 userPassword = PORT_Strdup(optstate->value); 116 break; 117 118 case 'd': 119 dbDir = PORT_Strdup(optstate->value); 120 break; 121 } 122 } 123 PL_DestroyOptState(optstate); 124 if (optstatus == PL_OPT_BAD) 125 Usage(); 126 127 if (dbDir) { 128 char *tmp = dbDir; 129 dbDir = SECU_ConfigDirectory(tmp); 130 PORT_Free(tmp); 131 } else { 132 /* Look in $SSL_DIR */ 133 dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir()); 134 } 135 PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir); 136 137 if (dbDir[0] == '\0') { 138 PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir); 139 ret = DIR_DOESNT_EXIST_ERR; 140 goto loser; 141 } 142 143 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 144 145 /* get the status of the directory and databases and output message */ 146 if (PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) { 147 PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir); 148 } else if (PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) { 149 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir); 150 } else { 151 if (!(flags & NSS_INIT_READONLY) && 152 PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { 153 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir); 154 } 155 if (!doInitTest) { 156 for (i = 0; i < 3; i++) { 157 dbString = PR_smprintf("%s/%s", dbDir, dbName[i]); 158 PR_fprintf(PR_STDOUT, "database checked is %s\n", dbString); 159 if (PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) { 160 PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR], 161 dbString); 162 } else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) { 163 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], 164 dbString); 165 } else if (!(flags & NSS_INIT_READONLY) && 166 PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) { 167 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR], 168 dbString); 169 } 170 PR_smprintf_free(dbString); 171 } 172 } 173 } 174 175 rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix, 176 secmodName, flags); 177 if (rv != SECSuccess) { 178 SECU_PrintPRandOSError(progName); 179 ret = NSS_INITIALIZE_FAILED_ERR; 180 } else { 181 ret = SUCCESS; 182 if (doInitTest) { 183 PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 184 int passwordSuccess = 0; 185 int type = CKM_DES3_CBC; 186 SECItem keyid = { 0, NULL, 0 }; 187 unsigned char keyIdData[] = { 0xff, 0xfe }; 188 PK11SymKey *key = NULL; 189 190 keyid.data = keyIdData; 191 keyid.len = sizeof(keyIdData); 192 193 PK11_SetPasswordFunc(getPassword); 194 rv = PK11_InitPin(slot, (char *)NULL, userPassword); 195 if (rv != SECSuccess) { 196 PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n", 197 SECU_Strerror(PORT_GetError())); 198 ret = CHANGEPW_FAILED_ERR; 199 } 200 if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) { 201 PR_fprintf(PR_STDERR, "New DB did not log in after init\n"); 202 ret = AUTHENTICATION_FAILED_ERR; 203 } 204 /* generate a symetric key */ 205 key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid, 206 PR_TRUE, &passwordSuccess); 207 208 if (!key) { 209 PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n", 210 SECU_Strerror(PORT_GetError())); 211 exit(UNSPECIFIED_ERR); 212 } 213 PK11_FreeSymKey(key); 214 PK11_Logout(slot); 215 216 PK11_Authenticate(slot, PR_TRUE, &passwordSuccess); 217 218 if (*userPassword && !passwordSuccess) { 219 PR_fprintf(PR_STDERR, "New DB Did not initalize\n"); 220 ret = AUTHENTICATION_FAILED_ERR; 221 } 222 key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess); 223 224 if (!key) { 225 PR_fprintf(PR_STDERR, "Could not find generated key: %s\n", 226 SECU_Strerror(PORT_GetError())); 227 ret = UNSPECIFIED_ERR; 228 } else { 229 PK11_FreeSymKey(key); 230 } 231 PK11_FreeSlot(slot); 232 } 233 234 if (NSS_Shutdown() != SECSuccess) { 235 PR_fprintf(PR_STDERR, "Could not find generated key: %s\n", 236 SECU_Strerror(PORT_GetError())); 237 exit(1); 238 } 239 } 240 241 loser: 242 return ret; 243 }