security/nss/cmd/crlutil/crlgen.c

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial