File: | s/cmd/vfychain/vfychain.c |
Warning: | line 463, column 25 Value stored to 'secStatus' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | * Read in a cert chain from one or more files, and verify the chain for |
7 | * some usage. |
8 | * * |
9 | * This code was modified from other code also kept in the NSS directory. |
10 | ****************************************************************************/ |
11 | |
12 | #include <stdio.h> |
13 | #include <string.h> |
14 | |
15 | #if defined(XP_UNIX1) |
16 | #include <unistd.h> |
17 | #endif |
18 | |
19 | #include "prerror.h" |
20 | |
21 | #include "pk11func.h" |
22 | #include "seccomon.h" |
23 | #include "secutil.h" |
24 | #include "secmod.h" |
25 | #include "secitem.h" |
26 | #include "cert.h" |
27 | #include "ocsp.h" |
28 | |
29 | /* #include <stdlib.h> */ |
30 | /* #include <errno.h> */ |
31 | /* #include <fcntl.h> */ |
32 | /* #include <stdarg.h> */ |
33 | |
34 | #include "nspr.h" |
35 | #include "plgetopt.h" |
36 | #include "prio.h" |
37 | #include "nss.h" |
38 | |
39 | /* #include "vfyutil.h" */ |
40 | |
41 | #define RD_BUF_SIZE(60 * 1024) (60 * 1024) |
42 | |
43 | int verbose; |
44 | |
45 | secuPWData pwdata = { PW_NONE, 0 }; |
46 | |
47 | static void |
48 | Usage(const char *progName) |
49 | { |
50 | fprintf(stderrstderr, |
51 | "Usage: %s [options] [revocation options] certfile " |
52 | "[[options] certfile] ...\n" |
53 | "\tWhere options are:\n" |
54 | "\t-a\t\t Following certfile is base64 encoded\n" |
55 | "\t-b YYMMDDHHMMZ\t Validate date (default: now)\n" |
56 | "\t-d directory\t Database directory\n" |
57 | "\t-i number of consecutive verifications\n" |
58 | "\t-f \t\t Enable cert fetching from AIA URL\n" |
59 | "\t-o oid\t\t Set policy OID for cert validation(Format OID.1.2.3)\n" |
60 | "\t-p \t\t Use PKIX Library to validate certificate by calling:\n" |
61 | "\t\t\t * CERT_VerifyCertificate if specified once,\n" |
62 | "\t\t\t * CERT_PKIXVerifyCert if specified twice and more.\n" |
63 | "\t-r\t\t Following certfile is raw binary DER (default)\n" |
64 | "\t-t\t\t Following cert is explicitly trusted (overrides db trust).\n" |
65 | "\t-u usage \t 0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA,\n" |
66 | "\t\t\t 4=Email signer, 5=Email recipient, 6=Object signer,\n" |
67 | "\t\t\t 9=ProtectedObjectSigner, 10=OCSP responder, 11=Any CA,\n" |
68 | "\t\t\t 12=IPsec\n" |
69 | "\t-T\t\t Trust both explicit trust anchors (-t) and the database.\n" |
70 | "\t\t\t (Default is to only trust certificates marked -t, if there are any,\n" |
71 | "\t\t\t or to trust the database if there are certificates marked -t.)\n" |
72 | "\t-v\t\t Verbose mode. Prints root cert subject(double the\n" |
73 | "\t\t\t argument for whole root cert info)\n" |
74 | "\t-w password\t Database password.\n" |
75 | "\t-W pwfile\t Password file.\n\n" |
76 | "\tRevocation options for PKIX API(invoked with -pp options) is a\n" |
77 | "\tcollection of the following flags:\n" |
78 | "\t\t[-g type [-h flags] [-m type [-s flags]] ...] ...\n" |
79 | "\tWhere:\n" |
80 | "\t-g test type\t Sets status checking test type. Possible values\n" |
81 | "\t\t\tare \"leaf\" or \"chain\"\n" |
82 | "\t-h test flags\t Sets revocation flags for the test type it\n" |
83 | "\t\t\tfollows. Possible flags: \"testLocalInfoFirst\" and\n" |
84 | "\t\t\t\"requireFreshInfo\".\n" |
85 | "\t-m method type\t Sets method type for the test type it follows.\n" |
86 | "\t\t\tPossible types are \"crl\" and \"ocsp\".\n" |
87 | "\t-s method flags\t Sets revocation flags for the method it follows.\n" |
88 | "\t\t\tPossible types are \"doNotUse\", \"forbidFetching\",\n" |
89 | "\t\t\t\"ignoreDefaultSrc\", \"requireInfo\" and \"failIfNoInfo\".\n", |
90 | progName); |
91 | exit(1); |
92 | } |
93 | |
94 | /************************************************************************** |
95 | ** |
96 | ** Error and information routines. |
97 | ** |
98 | **************************************************************************/ |
99 | |
100 | void |
101 | errWarn(char *function) |
102 | { |
103 | fprintf(stderrstderr, "Error in function %s: %s\n", |
104 | function, SECU_Strerror(PR_GetError())PR_ErrorToString((PR_GetError()), 0)); |
105 | } |
106 | |
107 | void |
108 | exitErr(char *function) |
109 | { |
110 | errWarn(function); |
111 | /* Exit gracefully. */ |
112 | /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/ |
113 | (void)NSS_Shutdown(); |
114 | PR_Cleanup(); |
115 | exit(1); |
116 | } |
117 | |
118 | typedef struct certMemStr { |
119 | struct certMemStr *next; |
120 | CERTCertificate *cert; |
121 | } certMem; |
122 | |
123 | certMem *theCerts; |
124 | CERTCertList *trustedCertList; |
125 | |
126 | void |
127 | rememberCert(CERTCertificate *cert, PRBool trusted) |
128 | { |
129 | if (trusted) { |
130 | if (!trustedCertList) { |
131 | trustedCertList = CERT_NewCertList(); |
132 | } |
133 | CERT_AddCertToListTail(trustedCertList, cert); |
134 | } else { |
135 | certMem *newCertMem = PORT_ZNew(certMem)(certMem *)PORT_ZAlloc_Util(sizeof(certMem)); |
136 | if (newCertMem) { |
137 | newCertMem->next = theCerts; |
138 | newCertMem->cert = cert; |
139 | theCerts = newCertMem; |
140 | } |
141 | } |
142 | } |
143 | |
144 | void |
145 | forgetCerts(void) |
146 | { |
147 | certMem *oldCertMem; |
148 | while (theCerts) { |
149 | oldCertMem = theCerts; |
150 | theCerts = theCerts->next; |
151 | CERT_DestroyCertificate(oldCertMem->cert); |
152 | PORT_FreePORT_Free_Util(oldCertMem); |
153 | } |
154 | if (trustedCertList) { |
155 | CERT_DestroyCertList(trustedCertList); |
156 | } |
157 | } |
158 | |
159 | CERTCertificate * |
160 | getCert(const char *name, PRBool isAscii, const char *progName) |
161 | { |
162 | CERTCertificate *cert; |
163 | CERTCertDBHandle *defaultDB; |
164 | PRFileDesc *fd; |
165 | SECStatus rv; |
166 | SECItem item = { 0, NULL((void*)0), 0 }; |
167 | |
168 | defaultDB = CERT_GetDefaultCertDB(); |
169 | |
170 | /* First, let's try to find the cert in existing DB. */ |
171 | cert = CERT_FindCertByNicknameOrEmailAddr(defaultDB, name); |
172 | if (cert) { |
173 | return cert; |
174 | } |
175 | |
176 | /* Don't have a cert with name "name" in the DB. Try to |
177 | * open a file with such name and get the cert from there.*/ |
178 | fd = PR_Open(name, PR_RDONLY0x01, 0777); |
179 | if (!fd) { |
180 | PRErrorCode err = PR_GetError(); |
181 | fprintf(stderrstderr, "open of %s failed, %d = %s\n", |
182 | name, err, SECU_Strerror(err)PR_ErrorToString((err), 0)); |
183 | return cert; |
184 | } |
185 | |
186 | rv = SECU_ReadDERFromFile(&item, fd, isAscii, PR_FALSE0); |
187 | PR_Close(fd); |
188 | if (rv != SECSuccess) { |
189 | fprintf(stderrstderr, "%s: SECU_ReadDERFromFile failed\n", progName); |
190 | return cert; |
191 | } |
192 | |
193 | if (!item.len) { /* file was empty */ |
194 | fprintf(stderrstderr, "cert file %s was empty.\n", name); |
195 | return cert; |
196 | } |
197 | |
198 | cert = CERT_NewTempCertificate(defaultDB, &item, |
199 | NULL((void*)0) /* nickname */, |
200 | PR_FALSE0 /* isPerm */, |
201 | PR_TRUE1 /* copyDER */); |
202 | if (!cert) { |
203 | PRErrorCode err = PR_GetError(); |
204 | fprintf(stderrstderr, "couldn't import %s, %d = %s\n", |
205 | name, err, SECU_Strerror(err)PR_ErrorToString((err), 0)); |
206 | } |
207 | PORT_FreePORT_Free_Util(item.data); |
208 | return cert; |
209 | } |
210 | |
211 | #define REVCONFIG_TEST_UNDEFINED0 0 |
212 | #define REVCONFIG_TEST_LEAF1 1 |
213 | #define REVCONFIG_TEST_CHAIN2 2 |
214 | #define REVCONFIG_METHOD_CRL1 1 |
215 | #define REVCONFIG_METHOD_OCSP2 2 |
216 | |
217 | #define REVCONFIG_TEST_LEAF_STR"leaf" "leaf" |
218 | #define REVCONFIG_TEST_CHAIN_STR"chain" "chain" |
219 | #define REVCONFIG_METHOD_CRL_STR"crl" "crl" |
220 | #define REVCONFIG_METHOD_OCSP_STR"ocsp" "ocsp" |
221 | |
222 | #define REVCONFIG_TEST_TESTLOCALINFOFIRST_STR"testLocalInfoFirst" "testLocalInfoFirst" |
223 | #define REVCONFIG_TEST_REQUIREFRESHINFO_STR"requireFreshInfo" "requireFreshInfo" |
224 | #define REVCONFIG_METHOD_DONOTUSEMETHOD_STR"doNotUse" "doNotUse" |
225 | #define REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR"forbidFetching" "forbidFetching" |
226 | #define REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR"ignoreDefaultSrc" "ignoreDefaultSrc" |
227 | #define REVCONFIG_METHOD_REQUIREINFO_STR"requireInfo" "requireInfo" |
228 | #define REVCONFIG_METHOD_FAILIFNOINFO_STR"failIfNoInfo" "failIfNoInfo" |
229 | |
230 | #define REV_METHOD_INDEX_MAX4 4 |
231 | |
232 | typedef struct RevMethodsStruct { |
233 | unsigned int testType; |
234 | char *testTypeStr; |
235 | unsigned int testFlags; |
236 | char *testFlagsStr; |
237 | unsigned int methodType; |
238 | char *methodTypeStr; |
239 | unsigned int methodFlags; |
240 | char *methodFlagsStr; |
241 | } RevMethods; |
242 | |
243 | RevMethods revMethodsData[REV_METHOD_INDEX_MAX4]; |
244 | |
245 | SECStatus |
246 | parseRevMethodsAndFlags() |
247 | { |
248 | int i; |
249 | unsigned int testType = 0; |
250 | |
251 | for (i = 0; i < REV_METHOD_INDEX_MAX4; i++) { |
252 | /* testType */ |
253 | if (revMethodsData[i].testTypeStr) { |
254 | char *typeStr = revMethodsData[i].testTypeStr; |
255 | |
256 | testType = 0; |
257 | if (!PORT_Strcmpstrcmp(typeStr, REVCONFIG_TEST_LEAF_STR"leaf")) { |
258 | testType = REVCONFIG_TEST_LEAF1; |
259 | } else if (!PORT_Strcmpstrcmp(typeStr, REVCONFIG_TEST_CHAIN_STR"chain")) { |
260 | testType = REVCONFIG_TEST_CHAIN2; |
261 | } |
262 | } |
263 | if (!testType) { |
264 | return SECFailure; |
265 | } |
266 | revMethodsData[i].testType = testType; |
267 | /* testFlags */ |
268 | if (revMethodsData[i].testFlagsStr) { |
269 | char *flagStr = revMethodsData[i].testFlagsStr; |
270 | unsigned int testFlags = 0; |
271 | |
272 | if (PORT_Strstrstrstr(flagStr, REVCONFIG_TEST_TESTLOCALINFOFIRST_STR"testLocalInfoFirst")) { |
273 | testFlags |= CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST1UL; |
274 | } |
275 | if (PORT_Strstrstrstr(flagStr, REVCONFIG_TEST_REQUIREFRESHINFO_STR"requireFreshInfo")) { |
276 | testFlags |= CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE2UL; |
277 | } |
278 | revMethodsData[i].testFlags = testFlags; |
279 | } |
280 | /* method type */ |
281 | if (revMethodsData[i].methodTypeStr) { |
282 | char *methodStr = revMethodsData[i].methodTypeStr; |
283 | unsigned int methodType = 0; |
284 | |
285 | if (!PORT_Strcmpstrcmp(methodStr, REVCONFIG_METHOD_CRL_STR"crl")) { |
286 | methodType = REVCONFIG_METHOD_CRL1; |
287 | } else if (!PORT_Strcmpstrcmp(methodStr, REVCONFIG_METHOD_OCSP_STR"ocsp")) { |
288 | methodType = REVCONFIG_METHOD_OCSP2; |
289 | } |
290 | if (!methodType) { |
291 | return SECFailure; |
292 | } |
293 | revMethodsData[i].methodType = methodType; |
294 | } |
295 | if (!revMethodsData[i].methodType) { |
296 | revMethodsData[i].testType = REVCONFIG_TEST_UNDEFINED0; |
297 | continue; |
298 | } |
299 | /* method flags */ |
300 | if (revMethodsData[i].methodFlagsStr) { |
301 | char *flagStr = revMethodsData[i].methodFlagsStr; |
302 | unsigned int methodFlags = 0; |
303 | |
304 | if (!PORT_Strstrstrstr(flagStr, REVCONFIG_METHOD_DONOTUSEMETHOD_STR"doNotUse")) { |
305 | methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD1UL; |
306 | } |
307 | if (PORT_Strstrstrstr(flagStr, |
308 | REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR"forbidFetching")) { |
309 | methodFlags |= CERT_REV_M_FORBID_NETWORK_FETCHING2UL; |
310 | } |
311 | if (PORT_Strstrstrstr(flagStr, REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR"ignoreDefaultSrc")) { |
312 | methodFlags |= CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE4UL; |
313 | } |
314 | if (PORT_Strstrstrstr(flagStr, REVCONFIG_METHOD_REQUIREINFO_STR"requireInfo")) { |
315 | methodFlags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE8UL; |
316 | } |
317 | if (PORT_Strstrstrstr(flagStr, REVCONFIG_METHOD_FAILIFNOINFO_STR"failIfNoInfo")) { |
318 | methodFlags |= CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO16UL; |
319 | } |
320 | revMethodsData[i].methodFlags = methodFlags; |
321 | } else { |
322 | revMethodsData[i].methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD1UL; |
323 | } |
324 | } |
325 | return SECSuccess; |
326 | } |
327 | |
328 | SECStatus |
329 | configureRevocationParams(CERTRevocationFlags *flags) |
330 | { |
331 | int i; |
332 | unsigned int testType = REVCONFIG_TEST_UNDEFINED0; |
333 | static CERTRevocationTests *revTests = NULL((void*)0); |
334 | PRUint64 *revFlags = NULL((void*)0); |
335 | |
336 | for (i = 0; i < REV_METHOD_INDEX_MAX4; i++) { |
337 | if (revMethodsData[i].testType == REVCONFIG_TEST_UNDEFINED0) { |
338 | continue; |
339 | } |
340 | if (revMethodsData[i].testType != testType) { |
341 | testType = revMethodsData[i].testType; |
342 | if (testType == REVCONFIG_TEST_CHAIN2) { |
343 | revTests = &flags->chainTests; |
344 | } else { |
345 | revTests = &flags->leafTests; |
346 | } |
347 | revTests->number_of_preferred_methods = 0; |
348 | revTests->preferred_methods = 0; |
349 | revFlags = revTests->cert_rev_flags_per_method; |
350 | } |
351 | /* Set the number of the methods independently to the max number of |
352 | * methods. If method flags are not set it will be ignored due to |
353 | * default DO_NOT_USE flag. */ |
354 | revTests->number_of_defined_methods = cert_revocation_method_count; |
355 | revTests->cert_rev_method_independent_flags |= |
356 | revMethodsData[i].testFlags; |
357 | if (revMethodsData[i].methodType == REVCONFIG_METHOD_CRL1) { |
358 | revFlags[cert_revocation_method_crl] = |
359 | revMethodsData[i].methodFlags; |
360 | } else if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP2) { |
361 | revFlags[cert_revocation_method_ocsp] = |
362 | revMethodsData[i].methodFlags; |
363 | } |
364 | } |
365 | return SECSuccess; |
366 | } |
367 | |
368 | void |
369 | freeRevocationMethodData() |
370 | { |
371 | int i = 0; |
372 | for (; i < REV_METHOD_INDEX_MAX4; i++) { |
373 | if (revMethodsData[i].testTypeStr) { |
374 | PORT_FreePORT_Free_Util(revMethodsData[i].testTypeStr); |
375 | } |
376 | if (revMethodsData[i].testFlagsStr) { |
377 | PORT_FreePORT_Free_Util(revMethodsData[i].testFlagsStr); |
378 | } |
379 | if (revMethodsData[i].methodTypeStr) { |
380 | PORT_FreePORT_Free_Util(revMethodsData[i].methodTypeStr); |
381 | } |
382 | if (revMethodsData[i].methodFlagsStr) { |
383 | PORT_FreePORT_Free_Util(revMethodsData[i].methodFlagsStr); |
384 | } |
385 | } |
386 | } |
387 | |
388 | PRBool |
389 | isOCSPEnabled() |
390 | { |
391 | int i; |
392 | |
393 | for (i = 0; i < REV_METHOD_INDEX_MAX4; i++) { |
394 | if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP2) { |
395 | return PR_TRUE1; |
396 | } |
397 | } |
398 | return PR_FALSE0; |
399 | } |
400 | |
401 | int |
402 | main(int argc, char *argv[], char *envp[]) |
403 | { |
404 | char *certDir = NULL((void*)0); |
405 | char *progName = NULL((void*)0); |
406 | char *oidStr = NULL((void*)0); |
407 | CERTCertificate *cert; |
408 | CERTCertificate *firstCert = NULL((void*)0); |
409 | CERTCertificate *issuerCert = NULL((void*)0); |
410 | CERTCertDBHandle *defaultDB = NULL((void*)0); |
411 | PRBool isAscii = PR_FALSE0; |
412 | PRBool trusted = PR_FALSE0; |
413 | SECStatus secStatus; |
414 | SECCertificateUsage certUsage = certificateUsageSSLServer(0x0002); |
415 | PLOptState *optstate; |
416 | PRTime time = 0; |
417 | PLOptStatus status; |
418 | int usePkix = 0; |
419 | int rv = 1; |
420 | int usage; |
421 | CERTVerifyLog log; |
422 | CERTCertList *builtChain = NULL((void*)0); |
423 | PRBool certFetching = PR_FALSE0; |
424 | int revDataIndex = 0; |
425 | PRBool ocsp_fetchingFailureIsAFailure = PR_TRUE1; |
426 | PRBool useDefaultRevFlags = PR_TRUE1; |
427 | PRBool onlyTrustAnchors = PR_TRUE1; |
428 | int vfyCounts = 1; |
429 | |
430 | PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
431 | |
432 | progName = PL_strdup(argv[0]); |
433 | |
434 | optstate = PL_CreateOptState(argc, argv, "ab:c:d:efg:h:i:m:o:prs:tTu:vw:W:"); |
435 | while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
436 | switch (optstate->option) { |
437 | case 0: /* positional parameter */ |
438 | goto breakout; |
439 | case 'a': |
440 | isAscii = PR_TRUE1; |
441 | break; |
442 | case 'b': |
443 | secStatus = DER_AsciiToTimeDER_AsciiToTime_Util(&time, optstate->value); |
444 | if (secStatus != SECSuccess) |
445 | Usage(progName); |
446 | break; |
447 | case 'd': |
448 | certDir = PL_strdup(optstate->value); |
449 | break; |
450 | case 'e': |
451 | ocsp_fetchingFailureIsAFailure = PR_FALSE0; |
452 | break; |
453 | case 'f': |
454 | certFetching = PR_TRUE1; |
455 | break; |
456 | case 'g': |
457 | if (revMethodsData[revDataIndex].testTypeStr || |
458 | revMethodsData[revDataIndex].methodTypeStr) { |
459 | revDataIndex += 1; |
460 | if (revDataIndex == REV_METHOD_INDEX_MAX4) { |
461 | fprintf(stderrstderr, "Invalid revocation configuration" |
462 | "specified.\n"); |
463 | secStatus = SECFailure; |
Value stored to 'secStatus' is never read | |
464 | break; |
465 | } |
466 | } |
467 | useDefaultRevFlags = PR_FALSE0; |
468 | revMethodsData[revDataIndex].testTypeStr = |
469 | PL_strdup(optstate->value); |
470 | break; |
471 | case 'h': |
472 | revMethodsData[revDataIndex].testFlagsStr = |
473 | PL_strdup(optstate->value); |
474 | break; |
475 | case 'i': |
476 | vfyCounts = PORT_Atoi(optstate->value)(int)strtol(optstate->value, ((void*)0), 10); |
477 | break; |
478 | break; |
479 | case 'm': |
480 | if (revMethodsData[revDataIndex].methodTypeStr) { |
481 | revDataIndex += 1; |
482 | if (revDataIndex == REV_METHOD_INDEX_MAX4) { |
483 | fprintf(stderrstderr, "Invalid revocation configuration" |
484 | "specified.\n"); |
485 | secStatus = SECFailure; |
486 | break; |
487 | } |
488 | } |
489 | useDefaultRevFlags = PR_FALSE0; |
490 | revMethodsData[revDataIndex].methodTypeStr = |
491 | PL_strdup(optstate->value); |
492 | break; |
493 | case 'o': |
494 | oidStr = PL_strdup(optstate->value); |
495 | break; |
496 | case 'p': |
497 | usePkix += 1; |
498 | break; |
499 | case 'r': |
500 | isAscii = PR_FALSE0; |
501 | break; |
502 | case 's': |
503 | revMethodsData[revDataIndex].methodFlagsStr = |
504 | PL_strdup(optstate->value); |
505 | break; |
506 | case 't': |
507 | trusted = PR_TRUE1; |
508 | break; |
509 | case 'T': |
510 | onlyTrustAnchors = PR_FALSE0; |
511 | break; |
512 | case 'u': |
513 | usage = PORT_Atoi(optstate->value)(int)strtol(optstate->value, ((void*)0), 10); |
514 | if (usage < 0 || usage > 62) |
515 | Usage(progName); |
516 | certUsage = ((SECCertificateUsage)1) << usage; |
517 | if (certUsage > certificateUsageHighest(0x1000)) |
518 | Usage(progName); |
519 | break; |
520 | case 'w': |
521 | pwdata.source = PW_PLAINTEXT; |
522 | pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value); |
523 | break; |
524 | |
525 | case 'W': |
526 | pwdata.source = PW_FROMFILE; |
527 | pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value); |
528 | break; |
529 | case 'v': |
530 | verbose++; |
531 | break; |
532 | default: |
533 | Usage(progName); |
534 | break; |
535 | } |
536 | } |
537 | breakout: |
538 | if (status != PL_OPT_OK) |
539 | Usage(progName); |
540 | |
541 | if (usePkix < 2) { |
542 | if (oidStr) { |
543 | fprintf(stderrstderr, "Policy oid(-o) can be used only with" |
544 | " CERT_PKIXVerifyCert(-pp) function.\n"); |
545 | Usage(progName); |
546 | } |
547 | if (trusted) { |
548 | fprintf(stderrstderr, "Cert trust flag can be used only with" |
549 | " CERT_PKIXVerifyCert(-pp) function.\n"); |
550 | Usage(progName); |
551 | } |
552 | if (!onlyTrustAnchors) { |
553 | fprintf(stderrstderr, "Cert trust anchor exclusiveness can be" |
554 | " used only with CERT_PKIXVerifyCert(-pp)" |
555 | " function.\n"); |
556 | } |
557 | } |
558 | |
559 | if (!useDefaultRevFlags && parseRevMethodsAndFlags()) { |
560 | fprintf(stderrstderr, "Invalid revocation configuration specified.\n"); |
561 | goto punt; |
562 | } |
563 | |
564 | /* Set our password function callback. */ |
565 | PK11_SetPasswordFunc(SECU_GetModulePassword); |
566 | |
567 | /* Initialize the NSS libraries. */ |
568 | if (certDir) { |
569 | secStatus = NSS_Init(certDir); |
570 | } else { |
571 | secStatus = NSS_NoDB_Init(NULL((void*)0)); |
572 | |
573 | /* load the builtins */ |
574 | SECMOD_AddNewModule("Builtins", DLL_PREFIX"lib" "nssckbi." DLL_SUFFIX"so", 0, 0); |
575 | } |
576 | if (secStatus != SECSuccess) { |
577 | exitErr("NSS_Init"); |
578 | } |
579 | SECU_RegisterDynamicOids(); |
580 | if (isOCSPEnabled()) { |
581 | CERT_EnableOCSPChecking(CERT_GetDefaultCertDB()); |
582 | CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB()); |
583 | if (!ocsp_fetchingFailureIsAFailure) { |
584 | CERT_SetOCSPFailureMode(ocspMode_FailureIsNotAVerificationFailure); |
585 | } |
586 | } |
587 | |
588 | while (status == PL_OPT_OK) { |
589 | switch (optstate->option) { |
590 | default: |
591 | Usage(progName); |
592 | break; |
593 | case 'a': |
594 | isAscii = PR_TRUE1; |
595 | break; |
596 | case 'r': |
597 | isAscii = PR_FALSE0; |
598 | break; |
599 | case 't': |
600 | trusted = PR_TRUE1; |
601 | break; |
602 | case 0: /* positional parameter */ |
603 | if (usePkix < 2 && trusted) { |
604 | fprintf(stderrstderr, "Cert trust flag can be used only with" |
605 | " CERT_PKIXVerifyCert(-pp) function.\n"); |
606 | Usage(progName); |
607 | } |
608 | cert = getCert(optstate->value, isAscii, progName); |
609 | if (!cert) |
610 | goto punt; |
611 | rememberCert(cert, trusted); |
612 | if (!firstCert) |
613 | firstCert = cert; |
614 | trusted = PR_FALSE0; |
615 | } |
616 | status = PL_GetNextOpt(optstate); |
617 | } |
618 | PL_DestroyOptState(optstate); |
619 | if (status == PL_OPT_BAD || !firstCert) |
620 | Usage(progName); |
621 | |
622 | /* Initialize log structure */ |
623 | log.arena = PORT_NewArenaPORT_NewArena_Util(512); |
624 | log.head = log.tail = NULL((void*)0); |
625 | log.count = 0; |
626 | |
627 | do { |
628 | if (usePkix < 2) { |
629 | /* NOW, verify the cert chain. */ |
630 | if (usePkix) { |
631 | /* Use old API with libpkix validation lib */ |
632 | CERT_SetUsePKIXForValidation(PR_TRUE1); |
633 | } |
634 | if (!time) |
635 | time = PR_Now(); |
636 | |
637 | defaultDB = CERT_GetDefaultCertDB(); |
638 | secStatus = CERT_VerifyCertificate(defaultDB, firstCert, |
639 | PR_TRUE1 /* check sig */, |
640 | certUsage, |
641 | time, |
642 | &pwdata, /* wincx */ |
643 | &log, /* error log */ |
644 | NULL((void*)0)); /* returned usages */ |
645 | } else |
646 | do { |
647 | static CERTValOutParam cvout[4]; |
648 | static CERTValInParam cvin[7]; |
649 | SECOidTag oidTag; |
650 | int inParamIndex = 0; |
651 | static PRUint64 revFlagsLeaf[2]; |
652 | static PRUint64 revFlagsChain[2]; |
653 | static CERTRevocationFlags rev; |
654 | |
655 | if (oidStr) { |
656 | PLArenaPool *arena; |
657 | SECOidData od; |
658 | memset(&od, 0, sizeof od); |
659 | od.offset = SEC_OID_UNKNOWN; |
660 | od.desc = "User Defined Policy OID"; |
661 | od.mechanism = CKM_INVALID_MECHANISM0xffffffffUL; |
662 | od.supportedExtension = INVALID_CERT_EXTENSION; |
663 | |
664 | arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048)); |
665 | if (!arena) { |
666 | fprintf(stderrstderr, "out of memory"); |
667 | goto punt; |
668 | } |
669 | |
670 | secStatus = SEC_StringToOID(arena, &od.oid, oidStr, 0); |
671 | if (secStatus != SECSuccess) { |
672 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0); |
673 | fprintf(stderrstderr, "Can not encode oid: %s(%s)\n", oidStr, |
674 | SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0)); |
675 | break; |
676 | } |
677 | |
678 | oidTag = SECOID_AddEntrySECOID_AddEntry_Util(&od); |
679 | PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0); |
680 | if (oidTag == SEC_OID_UNKNOWN) { |
681 | fprintf(stderrstderr, "Can not add new oid to the dynamic " |
682 | "table: %s\n", |
683 | oidStr); |
684 | secStatus = SECFailure; |
685 | break; |
686 | } |
687 | |
688 | cvin[inParamIndex].type = cert_pi_policyOID; |
689 | cvin[inParamIndex].value.arraySize = 1; |
690 | cvin[inParamIndex].value.array.oids = &oidTag; |
691 | |
692 | inParamIndex++; |
693 | } |
694 | |
695 | if (trustedCertList) { |
696 | cvin[inParamIndex].type = cert_pi_trustAnchors; |
697 | cvin[inParamIndex].value.pointer.chain = trustedCertList; |
698 | |
699 | inParamIndex++; |
700 | } |
701 | |
702 | cvin[inParamIndex].type = cert_pi_useAIACertFetch; |
703 | cvin[inParamIndex].value.scalar.b = certFetching; |
704 | inParamIndex++; |
705 | |
706 | rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf; |
707 | rev.chainTests.cert_rev_flags_per_method = revFlagsChain; |
708 | secStatus = configureRevocationParams(&rev); |
709 | if (secStatus) { |
710 | fprintf(stderrstderr, "Can not config revocation parameters "); |
711 | break; |
712 | } |
713 | |
714 | cvin[inParamIndex].type = cert_pi_revocationFlags; |
715 | cvin[inParamIndex].value.pointer.revocation = &rev; |
716 | inParamIndex++; |
717 | |
718 | if (time) { |
719 | cvin[inParamIndex].type = cert_pi_date; |
720 | cvin[inParamIndex].value.scalar.time = time; |
721 | inParamIndex++; |
722 | } |
723 | |
724 | if (!onlyTrustAnchors) { |
725 | cvin[inParamIndex].type = cert_pi_useOnlyTrustAnchors; |
726 | cvin[inParamIndex].value.scalar.b = onlyTrustAnchors; |
727 | inParamIndex++; |
728 | } |
729 | |
730 | cvin[inParamIndex].type = cert_pi_end; |
731 | |
732 | cvout[0].type = cert_po_trustAnchor; |
733 | cvout[0].value.pointer.cert = NULL((void*)0); |
734 | cvout[1].type = cert_po_certList; |
735 | cvout[1].value.pointer.chain = NULL((void*)0); |
736 | |
737 | /* setting pointer to CERTVerifyLog. Initialized structure |
738 | * will be used CERT_PKIXVerifyCert */ |
739 | cvout[2].type = cert_po_errorLog; |
740 | cvout[2].value.pointer.log = &log; |
741 | |
742 | cvout[3].type = cert_po_end; |
743 | |
744 | secStatus = CERT_PKIXVerifyCert(firstCert, certUsage, |
745 | cvin, cvout, &pwdata); |
746 | if (secStatus != SECSuccess) { |
747 | break; |
748 | } |
749 | issuerCert = cvout[0].value.pointer.cert; |
750 | builtChain = cvout[1].value.pointer.chain; |
751 | } while (0); |
752 | |
753 | /* Display validation results */ |
754 | if (secStatus != SECSuccess || log.count > 0) { |
755 | CERTVerifyLogNode *node = NULL((void*)0); |
756 | fprintf(stderrstderr, "Chain is bad!\n"); |
757 | |
758 | SECU_displayVerifyLog(stderrstderr, &log, verbose); |
759 | /* Have cert refs in the log only in case of failure. |
760 | * Destroy them. */ |
761 | for (node = log.head; node; node = node->next) { |
762 | if (node->cert) |
763 | CERT_DestroyCertificate(node->cert); |
764 | } |
765 | log.head = log.tail = NULL((void*)0); |
766 | log.count = 0; |
767 | rv = 1; |
768 | } else { |
769 | fprintf(stderrstderr, "Chain is good!\n"); |
770 | if (issuerCert) { |
771 | if (verbose > 1) { |
772 | rv = SEC_PrintCertificateAndTrust(issuerCert, "Root Certificate", |
773 | NULL((void*)0)); |
774 | if (rv != SECSuccess) { |
775 | SECU_PrintError(progName, "problem printing certificate"); |
776 | } |
777 | } else if (verbose > 0) { |
778 | SECU_PrintName(stdoutstdout, &issuerCert->subject, "Root " |
779 | "Certificate Subject:", |
780 | 0); |
781 | } |
782 | CERT_DestroyCertificate(issuerCert); |
783 | } |
784 | if (builtChain) { |
785 | CERTCertListNode *node; |
786 | int count = 0; |
787 | char buff[256]; |
788 | |
789 | if (verbose) { |
790 | for (node = CERT_LIST_HEAD(builtChain)((CERTCertListNode *)(&builtChain->list)->next); !CERT_LIST_END(node, builtChain)(((void *)node) == ((void *)&builtChain->list)); |
791 | node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next), count++) { |
792 | snprintf(buff, sizeof(buff), "Certificate %d Subject", count + 1); |
793 | SECU_PrintName(stdoutstdout, &node->cert->subject, buff, 0); |
794 | } |
795 | } |
796 | CERT_DestroyCertList(builtChain); |
797 | } |
798 | rv = 0; |
799 | } |
800 | } while (--vfyCounts > 0); |
801 | |
802 | /* Need to destroy CERTVerifyLog arena at the end */ |
803 | PORT_FreeArenaPORT_FreeArena_Util(log.arena, PR_FALSE0); |
804 | |
805 | punt: |
806 | forgetCerts(); |
807 | if (NSS_Shutdown() != SECSuccess) { |
808 | SECU_PrintError(progName, "NSS_Shutdown"); |
809 | rv = 1; |
810 | } |
811 | PORT_FreePORT_Free_Util(progName); |
812 | PORT_FreePORT_Free_Util(certDir); |
813 | PORT_FreePORT_Free_Util(oidStr); |
814 | freeRevocationMethodData(); |
815 | if (pwdata.data) { |
816 | PORT_FreePORT_Free_Util(pwdata.data); |
817 | } |
818 | PL_ArenaFinish(); |
819 | PR_Cleanup(); |
820 | return rv; |
821 | } |