Blame nss/cmd/crlutil/crlgen.c

Packit 40b132
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit 40b132
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit 40b132
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit 40b132
Packit 40b132
/*
Packit 40b132
** crlgen.c
Packit 40b132
**
Packit 40b132
** utility for managing certificates revocation lists generation
Packit 40b132
**
Packit 40b132
*/
Packit 40b132
Packit 40b132
Packit 40b132
#include <stdio.h>
Packit 40b132
#include <math.h>
Packit 40b132
Packit 40b132
#include "nspr.h"
Packit 40b132
#include "plgetopt.h"
Packit 40b132
#include "nss.h"
Packit 40b132
#include "secutil.h"
Packit 40b132
#include "cert.h"
Packit 40b132
#include "certi.h"
Packit 40b132
#include "certdb.h"
Packit 40b132
#include "pk11func.h"
Packit 40b132
#include "crlgen.h"
Packit 40b132
Packit 40b132
Packit 40b132
/* Destroys extHandle and data. data was create on heap.
Packit 40b132
 * extHandle creaded by CERT_StartCRLEntryExtensions. entry
Packit 40b132
 * was allocated on arena.*/
Packit 40b132
static void
Packit 40b132
destroyEntryData(CRLGENEntryData *data)
Packit 40b132
{
Packit 40b132
    if (!data)
Packit 40b132
        return;
Packit 40b132
    PORT_Assert(data->entry);
Packit 40b132
    if (data->extHandle)
Packit 40b132
        CERT_FinishExtensions(data->extHandle);
Packit 40b132
    PORT_Free(data);
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Prints error messages along with line number */
Packit 40b132
void 
Packit 40b132
crlgen_PrintError(int line, char *msg, ...)
Packit 40b132
{
Packit 40b132
    va_list args;
Packit 40b132
Packit 40b132
    va_start(args, msg);
Packit 40b132
Packit 40b132
    fprintf(stderr, "crlgen: (line: %d) ", line);
Packit 40b132
    vfprintf(stderr, msg, args);
Packit 40b132
Packit 40b132
    va_end(args);
Packit 40b132
}
Packit 40b132
/* Finds CRLGENEntryData in hashtable according PRUint64 value
Packit 40b132
 * - certId : cert serial number*/
Packit 40b132
static CRLGENEntryData*
Packit 40b132
crlgen_FindEntry(CRLGENGeneratorData *crlGenData, SECItem *certId) 
Packit 40b132
{
Packit 40b132
    if (!crlGenData->entryDataHashTable || !certId)
Packit 40b132
        return NULL;
Packit 40b132
    return (CRLGENEntryData*)
Packit 40b132
        PL_HashTableLookup(crlGenData->entryDataHashTable,
Packit 40b132
                           certId);
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Removes CRLGENEntryData from hashtable according to certId
Packit 40b132
 * - certId : cert serial number*/
Packit 40b132
static SECStatus
Packit 40b132
crlgen_RmEntry(CRLGENGeneratorData *crlGenData, SECItem *certId) 
Packit 40b132
{
Packit 40b132
    CRLGENEntryData *data = NULL;
Packit 40b132
Packit 40b132
    if (!crlGenData->entryDataHashTable)
Packit 40b132
        return SECSuccess;
Packit 40b132
    data = crlgen_FindEntry(crlGenData, certId);
Packit 40b132
    if (!data)
Packit 40b132
        return SECSuccess;
Packit 40b132
    if (PL_HashTableRemove(crlGenData->entryDataHashTable, certId))
Packit 40b132
        return SECSuccess;
Packit 40b132
    destroyEntryData(data);
Packit 40b132
    return SECFailure;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Stores CRLGENEntryData in hashtable according to certId
Packit 40b132
 * - certId : cert serial number*/
Packit 40b132
static CRLGENEntryData*
Packit 40b132
crlgen_PlaceAnEntry(CRLGENGeneratorData *crlGenData,
Packit 40b132
                    CERTCrlEntry *entry, SECItem *certId)
Packit 40b132
{
Packit 40b132
    CRLGENEntryData *newData = NULL;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->entryDataHashTable &&
Packit 40b132
                entry);
Packit 40b132
    if (!crlGenData || !crlGenData->entryDataHashTable || !entry) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    newData = PORT_ZNew(CRLGENEntryData);
Packit 40b132
    if (!newData) {
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
    newData->entry = entry;
Packit 40b132
    newData->certId = certId;
Packit 40b132
    if (!PL_HashTableAdd(crlGenData->entryDataHashTable,
Packit 40b132
                         newData->certId, newData)) { 
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "Can not add entryData structure\n");
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
    return newData;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Use this structure to keep pointer when commiting entries extensions */
Packit 40b132
struct commitData {
Packit 40b132
    int pos;
Packit 40b132
    CERTCrlEntry **entries;
Packit 40b132
};
Packit 40b132
Packit 40b132
/* HT PL_HashTableEnumerateEntries callback. Sorts hashtable entries of the
Packit 40b132
 * table he. Returns value through arg parameter*/
Packit 40b132
static PRIntn PR_CALLBACK 
Packit 40b132
crlgen_CommitEntryData(PLHashEntry *he, PRIntn i, void *arg)
Packit 40b132
{
Packit 40b132
    CRLGENEntryData *data = NULL;
Packit 40b132
Packit 40b132
    PORT_Assert(he);
Packit 40b132
    if (!he) {
Packit 40b132
        return HT_ENUMERATE_NEXT;
Packit 40b132
    }
Packit 40b132
    data = (CRLGENEntryData*)he->value;
Packit 40b132
Packit 40b132
    PORT_Assert(data);
Packit 40b132
    PORT_Assert(arg);
Packit 40b132
Packit 40b132
    if (data) {
Packit 40b132
        struct commitData *dt = (struct commitData*)arg;
Packit 40b132
        dt->entries[dt->pos++] = data->entry;
Packit 40b132
        destroyEntryData(data);
Packit 40b132
    }
Packit 40b132
    return HT_ENUMERATE_NEXT;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
Packit 40b132
/* Copy char * datainto allocated in arena SECItem */
Packit 40b132
static SECStatus 
Packit 40b132
crlgen_SetString(PLArenaPool *arena, const char *dataIn, SECItem *value)
Packit 40b132
{
Packit 40b132
    SECItem item;
Packit 40b132
Packit 40b132
    PORT_Assert(arena && dataIn);
Packit 40b132
    if (!arena || !dataIn) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    item.data = (void*)dataIn;
Packit 40b132
    item.len = PORT_Strlen(dataIn);
Packit 40b132
Packit 40b132
    return SECITEM_CopyItem(arena, value, &item);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
Packit 40b132
static CERTGeneralName *
Packit 40b132
crlgen_GetGeneralName (PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
Packit 40b132
                       const char *data)
Packit 40b132
{
Packit 40b132
    CERTGeneralName *namesList = NULL;
Packit 40b132
    CERTGeneralName *current;
Packit 40b132
    CERTGeneralName *tail = NULL;
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
    const char *nextChunk = NULL;
Packit 40b132
    const char *currData = NULL;
Packit 40b132
    int intValue;
Packit 40b132
    char buffer[512];
Packit 40b132
    void *mark;
Packit 40b132
Packit 40b132
    if (!data)
Packit 40b132
        return NULL;
Packit 40b132
    PORT_Assert (arena);
Packit 40b132
    if (!arena) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    mark = PORT_ArenaMark (arena);
Packit 40b132
Packit 40b132
    nextChunk = data;
Packit 40b132
    currData = data;
Packit 40b132
    do {
Packit 40b132
        int nameLen = 0;
Packit 40b132
        char name[128];
Packit 40b132
        const char *sepPrt = NULL;
Packit 40b132
        nextChunk = PORT_Strchr(currData, '|');
Packit 40b132
        if (!nextChunk)
Packit 40b132
            nextChunk = data + strlen(data);
Packit 40b132
        sepPrt = PORT_Strchr(currData, ':');
Packit 40b132
        if (sepPrt == NULL || sepPrt >= nextChunk) {
Packit 40b132
            *buffer = '\0';
Packit 40b132
            sepPrt = nextChunk;
Packit 40b132
        } else {
Packit 40b132
            PORT_Memcpy(buffer, sepPrt + 1,
Packit 40b132
                        (nextChunk - sepPrt - 1));
Packit 40b132
            buffer[nextChunk - sepPrt - 1] = '\0';
Packit 40b132
        }
Packit 40b132
        nameLen = PR_MIN(sepPrt - currData, sizeof(name) - 1 );
Packit 40b132
        PORT_Memcpy(name, currData, nameLen);
Packit 40b132
        name[nameLen] = '\0';
Packit 40b132
        currData = nextChunk + 1;
Packit 40b132
Packit 40b132
        if (!PORT_Strcmp(name, "otherName"))
Packit 40b132
            intValue = certOtherName;
Packit 40b132
        else if (!PORT_Strcmp(name, "rfc822Name"))
Packit 40b132
            intValue = certRFC822Name;
Packit 40b132
        else if (!PORT_Strcmp(name, "dnsName"))
Packit 40b132
            intValue = certDNSName;
Packit 40b132
        else if (!PORT_Strcmp(name, "x400Address"))
Packit 40b132
            intValue = certX400Address;
Packit 40b132
        else if (!PORT_Strcmp(name, "directoryName"))
Packit 40b132
            intValue = certDirectoryName;
Packit 40b132
        else if (!PORT_Strcmp(name, "ediPartyName"))
Packit 40b132
            intValue = certEDIPartyName;
Packit 40b132
        else if (!PORT_Strcmp(name, "URI"))
Packit 40b132
            intValue = certURI;
Packit 40b132
        else if (!PORT_Strcmp(name, "ipAddress"))
Packit 40b132
            intValue = certIPAddress;
Packit 40b132
        else if (!PORT_Strcmp(name, "registerID"))
Packit 40b132
            intValue = certRegisterID;
Packit 40b132
        else intValue = -1;
Packit 40b132
Packit 40b132
        if (intValue >= certOtherName && intValue <= certRegisterID) {
Packit 40b132
            if (namesList == NULL) {
Packit 40b132
                namesList = current = tail = PORT_ArenaZNew(arena,
Packit 40b132
                                                            CERTGeneralName);
Packit 40b132
            } else {
Packit 40b132
                current = PORT_ArenaZNew(arena, CERTGeneralName);
Packit 40b132
            }
Packit 40b132
            if (current == NULL) {
Packit 40b132
                rv = SECFailure;
Packit 40b132
                break;
Packit 40b132
            }
Packit 40b132
        } else {
Packit 40b132
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
            break;
Packit 40b132
        }
Packit 40b132
        current->type = intValue;
Packit 40b132
        switch (current->type) {
Packit 40b132
          case certURI:
Packit 40b132
          case certDNSName:
Packit 40b132
          case certRFC822Name:
Packit 40b132
              current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer));
Packit 40b132
              if (current->name.other.data == NULL) {
Packit 40b132
                  rv = SECFailure;
Packit 40b132
                  break;
Packit 40b132
              }
Packit 40b132
              PORT_Memcpy(current->name.other.data, buffer,
Packit 40b132
                          current->name.other.len = strlen(buffer));
Packit 40b132
              break;
Packit 40b132
Packit 40b132
          case certEDIPartyName:
Packit 40b132
          case certIPAddress:
Packit 40b132
          case certOtherName:
Packit 40b132
          case certRegisterID:
Packit 40b132
          case certX400Address: {
Packit 40b132
Packit 40b132
              current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer) + 2);
Packit 40b132
              if (current->name.other.data == NULL) {
Packit 40b132
                  rv = SECFailure;
Packit 40b132
                  break;
Packit 40b132
              }
Packit 40b132
Packit 40b132
              PORT_Memcpy (current->name.other.data + 2, buffer, strlen (buffer));
Packit 40b132
/* This may not be accurate for all cases.For now, use this tag type */
Packit 40b132
              current->name.other.data[0] = (char)(((current->type - 1) & 0x1f)| 0x80);
Packit 40b132
              current->name.other.data[1] = (char)strlen (buffer);
Packit 40b132
              current->name.other.len = strlen (buffer) + 2;
Packit 40b132
              break;
Packit 40b132
          }
Packit 40b132
Packit 40b132
          case certDirectoryName: {
Packit 40b132
              CERTName *directoryName = NULL;
Packit 40b132
Packit 40b132
              directoryName = CERT_AsciiToName (buffer);
Packit 40b132
              if (!directoryName) {
Packit 40b132
                  rv = SECFailure;
Packit 40b132
                  break;
Packit 40b132
              }
Packit 40b132
Packit 40b132
              rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
Packit 40b132
              CERT_DestroyName (directoryName);
Packit 40b132
Packit 40b132
              break;
Packit 40b132
          }
Packit 40b132
        }
Packit 40b132
        if (rv != SECSuccess)
Packit 40b132
            break;
Packit 40b132
        current->l.next = &(namesList->l);
Packit 40b132
        current->l.prev = &(tail->l);
Packit 40b132
        tail->l.next = &(current->l);
Packit 40b132
        tail = current;
Packit 40b132
Packit 40b132
    } while(nextChunk != data + strlen(data));
Packit 40b132
Packit 40b132
    if (rv != SECSuccess) {
Packit 40b132
        PORT_ArenaRelease (arena, mark);
Packit 40b132
        namesList = NULL;
Packit 40b132
    }
Packit 40b132
    return (namesList);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Creates CERTGeneralName from parsed data for the Authority Key Extension */
Packit 40b132
static CERTGeneralName *
Packit 40b132
crlgen_DistinguishedName (PLArenaPool *arena, CRLGENGeneratorData *crlGenData,
Packit 40b132
                          const char *data)
Packit 40b132
{
Packit 40b132
    CERTName *directoryName = NULL;
Packit 40b132
    CERTGeneralName *current;
Packit 40b132
    SECStatus rv = SECFailure;
Packit 40b132
    void *mark;
Packit 40b132
Packit 40b132
    if (!data)
Packit 40b132
        return NULL;
Packit 40b132
    PORT_Assert (arena);
Packit 40b132
    if (!arena) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    mark = PORT_ArenaMark (arena);
Packit 40b132
Packit 40b132
    current = PORT_ArenaZNew(arena, CERTGeneralName);
Packit 40b132
    if (current == NULL) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
    current->type = certDirectoryName;
Packit 40b132
    current->l.next = &current->l;
Packit 40b132
    current->l.prev = &current->l;
Packit 40b132
    
Packit 40b132
    directoryName = CERT_AsciiToName ((char*)data);
Packit 40b132
    if (!directoryName) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
    
Packit 40b132
    rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
Packit 40b132
    CERT_DestroyName (directoryName);
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    if (rv != SECSuccess) {
Packit 40b132
        PORT_SetError (rv);
Packit 40b132
        PORT_ArenaRelease (arena, mark);
Packit 40b132
        current = NULL;
Packit 40b132
    }
Packit 40b132
    return (current);
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Adding Authority Key ID extension to extension handle. */
Packit 40b132
static SECStatus 
Packit 40b132
crlgen_AddAuthKeyID (CRLGENGeneratorData *crlGenData,
Packit 40b132
                     const char **dataArr)
Packit 40b132
{
Packit 40b132
    void *extHandle = NULL;
Packit 40b132
    CERTAuthKeyID *authKeyID = NULL;
Packit 40b132
    PLArenaPool *arena = NULL;
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
Packit 40b132
    PORT_Assert(dataArr && crlGenData);
Packit 40b132
    if (!crlGenData || !dataArr) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    extHandle = crlGenData->crlExtHandle;
Packit 40b132
Packit 40b132
    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of parameters.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
Packit 40b132
    if (!arena) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
Packit 40b132
    if (authKeyID == NULL) {
Packit 40b132
        rv = SECFailure;
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (dataArr[3] == NULL) {
Packit 40b132
        rv = crlgen_SetString (arena, dataArr[2], &authKeyID->keyID);
Packit 40b132
        if (rv != SECSuccess)
Packit 40b132
            goto loser;
Packit 40b132
    } else {
Packit 40b132
        rv = crlgen_SetString (arena, dataArr[3],
Packit 40b132
                               &authKeyID->authCertSerialNumber);
Packit 40b132
        if (rv != SECSuccess)
Packit 40b132
            goto loser;
Packit 40b132
Packit 40b132
        authKeyID->authCertIssuer = 
Packit 40b132
            crlgen_DistinguishedName (arena, crlGenData, dataArr[2]);
Packit 40b132
        if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError ()){
Packit 40b132
            crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
Packit 40b132
            rv = SECFailure;
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
    rv =
Packit 40b132
        SECU_EncodeAndAddExtensionValue(arena, extHandle, authKeyID,
Packit 40b132
                                        (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
Packit 40b132
                                        SEC_OID_X509_AUTH_KEY_ID, 
Packit 40b132
                                        (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
Packit 40b132
  loser:
Packit 40b132
    if (arena)
Packit 40b132
        PORT_FreeArena (arena, PR_FALSE);
Packit 40b132
    return rv;
Packit 40b132
} 
Packit 40b132
Packit 40b132
/* Creates and add Subject Alternative Names extension */
Packit 40b132
static SECStatus 
Packit 40b132
crlgen_AddIssuerAltNames(CRLGENGeneratorData *crlGenData,
Packit 40b132
                          const char **dataArr)
Packit 40b132
{
Packit 40b132
    CERTGeneralName *nameList = NULL;
Packit 40b132
    PLArenaPool *arena = NULL;
Packit 40b132
    void *extHandle = NULL;
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
Packit 40b132
Packit 40b132
    PORT_Assert(dataArr && crlGenData);
Packit 40b132
    if (!crlGenData || !dataArr) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (!dataArr || !dataArr[0] || !dataArr[1] || !dataArr[2]) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    PORT_Assert(dataArr && crlGenData);
Packit 40b132
    if (!crlGenData || !dataArr) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    extHandle = crlGenData->crlExtHandle;
Packit 40b132
Packit 40b132
    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of parameters.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
Packit 40b132
    if (!arena) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    nameList = crlgen_GetGeneralName(arena, crlGenData, dataArr[2]);
Packit 40b132
    if (nameList == NULL) {
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum, "syntax error.\n");
Packit 40b132
        rv = SECFailure;
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    rv =
Packit 40b132
        SECU_EncodeAndAddExtensionValue(arena, extHandle, nameList,
Packit 40b132
                                        (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
Packit 40b132
                                        SEC_OID_X509_ISSUER_ALT_NAME, 
Packit 40b132
                                        (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeAltNameExtension);
Packit 40b132
  loser:
Packit 40b132
    if (arena)
Packit 40b132
        PORT_FreeArena (arena, PR_FALSE);
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Creates and adds CRLNumber extension to extension handle.
Packit 40b132
 * Since, this is CRL extension, extension handle is the one 
Packit 40b132
 * related to CRL extensions */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_AddCrlNumber(CRLGENGeneratorData *crlGenData, const char **dataArr)
Packit 40b132
{
Packit 40b132
    PLArenaPool *arena = NULL;
Packit 40b132
    SECItem encodedItem;
Packit 40b132
    void *extHandle = crlGenData->crlExtHandle;
Packit 40b132
    void *dummy;
Packit 40b132
    SECStatus rv = SECFailure;
Packit 40b132
    int code = 0;
Packit 40b132
Packit 40b132
    PORT_Assert(dataArr && crlGenData);
Packit 40b132
    if (!crlGenData || !dataArr) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (!dataArr[0] || !dataArr[1] || !dataArr[2]) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
Packit 40b132
    if (arena == NULL) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    code = atoi(dataArr[2]);
Packit 40b132
    if (code == 0 && *dataArr[2] != '0') {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    dummy = SEC_ASN1EncodeInteger(arena, &encodedItem, code);
Packit 40b132
    if (!dummy) {
Packit 40b132
        rv = SECFailure;
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    rv = CERT_AddExtension (extHandle, SEC_OID_X509_CRL_NUMBER, &encodedItem, 
Packit 40b132
                            (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
Packit 40b132
                            PR_TRUE);
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    if (arena)
Packit 40b132
        PORT_FreeArena(arena, PR_FALSE);
Packit 40b132
    return rv;
Packit 40b132
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Creates Cert Revocation Reason code extension. Encodes it and
Packit 40b132
 * returns as SECItem structure */
Packit 40b132
static SECItem*
Packit 40b132
crlgen_CreateReasonCode(PLArenaPool *arena, const char **dataArr,
Packit 40b132
                        int *extCode)
Packit 40b132
{
Packit 40b132
    SECItem *encodedItem;
Packit 40b132
    void *dummy;
Packit 40b132
    void *mark;
Packit 40b132
    int code = 0;
Packit 40b132
Packit 40b132
    PORT_Assert(arena && dataArr);
Packit 40b132
    if (!arena || !dataArr) {
Packit 40b132
        goto loser;
Packit 40b132
    } 
Packit 40b132
Packit 40b132
    mark = PORT_ArenaMark(arena);
Packit 40b132
Packit 40b132
    encodedItem = PORT_ArenaZNew (arena, SECItem);
Packit 40b132
    if (encodedItem == NULL) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (dataArr[2] == NULL) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    code = atoi(dataArr[2]);
Packit 40b132
    /* aACompromise(10) is the last possible of the values 
Packit 40b132
     * for the Reason Core Extension */
Packit 40b132
    if ((code == 0 && *dataArr[2] != '0') || code > 10) {
Packit 40b132
        
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    dummy = SEC_ASN1EncodeInteger(arena, encodedItem, code);
Packit 40b132
    if (!dummy) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    *extCode = SEC_OID_X509_REASON_CODE;
Packit 40b132
    return encodedItem;
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    PORT_ArenaRelease (arena, mark);
Packit 40b132
    return NULL;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Creates Cert Invalidity Date extension. Encodes it and
Packit 40b132
 * returns as SECItem structure */
Packit 40b132
static SECItem*
Packit 40b132
crlgen_CreateInvalidityDate(PLArenaPool *arena, const char **dataArr,
Packit 40b132
                       int *extCode)
Packit 40b132
{
Packit 40b132
    SECItem *encodedItem;
Packit 40b132
    int length = 0;
Packit 40b132
    void *mark;
Packit 40b132
Packit 40b132
    PORT_Assert(arena && dataArr);
Packit 40b132
    if (!arena || !dataArr) {
Packit 40b132
        goto loser;
Packit 40b132
    } 
Packit 40b132
Packit 40b132
    mark = PORT_ArenaMark(arena);
Packit 40b132
Packit 40b132
    encodedItem = PORT_ArenaZNew(arena, SECItem);
Packit 40b132
    if (encodedItem == NULL) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    length = PORT_Strlen(dataArr[2]);
Packit 40b132
Packit 40b132
    encodedItem->type = siGeneralizedTime;
Packit 40b132
    encodedItem->data = PORT_ArenaAlloc(arena, length);
Packit 40b132
    if (!encodedItem->data) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    PORT_Memcpy(encodedItem->data, dataArr[2], (encodedItem->len = length) *
Packit 40b132
                sizeof(char));
Packit 40b132
Packit 40b132
    *extCode = SEC_OID_X509_INVALID_DATE;
Packit 40b132
    return encodedItem;
Packit 40b132
    
Packit 40b132
  loser:
Packit 40b132
    PORT_ArenaRelease(arena, mark);
Packit 40b132
    return NULL;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Creates(by calling extCreator function) and adds extension to a set
Packit 40b132
 * of already added certs. Uses values of rangeFrom and rangeTo from
Packit 40b132
 * CRLGENCrlGenCtl structure for identifying the inclusive set of certs */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_AddEntryExtension(CRLGENGeneratorData *crlGenData,
Packit 40b132
                         const char **dataArr, char *extName,
Packit 40b132
                         SECItem* (*extCreator)(PLArenaPool *arena,
Packit 40b132
                                                const char **dataArr,
Packit 40b132
                                                int *extCode))
Packit 40b132
{
Packit 40b132
    PRUint64 i = 0;
Packit 40b132
    SECStatus rv = SECFailure;
Packit 40b132
    int extCode = 0;
Packit 40b132
    PRUint64 lastRange ;
Packit 40b132
    SECItem *ext = NULL;
Packit 40b132
    PLArenaPool *arena = NULL;
Packit 40b132
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData &&  dataArr);
Packit 40b132
    if (!crlGenData || !dataArr) {
Packit 40b132
        goto loser;
Packit 40b132
    } 
Packit 40b132
    
Packit 40b132
    if (!dataArr[0] || !dataArr[1]) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum, 
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
    }
Packit 40b132
Packit 40b132
    lastRange = crlGenData->rangeTo - crlGenData->rangeFrom + 1;
Packit 40b132
Packit 40b132
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
Packit 40b132
    if (arena == NULL) {
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    ext = extCreator(arena, dataArr, &extCode);
Packit 40b132
    if (ext == NULL) {
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum, 
Packit 40b132
                          "got error while creating extension: %s\n",
Packit 40b132
                          extName);
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    for (i = 0;i < lastRange;i++) {
Packit 40b132
        CRLGENEntryData * extData = NULL;
Packit 40b132
        void *extHandle = NULL;
Packit 40b132
        SECItem * certIdItem =
Packit 40b132
            SEC_ASN1EncodeInteger(arena, NULL,
Packit 40b132
                                  crlGenData->rangeFrom + i);
Packit 40b132
        if (!certIdItem) {
Packit 40b132
            rv = SECFailure;
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        extData = crlgen_FindEntry(crlGenData, certIdItem);
Packit 40b132
        if (!extData) {
Packit 40b132
            crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                              "can not add extension: crl entry "
Packit 40b132
                              "(serial number: %d) is not in the list yet.\n",
Packit 40b132
                              crlGenData->rangeFrom + i);
Packit 40b132
            continue;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        extHandle = extData->extHandle;
Packit 40b132
        if (extHandle == NULL) {
Packit 40b132
            extHandle = extData->extHandle =
Packit 40b132
                CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
Packit 40b132
                                             (CERTCrlEntry*)extData->entry);
Packit 40b132
        }
Packit 40b132
        rv = CERT_AddExtension (extHandle, extCode, ext, 
Packit 40b132
                               (*dataArr[1] == '1') ? PR_TRUE : PR_FALSE,
Packit 40b132
                               PR_TRUE);
Packit 40b132
        if (rv == SECFailure) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    if (arena)
Packit 40b132
        PORT_FreeArena(arena, PR_FALSE);
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Commits all added entries and their's extensions into CRL. */
Packit 40b132
SECStatus
Packit 40b132
CRLGEN_CommitExtensionsAndEntries(CRLGENGeneratorData *crlGenData)
Packit 40b132
{
Packit 40b132
    int size = 0;
Packit 40b132
    CERTCrl *crl;
Packit 40b132
    PLArenaPool *arena;
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
    void *mark;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->signCrl && crlGenData->signCrl->arena);
Packit 40b132
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    arena = crlGenData->signCrl->arena;
Packit 40b132
    crl = &crlGenData->signCrl->crl;
Packit 40b132
Packit 40b132
    mark = PORT_ArenaMark(arena);
Packit 40b132
Packit 40b132
    if (crlGenData->crlExtHandle)
Packit 40b132
        CERT_FinishExtensions(crlGenData->crlExtHandle);
Packit 40b132
Packit 40b132
    size = crlGenData->entryDataHashTable->nentries;
Packit 40b132
    crl->entries = NULL;
Packit 40b132
    if (size) {
Packit 40b132
        crl->entries = PORT_ArenaZNewArray(arena, CERTCrlEntry*, size + 1);
Packit 40b132
        if (!crl->entries) {
Packit 40b132
            rv = SECFailure;
Packit 40b132
        } else {
Packit 40b132
            struct commitData dt;
Packit 40b132
            dt.entries = crl->entries;
Packit 40b132
            dt.pos = 0;
Packit 40b132
            PL_HashTableEnumerateEntries(crlGenData->entryDataHashTable,
Packit 40b132
                                         &crlgen_CommitEntryData, &dt);
Packit 40b132
            /* Last should be NULL */
Packit 40b132
            crl->entries[size] = NULL;
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (rv != SECSuccess)
Packit 40b132
        PORT_ArenaRelease(arena, mark);
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Initializes extHandle with data from extensions array */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_InitExtensionHandle(void *extHandle,
Packit 40b132
                           CERTCertExtension **extensions)
Packit 40b132
{
Packit 40b132
    CERTCertExtension *extension = NULL;
Packit 40b132
Packit 40b132
    if (!extensions)
Packit 40b132
        return SECSuccess;
Packit 40b132
Packit 40b132
    PORT_Assert(extHandle != NULL);
Packit 40b132
    if (!extHandle) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    extension = *extensions;
Packit 40b132
    while (extension) {
Packit 40b132
        SECOidTag oidTag = SECOID_FindOIDTag (&extension->id);
Packit 40b132
/* shell we skip unknown extensions? */
Packit 40b132
        CERT_AddExtension (extHandle, oidTag, &extension->value, 
Packit 40b132
                           (extension->critical.len != 0) ? PR_TRUE : PR_FALSE,
Packit 40b132
                           PR_FALSE);
Packit 40b132
        extension = *(++extensions);
Packit 40b132
    }
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Used for initialization of extension handles for crl and certs
Packit 40b132
 * extensions from existing CRL data then modifying existing CRL.*/
Packit 40b132
SECStatus
Packit 40b132
CRLGEN_ExtHandleInit(CRLGENGeneratorData *crlGenData)
Packit 40b132
{
Packit 40b132
    CERTCrl *crl = NULL;
Packit 40b132
    PRUint64 maxSN = 0;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->signCrl &&
Packit 40b132
                crlGenData->entryDataHashTable);
Packit 40b132
    if (!crlGenData || !crlGenData->signCrl ||
Packit 40b132
        !crlGenData->entryDataHashTable) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crl = &crlGenData->signCrl->crl;
Packit 40b132
    crlGenData->crlExtHandle = CERT_StartCRLExtensions(crl);
Packit 40b132
    crlgen_InitExtensionHandle(crlGenData->crlExtHandle,
Packit 40b132
                               crl->extensions);
Packit 40b132
    crl->extensions = NULL;
Packit 40b132
Packit 40b132
    if (crl->entries) {
Packit 40b132
        CERTCrlEntry **entry = crl->entries;
Packit 40b132
        while (*entry) {
Packit 40b132
            PRUint64 sn = DER_GetInteger(&(*entry)->serialNumber);
Packit 40b132
            CRLGENEntryData *extData =
Packit 40b132
                crlgen_PlaceAnEntry(crlGenData, *entry, &(*entry)->serialNumber);
Packit 40b132
            if ((*entry)->extensions) {
Packit 40b132
                extData->extHandle = 
Packit 40b132
                    CERT_StartCRLEntryExtensions(&crlGenData->signCrl->crl,
Packit 40b132
                                                 (CERTCrlEntry*)extData->entry);
Packit 40b132
                if (crlgen_InitExtensionHandle(extData->extHandle,
Packit 40b132
                                               (*entry)->extensions) == SECFailure)
Packit 40b132
                    return SECFailure;
Packit 40b132
            }
Packit 40b132
            (*entry)->extensions = NULL;
Packit 40b132
            entry++;
Packit 40b132
            maxSN = PR_MAX(maxSN, sn);
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crlGenData->rangeFrom = crlGenData->rangeTo = maxSN + 1;
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*****************************************************************************
Packit 40b132
 * Parser trigger functions start here
Packit 40b132
 */
Packit 40b132
Packit 40b132
/* Sets new internal range value for add/rm certs.*/
Packit 40b132
static SECStatus
Packit 40b132
crlgen_SetNewRangeField(CRLGENGeneratorData *crlGenData, char *value)
Packit 40b132
{
Packit 40b132
    long rangeFrom = 0, rangeTo = 0;
Packit 40b132
    char *dashPos = NULL;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (value == NULL) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if ((dashPos = strchr(value, '-')) != NULL) {
Packit 40b132
        char *rangeToS, *rangeFromS = value;
Packit 40b132
        *dashPos = '\0';
Packit 40b132
        rangeFrom = atoi(rangeFromS);
Packit 40b132
        *dashPos = '-';
Packit 40b132
Packit 40b132
        rangeToS = (char*)(dashPos + 1);
Packit 40b132
        rangeTo = atol(rangeToS);
Packit 40b132
    } else {
Packit 40b132
        rangeFrom = atol(value);
Packit 40b132
        rangeTo = rangeFrom;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (rangeFrom < 1 || rangeTo
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "bad cert id range: %s.\n", value);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crlGenData->rangeFrom = rangeFrom;
Packit 40b132
    crlGenData->rangeTo = rangeTo;
Packit 40b132
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Changes issuer subject field in CRL. By default this data is taken from
Packit 40b132
 * issuer cert subject field.Not yet implemented */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_SetIssuerField(CRLGENGeneratorData *crlGenData, char *value)
Packit 40b132
{
Packit 40b132
    crlgen_PrintError(crlGenData->parsedLineNum, 
Packit 40b132
                      "Can not change CRL issuer field.\n");
Packit 40b132
    return SECFailure;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Encode and sets CRL thisUpdate and nextUpdate time fields*/
Packit 40b132
static SECStatus
Packit 40b132
crlgen_SetTimeField(CRLGENGeneratorData *crlGenData, char *value,
Packit 40b132
                    PRBool setThisUpdate)
Packit 40b132
{
Packit 40b132
    CERTSignedCrl *signCrl;
Packit 40b132
    PLArenaPool *arena;
Packit 40b132
    CERTCrl *crl;
Packit 40b132
    int length = 0;
Packit 40b132
    SECItem *timeDest = NULL;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->signCrl &&
Packit 40b132
                crlGenData->signCrl->arena);
Packit 40b132
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    signCrl = crlGenData->signCrl;
Packit 40b132
    arena = signCrl->arena;
Packit 40b132
    crl = &signCrl->crl;
Packit 40b132
Packit 40b132
    if (value == NULL) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    length = PORT_Strlen(value);
Packit 40b132
    
Packit 40b132
    if (setThisUpdate == PR_TRUE) {
Packit 40b132
        timeDest = &crl->lastUpdate;
Packit 40b132
    } else {
Packit 40b132
        timeDest = &crl->nextUpdate;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    timeDest->type = siGeneralizedTime;
Packit 40b132
    timeDest->data = PORT_ArenaAlloc(arena, length);
Packit 40b132
    if (!timeDest->data) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    PORT_Memcpy(timeDest->data, value, length);
Packit 40b132
    timeDest->len = length;
Packit 40b132
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Adds new extension into CRL or added cert handles */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_AddExtension(CRLGENGeneratorData *crlGenData, const char **extData)
Packit 40b132
{
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->crlExtHandle);
Packit 40b132
    if (!crlGenData || !crlGenData->crlExtHandle) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (extData == NULL || *extData == NULL) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum, 
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    if (!PORT_Strcmp(*extData, "authKeyId"))
Packit 40b132
        return crlgen_AddAuthKeyID(crlGenData, extData);
Packit 40b132
    else if (!PORT_Strcmp(*extData, "issuerAltNames"))
Packit 40b132
        return crlgen_AddIssuerAltNames(crlGenData, extData);
Packit 40b132
    else if (!PORT_Strcmp(*extData, "crlNumber"))
Packit 40b132
        return crlgen_AddCrlNumber(crlGenData, extData);
Packit 40b132
    else if (!PORT_Strcmp(*extData, "reasonCode"))
Packit 40b132
        return crlgen_AddEntryExtension(crlGenData, extData, "reasonCode",
Packit 40b132
                                        crlgen_CreateReasonCode);
Packit 40b132
    else if (!PORT_Strcmp(*extData, "invalidityDate"))
Packit 40b132
        return crlgen_AddEntryExtension(crlGenData, extData, "invalidityDate",
Packit 40b132
                                        crlgen_CreateInvalidityDate);
Packit 40b132
    else {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
Packit 40b132
/* Created CRLGENEntryData for cert with serial number certId and
Packit 40b132
 * adds it to entryDataHashTable. certId can be a single cert serial
Packit 40b132
 * number or an inclusive rage of certs */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_AddCert(CRLGENGeneratorData *crlGenData,
Packit 40b132
        char *certId, char *revocationDate)
Packit 40b132
{
Packit 40b132
    CERTSignedCrl *signCrl;
Packit 40b132
    SECItem *certIdItem;
Packit 40b132
    PLArenaPool *arena;
Packit 40b132
    PRUint64 rangeFrom = 0, rangeTo = 0, i = 0;
Packit 40b132
    int timeValLength = -1;
Packit 40b132
    SECStatus rv = SECFailure;
Packit 40b132
    void *mark;
Packit 40b132
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && crlGenData->signCrl &&
Packit 40b132
                crlGenData->signCrl->arena);
Packit 40b132
    if (!crlGenData || !crlGenData->signCrl || !crlGenData->signCrl->arena) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    signCrl = crlGenData->signCrl;
Packit 40b132
    arena = signCrl->arena;
Packit 40b132
Packit 40b132
    if (!certId || !revocationDate) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                          "insufficient number of arguments.\n");
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    timeValLength = strlen(revocationDate);
Packit 40b132
Packit 40b132
    if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
Packit 40b132
        certId) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    rangeFrom = crlGenData->rangeFrom;
Packit 40b132
    rangeTo = crlGenData->rangeTo;
Packit 40b132
Packit 40b132
    for (i = 0;i < rangeTo - rangeFrom + 1;i++) {
Packit 40b132
        CERTCrlEntry *entry;
Packit 40b132
        mark = PORT_ArenaMark(arena);
Packit 40b132
        entry = PORT_ArenaZNew(arena, CERTCrlEntry);
Packit 40b132
        if (entry == NULL) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        certIdItem = SEC_ASN1EncodeInteger(arena, &entry->serialNumber,
Packit 40b132
                                           rangeFrom + i);
Packit 40b132
        if (!certIdItem) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        if (crlgen_FindEntry(crlGenData, certIdItem)) {
Packit 40b132
            crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                              "entry already exists. Use \"range\" "
Packit 40b132
                              "and \"rmcert\" before adding a new one with the "
Packit 40b132
                              "same serial number %ld\n", rangeFrom + i);
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        entry->serialNumber.type = siBuffer;
Packit 40b132
Packit 40b132
        entry->revocationDate.type = siGeneralizedTime;
Packit 40b132
Packit 40b132
        entry->revocationDate.data =
Packit 40b132
            PORT_ArenaAlloc(arena, timeValLength);
Packit 40b132
        if (entry->revocationDate.data == NULL) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PORT_Memcpy(entry->revocationDate.data, revocationDate,
Packit 40b132
                    timeValLength * sizeof(char));
Packit 40b132
        entry->revocationDate.len = timeValLength;
Packit 40b132
Packit 40b132
Packit 40b132
        entry->extensions = NULL;
Packit 40b132
        if (!crlgen_PlaceAnEntry(crlGenData, entry, certIdItem)) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
        mark = NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    rv = SECSuccess;
Packit 40b132
  loser:
Packit 40b132
    if (mark) {
Packit 40b132
        PORT_ArenaRelease(arena, mark);
Packit 40b132
    }
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Removes certs from entryDataHashTable which have certId serial number.
Packit 40b132
 * certId can have value of a range of certs */
Packit 40b132
static SECStatus
Packit 40b132
crlgen_RmCert(CRLGENGeneratorData *crlGenData, char *certId)
Packit 40b132
{
Packit 40b132
    PRUint64 i = 0;
Packit 40b132
    PLArenaPool *arena;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData && certId);
Packit 40b132
    if (!crlGenData || !certId) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    arena = crlGenData->signCrl->arena;
Packit 40b132
Packit 40b132
    if (crlgen_SetNewRangeField(crlGenData, certId) == SECFailure &&
Packit 40b132
        certId) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    for (i = 0;i < crlGenData->rangeTo - crlGenData->rangeFrom + 1;i++) {
Packit 40b132
        SECItem* certIdItem = SEC_ASN1EncodeInteger(NULL, NULL,
Packit 40b132
                                                    crlGenData->rangeFrom + i);
Packit 40b132
        if (certIdItem) {
Packit 40b132
            CRLGENEntryData *extData =
Packit 40b132
                crlgen_FindEntry(crlGenData, certIdItem);
Packit 40b132
            if (!extData) {
Packit 40b132
                printf("Cert with id %s is not in the list\n", certId);
Packit 40b132
            } else {
Packit 40b132
                crlgen_RmEntry(crlGenData, certIdItem);
Packit 40b132
            }
Packit 40b132
            SECITEM_FreeItem(certIdItem, PR_TRUE);
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*************************************************************************
Packit 40b132
 * Lex Parser Helper functions are used to store parsed information
Packit 40b132
 * in context related structures. Context(or state) is identified base on 
Packit 40b132
 * a type of a instruction parser currently is going through. New context
Packit 40b132
 * is identified by first token in a line. It can be addcert context,
Packit 40b132
 * addext context, etc. */
Packit 40b132
Packit 40b132
/* Updates CRL field depending on current context */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_updateCrlFn_field(CRLGENGeneratorData *crlGenData, void *str)
Packit 40b132
{
Packit 40b132
    CRLGENCrlField *fieldStr = (CRLGENCrlField*)str;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(crlGenData->contextId) {
Packit 40b132
      case CRLGEN_ISSUER_CONTEXT:
Packit 40b132
          crlgen_SetIssuerField(crlGenData, fieldStr->value);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
          return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_TRUE);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
          return crlgen_SetTimeField(crlGenData, fieldStr->value, PR_FALSE);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
          return crlgen_SetNewRangeField(crlGenData, fieldStr->value);
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "syntax error (unknow token type: %d)\n",
Packit 40b132
                            crlGenData->contextId);
Packit 40b132
          PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Sets parsed data for CRL field update into temporary structure */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_setNextDataFn_field(CRLGENGeneratorData *crlGenData, void *str,
Packit 40b132
                    void *data, unsigned short dtype)
Packit 40b132
{
Packit 40b132
    CRLGENCrlField *fieldStr = (CRLGENCrlField*)str;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch (crlGenData->contextId) {
Packit 40b132
      case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
          if (dtype != CRLGEN_TYPE_DIGIT && dtype != CRLGEN_TYPE_DIGIT_RANGE) {
Packit 40b132
              crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                                "range value should have "
Packit 40b132
                                "numeric or numeric range values.\n");
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
          if (dtype != CRLGEN_TYPE_ZDATE){
Packit 40b132
              crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                                "bad formated date. Should be "
Packit 40b132
                                "YYYYMMDDHHMMSSZ.\n");
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "syntax error (unknow token type: %d).\n",
Packit 40b132
                            crlGenData->contextId, data);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    fieldStr->value = PORT_Strdup(data);
Packit 40b132
    if (!fieldStr->value) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Triggers cert entries update depending on current context */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_updateCrlFn_cert(CRLGENGeneratorData *crlGenData, void *str)
Packit 40b132
{
Packit 40b132
    CRLGENCertEntry *certStr = (CRLGENCertEntry*)str;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(crlGenData->contextId) {
Packit 40b132
      case CRLGEN_ADD_CERT_CONTEXT:
Packit 40b132
          return crlgen_AddCert(crlGenData, certStr->certId,
Packit 40b132
                         certStr->revocationTime);
Packit 40b132
      case CRLGEN_RM_CERT_CONTEXT:
Packit 40b132
          return crlgen_RmCert(crlGenData, certStr->certId);
Packit 40b132
      default:
Packit 40b132
          PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "syntax error (unknow token type: %d).\n",
Packit 40b132
                            crlGenData->contextId);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Sets parsed data for CRL entries update into temporary structure */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_setNextDataFn_cert(CRLGENGeneratorData *crlGenData, void *str,
Packit 40b132
                   void *data, unsigned short dtype)
Packit 40b132
{
Packit 40b132
    CRLGENCertEntry *certStr = (CRLGENCertEntry*)str;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(dtype) {
Packit 40b132
      case CRLGEN_TYPE_DIGIT:
Packit 40b132
      case CRLGEN_TYPE_DIGIT_RANGE:
Packit 40b132
          certStr->certId = PORT_Strdup(data);
Packit 40b132
          if (!certStr->certId) {
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_TYPE_DATE:
Packit 40b132
      case CRLGEN_TYPE_ZDATE:
Packit 40b132
          certStr->revocationTime = PORT_Strdup(data);
Packit 40b132
          if (!certStr->revocationTime) {
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "syntax error (unknow token type: %d).\n",
Packit 40b132
                            crlGenData->contextId);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Triggers cert entries/crl extension update */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_updateCrlFn_extension(CRLGENGeneratorData *crlGenData, void *str)
Packit 40b132
{
Packit 40b132
    CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry*)str;
Packit 40b132
Packit 40b132
    return crlgen_AddExtension(crlGenData, (const char**)extStr->extData);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Defines maximum number of fields extension may have */
Packit 40b132
#define MAX_EXT_DATA_LENGTH 10
Packit 40b132
Packit 40b132
/* Sets parsed extension data for CRL entries/CRL extensions update
Packit 40b132
 * into temporary structure */ 
Packit 40b132
static SECStatus
Packit 40b132
crlgen_setNextDataFn_extension(CRLGENGeneratorData *crlGenData, void *str,
Packit 40b132
                        void *data, unsigned short dtype)
Packit 40b132
{
Packit 40b132
    CRLGENExtensionEntry *extStr = (CRLGENExtensionEntry*)str;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    if (extStr->extData == NULL) {
Packit 40b132
        extStr->extData = PORT_ZNewArray(char *, MAX_EXT_DATA_LENGTH);
Packit 40b132
        if (!extStr->extData) {
Packit 40b132
            return SECFailure;
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
    if (extStr->nextUpdatedData >= MAX_EXT_DATA_LENGTH) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        crlgen_PrintError(crlGenData->parsedLineNum, 
Packit 40b132
                          "number of fields in extension "
Packit 40b132
                          "exceeded maximum allowed data length: %d.\n",
Packit 40b132
                          MAX_EXT_DATA_LENGTH);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    extStr->extData[extStr->nextUpdatedData] = PORT_Strdup(data);
Packit 40b132
    if (!extStr->extData[extStr->nextUpdatedData]) {
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
    extStr->nextUpdatedData += 1;
Packit 40b132
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/****************************************************************************************
Packit 40b132
 * Top level functions are triggered directly by parser.
Packit 40b132
 */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * crl generation script parser recreates a temporary data staructure
Packit 40b132
 * for each line it is going through. This function cleans temp structure.
Packit 40b132
 */
Packit 40b132
void
Packit 40b132
crlgen_destroyTempData(CRLGENGeneratorData *crlGenData)
Packit 40b132
{
Packit 40b132
    if (crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
Packit 40b132
        switch(crlGenData->contextId) {
Packit 40b132
          case CRLGEN_ISSUER_CONTEXT:
Packit 40b132
          case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
          case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
          case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
              if (crlGenData->crlField->value)
Packit 40b132
                  PORT_Free(crlGenData->crlField->value);
Packit 40b132
              PORT_Free(crlGenData->crlField);
Packit 40b132
              break;
Packit 40b132
          case CRLGEN_ADD_CERT_CONTEXT:
Packit 40b132
          case CRLGEN_RM_CERT_CONTEXT:
Packit 40b132
              if (crlGenData->certEntry->certId)
Packit 40b132
                  PORT_Free(crlGenData->certEntry->certId);
Packit 40b132
              if (crlGenData->certEntry->revocationTime)
Packit 40b132
                  PORT_Free(crlGenData->certEntry->revocationTime);
Packit 40b132
              PORT_Free(crlGenData->certEntry);
Packit 40b132
              break;
Packit 40b132
          case CRLGEN_ADD_EXTENSION_CONTEXT:
Packit 40b132
              if (crlGenData->extensionEntry->extData) {
Packit 40b132
                  int i = 0;
Packit 40b132
                  for (;i < crlGenData->extensionEntry->nextUpdatedData;i++)
Packit 40b132
                      PORT_Free(*(crlGenData->extensionEntry->extData + i));
Packit 40b132
                  PORT_Free(crlGenData->extensionEntry->extData);
Packit 40b132
              }
Packit 40b132
              PORT_Free(crlGenData->extensionEntry);
Packit 40b132
              break;
Packit 40b132
        }
Packit 40b132
        crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
Packit 40b132
    }
Packit 40b132
}
Packit 40b132
Packit 40b132
SECStatus
Packit 40b132
crlgen_updateCrl(CRLGENGeneratorData *crlGenData)
Packit 40b132
{
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(crlGenData->contextId) {
Packit 40b132
      case CRLGEN_ISSUER_CONTEXT:
Packit 40b132
      case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
          rv = crlGenData->crlField->updateCrlFn(crlGenData, crlGenData->crlField);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_RM_CERT_CONTEXT:
Packit 40b132
      case CRLGEN_ADD_CERT_CONTEXT:
Packit 40b132
          rv = crlGenData->certEntry->updateCrlFn(crlGenData, crlGenData->certEntry);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_ADD_EXTENSION_CONTEXT:
Packit 40b132
          rv = crlGenData->extensionEntry->
Packit 40b132
              updateCrlFn(crlGenData, crlGenData->extensionEntry);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_UNKNOWN_CONTEXT:
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "unknown lang context type code: %d.\n",
Packit 40b132
                            crlGenData->contextId);
Packit 40b132
          PORT_Assert(0);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    /* Clrean structures after crl update */
Packit 40b132
    crlgen_destroyTempData(crlGenData);
Packit 40b132
Packit 40b132
    crlGenData->parsedLineNum += 1;
Packit 40b132
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
SECStatus
Packit 40b132
crlgen_setNextData(CRLGENGeneratorData *crlGenData, void *data,
Packit 40b132
                   unsigned short dtype)
Packit 40b132
{
Packit 40b132
    SECStatus rv = SECSuccess;
Packit 40b132
Packit 40b132
    PORT_Assert(crlGenData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(crlGenData->contextId) {
Packit 40b132
      case CRLGEN_ISSUER_CONTEXT:
Packit 40b132
      case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
          rv = crlGenData->crlField->setNextDataFn(crlGenData, crlGenData->crlField,
Packit 40b132
                                                   data, dtype);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_ADD_CERT_CONTEXT:
Packit 40b132
      case CRLGEN_RM_CERT_CONTEXT:
Packit 40b132
          rv = crlGenData->certEntry->setNextDataFn(crlGenData, crlGenData->certEntry,
Packit 40b132
                                                    data, dtype);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_ADD_EXTENSION_CONTEXT:
Packit 40b132
          rv =
Packit 40b132
              crlGenData->extensionEntry->
Packit 40b132
              setNextDataFn(crlGenData, crlGenData->extensionEntry, data, dtype);
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_UNKNOWN_CONTEXT:
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "unknown context type: %d.\n",
Packit 40b132
                            crlGenData->contextId);
Packit 40b132
          PORT_Assert(0);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    return rv;
Packit 40b132
}
Packit 40b132
Packit 40b132
SECStatus
Packit 40b132
crlgen_createNewLangStruct(CRLGENGeneratorData *crlGenData,
Packit 40b132
                           unsigned structType)
Packit 40b132
{
Packit 40b132
    PORT_Assert(crlGenData &&
Packit 40b132
                crlGenData->contextId == CRLGEN_UNKNOWN_CONTEXT);
Packit 40b132
    if (!crlGenData ||
Packit 40b132
        crlGenData->contextId != CRLGEN_UNKNOWN_CONTEXT) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return SECFailure;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    switch(structType) {
Packit 40b132
      case CRLGEN_ISSUER_CONTEXT:
Packit 40b132
      case CRLGEN_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_NEXT_UPDATE_CONTEXT:
Packit 40b132
      case CRLGEN_CHANGE_RANGE_CONTEXT:
Packit 40b132
          crlGenData->crlField = PORT_New(CRLGENCrlField);
Packit 40b132
          if (!crlGenData->crlField) {
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          crlGenData->contextId = structType;
Packit 40b132
          crlGenData->crlField->value = NULL;
Packit 40b132
          crlGenData->crlField->updateCrlFn = &crlgen_updateCrlFn_field;
Packit 40b132
          crlGenData->crlField->setNextDataFn = &crlgen_setNextDataFn_field;
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_RM_CERT_CONTEXT:
Packit 40b132
      case CRLGEN_ADD_CERT_CONTEXT:
Packit 40b132
          crlGenData->certEntry = PORT_New(CRLGENCertEntry);
Packit 40b132
          if (!crlGenData->certEntry) {
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          crlGenData->contextId = structType;
Packit 40b132
          crlGenData->certEntry->certId = 0;
Packit 40b132
          crlGenData->certEntry->revocationTime = NULL;
Packit 40b132
          crlGenData->certEntry->updateCrlFn = &crlgen_updateCrlFn_cert;
Packit 40b132
          crlGenData->certEntry->setNextDataFn = &crlgen_setNextDataFn_cert;
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_ADD_EXTENSION_CONTEXT:
Packit 40b132
          crlGenData->extensionEntry = PORT_New(CRLGENExtensionEntry);
Packit 40b132
          if (!crlGenData->extensionEntry) {
Packit 40b132
              return SECFailure;
Packit 40b132
          }
Packit 40b132
          crlGenData->contextId = structType;
Packit 40b132
          crlGenData->extensionEntry->extData = NULL;
Packit 40b132
          crlGenData->extensionEntry->nextUpdatedData = 0;
Packit 40b132
          crlGenData->extensionEntry->updateCrlFn =
Packit 40b132
              &crlgen_updateCrlFn_extension;
Packit 40b132
          crlGenData->extensionEntry->setNextDataFn =
Packit 40b132
              &crlgen_setNextDataFn_extension;
Packit 40b132
          break;
Packit 40b132
      case CRLGEN_UNKNOWN_CONTEXT:
Packit 40b132
          break;
Packit 40b132
      default:
Packit 40b132
          crlgen_PrintError(crlGenData->parsedLineNum,
Packit 40b132
                            "unknown context type: %d.\n", structType);
Packit 40b132
          PORT_Assert(0);
Packit 40b132
          return SECFailure;
Packit 40b132
    }
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* Parser initialization function */
Packit 40b132
CRLGENGeneratorData*
Packit 40b132
CRLGEN_InitCrlGeneration(CERTSignedCrl *signCrl, PRFileDesc *src)
Packit 40b132
{
Packit 40b132
    CRLGENGeneratorData *crlGenData = NULL;
Packit 40b132
Packit 40b132
    PORT_Assert(signCrl && src);
Packit 40b132
    if (!signCrl || !src) {
Packit 40b132
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crlGenData = PORT_ZNew(CRLGENGeneratorData);
Packit 40b132
    if (!crlGenData) {
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crlGenData->entryDataHashTable = 
Packit 40b132
        PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
Packit 40b132
                        PL_CompareValues, NULL, NULL);
Packit 40b132
    if (!crlGenData->entryDataHashTable) {
Packit 40b132
        PORT_Free(crlGenData);
Packit 40b132
        return NULL;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    crlGenData->src = src;
Packit 40b132
    crlGenData->parsedLineNum = 1;
Packit 40b132
    crlGenData->contextId = CRLGEN_UNKNOWN_CONTEXT;
Packit 40b132
    crlGenData->signCrl = signCrl;
Packit 40b132
    crlGenData->rangeFrom = 0;
Packit 40b132
    crlGenData->rangeTo = 0;
Packit 40b132
    crlGenData->crlExtHandle = NULL;
Packit 40b132
Packit 40b132
    PORT_SetError(0);
Packit 40b132
Packit 40b132
    return crlGenData;
Packit 40b132
}
Packit 40b132
Packit 40b132
void
Packit 40b132
CRLGEN_FinalizeCrlGeneration(CRLGENGeneratorData *crlGenData)
Packit 40b132
{
Packit 40b132
    if (!crlGenData)
Packit 40b132
        return;
Packit 40b132
    if (crlGenData->src)
Packit 40b132
        PR_Close(crlGenData->src);
Packit 40b132
    PL_HashTableDestroy(crlGenData->entryDataHashTable);
Packit 40b132
    PORT_Free(crlGenData);
Packit 40b132
}
Packit 40b132