Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/cmd/crlutil/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 46 kB image not shown  

Quelle  crlgen.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/*
** crlgen.c
**
** utility for managing certificates revocation lists generation
**
*/


#include <stdio.h>
#include <math.h>

#include "nspr.h"
#include "plgetopt.h"
#include "nss.h"
#include "secutil.h"
#include "cert.h"
#include "certi.h"
#include "certdb.h"
#include "pk11func.h"
#include "crlgen.h"

/* Destroys extHandle and data. data was create on heap.
 * extHandle creaded by CERT_StartCRLEntryExtensions. entry
 * was allocated on arena.*/

static void
destroyEntryData(CRLGENEntryData *data)
{
    if (!data)
        return;
    PORT_Assert(data->entry);
    if (data->extHandle)
        CERT_FinishExtensions(data->extHandle);
    PORT_Free(data);
}

/* Prints error messages along with line number */
void
crlgen_PrintError(int line, char *msg, ...)
{
    va_list args;

    va_start(args, msg);

    fprintf(stderr, "crlgen: (line: %d) ", line);
    vfprintf(stderr, msg, args);

    va_end(args);
}
/* Finds CRLGENEntryData in hashtable according PRUint64 value
 * - certId : cert serial number*/

static CRLGENEntryData *
crlgen_FindEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
{
    if (!crlGenData->entryDataHashTable || !certId)
        return NULL;
    return (CRLGENEntryData *)
        PL_HashTableLookup(crlGenData->entryDataHashTable,
                           certId);
}

/* Removes CRLGENEntryData from hashtable according to certId
 * - certId : cert serial number*/

static SECStatus
crlgen_RmEntry(CRLGENGeneratorData *crlGenData, SECItem *certId)
{
    CRLGENEntryData *data = NULL;
    SECStatus rv = SECSuccess;

    if (!crlGenData->entryDataHashTable) {
        return SECSuccess;
    }

    data = crlgen_FindEntry(crlGenData, certId);
    if (!data) {
        return SECSuccess;
    }

    if (!PL_HashTableRemove(crlGenData->entryDataHashTable, certId)) {
        rv = SECFailure;
    }

    destroyEntryData(data);
    return rv;
}

/* Stores CRLGENEntryData in hashtable according to certId
 * - certId : cert serial number*/

static CRLGENEntryData *
crlgen_PlaceAnEntry(CRLGENGeneratorData *crlGenData,
                    CERTCrlEntry *entry, SECItem *certId)
{
    CRLGENEntryData *newData = NULL;

    PORT_Assert(crlGenData && crlGenData->entryDataHashTable &&
                entry);
    if (!crlGenData || !crlGenData->entryDataHashTable || !entry) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    newData = PORT_ZNew(CRLGENEntryData);
    if (!newData) {
        return NULL;
    }
    newData->entry = entry;
    newData->certId = certId;
    if (!PL_HashTableAdd(crlGenData->entryDataHashTable,
                         newData->certId, newData)) {
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "Can not add entryData structure\n");
        return NULL;
    }
    return newData;
}

/* Use this structure to keep pointer when commiting entries extensions */
struct commitData {
    int pos;
    CERTCrlEntry **entries;
};

/* HT PL_HashTableEnumerateEntries callback. Sorts hashtable entries of the
 * table he. Returns value through arg parameter*/

static PRIntn PR_CALLBACK
crlgen_CommitEntryData(PLHashEntry *he, PRIntn i, void *arg)
{
    CRLGENEntryData *data = NULL;

    PORT_Assert(he);
    if (!he) {
        return HT_ENUMERATE_NEXT;
    }
    data = (CRLGENEntryData *)he->value;

    PORT_Assert(data);
    PORT_Assert(arg);

    if (data) {
        struct commitData *dt = (struct commitData *)arg;
        dt->entries[dt->pos++] = data->entry;
        destroyEntryData(data);
    }
    return HT_ENUMERATE_NEXT;
}

/* Copy char * datainto allocated in arena SECItem */
static SECStatus
crlgen_SetString(PLArenaPool *arena, const char *dataIn, SECItem *value)
{
    SECItem item;

    PORT_Assert(arena && dataIn);
    if (!arena || !dataIn) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    item.data = (void *)dataIn;
    item.len = PORT_Strlen(dataIn);

    return SECITEM_CopyItem(arena, value, &item);
}

/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
static CERTGeneralName *
crlgen_GetGeneralName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
                      const char *data)
{
    CERTGeneralName *namesList = NULL;
    CERTGeneralName *current;
    CERTGeneralName *tail = NULL;
    SECStatus rv = SECSuccess;
    const char *nextChunk = NULL;
    const char *currData = NULL;
    int intValue;
    char buffer[512];
    void *mark;

    if (!data)
        return NULL;
    PORT_Assert(arena);
    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    mark = PORT_ArenaMark(arena);

    nextChunk = data;
    currData = data;
    do {
        int nameLen = 0;
        char name[128];
        const char *sepPrt = NULL;
        nextChunk = PORT_Strchr(currData, '|');
        if (!nextChunk)
            nextChunk = data + strlen(data);
        sepPrt = PORT_Strchr(currData, ':');
        if (sepPrt == NULL || sepPrt >= nextChunk) {
            *buffer = '\0';
            sepPrt = nextChunk;
        } else {
            PORT_Memcpy(buffer, sepPrt + 1,
                        (nextChunk - sepPrt - 1));
            buffer[nextChunk - sepPrt - 1] = '\0';
        }
        nameLen = PR_MIN(sepPrt - currData, sizeof(name) - 1);
        PORT_Memcpy(name, currData, nameLen);
        name[nameLen] = '\0';
        currData = nextChunk + 1;

        if (!PORT_Strcmp(name, "otherName"))
            intValue = certOtherName;
        else if (!PORT_Strcmp(name, "rfc822Name"))
            intValue = certRFC822Name;
        else if (!PORT_Strcmp(name, "dnsName"))
            intValue = certDNSName;
        else if (!PORT_Strcmp(name, "x400Address"))
            intValue = certX400Address;
        else if (!PORT_Strcmp(name, "directoryName"))
            intValue = certDirectoryName;
        else if (!PORT_Strcmp(name, "ediPartyName"))
            intValue = certEDIPartyName;
        else if (!PORT_Strcmp(name, "URI"))
            intValue = certURI;
        else if (!PORT_Strcmp(name, "ipAddress"))
            intValue = certIPAddress;
        else if (!PORT_Strcmp(name, "registerID"))
            intValue = certRegisterID;
        else
            intValue = -1;

        if (intValue >= certOtherName && intValue <= certRegisterID) {
            if (namesList == NULL) {
                namesList = current = tail = PORT_ArenaZNew(arena,
                                                            CERTGeneralName);
            } else {
                current = PORT_ArenaZNew(arena, CERTGeneralName);
            }
            if (current == NULL) {
                rv = SECFailure;
                break;
            }
        } else {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            break;
        }
        current->type = intValue;
        switch (current->type) {
            case certURI:
            case certDNSName:
            case certRFC822Name:
                current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer));
                if (current->name.other.data == NULL) {
                    rv = SECFailure;
                    break;
                }
                PORT_Memcpy(current->name.other.data, buffer,
                            current->name.other.len = strlen(buffer));
                break;

            case certEDIPartyName:
            case certIPAddress:
            case certOtherName:
            case certRegisterID:
            case certX400Address: {

                current->name.other.data = PORT_ArenaAlloc(arena, strlen(buffer) + 2);
                if (current->name.other.data == NULL) {
                    rv = SECFailure;
                    break;
                }

                PORT_Memcpy(current->name.other.data + 2, buffer, strlen(buffer));
                /* This may not be accurate for all cases.For now, use this tag type */
                current->name.other.data[0] = (char)(((current->type - 1) & 0x1f) | 0x80);
                current->name.other.data[1] = (char)strlen(buffer);
                current->name.other.len = strlen(buffer) + 2;
                break;
            }

            case certDirectoryName: {
                CERTName *directoryName = NULL;

                directoryName = CERT_AsciiToName(buffer);
                if (!directoryName) {
                    rv = SECFailure;
                    break;
                }

                rv = CERT_CopyName(arena, ¤t->name.directoryName, directoryName);
                CERT_DestroyName(directoryName);

                break;
            }
        }
        if (rv != SECSuccess)
            break;
        current->l.next = &(namesList->l);
        current->l.prev = &(tail->l);
        tail->l.next = &(current->l);
        tail = current;

    } while (nextChunk != data + strlen(data));

    if (rv != SECSuccess) {
        PORT_ArenaRelease(arena, mark);
        namesList = NULL;
    }
    return (namesList);
}

/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
static CERTGeneralName *
crlgen_DistinguishedName(PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
                         const char *data)
{
    CERTName *directoryName = NULL;
    CERTGeneralName *current;
    SECStatus rv = SECFailure;
    void *mark;

    if (!data)
        return NULL;
    PORT_Assert(arena);
    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    mark = PORT_ArenaMark(arena);

    current = PORT_ArenaZNew(arena, CERTGeneralName);
    if (current == NULL) {
        goto loser;
    }
    current->type = certDirectoryName;
    current->l.next = ¤t->l;
    current->l.prev = ¤t->l;

    directoryName = CERT_AsciiToName((char *)data);
    if (!directoryName) {
        goto loser;
    }

    rv = CERT_CopyName(arena, ¤t->name.directoryName, directoryName);
    CERT_DestroyName(directoryName);

loser:
    if (rv != SECSuccess) {
        PORT_SetError(rv);
        PORT_ArenaRelease(arena, mark);
        current = NULL;
    }
    return (current);
}

/* Adding Authority Key ID extension to extension handle. */
static SECStatus
crlgen_AddAuthKeyID(CRLGENGeneratorData *crlGenData,
                    const char **dataArr)
{
    void *extHandle = NULL;
    CERTAuthKeyID *authKeyID = NULL;
    PLArenaPool *arena = NULL;
    SECStatus rv = SECSuccess;

    PORT_Assert(dataArr && crlGenData);
    if (!crlGenData || !dataArr) {
        return SECFailure;
    }

    extHandle = crlGenData->crlExtHandle;

    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of parameters.\n");
        return SECFailure;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) {
        return SECFailure;
    }

    authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
    if (authKeyID == NULL) {
        rv = SECFailure;
        goto loser;
    }

    if (dataArr[3] == NULL) {
        rv = crlgen_SetString(arena, dataArr[2], &authKeyID->keyID);
        if (rv != SECSuccess)
            goto loser;
    } else {
        rv = crlgen_SetString(arena, dataArr[3],
                              &authKeyID->authCertSerialNumber);
        if (rv != SECSuccess)
            goto loser;

        authKeyID->authCertIssuer =
            crlgen_DistinguishedName(arena, crlGenData, dataArr[2]);
        if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) {
            crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
            rv = SECFailure;
            goto loser;
        }
    }

    rv =
        SECU_EncodeAndAddExtensionValue(arena, extHandle, authKeyID,
                                        (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
                                        SEC_OID_X509_AUTH_KEY_ID,
                                        EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAuthKeyID);
loser:
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
    return rv;
}

/* Creates and add Subject Alternative Names extension */
static SECStatus
crlgen_AddIssuerAltNames(CRLGENGeneratorData *crlGenData,
                         const char **dataArr)
{
    CERTGeneralName *nameList = NULL;
    PLArenaPool *arena = NULL;
    void *extHandle = NULL;
    SECStatus rv = SECSuccess;

    PORT_Assert(dataArr && crlGenData);
    if (!crlGenData || !dataArr) {
        return SECFailure;
    }

    if (!dataArr || !dataArr[0] || !dataArr[1] || !dataArr[2]) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }

    PORT_Assert(dataArr && crlGenData);
    if (!crlGenData || !dataArr) {
        return SECFailure;
    }

    extHandle = crlGenData->crlExtHandle;

    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of parameters.\n");
        return SECFailure;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) {
        return SECFailure;
    }

    nameList = crlgen_GetGeneralName(arena, crlGenData, dataArr[2]);
    if (nameList == NULL) {
        crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
        rv = SECFailure;
        goto loser;
    }

    rv =
        SECU_EncodeAndAddExtensionValue(arena, extHandle, nameList,
                                        (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
                                        SEC_OID_X509_ISSUER_ALT_NAME,
                                        EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAltNameExtension);
loser:
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
    return rv;
}

/* Creates and adds CRLNumber extension to extension handle.
 * Since, this is CRL extension, extension handle is the one
 * related to CRL extensions */

static SECStatus
crlgen_AddCrlNumber(CRLGENGeneratorData *crlGenData, const char **dataArr)
{
    PLArenaPool *arena = NULL;
    SECItem encodedItem;
    void *dummy;
    SECStatus rv = SECFailure;
    int code = 0;

    PORT_Assert(dataArr && crlGenData);
    if (!crlGenData || !dataArr) {
        goto loser;
    }

    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        goto loser;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        goto loser;
    }

    code = atoi(dataArr[2]);
    if (code == 0 && *dataArr[2] != '0') {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto loser;
    }

    dummy = SEC_ASN1EncodeInteger(arena, &encodedItem, code);
    if (!dummy) {
        rv = SECFailure;
        goto loser;
    }

    rv = CERT_AddExtension(crlGenData->crlExtHandle, SEC_OID_X509_CRL_NUMBER,
                           &encodedItem,
                           (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
                           PR_TRUE);

loser:
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
    return rv;
}

/* Creates Cert Revocation Reason code extension. Encodes it and
 * returns as SECItem structure */

static SECItem *
crlgen_CreateReasonCode(PLArenaPool *arena, const char **dataArr,
                        int *extCode)
{
    SECItem *encodedItem;
    void *dummy;
    void *mark = NULL;
    int code = 0;

    PORT_Assert(arena && dataArr);
    if (!arena || !dataArr) {
        goto loser;
    }

    mark = PORT_ArenaMark(arena);

    encodedItem = PORT_ArenaZNew(arena, SECItem);
    if (encodedItem == NULL) {
        goto loser;
    }

    if (dataArr[2] == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto loser;
    }

    code = atoi(dataArr[2]);
    /* aACompromise(10) is the last possible of the values
     * for the Reason Core Extension */

    if ((code == 0 && *dataArr[2] != '0') || code > 10) {

        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto loser;
    }

    dummy = SEC_ASN1EncodeInteger(arena, encodedItem, code);
    if (!dummy) {
        goto loser;
    }

    *extCode = SEC_OID_X509_REASON_CODE;
    return encodedItem;

loser:
    if (mark) {
        PORT_ArenaRelease(arena, mark);
    }
    return NULL;
}

/* Creates Cert Invalidity Date extension. Encodes it and
 * returns as SECItem structure */

static SECItem *
crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr,
                            int *extCode)
{
    SECItem *encodedItem;
    int length = 0;
    void *mark = NULL;

    PORT_Assert(arena && dataArr);
    if (!arena || !dataArr) {
        goto loser;
    }

    mark = PORT_ArenaMark(arena);

    encodedItem = PORT_ArenaZNew(arena, SECItem);
    if (encodedItem == NULL) {
        goto loser;
    }

    length = PORT_Strlen(dataArr[2]);

    encodedItem->type = siGeneralizedTime;
    encodedItem->data = PORT_ArenaAlloc(arena, length);
    if (!encodedItem->data) {
        goto loser;
    }

    PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) * sizeof(char));

    *extCode = SEC_OID_X509_INVALID_DATE;
    return encodedItem;

loser:
    if (mark) {
        PORT_ArenaRelease(arena, mark);
    }
    return NULL;
}

/* Creates(by calling extCreator function) and adds extension to a set
 * of already added certs. Uses values of rangeFrom and rangeTo from
 * CRLGENCrlGenCtl structure for identifying the inclusive set of certs */

static SECStatus
crlgen_AddEntryExtension(CRLGENGeneratorData *crlGenData,
                         const char **dataArr, char *extName,
                         SECItem *(*extCreator)(PLArenaPool *arena,
                                                const char **dataArr,
                                                int *extCode))
{
    PRUint64 i = 0;
    SECStatus rv = SECFailure;
    int extCode = 0;
    PRUint64 lastRange;
    SECItem *ext = NULL;
    PLArenaPool *arena = NULL;

    PORT_Assert(crlGenData && dataArr);
    if (!crlGenData || !dataArr) {
        goto loser;
    }

    if (!dataArr[0] || !dataArr[1]) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
    }

    lastRange = crlGenData->rangeTo - crlGenData->rangeFrom + 1;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        goto loser;
    }

    ext = extCreator(arena, dataArr, &extCode);
    if (ext == NULL) {
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "got error while creating extension: %s\n",
                          extName);
        goto loser;
    }

    for (i = 0; i < lastRange; i++) {
        CRLGENEntryData *extData = NULL;
        void *extHandle = NULL;
        SECItem *certIdItem =
            SEC_ASN1EncodeInteger(arena, NULL,
                                  crlGenData->rangeFrom + i);
        if (!certIdItem) {
            rv = SECFailure;
            goto loser;
        }

        extData = crlgen_FindEntry(crlGenData, certIdItem);
        if (!extData) {
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "can not add extension: crl entry "
                              "(serial number: %d) is not in the list yet.\n",
                              crlGenData->rangeFrom + i);
            continue;
        }

        extHandle = extData->extHandle;
        if (extHandle == NULL) {
            extHandle = extData->extHandle =
                CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
                                             (CERTCrlEntry *)extData->entry);
        }
        rv = CERT_AddExtension(extHandle, extCode, ext,
                               (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
                               PR_TRUE);
        if (rv == SECFailure) {
            goto loser;
        }
    }

loser:
    if (arena)
        PORT_FreeArena(arena, PR_FALSE);
    return rv;
}

/* Commits all added entries and their's extensions into CRL. */
SECStatus
CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData)
{
    int size = 0;
    CERTCrl *crl;
    PLArenaPool *arena;
    SECStatus rv = SECSuccess;
    void *mark;

    PORT_Assert(crlGenData && crlGenData->signCrl && crlGenData->signCrl->arena);
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    arena = crlGenData->signCrl->arena;
    crl = &crlGenData->signCrl->crl;

    mark = PORT_ArenaMark(arena);

    if (crlGenData->crlExtHandle)
        CERT_FinishExtensions(crlGenData->crlExtHandle);

    size = crlGenData->entryDataHashTable->nentries;
    crl->entries = NULL;
    if (size) {
        crl->entries = PORT_ArenaZNewArray(arena, CERTCrlEntry *, size + 1);
        if (!crl->entries) {
            rv = SECFailure;
        } else {
            struct commitData dt;
            dt.entries = crl->entries;
            dt.pos = 0;
            PL_HashTableEnumerateEntries(crlGenData->entryDataHashTable,
                                         &crlgen_CommitEntryData, &dt);
            /* Last should be NULL */
            crl->entries[size] = NULL;
        }
    }

    if (rv != SECSuccess)
        PORT_ArenaRelease(arena, mark);
    return rv;
}

/* Initializes extHandle with data from extensions array */
static SECStatus
crlgen_InitExtensionHandle(void *extHandle,
                           CERTCertExtension **extensions)
{
    CERTCertExtension *extension = NULL;

    if (!extensions)
        return SECSuccess;

    PORT_Assert(extHandle != NULL);
    if (!extHandle) {
        return SECFailure;
    }

    extension = *extensions;
    while (extension) {
        SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
        /* shell we skip unknown extensions? */
        CERT_AddExtension(extHandle, oidTag, &extension->value,
                          (extension->critical.len != 0) ? PR_TRUE : PR_FALSE,
                          PR_FALSE);
        extension = *(++extensions);
    }
    return SECSuccess;
}

/* Used for initialization of extension handles for crl and certs
 * extensions from existing CRL data then modifying existing CRL.*/

SECStatus
CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData)
{
    CERTCrl *crl = NULL;
    PRUint64 maxSN = 0;

    PORT_Assert(crlGenData && crlGenData->signCrl &&
                crlGenData->entryDataHashTable);
    if (!crlGenData || !crlGenData->signCrl ||
        !crlGenData->entryDataHashTable) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    crl = &crlGenData->signCrl->crl;
    crlGenData->crlExtHandle = CERT_StartCRLExtensions(crl);
    crlgen_InitExtensionHandle(crlGenData->crlExtHandle,
                               crl->extensions);
    crl->extensions = NULL;

    if (crl->entries) {
        CERTCrlEntry **entry = crl->entries;
        while (*entry) {
            PRUint64 sn = DER_GetInteger(&(*entry)->serialNumber);
            CRLGENEntryData *extData =
                crlgen_PlaceAnEntry(crlGenData, *entry, &(*entry)->serialNumber);
            if ((*entry)->extensions) {
                extData->extHandle =
                    CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
                                                 (CERTCrlEntry *)extData->entry);
                if (crlgen_InitExtensionHandle(extData->extHandle,
                                               (*entry)->extensions) == SECFailure)
                    return SECFailure;
            }
            (*entry)->extensions = NULL;
            entry++;
            maxSN = PR_MAX(maxSN, sn);
        }
    }

    crlGenData->rangeFrom = crlGenData->rangeTo = maxSN + 1;
    return SECSuccess;
}

/*****************************************************************************
 * Parser trigger functions start here
 */


/* Sets new internal range value for add/rm certs.*/
static SECStatus
crlgen_SetNewRangeField(CRLGENGeneratorData *crlGenData, char *value)
{
    long rangeFrom = 0, rangeTo = 0;
    char *dashPos = NULL;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (value == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }

    if ((dashPos = strchr(value, '-')) != NULL) {
        char *rangeToS, *rangeFromS = value;
        *dashPos = '\0';
        rangeFrom = atoi(rangeFromS);
        *dashPos = '-';

        rangeToS = (char *)(dashPos + 1);
        rangeTo = atol(rangeToS);
    } else {
        rangeFrom = atol(value);
        rangeTo = rangeFrom;
    }

    if (rangeFrom < 1 || rangeTo < rangeFrom) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "bad cert id range: %s.\n", value);
        return SECFailure;
    }

    crlGenData->rangeFrom = rangeFrom;
    crlGenData->rangeTo = rangeTo;

    return SECSuccess;
}

/* Changes issuer subject field in CRL. By default this data is taken from
 * issuer cert subject field.Not yet implemented */

static SECStatus
crlgen_SetIssuerField(CRLGENGeneratorData *crlGenData, char *value)
{
    crlgen_PrintError(crlGenData->parsedLineNum,
                      "Can not change CRL issuer field.\n");
    return SECFailure;
}

/* Encode and sets CRL thisUpdate and nextUpdate time fields*/
static SECStatus
crlgen_SetTimeField(CRLGENGeneratorData *crlGenData, char *value,
                    PRBool setThisUpdate)
{
    CERTSignedCrl *signCrl;
    PLArenaPool *arena;
    CERTCrl *crl;
    int length = 0;
    SECItem *timeDest = NULL;

    PORT_Assert(crlGenData && crlGenData->signCrl &&
                crlGenData->signCrl->arena);
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    signCrl = crlGenData->signCrl;
    arena = signCrl->arena;
    crl = &signCrl->crl;

    if (value == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }
    length = PORT_Strlen(value);

    if (setThisUpdate == PR_TRUE) {
        timeDest = &crl->lastUpdate;
    } else {
        timeDest = &crl->nextUpdate;
    }

    timeDest->type = siGeneralizedTime;
    timeDest->data = PORT_ArenaAlloc(arena, length);
    if (!timeDest->data) {
        return SECFailure;
    }
    PORT_Memcpy(timeDest->data, value, length);
    timeDest->len = length;

    return SECSuccess;
}

/* Adds new extension into CRL or added cert handles */
static SECStatus
crlgen_AddExtension(CRLGENGeneratorData *crlGenData, const char **extData)
{
    PORT_Assert(crlGenData && crlGenData->crlExtHandle);
    if (!crlGenData || !crlGenData->crlExtHandle) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (extData == NULL || *extData == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }
    if (!PORT_Strcmp(*extData, "authKeyId"))
        return crlgen_AddAuthKeyID(crlGenData, extData);
    else if (!PORT_Strcmp(*extData, "issuerAltNames"))
        return crlgen_AddIssuerAltNames(crlGenData, extData);
    else if (!PORT_Strcmp(*extData, "crlNumber"))
        return crlgen_AddCrlNumber(crlGenData, extData);
    else if (!PORT_Strcmp(*extData, "reasonCode"))
        return crlgen_AddEntryExtension(crlGenData, extData, "reasonCode",
                                        crlgen_CreateReasonCode);
    else if (!PORT_Strcmp(*extData, "invalidityDate"))
        return crlgen_AddEntryExtension(crlGenData, extData, "invalidityDate",
                                        crlgen_CreateInvalidityDate);
    else {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }
}

/* Created CRLGENEntryData for cert with serial number certId and
 * adds it to entryDataHashTable. certId can be a single cert serial
 * number or an inclusive rage of certs */

static SECStatus
crlgen_AddCert(CRLGENGeneratorData *crlGenData,
               char *certId, char *revocationDate)
{
    CERTSignedCrl *signCrl;
    SECItem *certIdItem;
    PLArenaPool *arena;
    PRUint64 rangeFrom = 0, rangeTo = 0, i = 0;
    int timeValLength = -1;
    SECStatus rv = SECFailure;
    void *mark;

    PORT_Assert(crlGenData && crlGenData->signCrl &&
                crlGenData->signCrl->arena);
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    signCrl = crlGenData->signCrl;
    arena = signCrl->arena;

    if (!certId || !revocationDate) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "insufficient number of arguments.\n");
        return SECFailure;
    }

    timeValLength = strlen(revocationDate);

    if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
        certId) {
        return SECFailure;
    }
    rangeFrom = crlGenData->rangeFrom;
    rangeTo = crlGenData->rangeTo;

    for (i = 0; i < rangeTo - rangeFrom + 1; i++) {
        CERTCrlEntry *entry;
        mark = PORT_ArenaMark(arena);
        entry = PORT_ArenaZNew(arena, CERTCrlEntry);
        if (entry == NULL) {
            goto loser;
        }

        certIdItem = SEC_ASN1EncodeInteger(arena, &entry->serialNumber,
                                           rangeFrom + i);
        if (!certIdItem) {
            goto loser;
        }

        if (crlgen_FindEntry(crlGenData, certIdItem)) {
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "entry already exists. Use \"range\" "
                              "and \"rmcert\" before adding a new one with the "
                              "same serial number %ld\n",
                              rangeFrom + i);
            goto loser;
        }

        entry->serialNumber.type = siBuffer;

        entry->revocationDate.type = siGeneralizedTime;

        entry->revocationDate.data =
            PORT_ArenaAlloc(arena, timeValLength);
        if (entry->revocationDate.data == NULL) {
            goto loser;
        }

        PORT_Memcpy(entry->revocationDate.data, revocationDate,
                    timeValLength * sizeof(char));
        entry->revocationDate.len = timeValLength;

        entry->extensions = NULL;
        if (!crlgen_PlaceAnEntry(crlGenData, entry, certIdItem)) {
            goto loser;
        }
        mark = NULL;
    }

    rv = SECSuccess;
loser:
    if (mark) {
        PORT_ArenaRelease(arena, mark);
    }
    return rv;
}

/* Removes certs from entryDataHashTable which have certId serial number.
 * certId can have value of a range of certs */

static SECStatus
crlgen_RmCert(CRLGENGeneratorData *crlGenData, char *certId)
{
    PRUint64 i = 0;

    PORT_Assert(crlGenData && certId);
    if (!crlGenData || !certId) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
        certId) {
        return SECFailure;
    }

    for (i = 0; i < crlGenData->rangeTo - crlGenData->rangeFrom + 1; i++) {
        SECItem *certIdItem = SEC_ASN1EncodeInteger(NULL, NULL,
                                                    crlGenData->rangeFrom + i);
        if (certIdItem) {
            CRLGENEntryData *extData =
                crlgen_FindEntry(crlGenData, certIdItem);
            if (!extData) {
                printf("Cert with id %s is not in the list\n", certId);
            } else {
                crlgen_RmEntry(crlGenData, certIdItem);
            }
            SECITEM_FreeItem(certIdItem, PR_TRUE);
        }
    }

    return SECSuccess;
}

/*************************************************************************
 * Lex Parser Helper functions are used to store parsed information
 * in context related structures. Context(or state) is identified base on
 * a type of a instruction parser currently is going through. New context
 * is identified by first token in a line. It can be addcert context,
 * addext context, etc. */


/* Updates CRL field depending on current context */
static SECStatus
crlgen_updateCrlFn_field(CRLGENGeneratorData *crlGenData, void *str)
{
    CRLGENCrlField *fieldStr = (CRLGENCrlField *)str;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (crlGenData->contextId) {
        case CRLGEN_ISSUER_CONTEXT:
            crlgen_SetIssuerField(crlGenData, fieldStr->value);
            break;
        case CRLGEN_UPDATE_CONTEXT:
            return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_TRUE);
            break;
        case CRLGEN_NEXT_UPDATE_CONTEXT:
            return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_FALSE);
            break;
        case CRLGEN_CHANGE_RANGE_CONTEXT:
            return crlgen_SetNewRangeField(crlGenData, fieldStr->value);
            break;
        default:
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "syntax error (unknow token type: %d)\n",
                              crlGenData->contextId);
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return SECFailure;
    }
    return SECSuccess;
}

/* Sets parsed data for CRL field update into temporary structure */
static SECStatus
crlgen_setNextDataFn_field(CRLGENGeneratorData *crlGenData, void *str,
                           void *data, unsigned short dtype)
{
    CRLGENCrlField *fieldStr = (CRLGENCrlField *)str;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (crlGenData->contextId) {
        case CRLGEN_CHANGE_RANGE_CONTEXT:
            if (dtype != CRLGEN_TYPE_DIGIT && dtype != CRLGEN_TYPE_DIGIT_RANGE) {
                crlgen_PrintError(crlGenData->parsedLineNum,
                                  "range value should have "
                                  "numeric or numeric range values.\n");
                return SECFailure;
            }
            break;
        case CRLGEN_NEXT_UPDATE_CONTEXT:
        case CRLGEN_UPDATE_CONTEXT:
            if (dtype != CRLGEN_TYPE_ZDATE) {
                crlgen_PrintError(crlGenData->parsedLineNum,
                                  "bad formated date. Should be "
                                  "YYYYMMDDHHMMSSZ.\n");
                return SECFailure;
            }
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "syntax error (unknow token type: %d).\n",
                              crlGenData->contextId, data);
            return SECFailure;
    }
    fieldStr->value = PORT_Strdup(data);
    if (!fieldStr->value) {
        return SECFailure;
    }
    return SECSuccess;
}

/* Triggers cert entries update depending on current context */
static SECStatus
crlgen_updateCrlFn_cert(CRLGENGeneratorData *crlGenData, void *str)
{
    CRLGENCertEntry *certStr = (CRLGENCertEntry *)str;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (crlGenData->contextId) {
        case CRLGEN_ADD_CERT_CONTEXT:
            return crlgen_AddCert(crlGenData, certStr->certId,
                                  certStr->revocationTime);
        case CRLGEN_RM_CERT_CONTEXT:
            return crlgen_RmCert(crlGenData, certStr->certId);
        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "syntax error (unknow token type: %d).\n",
                              crlGenData->contextId);
            return SECFailure;
    }
}

/* Sets parsed data for CRL entries update into temporary structure */
static SECStatus
crlgen_setNextDataFn_cert(CRLGENGeneratorData *crlGenData, void *str,
                          void *data, unsigned short dtype)
{
    CRLGENCertEntry *certStr = (CRLGENCertEntry *)str;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (dtype) {
        case CRLGEN_TYPE_DIGIT:
        case CRLGEN_TYPE_DIGIT_RANGE:
            certStr->certId = PORT_Strdup(data);
            if (!certStr->certId) {
                return SECFailure;
            }
            break;
        case CRLGEN_TYPE_DATE:
        case CRLGEN_TYPE_ZDATE:
            certStr->revocationTime = PORT_Strdup(data);
            if (!certStr->revocationTime) {
                return SECFailure;
            }
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "syntax error (unknow token type: %d).\n",
                              crlGenData->contextId);
            return SECFailure;
    }
    return SECSuccess;
}

/* Triggers cert entries/crl extension update */
static SECStatus
crlgen_updateCrlFn_extension(CRLGENGeneratorData *crlGenData, void *str)
{
    CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str;

    return crlgen_AddExtension(crlGenData, (const char **)extStr->extData);
}

/* Defines maximum number of fields extension may have */
#define MAX_EXT_DATA_LENGTH 10

/* Sets parsed extension data for CRL entries/CRL extensions update
 * into temporary structure */

static SECStatus
crlgen_setNextDataFn_extension(CRLGENGeneratorData *crlGenData, void *str,
                               void *data, unsigned short dtype)
{
    CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry *)str;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (extStr->extData == NULL) {
        extStr->extData = PORT_ZNewArray(char *, MAX_EXT_DATA_LENGTH);
        if (!extStr->extData) {
            return SECFailure;
        }
    }
    if (extStr->nextUpdatedData >= MAX_EXT_DATA_LENGTH) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        crlgen_PrintError(crlGenData->parsedLineNum,
                          "number of fields in extension "
                          "exceeded maximum allowed data length: %d.\n",
                          MAX_EXT_DATA_LENGTH);
        return SECFailure;
    }
    extStr->extData[extStr->nextUpdatedData] = PORT_Strdup(data);
    if (!extStr->extData[extStr->nextUpdatedData]) {
        return SECFailure;
    }
    extStr->nextUpdatedData += 1;

    return SECSuccess;
}

/****************************************************************************************
 * Top level functions are triggered directly by parser.
 */


/*
 * crl generation script parser recreates a temporary data staructure
 * for each line it is going through. This function cleans temp structure.
 */

void
crlgen_destroyTempData(CRLGENGeneratorData *crlGenData)
{
    if (crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
        switch (crlGenData->contextId) {
            case CRLGEN_ISSUER_CONTEXT:
            case CRLGEN_UPDATE_CONTEXT:
            case CRLGEN_NEXT_UPDATE_CONTEXT:
            case CRLGEN_CHANGE_RANGE_CONTEXT:
                if (crlGenData->crlField->value)
                    PORT_Free(crlGenData->crlField->value);
                PORT_Free(crlGenData->crlField);
                break;
            case CRLGEN_ADD_CERT_CONTEXT:
            case CRLGEN_RM_CERT_CONTEXT:
                if (crlGenData->certEntry->certId)
                    PORT_Free(crlGenData->certEntry->certId);
                if (crlGenData->certEntry->revocationTime)
                    PORT_Free(crlGenData->certEntry->revocationTime);
                PORT_Free(crlGenData->certEntry);
                break;
            case CRLGEN_ADD_EXTENSION_CONTEXT:
                if (crlGenData->extensionEntry->extData) {
                    int i = 0;
                    for (; i < crlGenData->extensionEntry->nextUpdatedData; i++)
                        PORT_Free(*(crlGenData->extensionEntry->extData + i));
                    PORT_Free(crlGenData->extensionEntry->extData);
                }
                PORT_Free(crlGenData->extensionEntry);
                break;
        }
        crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
    }
}

SECStatus
crlgen_updateCrl(CRLGENGeneratorData *crlGenData)
{
    SECStatus rv = SECSuccess;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (crlGenData->contextId) {
        case CRLGEN_ISSUER_CONTEXT:
        case CRLGEN_UPDATE_CONTEXT:
        case CRLGEN_NEXT_UPDATE_CONTEXT:
        case CRLGEN_CHANGE_RANGE_CONTEXT:
            rv = crlGenData->crlField->updateCrlFn(crlGenData, crlGenData->crlField);
            break;
        case CRLGEN_RM_CERT_CONTEXT:
        case CRLGEN_ADD_CERT_CONTEXT:
            rv = crlGenData->certEntry->updateCrlFn(crlGenData, crlGenData->certEntry);
            break;
        case CRLGEN_ADD_EXTENSION_CONTEXT:
            rv = crlGenData->extensionEntry->updateCrlFn(crlGenData, crlGenData->extensionEntry);
            break;
        case CRLGEN_UNKNOWN_CONTEXT:
            break;
        default:
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "unknown lang context type code: %d.\n",
                              crlGenData->contextId);
            PORT_Assert(0);
            return SECFailure;
    }
    /* Clrean structures after crl update */
    crlgen_destroyTempData(crlGenData);

    crlGenData->parsedLineNum += 1;

    return rv;
}

SECStatus
crlgen_setNextData(CRLGENGeneratorData *crlGenData, void *data,
                   unsigned short dtype)
{
    SECStatus rv = SECSuccess;

    PORT_Assert(crlGenData);
    if (!crlGenData) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (crlGenData->contextId) {
        case CRLGEN_ISSUER_CONTEXT:
        case CRLGEN_UPDATE_CONTEXT:
        case CRLGEN_NEXT_UPDATE_CONTEXT:
        case CRLGEN_CHANGE_RANGE_CONTEXT:
            rv = crlGenData->crlField->setNextDataFn(crlGenData, crlGenData->crlField,
                                                     data, dtype);
            break;
        case CRLGEN_ADD_CERT_CONTEXT:
        case CRLGEN_RM_CERT_CONTEXT:
            rv = crlGenData->certEntry->setNextDataFn(crlGenData, crlGenData->certEntry,
                                                      data, dtype);
            break;
        case CRLGEN_ADD_EXTENSION_CONTEXT:
            rv =
                crlGenData->extensionEntry->setNextDataFn(crlGenData, crlGenData->extensionEntry, data, dtype);
            break;
        case CRLGEN_UNKNOWN_CONTEXT:
            break;
        default:
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "unknown context type: %d.\n",
                              crlGenData->contextId);
            PORT_Assert(0);
            return SECFailure;
    }
    return rv;
}

SECStatus
crlgen_createNewLangStruct(CRLGENGeneratorData *crlGenData,
                           unsigned structType)
{
    PORT_Assert(crlGenData &&
                crlGenData->contextId == CRLGEN_UNKNOWN_CONTEXT);
    if (!crlGenData ||
        crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    switch (structType) {
        case CRLGEN_ISSUER_CONTEXT:
        case CRLGEN_UPDATE_CONTEXT:
        case CRLGEN_NEXT_UPDATE_CONTEXT:
        case CRLGEN_CHANGE_RANGE_CONTEXT:
            crlGenData->crlField = PORT_New(CRLGENCrlField);
            if (!crlGenData->crlField) {
                return SECFailure;
            }
            crlGenData->contextId = structType;
            crlGenData->crlField->value = NULL;
            crlGenData->crlField->updateCrlFn = &crlgen_updateCrlFn_field;
            crlGenData->crlField->setNextDataFn = &crlgen_setNextDataFn_field;
            break;
        case CRLGEN_RM_CERT_CONTEXT:
        case CRLGEN_ADD_CERT_CONTEXT:
            crlGenData->certEntry = PORT_New(CRLGENCertEntry);
            if (!crlGenData->certEntry) {
                return SECFailure;
            }
            crlGenData->contextId = structType;
            crlGenData->certEntry->certId = 0;
            crlGenData->certEntry->revocationTime = NULL;
            crlGenData->certEntry->updateCrlFn = &crlgen_updateCrlFn_cert;
            crlGenData->certEntry->setNextDataFn = &crlgen_setNextDataFn_cert;
            break;
        case CRLGEN_ADD_EXTENSION_CONTEXT:
            crlGenData->extensionEntry = PORT_New(CRLGENExtensionEntry);
            if (!crlGenData->extensionEntry) {
                return SECFailure;
            }
            crlGenData->contextId = structType;
            crlGenData->extensionEntry->extData = NULL;
            crlGenData->extensionEntry->nextUpdatedData = 0;
            crlGenData->extensionEntry->updateCrlFn =
                &crlgen_updateCrlFn_extension;
            crlGenData->extensionEntry->setNextDataFn =
                &crlgen_setNextDataFn_extension;
            break;
        case CRLGEN_UNKNOWN_CONTEXT:
            break;
        default:
            crlgen_PrintError(crlGenData->parsedLineNum,
                              "unknown context type: %d.\n", structType);
            PORT_Assert(0);
            return SECFailure;
    }
    return SECSuccess;
}

/* Parser initialization function */
CRLGENGeneratorData *
CRLGEN_InitCrlGeneration(CERTSignedCrl *signCrl, PRFileDesc *src)
{
    CRLGENGeneratorData *crlGenData = NULL;

    PORT_Assert(signCrl && src);
    if (!signCrl || !src) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    crlGenData = PORT_ZNew(CRLGENGeneratorData);
    if (!crlGenData) {
        return NULL;
    }

    crlGenData->entryDataHashTable =
        PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
                        PL_CompareValues, NULL, NULL);
    if (!crlGenData->entryDataHashTable) {
        PORT_Free(crlGenData);
        return NULL;
    }

    crlGenData->src = src;
    crlGenData->parsedLineNum = 1;
    crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
    crlGenData->signCrl = signCrl;
    crlGenData->rangeFrom = 0;
    crlGenData->rangeTo = 0;
    crlGenData->crlExtHandle = NULL;

    PORT_SetError(0);

    return crlGenData;
}

void
CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData)
{
    if (!crlGenData)
        return;
    if (crlGenData->src)
        PR_Close(crlGenData->src);
    PL_HashTableDestroy(crlGenData->entryDataHashTable);
    PORT_Free(crlGenData);
}

Messung V0.5
C=98 H=87 G=92

¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.