crlgen.c (47861B)
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 ** crlgen.c 7 ** 8 ** utility for managing certificates revocation lists generation 9 ** 10 */ 11 12 #include <stdio.h> 13 #include <math.h> 14 15 #include "nspr.h" 16 #include "plgetopt.h" 17 #include "nss.h" 18 #include "secutil.h" 19 #include "cert.h" 20 #include "certi.h" 21 #include "certdb.h" 22 #include "pk11func.h" 23 #include "crlgen.h" 24 25 /* Destroys extHandle and data. data was create on heap. 26 * extHandle creaded by CERT_StartCRLEntryExtensions. entry 27 * was allocated on arena.*/ 28 static void 29 destroyEntryData(CRLGENEntryData *data) 30 { 31 if (!data) 32 return; 33 PORT_Assert(data->entry); 34 if (data->extHandle) 35 CERT_FinishExtensions(data->extHandle); 36 PORT_Free(data); 37 } 38 39 /* Prints error messages along with line number */ 40 void 41 crlgen_PrintError(int line, char *msg, ...) 42 { 43 va_list args; 44 45 va_start(args, msg); 46 47 fprintf(stderr, "crlgen: (line: %d) ", line); 48 vfprintf(stderr, msg, args); 49 50 va_end(args); 51 } 52 /* Finds CRLGENEntryData in hashtable according PRUint64 value 53 * - certId : cert serial number*/ 54 static CRLGENEntryData * 55 crlgen_FindEntry(CRLGENGeneratorData *crlGenData, SECItem *certId) 56 { 57 if (!crlGenData->entryDataHashTable || !certId) 58 return NULL; 59 return (CRLGENEntryData *) 60 PL_HashTableLookup(crlGenData->entryDataHashTable, 61 certId); 62 } 63 64 /* Removes CRLGENEntryData from hashtable according to certId 65 * - certId : cert serial number*/ 66 static SECStatus 67 crlgen_RmEntry(CRLGENGeneratorData *crlGenData, SECItem *certId) 68 { 69 CRLGENEntryData *data = NULL; 70 SECStatus rv = SECSuccess; 71 72 if (!crlGenData->entryDataHashTable) { 73 return SECSuccess; 74 } 75 76 data = crlgen_FindEntry(crlGenData, certId); 77 if (!data) { 78 return SECSuccess; 79 } 80 81 if (!PL_HashTableRemove(crlGenData->entryDataHashTable, certId)) { 82 rv = SECFailure; 83 } 84 85 destroyEntryData(data); 86 return rv; 87 } 88 89 /* Stores CRLGENEntryData in hashtable according to certId 90 * - certId : cert serial number*/ 91 static CRLGENEntryData * 92 crlgen_PlaceAnEntry(CRLGENGeneratorData *crlGenData, 93 CERTCrlEntry *entry, SECItem *certId) 94 { 95 CRLGENEntryData *newData = NULL; 96 97 PORT_Assert(crlGenData && crlGenData->entryDataHashTable && 98 entry); 99 if (!crlGenData || !crlGenData->entryDataHashTable || !entry) { 100 PORT_SetError(SEC_ERROR_INVALID_ARGS); 101 return NULL; 102 } 103 104 newData = PORT_ZNew(CRLGENEntryData); 105 if (!newData) { 106 return NULL; 107 } 108 newData->entry = entry; 109 newData->certId = certId; 110 if (!PL_HashTableAdd(crlGenData->entryDataHashTable, 111 newData->certId, newData)) { 112 crlgen_PrintError(crlGenData->parsedLineNum, 113 "Can not add entryData structure\n"); 114 return NULL; 115 } 116 return newData; 117 } 118 119 /* Use this structure to keep pointer when commiting entries extensions */ 120 struct commitData { 121 int pos; 122 CERTCrlEntry **entries; 123 }; 124 125 /* HT PL_HashTableEnumerateEntries callback. Sorts hashtable entries of the 126 * table he. Returns value through arg parameter*/ 127 static PRIntn PR_CALLBACK 128 crlgen_CommitEntryData(PLHashEntry *he, PRIntn i, void *arg) 129 { 130 CRLGENEntryData *data = NULL; 131 132 PORT_Assert(he); 133 if (!he) { 134 return HT_ENUMERATE_NEXT; 135 } 136 data = (CRLGENEntryData *)he->value; 137 138 PORT_Assert(data); 139 PORT_Assert(arg); 140 141 if (data) { 142 struct commitData *dt = (struct commitData *)arg; 143 dt->entries[dt->pos++] = data->entry; 144 destroyEntryData(data); 145 } 146 return HT_ENUMERATE_NEXT; 147 } 148 149 /* Copy char * datainto allocated in arena SECItem */ 150 static SECStatus 151 crlgen_SetString(PLArenaPool *arena, const char *dataIn, SECItem *value) 152 { 153 SECItem item; 154 155 PORT_Assert(arena && dataIn); 156 if (!arena || !dataIn) { 157 PORT_SetError(SEC_ERROR_INVALID_ARGS); 158 return SECFailure; 159 } 160 161 item.data = (void *)dataIn; 162 item.len = PORT_Strlen(dataIn); 163 164 return SECITEM_CopyItem(arena, value, &item); 165 } 166 167 /* Creates CERTGeneralName from parsed data for the Authority Key Extension */ 168 static CERTGeneralName * 169 crlgen_GetGeneralName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData, 170 const char *data) 171 { 172 CERTGeneralName *namesList = NULL; 173 CERTGeneralName *current; 174 CERTGeneralName *tail = NULL; 175 SECStatus rv = SECSuccess; 176 const char *nextChunk = NULL; 177 const char *currData = NULL; 178 int intValue; 179 char buffer[512]; 180 void *mark; 181 182 if (!data) 183 return NULL; 184 PORT_Assert(arena); 185 if (!arena) { 186 PORT_SetError(SEC_ERROR_INVALID_ARGS); 187 return NULL; 188 } 189 190 mark = PORT_ArenaMark(arena); 191 192 currData = data; 193 do { 194 int nameLen = 0; 195 char name[128]; 196 const char *sepPrt = NULL; 197 nextChunk = PORT_Strchr(currData, '|'); 198 if (!nextChunk) 199 nextChunk = data + strlen(data); 200 sepPrt = PORT_Strchr(currData, ':'); 201 if (sepPrt == NULL || sepPrt >= nextChunk) { 202 *buffer = '\0'; 203 sepPrt = nextChunk; 204 } else { 205 PORT_Memcpy(buffer, sepPrt + 1, 206 (nextChunk - sepPrt - 1)); 207 buffer[nextChunk - sepPrt - 1] = '\0'; 208 } 209 nameLen = PR_MIN(sepPrt - currData, sizeof(name) - 1); 210 PORT_Memcpy(name, currData, nameLen); 211 name[nameLen] = '\0'; 212 currData = nextChunk + 1; 213 214 if (!PORT_Strcmp(name, "otherName")) 215 intValue = certOtherName; 216 else if (!PORT_Strcmp(name, "rfc822Name")) 217 intValue = certRFC822Name; 218 else if (!PORT_Strcmp(name, "dnsName")) 219 intValue = certDNSName; 220 else if (!PORT_Strcmp(name, "x400Address")) 221 intValue = certX400Address; 222 else if (!PORT_Strcmp(name, "directoryName")) 223 intValue = certDirectoryName; 224 else if (!PORT_Strcmp(name, "ediPartyName")) 225 intValue = certEDIPartyName; 226 else if (!PORT_Strcmp(name, "URI")) 227 intValue = certURI; 228 else if (!PORT_Strcmp(name, "ipAddress")) 229 intValue = certIPAddress; 230 else if (!PORT_Strcmp(name, "registerID")) 231 intValue = certRegisterID; 232 else 233 intValue = -1; 234 235 if (intValue >= certOtherName && intValue <= certRegisterID) { 236 if (namesList == NULL) { 237 namesList = current = tail = PORT_ArenaZNew(arena, 238 CERTGeneralName); 239 } else { 240 current = PORT_ArenaZNew(arena, CERTGeneralName); 241 } 242 if (current == NULL) { 243 rv = SECFailure; 244 break; 245 } 246 } else { 247 PORT_SetError(SEC_ERROR_INVALID_ARGS); 248 break; 249 } 250 current->type = intValue; 251 switch (current->type) { 252 case certURI: 253 case certDNSName: 254 case certRFC822Name: 255 current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer)); 256 if (current->name.other.data == NULL) { 257 rv = SECFailure; 258 break; 259 } 260 PORT_Memcpy(current->name.other.data, buffer, 261 current->name.other.len = strlen(buffer)); 262 break; 263 264 case certEDIPartyName: 265 case certIPAddress: 266 case certOtherName: 267 case certRegisterID: 268 case certX400Address: { 269 270 current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer) + 2); 271 if (current->name.other.data == NULL) { 272 rv = SECFailure; 273 break; 274 } 275 276 PORT_Memcpy(current->name.other.data + 2, buffer, strlen(buffer)); 277 /* This may not be accurate for all cases.For now, use this tag type */ 278 current->name.other.data[0] = (char)(((current->type - 1) & 0x1f) | 0x80); 279 current->name.other.data[1] = (char)strlen(buffer); 280 current->name.other.len = strlen(buffer) + 2; 281 break; 282 } 283 284 case certDirectoryName: { 285 CERTName *directoryName = NULL; 286 287 directoryName = CERT_AsciiToName(buffer); 288 if (!directoryName) { 289 rv = SECFailure; 290 break; 291 } 292 293 rv = CERT_CopyName(arena, ¤t->name.directoryName, directoryName); 294 CERT_DestroyName(directoryName); 295 296 break; 297 } 298 } 299 if (rv != SECSuccess) 300 break; 301 current->l.next = &(namesList->l); 302 current->l.prev = &(tail->l); 303 tail->l.next = &(current->l); 304 tail = current; 305 306 } while (nextChunk != data + strlen(data)); 307 308 if (rv != SECSuccess) { 309 PORT_ArenaRelease(arena, mark); 310 namesList = NULL; 311 } 312 return (namesList); 313 } 314 315 /* Creates CERTGeneralName from parsed data for the Authority Key Extension */ 316 static CERTGeneralName * 317 crlgen_DistinguishedName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData, 318 const char *data) 319 { 320 CERTName *directoryName = NULL; 321 CERTGeneralName *current; 322 SECStatus rv = SECFailure; 323 void *mark; 324 325 if (!data) 326 return NULL; 327 PORT_Assert(arena); 328 if (!arena) { 329 PORT_SetError(SEC_ERROR_INVALID_ARGS); 330 return NULL; 331 } 332 333 mark = PORT_ArenaMark(arena); 334 335 current = PORT_ArenaZNew(arena, CERTGeneralName); 336 if (current == NULL) { 337 goto loser; 338 } 339 current->type = certDirectoryName; 340 current->l.next = ¤t->l; 341 current->l.prev = ¤t->l; 342 343 directoryName = CERT_AsciiToName((char *)data); 344 if (!directoryName) { 345 goto loser; 346 } 347 348 rv = CERT_CopyName(arena, ¤t->name.directoryName, directoryName); 349 CERT_DestroyName(directoryName); 350 351 loser: 352 if (rv != SECSuccess) { 353 PORT_SetError(rv); 354 PORT_ArenaRelease(arena, mark); 355 current = NULL; 356 } 357 return (current); 358 } 359 360 /* Adding Authority Key ID extension to extension handle. */ 361 static SECStatus 362 crlgen_AddAuthKeyID(CRLGENGeneratorData *crlGenData, 363 const char **dataArr) 364 { 365 void *extHandle = NULL; 366 CERTAuthKeyID *authKeyID = NULL; 367 PLArenaPool *arena = NULL; 368 SECStatus rv = SECSuccess; 369 370 PORT_Assert(dataArr && crlGenData); 371 if (!crlGenData || !dataArr) { 372 return SECFailure; 373 } 374 375 extHandle = crlGenData->crlExtHandle; 376 377 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) { 378 PORT_SetError(SEC_ERROR_INVALID_ARGS); 379 crlgen_PrintError(crlGenData->parsedLineNum, 380 "insufficient number of parameters.\n"); 381 return SECFailure; 382 } 383 384 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 385 if (!arena) { 386 return SECFailure; 387 } 388 389 authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID); 390 if (authKeyID == NULL) { 391 rv = SECFailure; 392 goto loser; 393 } 394 395 if (dataArr[3] == NULL) { 396 rv = crlgen_SetString(arena, dataArr[2], &authKeyID->keyID); 397 if (rv != SECSuccess) 398 goto loser; 399 } else { 400 rv = crlgen_SetString(arena, dataArr[3], 401 &authKeyID->authCertSerialNumber); 402 if (rv != SECSuccess) 403 goto loser; 404 405 authKeyID->authCertIssuer = 406 crlgen_DistinguishedName(arena, crlGenData, dataArr[2]); 407 if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) { 408 crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n"); 409 rv = SECFailure; 410 goto loser; 411 } 412 } 413 414 rv = 415 SECU_EncodeAndAddExtensionValue(arena, extHandle, authKeyID, 416 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE, 417 SEC_OID_X509_AUTH_KEY_ID, 418 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAuthKeyID); 419 loser: 420 if (arena) 421 PORT_FreeArena(arena, PR_FALSE); 422 return rv; 423 } 424 425 /* Creates and add Subject Alternative Names extension */ 426 static SECStatus 427 crlgen_AddIssuerAltNames(CRLGENGeneratorData *crlGenData, 428 const char **dataArr) 429 { 430 CERTGeneralName *nameList = NULL; 431 PLArenaPool *arena = NULL; 432 void *extHandle = NULL; 433 SECStatus rv = SECSuccess; 434 435 PORT_Assert(dataArr && crlGenData); 436 if (!crlGenData || !dataArr) { 437 return SECFailure; 438 } 439 440 if (!dataArr || !dataArr[0] || !dataArr[1] || !dataArr[2]) { 441 PORT_SetError(SEC_ERROR_INVALID_ARGS); 442 crlgen_PrintError(crlGenData->parsedLineNum, 443 "insufficient number of arguments.\n"); 444 return SECFailure; 445 } 446 447 PORT_Assert(dataArr && crlGenData); 448 if (!crlGenData || !dataArr) { 449 return SECFailure; 450 } 451 452 extHandle = crlGenData->crlExtHandle; 453 454 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) { 455 PORT_SetError(SEC_ERROR_INVALID_ARGS); 456 crlgen_PrintError(crlGenData->parsedLineNum, 457 "insufficient number of parameters.\n"); 458 return SECFailure; 459 } 460 461 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 462 if (!arena) { 463 return SECFailure; 464 } 465 466 nameList = crlgen_GetGeneralName(arena, crlGenData, dataArr[2]); 467 if (nameList == NULL) { 468 crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n"); 469 rv = SECFailure; 470 goto loser; 471 } 472 473 rv = 474 SECU_EncodeAndAddExtensionValue(arena, extHandle, nameList, 475 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE, 476 SEC_OID_X509_ISSUER_ALT_NAME, 477 EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAltNameExtension); 478 loser: 479 if (arena) 480 PORT_FreeArena(arena, PR_FALSE); 481 return rv; 482 } 483 484 /* Creates and adds CRLNumber extension to extension handle. 485 * Since, this is CRL extension, extension handle is the one 486 * related to CRL extensions */ 487 static SECStatus 488 crlgen_AddCrlNumber(CRLGENGeneratorData *crlGenData, const char **dataArr) 489 { 490 PLArenaPool *arena = NULL; 491 SECItem encodedItem; 492 void *dummy; 493 SECStatus rv = SECFailure; 494 int code = 0; 495 496 PORT_Assert(dataArr && crlGenData); 497 if (!crlGenData || !dataArr) { 498 goto loser; 499 } 500 501 if (!dataArr[0] || !dataArr[1] || !dataArr[2]) { 502 PORT_SetError(SEC_ERROR_INVALID_ARGS); 503 crlgen_PrintError(crlGenData->parsedLineNum, 504 "insufficient number of arguments.\n"); 505 goto loser; 506 } 507 508 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 509 if (arena == NULL) { 510 goto loser; 511 } 512 513 code = atoi(dataArr[2]); 514 if (code == 0 && *dataArr[2] != '0') { 515 PORT_SetError(SEC_ERROR_INVALID_ARGS); 516 goto loser; 517 } 518 519 dummy = SEC_ASN1EncodeInteger(arena, &encodedItem, code); 520 if (!dummy) { 521 rv = SECFailure; 522 goto loser; 523 } 524 525 rv = CERT_AddExtension(crlGenData->crlExtHandle, SEC_OID_X509_CRL_NUMBER, 526 &encodedItem, 527 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE, 528 PR_TRUE); 529 530 loser: 531 if (arena) 532 PORT_FreeArena(arena, PR_FALSE); 533 return rv; 534 } 535 536 /* Creates Cert Revocation Reason code extension. Encodes it and 537 * returns as SECItem structure */ 538 static SECItem * 539 crlgen_CreateReasonCode(PLArenaPool *arena, const char **dataArr, 540 int *extCode) 541 { 542 SECItem *encodedItem; 543 void *dummy; 544 void *mark = NULL; 545 int code = 0; 546 547 PORT_Assert(arena && dataArr); 548 if (!arena || !dataArr) { 549 goto loser; 550 } 551 552 mark = PORT_ArenaMark(arena); 553 554 encodedItem = PORT_ArenaZNew(arena, SECItem); 555 if (encodedItem == NULL) { 556 goto loser; 557 } 558 559 if (dataArr[2] == NULL) { 560 PORT_SetError(SEC_ERROR_INVALID_ARGS); 561 goto loser; 562 } 563 564 code = atoi(dataArr[2]); 565 /* aACompromise(10) is the last possible of the values 566 * for the Reason Core Extension */ 567 if ((code == 0 && *dataArr[2] != '0') || code > 10) { 568 569 PORT_SetError(SEC_ERROR_INVALID_ARGS); 570 goto loser; 571 } 572 573 dummy = SEC_ASN1EncodeInteger(arena, encodedItem, code); 574 if (!dummy) { 575 goto loser; 576 } 577 578 *extCode = SEC_OID_X509_REASON_CODE; 579 return encodedItem; 580 581 loser: 582 if (mark) { 583 PORT_ArenaRelease(arena, mark); 584 } 585 return NULL; 586 } 587 588 /* Creates Cert Invalidity Date extension. Encodes it and 589 * returns as SECItem structure */ 590 static SECItem * 591 crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr, 592 int *extCode) 593 { 594 SECItem *encodedItem; 595 int length = 0; 596 void *mark = NULL; 597 598 PORT_Assert(arena && dataArr); 599 if (!arena || !dataArr) { 600 goto loser; 601 } 602 603 mark = PORT_ArenaMark(arena); 604 605 encodedItem = PORT_ArenaZNew(arena, SECItem); 606 if (encodedItem == NULL) { 607 goto loser; 608 } 609 610 length = PORT_Strlen(dataArr[2]); 611 612 encodedItem->type = siGeneralizedTime; 613 encodedItem->data = PORT_ArenaAlloc(arena, length); 614 if (!encodedItem->data) { 615 goto loser; 616 } 617 618 PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) * sizeof(char)); 619 620 *extCode = SEC_OID_X509_INVALID_DATE; 621 return encodedItem; 622 623 loser: 624 if (mark) { 625 PORT_ArenaRelease(arena, mark); 626 } 627 return NULL; 628 } 629 630 /* Creates(by calling extCreator function) and adds extension to a set 631 * of already added certs. Uses values of rangeFrom and rangeTo from 632 * CRLGENCrlGenCtl structure for identifying the inclusive set of certs */ 633 static SECStatus 634 crlgen_AddEntryExtension(CRLGENGeneratorData *crlGenData, 635 const char **dataArr, char *extName, 636 SECItem *(*extCreator)(PLArenaPool *arena, 637 const char **dataArr, 638 int *extCode)) 639 { 640 PRUint64 i = 0; 641 SECStatus rv = SECFailure; 642 int extCode = 0; 643 PRUint64 lastRange; 644 SECItem *ext = NULL; 645 PLArenaPool *arena = NULL; 646 647 PORT_Assert(crlGenData && dataArr); 648 if (!crlGenData || !dataArr) { 649 goto loser; 650 } 651 652 if (!dataArr[0] || !dataArr[1]) { 653 PORT_SetError(SEC_ERROR_INVALID_ARGS); 654 crlgen_PrintError(crlGenData->parsedLineNum, 655 "insufficient number of arguments.\n"); 656 } 657 658 lastRange = crlGenData->rangeTo - crlGenData->rangeFrom + 1; 659 660 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 661 if (arena == NULL) { 662 goto loser; 663 } 664 665 ext = extCreator(arena, dataArr, &extCode); 666 if (ext == NULL) { 667 crlgen_PrintError(crlGenData->parsedLineNum, 668 "got error while creating extension: %s\n", 669 extName); 670 goto loser; 671 } 672 673 for (i = 0; i < lastRange; i++) { 674 CRLGENEntryData *extData = NULL; 675 void *extHandle = NULL; 676 SECItem *certIdItem = 677 SEC_ASN1EncodeInteger(arena, NULL, 678 crlGenData->rangeFrom + i); 679 if (!certIdItem) { 680 rv = SECFailure; 681 goto loser; 682 } 683 684 extData = crlgen_FindEntry(crlGenData, certIdItem); 685 if (!extData) { 686 crlgen_PrintError(crlGenData->parsedLineNum, 687 "can not add extension: crl entry " 688 "(serial number: %d) is not in the list yet.\n", 689 crlGenData->rangeFrom + i); 690 continue; 691 } 692 693 extHandle = extData->extHandle; 694 if (extHandle == NULL) { 695 extHandle = extData->extHandle = 696 CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl, 697 (CERTCrlEntry *)extData->entry); 698 } 699 rv = CERT_AddExtension(extHandle, extCode, ext, 700 (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE, 701 PR_TRUE); 702 if (rv == SECFailure) { 703 goto loser; 704 } 705 } 706 707 loser: 708 if (arena) 709 PORT_FreeArena(arena, PR_FALSE); 710 return rv; 711 } 712 713 /* Commits all added entries and their's extensions into CRL. */ 714 SECStatus 715 CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData) 716 { 717 int size = 0; 718 CERTCrl *crl; 719 PLArenaPool *arena; 720 SECStatus rv = SECSuccess; 721 void *mark; 722 723 PORT_Assert(crlGenData && crlGenData->signCrl && crlGenData->signCrl->arena); 724 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) { 725 PORT_SetError(SEC_ERROR_INVALID_ARGS); 726 return SECFailure; 727 } 728 729 arena = crlGenData->signCrl->arena; 730 crl = &crlGenData->signCrl->crl; 731 732 mark = PORT_ArenaMark(arena); 733 734 if (crlGenData->crlExtHandle) 735 CERT_FinishExtensions(crlGenData->crlExtHandle); 736 737 size = crlGenData->entryDataHashTable->nentries; 738 crl->entries = NULL; 739 if (size) { 740 crl->entries = PORT_ArenaZNewArray(arena, CERTCrlEntry *, size + 1); 741 if (!crl->entries) { 742 rv = SECFailure; 743 } else { 744 struct commitData dt; 745 dt.entries = crl->entries; 746 dt.pos = 0; 747 PL_HashTableEnumerateEntries(crlGenData->entryDataHashTable, 748 &crlgen_CommitEntryData, &dt); 749 /* Last should be NULL */ 750 crl->entries[size] = NULL; 751 } 752 } 753 754 if (rv != SECSuccess) 755 PORT_ArenaRelease(arena, mark); 756 return rv; 757 } 758 759 /* Initializes extHandle with data from extensions array */ 760 static SECStatus 761 crlgen_InitExtensionHandle(void *extHandle, 762 CERTCertExtension **extensions) 763 { 764 CERTCertExtension *extension = NULL; 765 766 if (!extensions) 767 return SECSuccess; 768 769 PORT_Assert(extHandle != NULL); 770 if (!extHandle) { 771 return SECFailure; 772 } 773 774 extension = *extensions; 775 while (extension) { 776 SECOidTag oidTag = SECOID_FindOIDTag(&extension->id); 777 /* shell we skip unknown extensions? */ 778 CERT_AddExtension(extHandle, oidTag, &extension->value, 779 (extension->critical.len != 0) ? PR_TRUE : PR_FALSE, 780 PR_FALSE); 781 extension = *(++extensions); 782 } 783 return SECSuccess; 784 } 785 786 /* Used for initialization of extension handles for crl and certs 787 * extensions from existing CRL data then modifying existing CRL.*/ 788 SECStatus 789 CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData) 790 { 791 CERTCrl *crl = NULL; 792 PRUint64 maxSN = 0; 793 794 PORT_Assert(crlGenData && crlGenData->signCrl && 795 crlGenData->entryDataHashTable); 796 if (!crlGenData || !crlGenData->signCrl || 797 !crlGenData->entryDataHashTable) { 798 PORT_SetError(SEC_ERROR_INVALID_ARGS); 799 return SECFailure; 800 } 801 802 crl = &crlGenData->signCrl->crl; 803 crlGenData->crlExtHandle = CERT_StartCRLExtensions(crl); 804 crlgen_InitExtensionHandle(crlGenData->crlExtHandle, 805 crl->extensions); 806 crl->extensions = NULL; 807 808 if (crl->entries) { 809 CERTCrlEntry **entry = crl->entries; 810 while (*entry) { 811 PRUint64 sn = DER_GetInteger(&(*entry)->serialNumber); 812 CRLGENEntryData *extData = 813 crlgen_PlaceAnEntry(crlGenData, *entry, &(*entry)->serialNumber); 814 if ((*entry)->extensions) { 815 extData->extHandle = 816 CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl, 817 (CERTCrlEntry *)extData->entry); 818 if (crlgen_InitExtensionHandle(extData->extHandle, 819 (*entry)->extensions) == SECFailure) 820 return SECFailure; 821 } 822 (*entry)->extensions = NULL; 823 entry++; 824 maxSN = PR_MAX(maxSN, sn); 825 } 826 } 827 828 crlGenData->rangeFrom = crlGenData->rangeTo = maxSN + 1; 829 return SECSuccess; 830 } 831 832 /***************************************************************************** 833 * Parser trigger functions start here 834 */ 835 836 /* Sets new internal range value for add/rm certs.*/ 837 static SECStatus 838 crlgen_SetNewRangeField(CRLGENGeneratorData *crlGenData, char *value) 839 { 840 long rangeFrom = 0, rangeTo = 0; 841 char *dashPos = NULL; 842 843 PORT_Assert(crlGenData); 844 if (!crlGenData) { 845 PORT_SetError(SEC_ERROR_INVALID_ARGS); 846 return SECFailure; 847 } 848 849 if (value == NULL) { 850 PORT_SetError(SEC_ERROR_INVALID_ARGS); 851 crlgen_PrintError(crlGenData->parsedLineNum, 852 "insufficient number of arguments.\n"); 853 return SECFailure; 854 } 855 856 if ((dashPos = strchr(value, '-')) != NULL) { 857 char *rangeToS, *rangeFromS = value; 858 *dashPos = '\0'; 859 rangeFrom = atoi(rangeFromS); 860 *dashPos = '-'; 861 862 rangeToS = (char *)(dashPos + 1); 863 rangeTo = atol(rangeToS); 864 } else { 865 rangeFrom = atol(value); 866 rangeTo = rangeFrom; 867 } 868 869 if (rangeFrom < 1 || rangeTo < rangeFrom) { 870 PORT_SetError(SEC_ERROR_INVALID_ARGS); 871 crlgen_PrintError(crlGenData->parsedLineNum, 872 "bad cert id range: %s.\n", value); 873 return SECFailure; 874 } 875 876 crlGenData->rangeFrom = rangeFrom; 877 crlGenData->rangeTo = rangeTo; 878 879 return SECSuccess; 880 } 881 882 /* Changes issuer subject field in CRL. By default this data is taken from 883 * issuer cert subject field.Not yet implemented */ 884 static SECStatus 885 crlgen_SetIssuerField(CRLGENGeneratorData *crlGenData, char *value) 886 { 887 crlgen_PrintError(crlGenData->parsedLineNum, 888 "Can not change CRL issuer field.\n"); 889 return SECFailure; 890 } 891 892 /* Encode and sets CRL thisUpdate and nextUpdate time fields*/ 893 static SECStatus 894 crlgen_SetTimeField(CRLGENGeneratorData *crlGenData, char *value, 895 PRBool setThisUpdate) 896 { 897 CERTSignedCrl *signCrl; 898 PLArenaPool *arena; 899 CERTCrl *crl; 900 int length = 0; 901 SECItem *timeDest = NULL; 902 903 PORT_Assert(crlGenData && crlGenData->signCrl && 904 crlGenData->signCrl->arena); 905 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) { 906 PORT_SetError(SEC_ERROR_INVALID_ARGS); 907 return SECFailure; 908 } 909 910 signCrl = crlGenData->signCrl; 911 arena = signCrl->arena; 912 crl = &signCrl->crl; 913 914 if (value == NULL) { 915 PORT_SetError(SEC_ERROR_INVALID_ARGS); 916 crlgen_PrintError(crlGenData->parsedLineNum, 917 "insufficient number of arguments.\n"); 918 return SECFailure; 919 } 920 length = PORT_Strlen(value); 921 922 if (setThisUpdate == PR_TRUE) { 923 timeDest = &crl->lastUpdate; 924 } else { 925 timeDest = &crl->nextUpdate; 926 } 927 928 timeDest->type = siGeneralizedTime; 929 timeDest->data = PORT_ArenaAlloc(arena, length); 930 if (!timeDest->data) { 931 return SECFailure; 932 } 933 PORT_Memcpy(timeDest->data, value, length); 934 timeDest->len = length; 935 936 return SECSuccess; 937 } 938 939 /* Adds new extension into CRL or added cert handles */ 940 static SECStatus 941 crlgen_AddExtension(CRLGENGeneratorData *crlGenData, const char **extData) 942 { 943 PORT_Assert(crlGenData && crlGenData->crlExtHandle); 944 if (!crlGenData || !crlGenData->crlExtHandle) { 945 PORT_SetError(SEC_ERROR_INVALID_ARGS); 946 return SECFailure; 947 } 948 949 if (extData == NULL || *extData == NULL) { 950 PORT_SetError(SEC_ERROR_INVALID_ARGS); 951 crlgen_PrintError(crlGenData->parsedLineNum, 952 "insufficient number of arguments.\n"); 953 return SECFailure; 954 } 955 if (!PORT_Strcmp(*extData, "authKeyId")) 956 return crlgen_AddAuthKeyID(crlGenData, extData); 957 else if (!PORT_Strcmp(*extData, "issuerAltNames")) 958 return crlgen_AddIssuerAltNames(crlGenData, extData); 959 else if (!PORT_Strcmp(*extData, "crlNumber")) 960 return crlgen_AddCrlNumber(crlGenData, extData); 961 else if (!PORT_Strcmp(*extData, "reasonCode")) 962 return crlgen_AddEntryExtension(crlGenData, extData, "reasonCode", 963 crlgen_CreateReasonCode); 964 else if (!PORT_Strcmp(*extData, "invalidityDate")) 965 return crlgen_AddEntryExtension(crlGenData, extData, "invalidityDate", 966 crlgen_CreateInvalidityDate); 967 else { 968 PORT_SetError(SEC_ERROR_INVALID_ARGS); 969 crlgen_PrintError(crlGenData->parsedLineNum, 970 "insufficient number of arguments.\n"); 971 return SECFailure; 972 } 973 } 974 975 /* Created CRLGENEntryData for cert with serial number certId and 976 * adds it to entryDataHashTable. certId can be a single cert serial 977 * number or an inclusive rage of certs */ 978 static SECStatus 979 crlgen_AddCert(CRLGENGeneratorData *crlGenData, 980 char *certId, char *revocationDate) 981 { 982 CERTSignedCrl *signCrl; 983 SECItem *certIdItem; 984 PLArenaPool *arena; 985 PRUint64 rangeFrom = 0, rangeTo = 0, i = 0; 986 int timeValLength = -1; 987 SECStatus rv = SECFailure; 988 void *mark; 989 990 PORT_Assert(crlGenData && crlGenData->signCrl && 991 crlGenData->signCrl->arena); 992 if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) { 993 PORT_SetError(SEC_ERROR_INVALID_ARGS); 994 return SECFailure; 995 } 996 997 signCrl = crlGenData->signCrl; 998 arena = signCrl->arena; 999 1000 if (!certId || !revocationDate) { 1001 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1002 crlgen_PrintError(crlGenData->parsedLineNum, 1003 "insufficient number of arguments.\n"); 1004 return SECFailure; 1005 } 1006 1007 timeValLength = strlen(revocationDate); 1008 1009 if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure && 1010 certId) { 1011 return SECFailure; 1012 } 1013 rangeFrom = crlGenData->rangeFrom; 1014 rangeTo = crlGenData->rangeTo; 1015 1016 for (i = 0; i < rangeTo - rangeFrom + 1; i++) { 1017 CERTCrlEntry *entry; 1018 mark = PORT_ArenaMark(arena); 1019 entry = PORT_ArenaZNew(arena, CERTCrlEntry); 1020 if (entry == NULL) { 1021 goto loser; 1022 } 1023 1024 certIdItem = SEC_ASN1EncodeInteger(arena, &entry->serialNumber, 1025 rangeFrom + i); 1026 if (!certIdItem) { 1027 goto loser; 1028 } 1029 1030 if (crlgen_FindEntry(crlGenData, certIdItem)) { 1031 crlgen_PrintError(crlGenData->parsedLineNum, 1032 "entry already exists. Use \"range\" " 1033 "and \"rmcert\" before adding a new one with the " 1034 "same serial number %ld\n", 1035 rangeFrom + i); 1036 goto loser; 1037 } 1038 1039 entry->serialNumber.type = siBuffer; 1040 1041 entry->revocationDate.type = siGeneralizedTime; 1042 1043 entry->revocationDate.data = 1044 PORT_ArenaAlloc(arena, timeValLength); 1045 if (entry->revocationDate.data == NULL) { 1046 goto loser; 1047 } 1048 1049 PORT_Memcpy(entry->revocationDate.data, revocationDate, 1050 timeValLength * sizeof(char)); 1051 entry->revocationDate.len = timeValLength; 1052 1053 entry->extensions = NULL; 1054 if (!crlgen_PlaceAnEntry(crlGenData, entry, certIdItem)) { 1055 goto loser; 1056 } 1057 mark = NULL; 1058 } 1059 1060 rv = SECSuccess; 1061 loser: 1062 if (mark) { 1063 PORT_ArenaRelease(arena, mark); 1064 } 1065 return rv; 1066 } 1067 1068 /* Removes certs from entryDataHashTable which have certId serial number. 1069 * certId can have value of a range of certs */ 1070 static SECStatus 1071 crlgen_RmCert(CRLGENGeneratorData *crlGenData, char *certId) 1072 { 1073 PRUint64 i = 0; 1074 1075 PORT_Assert(crlGenData && certId); 1076 if (!crlGenData || !certId) { 1077 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1078 return SECFailure; 1079 } 1080 1081 if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure && 1082 certId) { 1083 return SECFailure; 1084 } 1085 1086 for (i = 0; i < crlGenData->rangeTo - crlGenData->rangeFrom + 1; i++) { 1087 SECItem *certIdItem = SEC_ASN1EncodeInteger(NULL, NULL, 1088 crlGenData->rangeFrom + i); 1089 if (certIdItem) { 1090 CRLGENEntryData *extData = 1091 crlgen_FindEntry(crlGenData, certIdItem); 1092 if (!extData) { 1093 printf("Cert with id %s is not in the list\n", certId); 1094 } else { 1095 crlgen_RmEntry(crlGenData, certIdItem); 1096 } 1097 SECITEM_FreeItem(certIdItem, PR_TRUE); 1098 } 1099 } 1100 1101 return SECSuccess; 1102 } 1103 1104 /************************************************************************* 1105 * Lex Parser Helper functions are used to store parsed information 1106 * in context related structures. Context(or state) is identified base on 1107 * a type of a instruction parser currently is going through. New context 1108 * is identified by first token in a line. It can be addcert context, 1109 * addext context, etc. */ 1110 1111 /* Updates CRL field depending on current context */ 1112 static SECStatus 1113 crlgen_updateCrlFn_field(CRLGENGeneratorData *crlGenData, void *str) 1114 { 1115 CRLGENCrlField *fieldStr = (CRLGENCrlField *)str; 1116 1117 PORT_Assert(crlGenData); 1118 if (!crlGenData) { 1119 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1120 return SECFailure; 1121 } 1122 1123 switch (crlGenData->contextId) { 1124 case CRLGEN_ISSUER_CONTEXT: 1125 crlgen_SetIssuerField(crlGenData, fieldStr->value); 1126 break; 1127 case CRLGEN_UPDATE_CONTEXT: 1128 return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_TRUE); 1129 break; 1130 case CRLGEN_NEXT_UPDATE_CONTEXT: 1131 return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_FALSE); 1132 break; 1133 case CRLGEN_CHANGE_RANGE_CONTEXT: 1134 return crlgen_SetNewRangeField(crlGenData, fieldStr->value); 1135 break; 1136 default: 1137 crlgen_PrintError(crlGenData->parsedLineNum, 1138 "syntax error (unknow token type: %d)\n", 1139 crlGenData->contextId); 1140 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1141 return SECFailure; 1142 } 1143 return SECSuccess; 1144 } 1145 1146 /* Sets parsed data for CRL field update into temporary structure */ 1147 static SECStatus 1148 crlgen_setNextDataFn_field(CRLGENGeneratorData *crlGenData, void *str, 1149 void *data, unsigned short dtype) 1150 { 1151 CRLGENCrlField *fieldStr = (CRLGENCrlField *)str; 1152 1153 PORT_Assert(crlGenData); 1154 if (!crlGenData) { 1155 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1156 return SECFailure; 1157 } 1158 1159 switch (crlGenData->contextId) { 1160 case CRLGEN_CHANGE_RANGE_CONTEXT: 1161 if (dtype != CRLGEN_TYPE_DIGIT && dtype != CRLGEN_TYPE_DIGIT_RANGE) { 1162 crlgen_PrintError(crlGenData->parsedLineNum, 1163 "range value should have " 1164 "numeric or numeric range values.\n"); 1165 return SECFailure; 1166 } 1167 break; 1168 case CRLGEN_NEXT_UPDATE_CONTEXT: 1169 case CRLGEN_UPDATE_CONTEXT: 1170 if (dtype != CRLGEN_TYPE_ZDATE) { 1171 crlgen_PrintError(crlGenData->parsedLineNum, 1172 "bad formated date. Should be " 1173 "YYYYMMDDHHMMSSZ.\n"); 1174 return SECFailure; 1175 } 1176 break; 1177 default: 1178 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1179 crlgen_PrintError(crlGenData->parsedLineNum, 1180 "syntax error (unknow token type: %d).\n", 1181 crlGenData->contextId, data); 1182 return SECFailure; 1183 } 1184 fieldStr->value = PORT_Strdup(data); 1185 if (!fieldStr->value) { 1186 return SECFailure; 1187 } 1188 return SECSuccess; 1189 } 1190 1191 /* Triggers cert entries update depending on current context */ 1192 static SECStatus 1193 crlgen_updateCrlFn_cert(CRLGENGeneratorData *crlGenData, void *str) 1194 { 1195 CRLGENCertEntry *certStr = (CRLGENCertEntry *)str; 1196 1197 PORT_Assert(crlGenData); 1198 if (!crlGenData) { 1199 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1200 return SECFailure; 1201 } 1202 1203 switch (crlGenData->contextId) { 1204 case CRLGEN_ADD_CERT_CONTEXT: 1205 return crlgen_AddCert(crlGenData, certStr->certId, 1206 certStr->revocationTime); 1207 case CRLGEN_RM_CERT_CONTEXT: 1208 return crlgen_RmCert(crlGenData, certStr->certId); 1209 default: 1210 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1211 crlgen_PrintError(crlGenData->parsedLineNum, 1212 "syntax error (unknow token type: %d).\n", 1213 crlGenData->contextId); 1214 return SECFailure; 1215 } 1216 } 1217 1218 /* Sets parsed data for CRL entries update into temporary structure */ 1219 static SECStatus 1220 crlgen_setNextDataFn_cert(CRLGENGeneratorData *crlGenData, void *str, 1221 void *data, unsigned short dtype) 1222 { 1223 CRLGENCertEntry *certStr = (CRLGENCertEntry *)str; 1224 1225 PORT_Assert(crlGenData); 1226 if (!crlGenData) { 1227 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1228 return SECFailure; 1229 } 1230 1231 switch (dtype) { 1232 case CRLGEN_TYPE_DIGIT: 1233 case CRLGEN_TYPE_DIGIT_RANGE: 1234 certStr->certId = PORT_Strdup(data); 1235 if (!certStr->certId) { 1236 return SECFailure; 1237 } 1238 break; 1239 case CRLGEN_TYPE_DATE: 1240 case CRLGEN_TYPE_ZDATE: 1241 certStr->revocationTime = PORT_Strdup(data); 1242 if (!certStr->revocationTime) { 1243 return SECFailure; 1244 } 1245 break; 1246 default: 1247 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1248 crlgen_PrintError(crlGenData->parsedLineNum, 1249 "syntax error (unknow token type: %d).\n", 1250 crlGenData->contextId); 1251 return SECFailure; 1252 } 1253 return SECSuccess; 1254 } 1255 1256 /* Triggers cert entries/crl extension update */ 1257 static SECStatus 1258 crlgen_updateCrlFn_extension(CRLGENGeneratorData *crlGenData, void *str) 1259 { 1260 CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str; 1261 1262 return crlgen_AddExtension(crlGenData, (const char **)extStr->extData); 1263 } 1264 1265 /* Defines maximum number of fields extension may have */ 1266 #define MAX_EXT_DATA_LENGTH 10 1267 1268 /* Sets parsed extension data for CRL entries/CRL extensions update 1269 * into temporary structure */ 1270 static SECStatus 1271 crlgen_setNextDataFn_extension(CRLGENGeneratorData *crlGenData, void *str, 1272 void *data, unsigned short dtype) 1273 { 1274 CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str; 1275 1276 PORT_Assert(crlGenData); 1277 if (!crlGenData) { 1278 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1279 return SECFailure; 1280 } 1281 1282 if (extStr->extData == NULL) { 1283 extStr->extData = PORT_ZNewArray(char *, MAX_EXT_DATA_LENGTH); 1284 if (!extStr->extData) { 1285 return SECFailure; 1286 } 1287 } 1288 if (extStr->nextUpdatedData >= MAX_EXT_DATA_LENGTH) { 1289 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1290 crlgen_PrintError(crlGenData->parsedLineNum, 1291 "number of fields in extension " 1292 "exceeded maximum allowed data length: %d.\n", 1293 MAX_EXT_DATA_LENGTH); 1294 return SECFailure; 1295 } 1296 extStr->extData[extStr->nextUpdatedData] = PORT_Strdup(data); 1297 if (!extStr->extData[extStr->nextUpdatedData]) { 1298 return SECFailure; 1299 } 1300 extStr->nextUpdatedData += 1; 1301 1302 return SECSuccess; 1303 } 1304 1305 /**************************************************************************************** 1306 * Top level functions are triggered directly by parser. 1307 */ 1308 1309 /* 1310 * crl generation script parser recreates a temporary data staructure 1311 * for each line it is going through. This function cleans temp structure. 1312 */ 1313 void 1314 crlgen_destroyTempData(CRLGENGeneratorData *crlGenData) 1315 { 1316 if (crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) { 1317 switch (crlGenData->contextId) { 1318 case CRLGEN_ISSUER_CONTEXT: 1319 case CRLGEN_UPDATE_CONTEXT: 1320 case CRLGEN_NEXT_UPDATE_CONTEXT: 1321 case CRLGEN_CHANGE_RANGE_CONTEXT: 1322 if (crlGenData->crlField->value) 1323 PORT_Free(crlGenData->crlField->value); 1324 PORT_Free(crlGenData->crlField); 1325 break; 1326 case CRLGEN_ADD_CERT_CONTEXT: 1327 case CRLGEN_RM_CERT_CONTEXT: 1328 if (crlGenData->certEntry->certId) 1329 PORT_Free(crlGenData->certEntry->certId); 1330 if (crlGenData->certEntry->revocationTime) 1331 PORT_Free(crlGenData->certEntry->revocationTime); 1332 PORT_Free(crlGenData->certEntry); 1333 break; 1334 case CRLGEN_ADD_EXTENSION_CONTEXT: 1335 if (crlGenData->extensionEntry->extData) { 1336 int i = 0; 1337 for (; i < crlGenData->extensionEntry->nextUpdatedData; i++) 1338 PORT_Free(*(crlGenData->extensionEntry->extData + i)); 1339 PORT_Free(crlGenData->extensionEntry->extData); 1340 } 1341 PORT_Free(crlGenData->extensionEntry); 1342 break; 1343 } 1344 crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT; 1345 } 1346 } 1347 1348 SECStatus 1349 crlgen_updateCrl(CRLGENGeneratorData *crlGenData) 1350 { 1351 SECStatus rv = SECSuccess; 1352 1353 PORT_Assert(crlGenData); 1354 if (!crlGenData) { 1355 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1356 return SECFailure; 1357 } 1358 1359 switch (crlGenData->contextId) { 1360 case CRLGEN_ISSUER_CONTEXT: 1361 case CRLGEN_UPDATE_CONTEXT: 1362 case CRLGEN_NEXT_UPDATE_CONTEXT: 1363 case CRLGEN_CHANGE_RANGE_CONTEXT: 1364 rv = crlGenData->crlField->updateCrlFn(crlGenData, crlGenData->crlField); 1365 break; 1366 case CRLGEN_RM_CERT_CONTEXT: 1367 case CRLGEN_ADD_CERT_CONTEXT: 1368 rv = crlGenData->certEntry->updateCrlFn(crlGenData, crlGenData->certEntry); 1369 break; 1370 case CRLGEN_ADD_EXTENSION_CONTEXT: 1371 rv = crlGenData->extensionEntry->updateCrlFn(crlGenData, crlGenData->extensionEntry); 1372 break; 1373 case CRLGEN_UNKNOWN_CONTEXT: 1374 break; 1375 default: 1376 crlgen_PrintError(crlGenData->parsedLineNum, 1377 "unknown lang context type code: %d.\n", 1378 crlGenData->contextId); 1379 PORT_Assert(0); 1380 return SECFailure; 1381 } 1382 /* Clrean structures after crl update */ 1383 crlgen_destroyTempData(crlGenData); 1384 1385 crlGenData->parsedLineNum += 1; 1386 1387 return rv; 1388 } 1389 1390 SECStatus 1391 crlgen_setNextData(CRLGENGeneratorData *crlGenData, void *data, 1392 unsigned short dtype) 1393 { 1394 SECStatus rv = SECSuccess; 1395 1396 PORT_Assert(crlGenData); 1397 if (!crlGenData) { 1398 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1399 return SECFailure; 1400 } 1401 1402 switch (crlGenData->contextId) { 1403 case CRLGEN_ISSUER_CONTEXT: 1404 case CRLGEN_UPDATE_CONTEXT: 1405 case CRLGEN_NEXT_UPDATE_CONTEXT: 1406 case CRLGEN_CHANGE_RANGE_CONTEXT: 1407 rv = crlGenData->crlField->setNextDataFn(crlGenData, crlGenData->crlField, 1408 data, dtype); 1409 break; 1410 case CRLGEN_ADD_CERT_CONTEXT: 1411 case CRLGEN_RM_CERT_CONTEXT: 1412 rv = crlGenData->certEntry->setNextDataFn(crlGenData, crlGenData->certEntry, 1413 data, dtype); 1414 break; 1415 case CRLGEN_ADD_EXTENSION_CONTEXT: 1416 rv = 1417 crlGenData->extensionEntry->setNextDataFn(crlGenData, crlGenData->extensionEntry, data, dtype); 1418 break; 1419 case CRLGEN_UNKNOWN_CONTEXT: 1420 break; 1421 default: 1422 crlgen_PrintError(crlGenData->parsedLineNum, 1423 "unknown context type: %d.\n", 1424 crlGenData->contextId); 1425 PORT_Assert(0); 1426 return SECFailure; 1427 } 1428 return rv; 1429 } 1430 1431 SECStatus 1432 crlgen_createNewLangStruct(CRLGENGeneratorData *crlGenData, 1433 unsigned structType) 1434 { 1435 PORT_Assert(crlGenData && 1436 crlGenData->contextId == CRLGEN_UNKNOWN_CONTEXT); 1437 if (!crlGenData || 1438 crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) { 1439 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1440 return SECFailure; 1441 } 1442 1443 switch (structType) { 1444 case CRLGEN_ISSUER_CONTEXT: 1445 case CRLGEN_UPDATE_CONTEXT: 1446 case CRLGEN_NEXT_UPDATE_CONTEXT: 1447 case CRLGEN_CHANGE_RANGE_CONTEXT: 1448 crlGenData->crlField = PORT_New(CRLGENCrlField); 1449 if (!crlGenData->crlField) { 1450 return SECFailure; 1451 } 1452 crlGenData->contextId = structType; 1453 crlGenData->crlField->value = NULL; 1454 crlGenData->crlField->updateCrlFn = &crlgen_updateCrlFn_field; 1455 crlGenData->crlField->setNextDataFn = &crlgen_setNextDataFn_field; 1456 break; 1457 case CRLGEN_RM_CERT_CONTEXT: 1458 case CRLGEN_ADD_CERT_CONTEXT: 1459 crlGenData->certEntry = PORT_New(CRLGENCertEntry); 1460 if (!crlGenData->certEntry) { 1461 return SECFailure; 1462 } 1463 crlGenData->contextId = structType; 1464 crlGenData->certEntry->certId = 0; 1465 crlGenData->certEntry->revocationTime = NULL; 1466 crlGenData->certEntry->updateCrlFn = &crlgen_updateCrlFn_cert; 1467 crlGenData->certEntry->setNextDataFn = &crlgen_setNextDataFn_cert; 1468 break; 1469 case CRLGEN_ADD_EXTENSION_CONTEXT: 1470 crlGenData->extensionEntry = PORT_New(CRLGENExtensionEntry); 1471 if (!crlGenData->extensionEntry) { 1472 return SECFailure; 1473 } 1474 crlGenData->contextId = structType; 1475 crlGenData->extensionEntry->extData = NULL; 1476 crlGenData->extensionEntry->nextUpdatedData = 0; 1477 crlGenData->extensionEntry->updateCrlFn = 1478 &crlgen_updateCrlFn_extension; 1479 crlGenData->extensionEntry->setNextDataFn = 1480 &crlgen_setNextDataFn_extension; 1481 break; 1482 case CRLGEN_UNKNOWN_CONTEXT: 1483 break; 1484 default: 1485 crlgen_PrintError(crlGenData->parsedLineNum, 1486 "unknown context type: %d.\n", structType); 1487 PORT_Assert(0); 1488 return SECFailure; 1489 } 1490 return SECSuccess; 1491 } 1492 1493 /* Parser initialization function */ 1494 CRLGENGeneratorData * 1495 CRLGEN_InitCrlGeneration(CERTSignedCrl *signCrl, PRFileDesc *src) 1496 { 1497 CRLGENGeneratorData *crlGenData = NULL; 1498 1499 PORT_Assert(signCrl && src); 1500 if (!signCrl || !src) { 1501 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1502 return NULL; 1503 } 1504 1505 crlGenData = PORT_ZNew(CRLGENGeneratorData); 1506 if (!crlGenData) { 1507 return NULL; 1508 } 1509 1510 crlGenData->entryDataHashTable = 1511 PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, 1512 PL_CompareValues, NULL, NULL); 1513 if (!crlGenData->entryDataHashTable) { 1514 PORT_Free(crlGenData); 1515 return NULL; 1516 } 1517 1518 crlGenData->src = src; 1519 crlGenData->parsedLineNum = 1; 1520 crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT; 1521 crlGenData->signCrl = signCrl; 1522 crlGenData->rangeFrom = 0; 1523 crlGenData->rangeTo = 0; 1524 crlGenData->crlExtHandle = NULL; 1525 1526 PORT_SetError(0); 1527 1528 return crlGenData; 1529 } 1530 1531 void 1532 CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData) 1533 { 1534 if (!crlGenData) 1535 return; 1536 if (crlGenData->src) 1537 PR_Close(crlGenData->src); 1538 PL_HashTableDestroy(crlGenData->entryDataHashTable); 1539 PORT_Free(crlGenData); 1540 }