Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
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>
16 #if defined(WIN32)
17 #include "fcntl.h"
18 #include "io.h"
19 #endif
21 #include "secutil.h"
22 #include "pk11pub.h"
24 #if defined(XP_UNIX)
25 #include <unistd.h>
26 #endif
28 #include "nspr.h"
29 #include "prtypes.h"
30 #include "certdb.h"
31 #include "nss.h"
32 #include "../modutil/modutil.h"
34 #include "plgetopt.h"
36 static char *progName;
38 char *dbDir = NULL;
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;
46 static char *
47 getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
48 {
49 int *success = (int *)arg;
51 if (retry) {
52 *success = 0;
53 return NULL;
54 }
56 *success = 1;
57 return PORT_Strdup(userPassword);
58 }
61 static void Usage(const char *progName)
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 }
75 int main(int argc, char **argv)
76 {
77 PLOptState *optstate;
78 PLOptStatus optstatus;
80 PRUint32 flags = 0;
81 Error ret;
82 SECStatus rv;
83 char * dbString = NULL;
84 PRBool doInitTest = PR_FALSE;
85 int i;
87 progName = strrchr(argv[0], '/');
88 if (!progName)
89 progName = strrchr(argv[0], '\\');
90 progName = progName ? progName+1 : argv[0];
92 optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
94 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
95 switch (optstate->option) {
96 case 'h':
97 default : Usage(progName); break;
99 case 'r': flags |= NSS_INIT_READONLY; break;
101 case 'f': flags |= NSS_INIT_FORCEOPEN; break;
103 case 'i': doInitTest = PR_TRUE; break;
105 case 'p':
106 userPassword = PORT_Strdup(optstate->value);
107 break;
109 case 'd':
110 dbDir = PORT_Strdup(optstate->value);
111 break;
113 }
114 }
115 if (optstatus == PL_OPT_BAD)
116 Usage(progName);
118 if (!dbDir) {
119 dbDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
120 }
121 dbDir = SECU_ConfigDirectory(dbDir);
122 PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
124 if( dbDir[0] == '\0') {
125 PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
126 ret= DIR_DOESNT_EXIST_ERR;
127 goto loser;
128 }
131 PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
133 /* get the status of the directory and databases and output message */
134 if(PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
135 PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
136 } else if(PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
137 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
138 } else {
139 if( !( flags & NSS_INIT_READONLY ) &&
140 PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
141 PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
142 }
143 if (!doInitTest) {
144 for (i=0;i<3;i++) {
145 dbString=PR_smprintf("%s/%s",dbDir,dbName[i]);
146 PR_fprintf(PR_STDOUT, "database checked is %s\n",dbString);
147 if(PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
148 PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
149 dbString);
150 } else if(PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
151 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
152 dbString);
153 } else if( !( flags & NSS_INIT_READONLY ) &&
154 PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
155 PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
156 dbString);
157 }
158 }
159 }
160 }
163 rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
164 secmodName, flags);
165 if (rv != SECSuccess) {
166 SECU_PrintPRandOSError(progName);
167 ret=NSS_INITIALIZE_FAILED_ERR;
168 } else {
169 ret=SUCCESS;
170 if (doInitTest) {
171 PK11SlotInfo * slot = PK11_GetInternalKeySlot();
172 SECStatus rv;
173 int passwordSuccess = 0;
174 int type = CKM_DES3_CBC;
175 SECItem keyid = { 0, NULL, 0 };
176 unsigned char keyIdData[] = { 0xff, 0xfe };
177 PK11SymKey *key = NULL;
179 keyid.data = keyIdData;
180 keyid.len = sizeof(keyIdData);
182 PK11_SetPasswordFunc(getPassword);
183 rv = PK11_InitPin(slot, (char *)NULL, userPassword);
184 if (rv != SECSuccess) {
185 PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
186 SECU_Strerror(PORT_GetError()));
187 ret = CHANGEPW_FAILED_ERR;
188 }
189 if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
190 PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
191 ret = AUTHENTICATION_FAILED_ERR;
192 }
193 /* generate a symetric key */
194 key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
195 PR_TRUE, &passwordSuccess);
197 if (!key) {
198 PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
199 SECU_Strerror(PORT_GetError()));
200 exit (UNSPECIFIED_ERR);
201 }
202 PK11_FreeSymKey(key);
203 PK11_Logout(slot);
205 PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
207 if (*userPassword && !passwordSuccess) {
208 PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
209 ret = AUTHENTICATION_FAILED_ERR;
210 }
211 key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
213 if (!key) {
214 PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
215 SECU_Strerror(PORT_GetError()));
216 ret = UNSPECIFIED_ERR;
217 } else {
218 PK11_FreeSymKey(key);
219 }
220 PK11_FreeSlot(slot);
221 }
223 if (NSS_Shutdown() != SECSuccess) {
224 PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
225 SECU_Strerror(PORT_GetError()));
226 exit(1);
227 }
228 }
230 loser:
231 return ret;
232 }