Bug Summary

File:s/cmd/vfychain/vfychain.c
Warning:line 463, column 25
Value stored to 'secStatus' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name vfychain.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/vfychain -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/vfychain -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DLL_PREFIX="lib" -D DLL_SUFFIX="so" -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/seccmd -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c vfychain.c
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
43int verbose;
44
45secuPWData pwdata = { PW_NONE, 0 };
46
47static void
48Usage(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
100void
101errWarn(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
107void
108exitErr(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
118typedef struct certMemStr {
119 struct certMemStr *next;
120 CERTCertificate *cert;
121} certMem;
122
123certMem *theCerts;
124CERTCertList *trustedCertList;
125
126void
127rememberCert(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
144void
145forgetCerts(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
159CERTCertificate *
160getCert(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
232typedef 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
243RevMethods revMethodsData[REV_METHOD_INDEX_MAX4];
244
245SECStatus
246parseRevMethodsAndFlags()
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
328SECStatus
329configureRevocationParams(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
368void
369freeRevocationMethodData()
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
388PRBool
389isOCSPEnabled()
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
401int
402main(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 }
537breakout:
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
805punt:
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}