~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/cmd/crlutil/crlgen.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

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