Bug Summary

File:s/cmd/crlutil/crlutil.c
Warning:line 893, column 13
Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status'

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 crlutil.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/crlutil -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/crlutil -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D NSPR20 -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 -I ../../../dist/public/dbm -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 crlutil.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** certutil.c
7**
8** utility for managing certificates and the cert database
9**
10*/
11/* test only */
12
13#include "nspr.h"
14#include "plgetopt.h"
15#include "secutil.h"
16#include "cert.h"
17#include "certi.h"
18#include "certdb.h"
19#include "nss.h"
20#include "pk11func.h"
21#include "crlgen.h"
22
23#define SEC_CERT_DB_EXISTS0 0
24#define SEC_CREATE_CERT_DB1 1
25
26static char *progName;
27
28static CERTSignedCrl *
29FindCRL(CERTCertDBHandle *certHandle, char *name, int type)
30{
31 CERTSignedCrl *crl = NULL((void*)0);
32 CERTCertificate *cert = NULL((void*)0);
33 SECItem derName;
34
35 derName.data = NULL((void*)0);
36 derName.len = 0;
37
38 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name);
39 if (!cert) {
40 CERTName *certName = NULL((void*)0);
41 PLArenaPool *arena = NULL((void*)0);
42 SECStatus rv = SECSuccess;
43
44 certName = CERT_AsciiToName(name);
45 if (certName) {
46 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
47 if (arena) {
48 SECItem *nameItem =
49 SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, NULL((void*)0), (void *)certName,
50 SEC_ASN1_GET(CERT_NameTemplate)CERT_NameTemplate);
51 if (nameItem) {
52 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &derName, nameItem);
53 }
54 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
55 }
56 CERT_DestroyName(certName);
57 }
58
59 if (rv != SECSuccess) {
60 SECU_PrintError(progName, "SECITEM_CopyItem failed, out of memory");
61 return ((CERTSignedCrl *)NULL((void*)0));
62 }
63
64 if (!derName.len || !derName.data) {
65 SECU_PrintError(progName, "could not find certificate named '%s'", name);
66 return ((CERTSignedCrl *)NULL((void*)0));
67 }
68 } else {
69 SECStatus rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &derName, &cert->derSubject);
70 CERT_DestroyCertificate(cert);
71 if (rv != SECSuccess) {
72 return ((CERTSignedCrl *)NULL((void*)0));
73 }
74 }
75
76 crl = SEC_FindCrlByName(certHandle, &derName, type);
77 if (crl == NULL((void*)0))
78 SECU_PrintError(progName, "could not find %s's CRL", name);
79 if (derName.data) {
80 SECITEM_FreeItemSECITEM_FreeItem_Util(&derName, PR_FALSE0);
81 }
82 return (crl);
83}
84
85static SECStatus
86DisplayCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType)
87{
88 CERTSignedCrl *crl = NULL((void*)0);
89
90 crl = FindCRL(certHandle, nickName, crlType);
91
92 if (crl) {
93 SECU_PrintCRLInfo(stdoutstdout, &crl->crl, "CRL Info:\n", 0);
94 SEC_DestroyCrl(crl);
95 return SECSuccess;
96 }
97 return SECFailure;
98}
99
100static void
101ListCRLNames(CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
102{
103 CERTCrlHeadNode *crlList = NULL((void*)0);
104 CERTCrlNode *crlNode = NULL((void*)0);
105 CERTName *name = NULL((void*)0);
106 PLArenaPool *arena = NULL((void*)0);
107 SECStatus rv;
108
109 do {
110 arena = PORT_NewArenaPORT_NewArena_Util(SEC_ASN1_DEFAULT_ARENA_SIZE(2048));
111 if (arena == NULL((void*)0)) {
112 fprintf(stderrstderr, "%s: fail to allocate memory\n", progName);
113 break;
114 }
115
116 name = PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(*name));
117 if (name == NULL((void*)0)) {
118 fprintf(stderrstderr, "%s: fail to allocate memory\n", progName);
119 break;
120 }
121 name->arena = arena;
122
123 rv = SEC_LookupCrls(certHandle, &crlList, crlType);
124 if (rv != SECSuccess) {
125 fprintf(stderrstderr, "%s: fail to look up CRLs (%s)\n", progName,
126 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
127 break;
128 }
129
130 /* just in case */
131 if (!crlList)
132 break;
133
134 crlNode = crlList->first;
135
136 fprintf(stdoutstdout, "\n");
137 fprintf(stdoutstdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
138 while (crlNode) {
139 char *asciiname = NULL((void*)0);
140 CERTCertificate *cert = NULL((void*)0);
141 if (crlNode->crl && crlNode->crl->crl.derName.data != NULL((void*)0)) {
142 cert = CERT_FindCertByName(certHandle,
143 &crlNode->crl->crl.derName);
144 if (!cert) {
145 SECU_PrintError(progName, "could not find signing "
146 "certificate in database");
147 }
148 }
149 if (cert) {
150 char *certName = NULL((void*)0);
151 if (cert->nickname && PORT_Strlen(cert->nickname)strlen(cert->nickname) > 0) {
152 certName = cert->nickname;
153 } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr)strlen(cert->emailAddr) > 0) {
154 certName = cert->emailAddr;
155 }
156 if (certName) {
157 asciiname = PORT_StrdupPORT_Strdup_Util(certName);
158 }
159 CERT_DestroyCertificate(cert);
160 }
161
162 if (!asciiname) {
163 name = &crlNode->crl->crl.name;
164 if (!name) {
165 SECU_PrintError(progName, "fail to get the CRL "
166 "issuer name");
167 continue;
168 }
169 asciiname = CERT_NameToAscii(name);
170 }
171 fprintf(stdoutstdout, "%-40s %-5s\n", asciiname, "CRL");
172 if (asciiname) {
173 PORT_FreePORT_Free_Util(asciiname);
174 }
175 if (PR_TRUE1 == deletecrls) {
176 CERTSignedCrl *acrl = NULL((void*)0);
177 SECItem *issuer = &crlNode->crl->crl.derName;
178 acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
179 if (acrl) {
180 SEC_DeletePermCRL(acrl);
181 SEC_DestroyCrl(acrl);
182 }
183 }
184 crlNode = crlNode->next;
185 }
186
187 } while (0);
188 if (crlList)
189 PORT_FreeArenaPORT_FreeArena_Util(crlList->arena, PR_FALSE0);
190 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
191}
192
193static SECStatus
194ListCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType)
195{
196 if (nickName == NULL((void*)0)) {
197 ListCRLNames(certHandle, crlType, PR_FALSE0);
198 return SECSuccess;
199 }
200
201 return DisplayCRL(certHandle, nickName, crlType);
202}
203
204static SECStatus
205DeleteCRL(CERTCertDBHandle *certHandle, char *name, int type)
206{
207 CERTSignedCrl *crl = NULL((void*)0);
208 SECStatus rv = SECFailure;
209
210 crl = FindCRL(certHandle, name, type);
211 if (!crl) {
212 SECU_PrintError(progName, "could not find the issuer %s's CRL", name);
213 return SECFailure;
214 }
215 rv = SEC_DeletePermCRL(crl);
216 SEC_DestroyCrl(crl);
217 if (rv != SECSuccess) {
218 SECU_PrintError(progName, "fail to delete the issuer %s's CRL "
219 "from the perm database (reason: %s)",
220 name, SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
221 return SECFailure;
222 }
223 return (rv);
224}
225
226SECStatus
227ImportCRL(CERTCertDBHandle *certHandle, char *url, int type,
228 PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions,
229 secuPWData *pwdata)
230{
231 CERTSignedCrl *crl = NULL((void*)0);
232 SECItem crlDER;
233 PK11SlotInfo *slot = NULL((void*)0);
234 int rv;
235
236 crlDER.data = NULL((void*)0);
237
238 /* Read in the entire file specified with the -f argument */
239 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE0, PR_FALSE0);
240 if (rv != SECSuccess) {
241 SECU_PrintError(progName, "unable to read input file");
242 return (SECFailure);
243 }
244
245 decodeOptions |= CRL_DECODE_DONT_COPY_DER0x00000001;
246
247 slot = PK11_GetInternalKeySlot();
248
249 if (PK11_NeedLogin(slot)) {
250 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
251 if (rv != SECSuccess)
252 goto loser;
253 }
254
255 crl = PK11_ImportCRL(slot, &crlDER, url, type,
256 NULL((void*)0), importOptions, NULL((void*)0), decodeOptions);
257
258 if (!crl) {
259 const char *errString;
260
261 rv = SECFailure;
262 errString = SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0);
263 if (errString && PORT_Strlen(errString)strlen(errString) == 0)
264 SECU_PrintError(progName,
265 "CRL is not imported (error: input CRL is not up to date.)");
266 else
267 SECU_PrintError(progName, "unable to import CRL");
268 } else {
269 SEC_DestroyCrl(crl);
270 }
271loser:
272 if (slot) {
273 PK11_FreeSlot(slot);
274 }
275 SECITEM_FreeItemSECITEM_FreeItem_Util(&crlDER, PR_FALSE0);
276 return (rv);
277}
278
279SECStatus
280DumpCRL(PRFileDesc *inFile)
281{
282 int rv;
283 PLArenaPool *arena = NULL((void*)0);
284 CERTSignedCrl *newCrl = NULL((void*)0);
285
286 SECItem crlDER;
287 crlDER.data = NULL((void*)0);
288
289 /* Read in the entire file specified with the -f argument */
290 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE0, PR_FALSE0);
291 if (rv != SECSuccess) {
292 SECU_PrintError(progName, "unable to read input file");
293 return (SECFailure);
294 }
295
296 rv = SEC_ERROR_NO_MEMORY;
297 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
298 if (!arena)
299 return rv;
300
301 newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE1,
302 CRL_DECODE_DEFAULT_OPTIONS0x00000000);
303 if (!newCrl)
304 return SECFailure;
305
306 SECU_PrintCRLInfo(stdoutstdout, &newCrl->crl, "CRL file contents", 0);
307
308 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
309 return rv;
310}
311
312static CERTCertificate *
313FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl,
314 char *certNickName)
315{
316 CERTCertificate *cert = NULL((void*)0), *certTemp = NULL((void*)0);
317 SECStatus rv = SECFailure;
318 CERTAuthKeyID *authorityKeyID = NULL((void*)0);
319 SECItem *subject = NULL((void*)0);
320
321 PORT_Assert(certHandle != NULL)((certHandle != ((void*)0))?((void)0):PR_Assert("certHandle != NULL"
,"crlutil.c",321))
;
322 if (!certHandle || (!signCrl && !certNickName)) {
323 SECU_PrintError(progName, "invalid args for function "
324 "FindSigningCert \n");
325 return NULL((void*)0);
326 }
327
328 if (signCrl) {
329#if 0
330 authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl);
331#endif
332 subject = &signCrl->crl.derName;
333 } else {
334 certTemp = CERT_FindCertByNickname(certHandle, certNickName);
335 if (!certTemp) {
336 SECU_PrintError(progName, "could not find certificate \"%s\" "
337 "in database",
338 certNickName);
339 goto loser;
340 }
341 subject = &certTemp->derSubject;
342 }
343
344 cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now());
345 if (!cert) {
346 SECU_PrintError(progName, "could not find signing certificate "
347 "in database");
348 goto loser;
349 } else {
350 rv = SECSuccess;
351 }
352
353loser:
354 if (certTemp)
355 CERT_DestroyCertificate(certTemp);
356 if (cert && rv != SECSuccess)
357 CERT_DestroyCertificate(cert);
358 return cert;
359}
360
361static CERTSignedCrl *
362CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle,
363 CERTCertificate **cert, char *certNickName,
364 PRFileDesc *inFile, PRInt32 decodeOptions,
365 PRInt32 importOptions, secuPWData *pwdata)
366{
367 SECItem crlDER = { 0, NULL((void*)0), 0 };
368 CERTSignedCrl *signCrl = NULL((void*)0);
369 CERTSignedCrl *modCrl = NULL((void*)0);
370 PLArenaPool *modArena = NULL((void*)0);
371 SECStatus rv = SECSuccess;
372
373 if (!arena || !certHandle || !certNickName) {
374 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
375 SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n");
376 return NULL((void*)0);
377 }
378
379 modArena = PORT_NewArenaPORT_NewArena_Util(SEC_ASN1_DEFAULT_ARENA_SIZE(2048));
380 if (!modArena) {
381 SECU_PrintError(progName, "fail to allocate memory\n");
382 return NULL((void*)0);
383 }
384
385 if (inFile != NULL((void*)0)) {
386 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE0, PR_FALSE0);
387 if (rv != SECSuccess) {
388 SECU_PrintError(progName, "unable to read input file");
389 goto loser;
390 }
391
392 decodeOptions |= CRL_DECODE_DONT_COPY_DER0x00000001;
393
394 modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE1,
395 decodeOptions);
396 if (!modCrl) {
397 SECU_PrintError(progName, "fail to decode CRL");
398 goto loser;
399 }
400
401 if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS0x00000001)) {
402 /* If caCert is a v2 certificate, make sure that it
403 * can be used for crl signing purpose */
404 *cert = FindSigningCert(certHandle, modCrl, NULL((void*)0));
405 if (!*cert) {
406 goto loser;
407 }
408
409 rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
410 PR_Now(), pwdata);
411 if (rv != SECSuccess) {
412 SECU_PrintError(progName, "fail to verify signed data\n");
413 goto loser;
414 }
415 }
416 } else {
417 modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE1);
418 if (!modCrl) {
419 SECU_PrintError(progName, "fail to find crl %s in database\n",
420 certNickName);
421 goto loser;
422 }
423 }
424
425 signCrl = PORT_ArenaZNew(arena, CERTSignedCrl)(CERTSignedCrl *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTSignedCrl
))
;
426 if (signCrl == NULL((void*)0)) {
427 SECU_PrintError(progName, "fail to allocate memory\n");
428 goto loser;
429 }
430
431 rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl);
432 if (rv != SECSuccess) {
433 SECU_PrintError(progName, "unable to dublicate crl for "
434 "modification.");
435 goto loser;
436 }
437
438 /* Make sure the update time is current. It can be modified later
439 * by "update <time>" command from crl generation script */
440 rv = DER_EncodeTimeChoiceDER_EncodeTimeChoice_Util(arena, &signCrl->crl.lastUpdate, PR_Now());
441 if (rv != SECSuccess) {
442 SECU_PrintError(progName, "fail to encode current time\n");
443 goto loser;
444 }
445
446 signCrl->arena = arena;
447 signCrl->referenceCount = 1;
448
449loser:
450 if (crlDER.data) {
451 SECITEM_FreeItemSECITEM_FreeItem_Util(&crlDER, PR_FALSE0);
452 }
453 if (modArena && (!modCrl || modCrl->arena != modArena)) {
454 PORT_FreeArenaPORT_FreeArena_Util(modArena, PR_FALSE0);
455 }
456 if (modCrl)
457 SEC_DestroyCrl(modCrl);
458 if (rv != SECSuccess && signCrl) {
459 SEC_DestroyCrl(signCrl);
460 signCrl = NULL((void*)0);
461 }
462 return signCrl;
463}
464
465static CERTSignedCrl *
466CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle,
467 CERTCertificate *cert)
468{
469 CERTSignedCrl *signCrl = NULL((void*)0);
470 void *dummy = NULL((void*)0);
471 SECStatus rv;
472 void *mark = NULL((void*)0);
473
474 /* if the CERTSignedCrl structure changes, this function will need to be
475 updated as well */
476 if (!cert || !arena) {
477 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
478 SECU_PrintError(progName, "invalid args for function "
479 "CreateNewCrl\n");
480 return NULL((void*)0);
481 }
482
483 mark = PORT_ArenaMarkPORT_ArenaMark_Util(arena);
484
485 signCrl = PORT_ArenaZNew(arena, CERTSignedCrl)(CERTSignedCrl *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTSignedCrl
))
;
486 if (signCrl == NULL((void*)0)) {
487 SECU_PrintError(progName, "fail to allocate memory\n");
488 return NULL((void*)0);
489 }
490
491 dummy = SEC_ASN1EncodeIntegerSEC_ASN1EncodeInteger_Util(arena, &signCrl->crl.version,
492 SEC_CRL_VERSION_21);
493 /* set crl->version */
494 if (!dummy) {
495 SECU_PrintError(progName, "fail to create crl version data "
496 "container\n");
497 goto loser;
498 }
499
500 /* copy SECItem name from cert */
501 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &signCrl->crl.derName, &cert->derSubject);
502 if (rv != SECSuccess) {
503 SECU_PrintError(progName, "fail to duplicate der name from "
504 "certificate.\n");
505 goto loser;
506 }
507
508 /* copy CERTName name structure from cert issuer */
509 rv = CERT_CopyName(arena, &signCrl->crl.name, &cert->subject);
510 if (rv != SECSuccess) {
511 SECU_PrintError(progName, "fail to duplicate RD name from "
512 "certificate.\n");
513 goto loser;
514 }
515
516 rv = DER_EncodeTimeChoiceDER_EncodeTimeChoice_Util(arena, &signCrl->crl.lastUpdate, PR_Now());
517 if (rv != SECSuccess) {
518 SECU_PrintError(progName, "fail to encode current time\n");
519 goto loser;
520 }
521
522 /* set fields */
523 signCrl->arena = arena;
524 signCrl->dbhandle = certHandle;
525 signCrl->crl.arena = arena;
526
527 PORT_ArenaUnmarkPORT_ArenaUnmark_Util(arena, mark);
528
529 return signCrl;
530
531loser:
532 PORT_ArenaReleasePORT_ArenaRelease_Util(arena, mark);
533 return NULL((void*)0);
534}
535
536static SECStatus
537UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile)
538{
539 CRLGENGeneratorData *crlGenData = NULL((void*)0);
540 SECStatus rv;
541
542 if (!signCrl || !inCrlInitFile) {
543 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
544 SECU_PrintError(progName, "invalid args for function "
545 "CreateNewCrl\n");
546 return SECFailure;
547 }
548
549 crlGenData = CRLGEN_InitCrlGeneration(signCrl, inCrlInitFile);
550 if (!crlGenData) {
551 SECU_PrintError(progName, "can not initialize parser structure.\n");
552 return SECFailure;
553 }
554
555 rv = CRLGEN_ExtHandleInit(crlGenData);
556 if (rv == SECFailure) {
557 SECU_PrintError(progName, "can not initialize entries handle.\n");
558 goto loser;
559 }
560
561 rv = CRLGEN_StartCrlGen(crlGenData);
562 if (rv != SECSuccess) {
563 SECU_PrintError(progName, "crl generation failed");
564 goto loser;
565 }
566
567loser:
568 /* CommitExtensionsAndEntries is partially responsible for freeing
569 * up memory that was used for CRL generation. Should be called regardless
570 * of previouse call status, but only after initialization of
571 * crlGenData was done. It will commit all changes that was done before
572 * an error has occurred.
573 */
574 if (SECSuccess != CRLGEN_CommitExtensionsAndEntries(crlGenData)) {
575 SECU_PrintError(progName, "crl generation failed");
576 rv = SECFailure;
577 }
578 CRLGEN_FinalizeCrlGeneration(crlGenData);
579 return rv;
580}
581
582static SECStatus
583SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert,
584 char *outFileName, SECOidTag hashAlgTag, int ascii,
585 char *slotName, char *url, secuPWData *pwdata)
586{
587 PK11SlotInfo *slot = NULL((void*)0);
588 PRFileDesc *outFile = NULL((void*)0);
589 SECStatus rv;
590 SignAndEncodeFuncExitStat errCode;
591
592 PORT_Assert(signCrl && (!ascii || outFileName))((signCrl && (!ascii || outFileName))?((void)0):PR_Assert
("signCrl && (!ascii || outFileName)","crlutil.c",592
))
;
593 if (!signCrl || (ascii && !outFileName)) {
594 SECU_PrintError(progName, "invalid args for function "
595 "SignAndStoreCrl\n");
596 return SECFailure;
597 }
598
599 if (!slotName || !PL_strcmp(slotName, "internal"))
600 slot = PK11_GetInternalKeySlot();
601 else
602 slot = PK11_FindSlotByName(slotName);
603 if (!slot) {
604 SECU_PrintError(progName, "can not find requested slot");
605 return SECFailure;
606 }
607
608 if (PK11_NeedLogin(slot)) {
609 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
610 if (rv != SECSuccess)
611 goto loser;
612 }
613
614 rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode);
615 if (rv != SECSuccess) {
616 char *errMsg = NULL((void*)0);
617 switch (errCode) {
618 case noKeyFound:
619 errMsg = "No private key found of signing cert";
620 break;
621
622 case noSignatureMatch:
623 errMsg = "Key and Algorithm OId are do not match";
624 break;
625
626 default:
627 case failToEncode:
628 errMsg = "Failed to encode crl structure";
629 break;
630
631 case failToSign:
632 errMsg = "Failed to sign crl structure";
633 break;
634
635 case noMem:
636 errMsg = "Can not allocate memory";
637 break;
638 }
639 SECU_PrintError(progName, "%s\n", errMsg);
640 goto loser;
641 }
642
643 if (outFileName) {
644 outFile = PR_Open(outFileName, PR_WRONLY0x02 | PR_CREATE_FILE0x08, PR_IRUSR00400 | PR_IWUSR00200);
645 if (!outFile) {
646 SECU_PrintError(progName, "unable to open \"%s\" for writing\n",
647 outFileName);
648 goto loser;
649 }
650 }
651
652 rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url);
653 if (rv != SECSuccess) {
654 SECU_PrintError(progName, "fail to save CRL\n");
655 }
656
657loser:
658 if (outFile)
659 PR_Close(outFile);
660 if (slot)
661 PK11_FreeSlot(slot);
662 return rv;
663}
664
665static SECStatus
666GenerateCRL(CERTCertDBHandle *certHandle, char *certNickName,
667 PRFileDesc *inCrlInitFile, PRFileDesc *inFile,
668 char *outFileName, int ascii, char *slotName,
669 PRInt32 importOptions, char *alg, PRBool quiet,
670 PRInt32 decodeOptions, char *url, secuPWData *pwdata,
671 int modifyFlag)
672{
673 CERTCertificate *cert = NULL((void*)0);
674 CERTSignedCrl *signCrl = NULL((void*)0);
675 PLArenaPool *arena = NULL((void*)0);
676 SECStatus rv;
677 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
678
679 if (alg) {
680 hashAlgTag = SECU_StringToSignatureAlgTag(alg);
681 if (hashAlgTag == SEC_OID_UNKNOWN) {
682 SECU_PrintError(progName, "%s -Z: %s is not a recognized type.\n",
683 progName, alg);
684 return SECFailure;
685 }
686 } else {
687 hashAlgTag = SEC_OID_UNKNOWN;
688 }
689
690 arena = PORT_NewArenaPORT_NewArena_Util(SEC_ASN1_DEFAULT_ARENA_SIZE(2048));
691 if (!arena) {
692 SECU_PrintError(progName, "fail to allocate memory\n");
693 return SECFailure;
694 }
695
696 if (modifyFlag == PR_TRUE1) {
697 signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName,
698 inFile, decodeOptions, importOptions,
699 pwdata);
700 if (signCrl == NULL((void*)0)) {
701 rv = SECFailure;
702 goto loser;
703 }
704 }
705
706 if (!cert) {
707 cert = FindSigningCert(certHandle, signCrl, certNickName);
708 if (cert == NULL((void*)0)) {
709 rv = SECFailure;
710 goto loser;
711 }
712 }
713
714 if (!signCrl) {
715 if (modifyFlag == PR_TRUE1) {
716 if (!outFileName) {
717 int len = strlen(certNickName) + 5;
718 outFileName = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, len);
719 PR_snprintf(outFileName, len, "%s.crl", certNickName);
720 }
721 SECU_PrintError(progName, "Will try to generate crl. "
722 "It will be saved in file: %s",
723 outFileName);
724 }
725 signCrl = CreateNewCrl(arena, certHandle, cert);
726 if (!signCrl) {
727 rv = SECFailure;
728 goto loser;
729 }
730 }
731
732 rv = UpdateCrl(signCrl, inCrlInitFile);
733 if (rv != SECSuccess) {
734 goto loser;
735 }
736
737 rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii,
738 slotName, url, pwdata);
739 if (rv != SECSuccess) {
740 goto loser;
741 }
742
743 if (signCrl && !quiet) {
744 SECU_PrintCRLInfo(stdoutstdout, &signCrl->crl, "CRL Info:\n", 0);
745 }
746
747loser:
748 if (arena && (!signCrl || !signCrl->arena))
749 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
750 if (signCrl)
751 SEC_DestroyCrl(signCrl);
752 if (cert)
753 CERT_DestroyCertificate(cert);
754 return (rv);
755}
756
757static void
758Usage()
759{
760 fprintf(stderrstderr,
761 "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n"
762 " %s -D -n nickname [-d keydir] [-P dbprefix]\n"
763 " %s -S -i crl\n"
764 " %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B] "
765 "[-p pwd-file] -w [pwd-string]\n"
766 " %s -E -t crlType [-d keydir] [-P dbprefix]\n"
767 " %s -T\n"
768 " %s -G|-M -c crl-init-file -n nickname [-i crl] [-u url] "
769 "[-d keydir] [-P dbprefix] [-Z alg] ] [-p pwd-file] -w [pwd-string] "
770 "[-a] [-B]\n",
771 progName, progName, progName, progName, progName, progName, progName);
772
773 fprintf(stderrstderr, "%-15s List CRL\n", "-L");
774 fprintf(stderrstderr, "%-20s Specify the nickname of the CA certificate\n",
775 "-n nickname");
776 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
777 "-d keydir");
778 fprintf(stderrstderr, "%-20s Cert & Key database prefix (default is \"\")\n",
779 "-P dbprefix");
780
781 fprintf(stderrstderr, "%-15s Delete a CRL from the cert database\n", "-D");
782 fprintf(stderrstderr, "%-20s Specify the nickname for the CA certificate\n",
783 "-n nickname");
784 fprintf(stderrstderr, "%-20s Specify the crl type.\n", "-t crlType");
785 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
786 "-d keydir");
787 fprintf(stderrstderr, "%-20s Cert & Key database prefix (default is \"\")\n",
788 "-P dbprefix");
789
790 fprintf(stderrstderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E");
791 fprintf(stderrstderr, "%-20s Specify the crl type.\n", "-t crlType");
792 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
793 "-d keydir");
794 fprintf(stderrstderr, "%-20s Cert & Key database prefix (default is \"\")\n",
795 "-P dbprefix");
796
797 fprintf(stderrstderr, "%-15s Show contents of a CRL file (without database)\n", "-S");
798 fprintf(stderrstderr, "%-20s Specify the file which contains the CRL to show\n",
799 "-i crl");
800
801 fprintf(stderrstderr, "%-15s Import a CRL to the cert database\n", "-I");
802 fprintf(stderrstderr, "%-20s Specify the file which contains the CRL to import\n",
803 "-i crl");
804 fprintf(stderrstderr, "%-20s Specify the url.\n", "-u url");
805 fprintf(stderrstderr, "%-20s Specify the crl type.\n", "-t crlType");
806 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
807 "-d keydir");
808 fprintf(stderrstderr, "%-20s Cert & Key database prefix (default is \"\")\n",
809 "-P dbprefix");
810#ifdef DEBUG1
811 fprintf(stderrstderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T");
812#endif
813 fprintf(stderrstderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " ");
814 fprintf(stderrstderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " ");
815 fprintf(stderrstderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " ");
816 fprintf(stderrstderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
817 fprintf(stderrstderr, "\n%-20s Partial decode for faster operation.\n", "-p");
818 fprintf(stderrstderr, "%-20s Repeat the operation.\n", "-r <iterations>");
819 fprintf(stderrstderr, "\n%-15s Create CRL\n", "-G");
820 fprintf(stderrstderr, "%-15s Modify CRL\n", "-M");
821 fprintf(stderrstderr, "%-20s Specify crl initialization file\n",
822 "-c crl-conf-file");
823 fprintf(stderrstderr, "%-20s Specify the nickname of the CA certificate\n",
824 "-n nickname");
825 fprintf(stderrstderr, "%-20s Specify the file which contains the CRL to import\n",
826 "-i crl");
827 fprintf(stderrstderr, "%-20s Specify a CRL output file\n",
828 "-o crl-output-file");
829 fprintf(stderrstderr, "%-20s Specify to use base64 encoded CRL output format\n",
830 "-a");
831 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
832 "-d keydir");
833 fprintf(stderrstderr, "%-20s Provide path to a default pwd file\n",
834 "-f pwd-file");
835 fprintf(stderrstderr, "%-20s Provide db password in command line\n",
836 "-w pwd-string");
837 fprintf(stderrstderr, "%-20s Cert & Key database prefix (default is \"\")\n",
838 "-P dbprefix");
839 fprintf(stderrstderr, "%-20s Specify the url.\n", "-u url");
840 fprintf(stderrstderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
841
842 exit(-1);
843}
844
845int
846main(int argc, char **argv)
847{
848 CERTCertDBHandle *certHandle;
849 PRFileDesc *inFile;
850 PRFileDesc *inCrlInitFile = NULL((void*)0);
851 int generateCRL;
852 int modifyCRL;
853 int listCRL;
854 int importCRL;
855 int showFileCRL;
856 int deleteCRL;
857 int rv;
858 char *nickName;
859 char *url;
860 char *dbPrefix = PORT_StrdupPORT_Strdup_Util("");
861 char *alg = NULL((void*)0);
862 char *outFile = NULL((void*)0);
863 char *slotName = NULL((void*)0);
864 int ascii = 0;
865 int crlType;
866 PLOptState *optstate;
867 PLOptStatus status;
868 SECStatus secstatus;
869 PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS0x00000000;
870 PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS0x00000000;
871 PRBool quiet = PR_FALSE0;
872 PRBool test = PR_FALSE0;
873 PRBool erase = PR_FALSE0;
874 PRInt32 i = 0;
875 PRInt32 iterations = 1;
876 PRBool readonly = PR_FALSE0;
877
878 secuPWData pwdata = { PW_NONE, 0 };
879
880 progName = strrchr(argv[0], '/');
881 progName = progName ? progName + 1 : argv[0];
882
883 rv = 0;
884 deleteCRL = importCRL = listCRL = generateCRL = modifyCRL = showFileCRL = 0;
885 inFile = NULL((void*)0);
886 nickName = url = NULL((void*)0);
887 certHandle = NULL((void*)0);
888 crlType = SEC_CRL_TYPE1;
889 /*
890 * Parse command line arguments
891 */
892 optstate = PL_CreateOptState(argc, argv, "sqBCDGILMSTEP:f:d:i:h:n:p:t:u:r:aZ:o:c:");
893 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status'
894 switch (optstate->option) {
895 case '?':
896 Usage();
897 break;
898
899 case 'T':
900 test = PR_TRUE1;
901 break;
902
903 case 'E':
904 erase = PR_TRUE1;
905 break;
906
907 case 'B':
908 importOptions |= CRL_IMPORT_BYPASS_CHECKS0x00000001;
909 break;
910
911 case 'G':
912 generateCRL = 1;
913 break;
914
915 case 'M':
916 modifyCRL = 1;
917 break;
918
919 case 'D':
920 deleteCRL = 1;
921 break;
922
923 case 'I':
924 importCRL = 1;
925 break;
926
927 case 'S':
928 showFileCRL = 1;
929 break;
930
931 case 'C':
932 case 'L':
933 listCRL = 1;
934 break;
935
936 case 'P':
937 PORT_FreePORT_Free_Util(dbPrefix);
938 dbPrefix = PORT_StrdupPORT_Strdup_Util(optstate->value);
939 break;
940
941 case 'Z':
942 alg = PORT_StrdupPORT_Strdup_Util(optstate->value);
943 break;
944
945 case 'a':
946 ascii = 1;
947 break;
948
949 case 'c':
950 inCrlInitFile = PR_Open(optstate->value, PR_RDONLY0x01, 0);
951 if (!inCrlInitFile) {
952 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: unable to open \"%s\" for reading\n",
953 progName, optstate->value);
954 rv = SECFailure;
955 goto loser;
956 }
957 break;
958
959 case 'd':
960 SECU_ConfigDirectory(optstate->value);
961 break;
962
963 case 'f':
964 pwdata.source = PW_FROMFILE;
965 pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value);
966 break;
967
968 case 'h':
969 slotName = PORT_StrdupPORT_Strdup_Util(optstate->value);
970 break;
971
972 case 'i':
973 inFile = PR_Open(optstate->value, PR_RDONLY0x01, 0);
974 if (!inFile) {
975 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: unable to open \"%s\" for reading\n",
976 progName, optstate->value);
977 rv = SECFailure;
978 goto loser;
979 }
980 break;
981
982 case 'n':
983 nickName = PORT_StrdupPORT_Strdup_Util(optstate->value);
984 break;
985
986 case 'o':
987 outFile = PORT_StrdupPORT_Strdup_Util(optstate->value);
988 break;
989
990 case 'p':
991 decodeOptions |= CRL_DECODE_SKIP_ENTRIES0x00000002;
992 break;
993
994 case 'r': {
995 const char *str = optstate->value;
996 if (str && atoi(str) > 0)
997 iterations = atoi(str);
998 } break;
999
1000 case 't': {
1001 crlType = atoi(optstate->value);
1002 if (crlType != SEC_CRL_TYPE1 && crlType != SEC_KRL_TYPE0) {
1003 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: invalid crl type\n", progName);
1004 rv = SECFailure;
1005 goto loser;
1006 }
1007 break;
1008
1009 case 'q':
1010 quiet = PR_TRUE1;
1011 break;
1012
1013 case 'w':
1014 pwdata.source = PW_PLAINTEXT;
1015 pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value);
1016 break;
1017
1018 case 'u':
1019 url = PORT_StrdupPORT_Strdup_Util(optstate->value);
1020 break;
1021 }
1022 }
1023 }
1024
1025 if (deleteCRL && !nickName)
1026 Usage();
1027 if (importCRL && !inFile)
1028 Usage();
1029 if (showFileCRL && !inFile)
1030 Usage();
1031 if ((generateCRL && !nickName) ||
1032 (modifyCRL && !inFile && !nickName))
1033 Usage();
1034 if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL ||
1035 modifyCRL || test || erase))
1036 Usage();
1037
1038 if (listCRL || showFileCRL) {
1039 readonly = PR_TRUE1;
1040 }
1041
1042 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
1043
1044 PK11_SetPasswordFunc(SECU_GetModulePassword);
1045
1046 if (showFileCRL) {
1047 rv = NSS_NoDB_Init(NULL((void*)0));
1048 if (rv != SECSuccess) {
1049 goto loser;
1050 }
1051 } else {
1052 secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL((void*)0)), dbPrefix, dbPrefix,
1053 "secmod.db", readonly ? NSS_INIT_READONLY0x1 : 0);
1054 if (secstatus != SECSuccess) {
1055 SECU_PrintPRandOSError(progName);
1056 rv = SECFailure;
1057 goto loser;
1058 }
1059 }
1060
1061 SECU_RegisterDynamicOids();
1062
1063 certHandle = CERT_GetDefaultCertDB();
1064 if (certHandle == NULL((void*)0)) {
1065 SECU_PrintError(progName, "unable to open the cert db");
1066 rv = SECFailure;
1067 goto loser;
1068 }
1069
1070 CRLGEN_InitCrlGenParserLock();
1071
1072 for (i = 0; i < iterations; i++) {
1073 /* Read in the private key info */
1074 if (deleteCRL)
1075 DeleteCRL(certHandle, nickName, crlType);
1076 else if (listCRL) {
1077 rv = ListCRL(certHandle, nickName, crlType);
1078 } else if (importCRL) {
1079 rv = ImportCRL(certHandle, url, crlType, inFile, importOptions,
1080 decodeOptions, &pwdata);
1081 } else if (showFileCRL) {
1082 rv = DumpCRL(inFile);
1083 } else if (generateCRL || modifyCRL) {
1084 if (!inCrlInitFile)
1085 inCrlInitFile = PR_STDINPR_GetSpecialFD(PR_StandardInput);
1086 rv = GenerateCRL(certHandle, nickName, inCrlInitFile,
1087 inFile, outFile, ascii, slotName,
1088 importOptions, alg, quiet,
1089 decodeOptions, url, &pwdata,
1090 modifyCRL);
1091 } else if (erase) {
1092 /* list and delete all CRLs */
1093 ListCRLNames(certHandle, crlType, PR_TRUE1);
1094 }
1095#ifdef DEBUG1
1096 else if (test) {
1097 /* list and delete all CRLs */
1098 ListCRLNames(certHandle, crlType, PR_TRUE1);
1099 /* list CRLs */
1100 ListCRLNames(certHandle, crlType, PR_FALSE0);
1101 /* import CRL as a blob */
1102 rv = ImportCRL(certHandle, url, crlType, inFile, importOptions,
1103 decodeOptions, &pwdata);
1104 /* list CRLs */
1105 ListCRLNames(certHandle, crlType, PR_FALSE0);
1106 }
1107#endif
1108 }
1109
1110 CRLGEN_DestroyCrlGenParserLock();
1111
1112loser:
1113 PL_DestroyOptState(optstate);
1114
1115 if (inFile) {
1116 PR_Close(inFile);
1117 }
1118 if (alg) {
1119 PORT_FreePORT_Free_Util(alg);
1120 }
1121 if (slotName) {
1122 PORT_FreePORT_Free_Util(slotName);
1123 }
1124 if (nickName) {
1125 PORT_FreePORT_Free_Util(nickName);
1126 }
1127 if (outFile) {
1128 PORT_FreePORT_Free_Util(outFile);
1129 }
1130 if (url) {
1131 PORT_FreePORT_Free_Util(url);
1132 }
1133 if (pwdata.data) {
1134 PORT_FreePORT_Free_Util(pwdata.data);
1135 }
1136
1137 PORT_FreePORT_Free_Util(dbPrefix);
1138
1139 if (NSS_Shutdown() != SECSuccess) {
1140 rv = SECFailure;
1141 }
1142
1143 return (rv != SECSuccess);
1144}