crlutil.c (35140B)
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_EXISTS 0 24 #define SEC_CREATE_CERT_DB 1 25 26 static char *progName; 27 28 static CERTSignedCrl * 29 FindCRL(CERTCertDBHandle *certHandle, char *name, int type) 30 { 31 CERTSignedCrl *crl = NULL; 32 CERTCertificate *cert = NULL; 33 SECItem derName; 34 35 derName.data = NULL; 36 derName.len = 0; 37 38 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name); 39 if (!cert) { 40 CERTName *certName = NULL; 41 PLArenaPool *arena = NULL; 42 SECStatus rv = SECSuccess; 43 44 certName = CERT_AsciiToName(name); 45 if (certName) { 46 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 47 if (arena) { 48 SECItem *nameItem = 49 SEC_ASN1EncodeItem(arena, NULL, (void *)certName, 50 SEC_ASN1_GET(CERT_NameTemplate)); 51 if (nameItem) { 52 rv = SECITEM_CopyItem(NULL, &derName, nameItem); 53 } 54 PORT_FreeArena(arena, PR_FALSE); 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); 62 } 63 64 if (!derName.len || !derName.data) { 65 SECU_PrintError(progName, "could not find certificate named '%s'", name); 66 return ((CERTSignedCrl *)NULL); 67 } 68 } else { 69 SECStatus rv = SECITEM_CopyItem(NULL, &derName, &cert->derSubject); 70 CERT_DestroyCertificate(cert); 71 if (rv != SECSuccess) { 72 return ((CERTSignedCrl *)NULL); 73 } 74 } 75 76 crl = SEC_FindCrlByName(certHandle, &derName, type); 77 if (crl == NULL) 78 SECU_PrintError(progName, "could not find %s's CRL", name); 79 if (derName.data) { 80 SECITEM_FreeItem(&derName, PR_FALSE); 81 } 82 return (crl); 83 } 84 85 static SECStatus 86 DisplayCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType) 87 { 88 CERTSignedCrl *crl = NULL; 89 90 crl = FindCRL(certHandle, nickName, crlType); 91 92 if (crl) { 93 SECU_PrintCRLInfo(stdout, &crl->crl, "CRL Info:\n", 0); 94 SEC_DestroyCrl(crl); 95 return SECSuccess; 96 } 97 return SECFailure; 98 } 99 100 static void 101 ListCRLNames(CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls) 102 { 103 CERTCrlHeadNode *crlList = NULL; 104 CERTCrlNode *crlNode = NULL; 105 CERTName *name = NULL; 106 PLArenaPool *arena = NULL; 107 SECStatus rv; 108 109 do { 110 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 111 if (arena == NULL) { 112 fprintf(stderr, "%s: fail to allocate memory\n", progName); 113 break; 114 } 115 116 name = PORT_ArenaZAlloc(arena, sizeof(*name)); 117 if (name == NULL) { 118 fprintf(stderr, "%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(stderr, "%s: fail to look up CRLs (%s)\n", progName, 126 SECU_Strerror(PORT_GetError())); 127 break; 128 } 129 130 /* just in case */ 131 if (!crlList) 132 break; 133 134 crlNode = crlList->first; 135 136 fprintf(stdout, "\n"); 137 fprintf(stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type"); 138 while (crlNode) { 139 char *asciiname = NULL; 140 CERTCertificate *cert = NULL; 141 if (crlNode->crl && crlNode->crl->crl.derName.data != NULL) { 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; 151 if (cert->nickname && PORT_Strlen(cert->nickname) > 0) { 152 certName = cert->nickname; 153 } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) { 154 certName = cert->emailAddr; 155 } 156 if (certName) { 157 asciiname = PORT_Strdup(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(stdout, "%-40s %-5s\n", asciiname, "CRL"); 172 if (asciiname) { 173 PORT_Free(asciiname); 174 } 175 if (PR_TRUE == deletecrls) { 176 CERTSignedCrl *acrl = NULL; 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_FreeArena(crlList->arena, PR_FALSE); 190 PORT_FreeArena(arena, PR_FALSE); 191 } 192 193 static SECStatus 194 ListCRL(CERTCertDBHandle *certHandle, char *nickName, int crlType) 195 { 196 if (nickName == NULL) { 197 ListCRLNames(certHandle, crlType, PR_FALSE); 198 return SECSuccess; 199 } 200 201 return DisplayCRL(certHandle, nickName, crlType); 202 } 203 204 static SECStatus 205 DeleteCRL(CERTCertDBHandle *certHandle, char *name, int type) 206 { 207 CERTSignedCrl *crl = NULL; 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())); 221 return SECFailure; 222 } 223 return (rv); 224 } 225 226 SECStatus 227 ImportCRL(CERTCertDBHandle *certHandle, char *url, int type, 228 PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions, 229 secuPWData *pwdata) 230 { 231 CERTSignedCrl *crl = NULL; 232 SECItem crlDER; 233 PK11SlotInfo *slot = NULL; 234 int rv; 235 236 crlDER.data = NULL; 237 238 /* Read in the entire file specified with the -f argument */ 239 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 240 if (rv != SECSuccess) { 241 SECU_PrintError(progName, "unable to read input file"); 242 return (SECFailure); 243 } 244 245 decodeOptions |= CRL_DECODE_DONT_COPY_DER; 246 247 slot = PK11_GetInternalKeySlot(); 248 249 if (PK11_NeedLogin(slot)) { 250 rv = PK11_Authenticate(slot, PR_TRUE, pwdata); 251 if (rv != SECSuccess) 252 goto loser; 253 } 254 255 crl = PK11_ImportCRL(slot, &crlDER, url, type, 256 NULL, importOptions, NULL, decodeOptions); 257 258 if (!crl) { 259 const char *errString; 260 261 rv = SECFailure; 262 errString = SECU_Strerror(PORT_GetError()); 263 if (errString && PORT_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 } 271 loser: 272 if (slot) { 273 PK11_FreeSlot(slot); 274 } 275 SECITEM_FreeItem(&crlDER, PR_FALSE); 276 return (rv); 277 } 278 279 SECStatus 280 DumpCRL(PRFileDesc *inFile) 281 { 282 int rv; 283 PLArenaPool *arena = NULL; 284 CERTSignedCrl *newCrl = NULL; 285 286 SECItem crlDER; 287 crlDER.data = NULL; 288 289 /* Read in the entire file specified with the -f argument */ 290 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 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_NewArena(DER_DEFAULT_CHUNKSIZE); 298 if (!arena) 299 return rv; 300 301 newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE, 302 CRL_DECODE_DEFAULT_OPTIONS); 303 if (!newCrl) 304 return SECFailure; 305 306 SECU_PrintCRLInfo(stdout, &newCrl->crl, "CRL file contents", 0); 307 308 PORT_FreeArena(arena, PR_FALSE); 309 return rv; 310 } 311 312 static CERTCertificate * 313 FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl, 314 char *certNickName) 315 { 316 CERTCertificate *cert = NULL, *certTemp = NULL; 317 SECStatus rv = SECFailure; 318 CERTAuthKeyID *authorityKeyID = NULL; 319 SECItem *subject = NULL; 320 321 PORT_Assert(certHandle != NULL); 322 if (!certHandle || (!signCrl && !certNickName)) { 323 SECU_PrintError(progName, "invalid args for function " 324 "FindSigningCert \n"); 325 return NULL; 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 353 loser: 354 if (certTemp) 355 CERT_DestroyCertificate(certTemp); 356 if (cert && rv != SECSuccess) 357 CERT_DestroyCertificate(cert); 358 return cert; 359 } 360 361 static CERTSignedCrl * 362 CreateModifiedCRLCopy(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, 0 }; 368 CERTSignedCrl *signCrl = NULL; 369 CERTSignedCrl *modCrl = NULL; 370 PLArenaPool *modArena = NULL; 371 SECStatus rv = SECSuccess; 372 373 if (!arena || !certHandle || !certNickName) { 374 PORT_SetError(SEC_ERROR_INVALID_ARGS); 375 SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n"); 376 return NULL; 377 } 378 379 modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 380 if (!modArena) { 381 SECU_PrintError(progName, "fail to allocate memory\n"); 382 return NULL; 383 } 384 385 if (inFile != NULL) { 386 rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 387 if (rv != SECSuccess) { 388 SECU_PrintError(progName, "unable to read input file"); 389 goto loser; 390 } 391 392 decodeOptions |= CRL_DECODE_DONT_COPY_DER; 393 394 modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE, 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_CHECKS)) { 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); 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_TYPE); 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); 426 if (signCrl == NULL) { 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_EncodeTimeChoice(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 449 loser: 450 if (crlDER.data) { 451 SECITEM_FreeItem(&crlDER, PR_FALSE); 452 } 453 if (modArena && (!modCrl || modCrl->arena != modArena)) { 454 PORT_FreeArena(modArena, PR_FALSE); 455 } 456 if (modCrl) 457 SEC_DestroyCrl(modCrl); 458 if (rv != SECSuccess && signCrl) { 459 SEC_DestroyCrl(signCrl); 460 signCrl = NULL; 461 } 462 return signCrl; 463 } 464 465 static CERTSignedCrl * 466 CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle, 467 CERTCertificate *cert) 468 { 469 CERTSignedCrl *signCrl = NULL; 470 void *dummy = NULL; 471 SECStatus rv; 472 void *mark = NULL; 473 474 /* if the CERTSignedCrl structure changes, this function will need to be 475 updated as well */ 476 if (!cert || !arena) { 477 PORT_SetError(SEC_ERROR_INVALID_ARGS); 478 SECU_PrintError(progName, "invalid args for function " 479 "CreateNewCrl\n"); 480 return NULL; 481 } 482 483 mark = PORT_ArenaMark(arena); 484 485 signCrl = PORT_ArenaZNew(arena, CERTSignedCrl); 486 if (signCrl == NULL) { 487 SECU_PrintError(progName, "fail to allocate memory\n"); 488 return NULL; 489 } 490 491 dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version, 492 SEC_CRL_VERSION_2); 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_CopyItem(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_EncodeTimeChoice(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_ArenaUnmark(arena, mark); 528 529 return signCrl; 530 531 loser: 532 PORT_ArenaRelease(arena, mark); 533 return NULL; 534 } 535 536 static SECStatus 537 UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile) 538 { 539 CRLGENGeneratorData *crlGenData = NULL; 540 SECStatus rv; 541 542 if (!signCrl || !inCrlInitFile) { 543 PORT_SetError(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 567 loser: 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 582 static SECStatus 583 SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert, 584 char *outFileName, SECOidTag hashAlgTag, int ascii, 585 char *slotName, char *url, secuPWData *pwdata) 586 { 587 PK11SlotInfo *slot = NULL; 588 PRFileDesc *outFile = NULL; 589 SECStatus rv; 590 SignAndEncodeFuncExitStat errCode; 591 592 PORT_Assert(signCrl && (!ascii || outFileName)); 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_TRUE, 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; 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_WRONLY | PR_CREATE_FILE, PR_IRUSR | PR_IWUSR); 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 657 loser: 658 if (outFile) 659 PR_Close(outFile); 660 if (slot) 661 PK11_FreeSlot(slot); 662 return rv; 663 } 664 665 static SECStatus 666 GenerateCRL(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; 674 CERTSignedCrl *signCrl = NULL; 675 PLArenaPool *arena = NULL; 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_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 691 if (!arena) { 692 SECU_PrintError(progName, "fail to allocate memory\n"); 693 return SECFailure; 694 } 695 696 if (modifyFlag == PR_TRUE) { 697 signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName, 698 inFile, decodeOptions, importOptions, 699 pwdata); 700 if (signCrl == NULL) { 701 rv = SECFailure; 702 goto loser; 703 } 704 } 705 706 if (!cert) { 707 cert = FindSigningCert(certHandle, signCrl, certNickName); 708 if (cert == NULL) { 709 rv = SECFailure; 710 goto loser; 711 } 712 } 713 714 if (!signCrl) { 715 if (modifyFlag == PR_TRUE) { 716 if (!outFileName) { 717 int len = strlen(certNickName) + 5; 718 outFileName = PORT_ArenaAlloc(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(stdout, &signCrl->crl, "CRL Info:\n", 0); 745 } 746 747 loser: 748 if (arena && (!signCrl || !signCrl->arena)) 749 PORT_FreeArena(arena, PR_FALSE); 750 if (signCrl) 751 SEC_DestroyCrl(signCrl); 752 if (cert) 753 CERT_DestroyCertificate(cert); 754 return (rv); 755 } 756 757 static void 758 Usage() 759 { 760 fprintf(stderr, 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(stderr, "%-15s List CRL\n", "-L"); 774 fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n", 775 "-n nickname"); 776 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 777 "-d keydir"); 778 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 779 "-P dbprefix"); 780 781 fprintf(stderr, "%-15s Delete a CRL from the cert database\n", "-D"); 782 fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n", 783 "-n nickname"); 784 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 785 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 786 "-d keydir"); 787 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 788 "-P dbprefix"); 789 790 fprintf(stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E"); 791 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 792 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 793 "-d keydir"); 794 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 795 "-P dbprefix"); 796 797 fprintf(stderr, "%-15s Show contents of a CRL file (without database)\n", "-S"); 798 fprintf(stderr, "%-20s Specify the file which contains the CRL to show\n", 799 "-i crl"); 800 801 fprintf(stderr, "%-15s Import a CRL to the cert database\n", "-I"); 802 fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n", 803 "-i crl"); 804 fprintf(stderr, "%-20s Specify the url.\n", "-u url"); 805 fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 806 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 807 "-d keydir"); 808 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 809 "-P dbprefix"); 810 #ifdef DEBUG 811 fprintf(stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T"); 812 #endif 813 fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " "); 814 fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " "); 815 fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " "); 816 fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B"); 817 fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p"); 818 fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>"); 819 fprintf(stderr, "\n%-15s Create CRL\n", "-G"); 820 fprintf(stderr, "%-15s Modify CRL\n", "-M"); 821 fprintf(stderr, "%-20s Specify crl initialization file\n", 822 "-c crl-conf-file"); 823 fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n", 824 "-n nickname"); 825 fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n", 826 "-i crl"); 827 fprintf(stderr, "%-20s Specify a CRL output file\n", 828 "-o crl-output-file"); 829 fprintf(stderr, "%-20s Specify to use base64 encoded CRL output format\n", 830 "-a"); 831 fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 832 "-d keydir"); 833 fprintf(stderr, "%-20s Provide path to a default pwd file\n", 834 "-f pwd-file"); 835 fprintf(stderr, "%-20s Provide db password in command line\n", 836 "-w pwd-string"); 837 fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 838 "-P dbprefix"); 839 fprintf(stderr, "%-20s Specify the url.\n", "-u url"); 840 fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B"); 841 842 exit(-1); 843 } 844 845 int 846 main(int argc, char **argv) 847 { 848 CERTCertDBHandle *certHandle; 849 PRFileDesc *inFile; 850 PRFileDesc *inCrlInitFile = NULL; 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_Strdup(""); 861 char *alg = NULL; 862 char *outFile = NULL; 863 char *slotName = NULL; 864 int ascii = 0; 865 int crlType; 866 PLOptState *optstate; 867 PLOptStatus status; 868 SECStatus secstatus; 869 PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS; 870 PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS; 871 PRBool quiet = PR_FALSE; 872 PRBool test = PR_FALSE; 873 PRBool erase = PR_FALSE; 874 PRInt32 i = 0; 875 PRInt32 iterations = 1; 876 PRBool readonly = PR_FALSE; 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; 886 nickName = url = NULL; 887 certHandle = NULL; 888 crlType = SEC_CRL_TYPE; 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) { 894 switch (optstate->option) { 895 case '?': 896 Usage(); 897 break; 898 899 case 'T': 900 test = PR_TRUE; 901 break; 902 903 case 'E': 904 erase = PR_TRUE; 905 break; 906 907 case 'B': 908 importOptions |= CRL_IMPORT_BYPASS_CHECKS; 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_Free(dbPrefix); 938 dbPrefix = PORT_Strdup(optstate->value); 939 break; 940 941 case 'Z': 942 alg = PORT_Strdup(optstate->value); 943 break; 944 945 case 'a': 946 ascii = 1; 947 break; 948 949 case 'c': 950 inCrlInitFile = PR_Open(optstate->value, PR_RDONLY, 0); 951 if (!inCrlInitFile) { 952 PR_fprintf(PR_STDERR, "%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_Strdup(optstate->value); 966 break; 967 968 case 'h': 969 slotName = PORT_Strdup(optstate->value); 970 break; 971 972 case 'i': 973 inFile = PR_Open(optstate->value, PR_RDONLY, 0); 974 if (!inFile) { 975 PR_fprintf(PR_STDERR, "%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_Strdup(optstate->value); 984 break; 985 986 case 'o': 987 outFile = PORT_Strdup(optstate->value); 988 break; 989 990 case 'p': 991 decodeOptions |= CRL_DECODE_SKIP_ENTRIES; 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_TYPE && crlType != SEC_KRL_TYPE) { 1003 PR_fprintf(PR_STDERR, "%s: invalid crl type\n", progName); 1004 rv = SECFailure; 1005 goto loser; 1006 } 1007 break; 1008 1009 case 'q': 1010 quiet = PR_TRUE; 1011 break; 1012 1013 case 'w': 1014 pwdata.source = PW_PLAINTEXT; 1015 pwdata.data = PORT_Strdup(optstate->value); 1016 break; 1017 1018 case 'u': 1019 url = PORT_Strdup(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_TRUE; 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); 1048 if (rv != SECSuccess) { 1049 goto loser; 1050 } 1051 } else { 1052 secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix, 1053 "secmod.db", readonly ? NSS_INIT_READONLY : 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) { 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_STDIN; 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_TRUE); 1094 } 1095 #ifdef DEBUG 1096 else if (test) { 1097 /* list and delete all CRLs */ 1098 ListCRLNames(certHandle, crlType, PR_TRUE); 1099 /* list CRLs */ 1100 ListCRLNames(certHandle, crlType, PR_FALSE); 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_FALSE); 1106 } 1107 #endif 1108 } 1109 1110 CRLGEN_DestroyCrlGenParserLock(); 1111 1112 loser: 1113 PL_DestroyOptState(optstate); 1114 1115 if (inFile) { 1116 PR_Close(inFile); 1117 } 1118 if (alg) { 1119 PORT_Free(alg); 1120 } 1121 if (slotName) { 1122 PORT_Free(slotName); 1123 } 1124 if (nickName) { 1125 PORT_Free(nickName); 1126 } 1127 if (outFile) { 1128 PORT_Free(outFile); 1129 } 1130 if (url) { 1131 PORT_Free(url); 1132 } 1133 if (pwdata.data) { 1134 PORT_Free(pwdata.data); 1135 } 1136 1137 PORT_Free(dbPrefix); 1138 1139 if (NSS_Shutdown() != SECSuccess) { 1140 rv = SECFailure; 1141 } 1142 1143 return (rv != SECSuccess); 1144 }