~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/certdb/certdb.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

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
 *    Aaron Spangler <aaron@spangler.ods.org>
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
/*
 
39
 * Certificate handling code
 
40
 *
 
41
 * $Id: certdb.c,v 1.76.2.1 2006/02/16 00:14:18 julien.pierre.bugs%sun.com Exp $
 
42
 */
 
43
 
 
44
#include "nssilock.h"
 
45
#include "prmon.h"
 
46
#include "prtime.h"
 
47
#include "cert.h"
 
48
#include "certi.h"
 
49
#include "secder.h"
 
50
#include "secoid.h"
 
51
#include "secasn1.h"
 
52
#include "genname.h"
 
53
#include "keyhi.h"
 
54
#include "secitem.h"
 
55
#include "mcom_db.h"
 
56
#include "certdb.h"
 
57
#include "prprf.h"
 
58
#include "sechash.h"
 
59
#include "prlong.h"
 
60
#include "certxutl.h"
 
61
#include "portreg.h"
 
62
#include "secerr.h"
 
63
#include "sslerr.h"
 
64
#include "nsslocks.h"
 
65
#include "pk11func.h"
 
66
#include "xconst.h"   /* for  CERT_DecodeAltNameExtension */
 
67
 
 
68
#ifndef NSS_3_4_CODE
 
69
#define NSS_3_4_CODE
 
70
#endif /* NSS_3_4_CODE */
 
71
#include "pki.h"
 
72
#include "pki3hack.h"
 
73
 
 
74
/*
 
75
 * Certificate database handling code
 
76
 */
 
77
 
 
78
 
 
79
const SEC_ASN1Template CERT_CertExtensionTemplate[] = {
 
80
    { SEC_ASN1_SEQUENCE,
 
81
          0, NULL, sizeof(CERTCertExtension) },
 
82
    { SEC_ASN1_OBJECT_ID,
 
83
          offsetof(CERTCertExtension,id) },
 
84
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,             /* XXX DER_DEFAULT */
 
85
          offsetof(CERTCertExtension,critical) },
 
86
    { SEC_ASN1_OCTET_STRING,
 
87
          offsetof(CERTCertExtension,value) },
 
88
    { 0, }
 
89
};
 
90
 
 
91
const SEC_ASN1Template CERT_SequenceOfCertExtensionTemplate[] = {
 
92
    { SEC_ASN1_SEQUENCE_OF, 0, CERT_CertExtensionTemplate }
 
93
};
 
94
 
 
95
const SEC_ASN1Template CERT_CertificateTemplate[] = {
 
96
    { SEC_ASN1_SEQUENCE,
 
97
      0, NULL, sizeof(CERTCertificate) },
 
98
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
99
          SEC_ASN1_CONTEXT_SPECIFIC | 0,                /* XXX DER_DEFAULT */ 
 
100
          offsetof(CERTCertificate,version),
 
101
          SEC_IntegerTemplate },
 
102
    { SEC_ASN1_INTEGER,
 
103
          offsetof(CERTCertificate,serialNumber) },
 
104
    { SEC_ASN1_INLINE,
 
105
          offsetof(CERTCertificate,signature),
 
106
          SECOID_AlgorithmIDTemplate },
 
107
    { SEC_ASN1_SAVE, 
 
108
          offsetof(CERTCertificate,derIssuer) },
 
109
    { SEC_ASN1_INLINE,
 
110
          offsetof(CERTCertificate,issuer),
 
111
          CERT_NameTemplate },
 
112
    { SEC_ASN1_INLINE,
 
113
          offsetof(CERTCertificate,validity),
 
114
          CERT_ValidityTemplate },
 
115
    { SEC_ASN1_SAVE,
 
116
          offsetof(CERTCertificate,derSubject) },
 
117
    { SEC_ASN1_INLINE,
 
118
          offsetof(CERTCertificate,subject),
 
119
          CERT_NameTemplate },
 
120
    { SEC_ASN1_SAVE,
 
121
          offsetof(CERTCertificate,derPublicKey) },
 
122
    { SEC_ASN1_INLINE,
 
123
          offsetof(CERTCertificate,subjectPublicKeyInfo),
 
124
          CERT_SubjectPublicKeyInfoTemplate },
 
125
    { SEC_ASN1_OPTIONAL |  SEC_ASN1_CONTEXT_SPECIFIC | 1,
 
126
          offsetof(CERTCertificate,issuerID),
 
127
          SEC_BitStringTemplate },
 
128
    { SEC_ASN1_OPTIONAL |  SEC_ASN1_CONTEXT_SPECIFIC | 2,
 
129
          offsetof(CERTCertificate,subjectID),
 
130
          SEC_BitStringTemplate },
 
131
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
132
          SEC_ASN1_CONTEXT_SPECIFIC | 3,
 
133
          offsetof(CERTCertificate,extensions),
 
134
          CERT_SequenceOfCertExtensionTemplate },
 
135
    { 0 }
 
136
};
 
137
 
 
138
const SEC_ASN1Template SEC_SignedCertificateTemplate[] =
 
139
{
 
140
    { SEC_ASN1_SEQUENCE,
 
141
          0, NULL, sizeof(CERTCertificate) },
 
142
    { SEC_ASN1_SAVE, 
 
143
          offsetof(CERTCertificate,signatureWrap.data) },
 
144
    { SEC_ASN1_INLINE, 
 
145
          0, CERT_CertificateTemplate },
 
146
    { SEC_ASN1_INLINE,
 
147
          offsetof(CERTCertificate,signatureWrap.signatureAlgorithm),
 
148
          SECOID_AlgorithmIDTemplate },
 
149
    { SEC_ASN1_BIT_STRING,
 
150
          offsetof(CERTCertificate,signatureWrap.signature) },
 
151
    { 0 }
 
152
};
 
153
 
 
154
/*
 
155
 * Find the subjectName in a DER encoded certificate
 
156
 */
 
157
const SEC_ASN1Template SEC_CertSubjectTemplate[] = {
 
158
    { SEC_ASN1_SEQUENCE,
 
159
          0, NULL, sizeof(SECItem) },
 
160
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
161
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
 
162
          0, SEC_SkipTemplate },        /* version */
 
163
    { SEC_ASN1_SKIP },          /* serial number */
 
164
    { SEC_ASN1_SKIP },          /* signature algorithm */
 
165
    { SEC_ASN1_SKIP },          /* issuer */
 
166
    { SEC_ASN1_SKIP },          /* validity */
 
167
    { SEC_ASN1_ANY, 0, NULL },          /* subject */
 
168
    { SEC_ASN1_SKIP_REST },
 
169
    { 0 }
 
170
};
 
171
 
 
172
/*
 
173
 * Find the issuerName in a DER encoded certificate
 
174
 */
 
175
const SEC_ASN1Template SEC_CertIssuerTemplate[] = {
 
176
    { SEC_ASN1_SEQUENCE,
 
177
          0, NULL, sizeof(SECItem) },
 
178
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
179
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
 
180
          0, SEC_SkipTemplate },        /* version */
 
181
    { SEC_ASN1_SKIP },          /* serial number */
 
182
    { SEC_ASN1_SKIP },          /* signature algorithm */
 
183
    { SEC_ASN1_ANY, 0, NULL },          /* issuer */
 
184
    { SEC_ASN1_SKIP_REST },
 
185
    { 0 }
 
186
};
 
187
/*
 
188
 * Find the subjectName in a DER encoded certificate
 
189
 */
 
190
const SEC_ASN1Template SEC_CertSerialNumberTemplate[] = {
 
191
    { SEC_ASN1_SEQUENCE,
 
192
          0, NULL, sizeof(SECItem) },
 
193
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
194
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
 
195
          0, SEC_SkipTemplate },        /* version */
 
196
    { SEC_ASN1_ANY, 0, NULL }, /* serial number */
 
197
    { SEC_ASN1_SKIP_REST },
 
198
    { 0 }
 
199
};
 
200
 
 
201
/*
 
202
 * Find the issuer and serialNumber in a DER encoded certificate.
 
203
 * This data is used as the database lookup key since its the unique
 
204
 * identifier of a certificate.
 
205
 */
 
206
const SEC_ASN1Template CERT_CertKeyTemplate[] = {
 
207
    { SEC_ASN1_SEQUENCE,
 
208
          0, NULL, sizeof(CERTCertKey) },
 
209
    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
 
210
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
 
211
          0, SEC_SkipTemplate },        /* version */ 
 
212
    { SEC_ASN1_INTEGER,
 
213
          offsetof(CERTCertKey,serialNumber) },
 
214
    { SEC_ASN1_SKIP },          /* signature algorithm */
 
215
    { SEC_ASN1_ANY,
 
216
          offsetof(CERTCertKey,derIssuer) },
 
217
    { SEC_ASN1_SKIP_REST },
 
218
    { 0 }
 
219
};
 
220
 
 
221
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateTemplate)
 
222
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SignedCertificateTemplate)
 
223
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SequenceOfCertExtensionTemplate)
 
224
 
 
225
SECStatus
 
226
CERT_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
 
227
                        SECItem *key)
 
228
{
 
229
    key->len = sn->len + issuer->len;
 
230
 
 
231
    if ((sn->data == NULL) || (issuer->data == NULL)) {
 
232
        goto loser;
 
233
    }
 
234
    
 
235
    key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
 
236
    if ( !key->data ) {
 
237
        goto loser;
 
238
    }
 
239
 
 
240
    /* copy the serialNumber */
 
241
    PORT_Memcpy(key->data, sn->data, sn->len);
 
242
 
 
243
    /* copy the issuer */
 
244
    PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
 
245
 
 
246
    return(SECSuccess);
 
247
 
 
248
loser:
 
249
    return(SECFailure);
 
250
}
 
251
 
 
252
 
 
253
/*
 
254
 * Extract the subject name from a DER certificate
 
255
 */
 
256
SECStatus
 
257
CERT_NameFromDERCert(SECItem *derCert, SECItem *derName)
 
258
{
 
259
    int rv;
 
260
    PRArenaPool *arena;
 
261
    CERTSignedData sd;
 
262
    void *tmpptr;
 
263
    
 
264
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
265
    
 
266
    if ( ! arena ) {
 
267
        return(SECFailure);
 
268
    }
 
269
   
 
270
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
 
271
    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
 
272
    
 
273
    if ( rv ) {
 
274
        goto loser;
 
275
    }
 
276
    
 
277
    PORT_Memset(derName, 0, sizeof(SECItem));
 
278
    rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSubjectTemplate, &sd.data);
 
279
 
 
280
    if ( rv ) {
 
281
        goto loser;
 
282
    }
 
283
 
 
284
    tmpptr = derName->data;
 
285
    derName->data = (unsigned char*)PORT_Alloc(derName->len);
 
286
    if ( derName->data == NULL ) {
 
287
        goto loser;
 
288
    }
 
289
    
 
290
    PORT_Memcpy(derName->data, tmpptr, derName->len);
 
291
    
 
292
    PORT_FreeArena(arena, PR_FALSE);
 
293
    return(SECSuccess);
 
294
 
 
295
loser:
 
296
    PORT_FreeArena(arena, PR_FALSE);
 
297
    return(SECFailure);
 
298
}
 
299
 
 
300
SECStatus
 
301
CERT_IssuerNameFromDERCert(SECItem *derCert, SECItem *derName)
 
302
{
 
303
    int rv;
 
304
    PRArenaPool *arena;
 
305
    CERTSignedData sd;
 
306
    void *tmpptr;
 
307
    
 
308
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
309
    
 
310
    if ( ! arena ) {
 
311
        return(SECFailure);
 
312
    }
 
313
   
 
314
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
 
315
    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
 
316
    
 
317
    if ( rv ) {
 
318
        goto loser;
 
319
    }
 
320
    
 
321
    PORT_Memset(derName, 0, sizeof(SECItem));
 
322
    rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertIssuerTemplate, &sd.data);
 
323
 
 
324
    if ( rv ) {
 
325
        goto loser;
 
326
    }
 
327
 
 
328
    tmpptr = derName->data;
 
329
    derName->data = (unsigned char*)PORT_Alloc(derName->len);
 
330
    if ( derName->data == NULL ) {
 
331
        goto loser;
 
332
    }
 
333
    
 
334
    PORT_Memcpy(derName->data, tmpptr, derName->len);
 
335
    
 
336
    PORT_FreeArena(arena, PR_FALSE);
 
337
    return(SECSuccess);
 
338
 
 
339
loser:
 
340
    PORT_FreeArena(arena, PR_FALSE);
 
341
    return(SECFailure);
 
342
}
 
343
 
 
344
SECStatus
 
345
CERT_SerialNumberFromDERCert(SECItem *derCert, SECItem *derName)
 
346
{
 
347
    int rv;
 
348
    PRArenaPool *arena;
 
349
    CERTSignedData sd;
 
350
    void *tmpptr;
 
351
    
 
352
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
353
    
 
354
    if ( ! arena ) {
 
355
        return(SECFailure);
 
356
    }
 
357
   
 
358
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
 
359
    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
 
360
    
 
361
    if ( rv ) {
 
362
        goto loser;
 
363
    }
 
364
    
 
365
    PORT_Memset(derName, 0, sizeof(SECItem));
 
366
    rv = SEC_QuickDERDecodeItem(arena, derName, SEC_CertSerialNumberTemplate, &sd.data);
 
367
 
 
368
    if ( rv ) {
 
369
        goto loser;
 
370
    }
 
371
 
 
372
    tmpptr = derName->data;
 
373
    derName->data = (unsigned char*)PORT_Alloc(derName->len);
 
374
    if ( derName->data == NULL ) {
 
375
        goto loser;
 
376
    }
 
377
    
 
378
    PORT_Memcpy(derName->data, tmpptr, derName->len);
 
379
    
 
380
    PORT_FreeArena(arena, PR_FALSE);
 
381
    return(SECSuccess);
 
382
 
 
383
loser:
 
384
    PORT_FreeArena(arena, PR_FALSE);
 
385
    return(SECFailure);
 
386
}
 
387
 
 
388
/*
 
389
 * Generate a database key, based on serial number and issuer, from a
 
390
 * DER certificate.
 
391
 */
 
392
SECStatus
 
393
CERT_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
 
394
{
 
395
    int rv;
 
396
    CERTSignedData sd;
 
397
    CERTCertKey certkey;
 
398
 
 
399
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
 
400
    rv = SEC_ASN1DecodeItem(arena, &sd, CERT_SignedDataTemplate, derCert);
 
401
    
 
402
    if ( rv ) {
 
403
        goto loser;
 
404
    }
 
405
    
 
406
    PORT_Memset(&certkey, 0, sizeof(CERTCertKey));
 
407
    rv = SEC_ASN1DecodeItem(arena, &certkey, CERT_CertKeyTemplate, &sd.data);
 
408
 
 
409
    if ( rv ) {
 
410
        goto loser;
 
411
    }
 
412
 
 
413
    return(CERT_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
 
414
                                   &certkey.serialNumber, key));
 
415
loser:
 
416
    return(SECFailure);
 
417
}
 
418
 
 
419
/*
 
420
 * fill in keyUsage field of the cert based on the cert extension
 
421
 * if the extension is not critical, then we allow all uses
 
422
 */
 
423
static SECStatus
 
424
GetKeyUsage(CERTCertificate *cert)
 
425
{
 
426
    SECStatus rv;
 
427
    SECItem tmpitem;
 
428
    
 
429
    rv = CERT_FindKeyUsageExtension(cert, &tmpitem);
 
430
    if ( rv == SECSuccess ) {
 
431
        /* remember the actual value of the extension */
 
432
        cert->rawKeyUsage = tmpitem.data[0];
 
433
        cert->keyUsagePresent = PR_TRUE;
 
434
        cert->keyUsage = tmpitem.data[0];
 
435
 
 
436
        PORT_Free(tmpitem.data);
 
437
        tmpitem.data = NULL;
 
438
        
 
439
    } else {
 
440
        /* if the extension is not present, then we allow all uses */
 
441
        cert->keyUsage = KU_ALL;
 
442
        cert->rawKeyUsage = KU_ALL;
 
443
        cert->keyUsagePresent = PR_FALSE;
 
444
    }
 
445
 
 
446
    if ( CERT_GovtApprovedBitSet(cert) ) {
 
447
        cert->keyUsage |= KU_NS_GOVT_APPROVED;
 
448
        cert->rawKeyUsage |= KU_NS_GOVT_APPROVED;
 
449
    }
 
450
    
 
451
    return(SECSuccess);
 
452
}
 
453
 
 
454
 
 
455
/*
 
456
 * determine if a fortezza V1 Cert is a CA or not.
 
457
 */
 
458
static PRBool
 
459
fortezzaIsCA( CERTCertificate *cert) {
 
460
    PRBool isCA = PR_FALSE;
 
461
    CERTSubjectPublicKeyInfo *spki = &cert->subjectPublicKeyInfo;
 
462
    int tag;
 
463
 
 
464
    tag = SECOID_GetAlgorithmTag(&spki->algorithm);
 
465
    if ((tag == SEC_OID_MISSI_KEA_DSS_OLD) ||
 
466
       (tag == SEC_OID_MISSI_KEA_DSS) ||
 
467
       (tag == SEC_OID_MISSI_DSS_OLD) ||
 
468
       (tag == SEC_OID_MISSI_DSS) ) {
 
469
        SECItem rawkey;
 
470
        unsigned char *rawptr;
 
471
        unsigned char *end;
 
472
        int len;
 
473
 
 
474
        rawkey = spki->subjectPublicKey;
 
475
        DER_ConvertBitString(&rawkey);
 
476
        rawptr = rawkey.data;
 
477
        end = rawkey.data + rawkey.len;
 
478
 
 
479
        /* version */   
 
480
        rawptr += sizeof(((SECKEYPublicKey*)0)->u.fortezza.KMID)+2;
 
481
 
 
482
        /* clearance (the string up to the first byte with the hi-bit on */
 
483
        while ((rawptr < end) && (*rawptr++ & 0x80));
 
484
        if (rawptr >= end) { return PR_FALSE; }
 
485
 
 
486
        /* KEAPrivilege (the string up to the first byte with the hi-bit on */
 
487
        while ((rawptr < end) && (*rawptr++ & 0x80));
 
488
        if (rawptr >= end) { return PR_FALSE; }
 
489
 
 
490
        /* skip the key */
 
491
        len = (*rawptr << 8) | rawptr[1];
 
492
        rawptr += 2 + len;
 
493
 
 
494
        /* shared key */
 
495
        if (rawptr >= end) { return PR_FALSE; }
 
496
        /* DSS Version is next */
 
497
        rawptr += 2;
 
498
 
 
499
        /* DSSPrivilege (the string up to the first byte with the hi-bit on */
 
500
        if (*rawptr & 0x30) isCA = PR_TRUE;
 
501
        
 
502
   }
 
503
   return isCA;
 
504
}
 
505
 
 
506
static SECStatus
 
507
findOIDinOIDSeqByTagNum(CERTOidSequence *seq, SECOidTag tagnum)
 
508
{
 
509
    SECItem **oids;
 
510
    SECItem *oid;
 
511
    SECStatus rv = SECFailure;
 
512
    
 
513
    if (seq != NULL) {
 
514
        oids = seq->oids;
 
515
        while (oids != NULL && *oids != NULL) {
 
516
            oid = *oids;
 
517
            if (SECOID_FindOIDTag(oid) == tagnum) {
 
518
                rv = SECSuccess;
 
519
                break;
 
520
            }
 
521
            oids++;
 
522
        }
 
523
    }
 
524
    return rv;
 
525
}
 
526
 
 
527
/*
 
528
 * fill in nsCertType field of the cert based on the cert extension
 
529
 */
 
530
SECStatus
 
531
cert_GetCertType(CERTCertificate *cert)
 
532
{
 
533
    SECStatus rv;
 
534
    SECItem tmpitem;
 
535
    SECItem encodedExtKeyUsage;
 
536
    CERTOidSequence *extKeyUsage = NULL;
 
537
    PRBool basicConstraintPresent = PR_FALSE;
 
538
    CERTBasicConstraints basicConstraint;
 
539
    unsigned int nsCertType = 0;
 
540
 
 
541
    if (cert->nsCertType) {
 
542
        /* once set, no need to recalculate */
 
543
        return SECSuccess;
 
544
    }
 
545
 
 
546
    tmpitem.data = NULL;
 
547
    CERT_FindNSCertTypeExtension(cert, &tmpitem);
 
548
    encodedExtKeyUsage.data = NULL;
 
549
    rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, 
 
550
                                &encodedExtKeyUsage);
 
551
    if (rv == SECSuccess) {
 
552
        extKeyUsage = CERT_DecodeOidSequence(&encodedExtKeyUsage);
 
553
    }
 
554
    rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
 
555
    if (rv == SECSuccess) {
 
556
        basicConstraintPresent = PR_TRUE;
 
557
    }
 
558
    if (tmpitem.data != NULL || extKeyUsage != NULL) {
 
559
        if (tmpitem.data == NULL) {
 
560
            nsCertType = 0;
 
561
        } else {
 
562
            nsCertType = tmpitem.data[0];
 
563
        }
 
564
 
 
565
        /* free tmpitem data pointer to avoid memory leak */
 
566
        PORT_Free(tmpitem.data);
 
567
        tmpitem.data = NULL;
 
568
        
 
569
        /*
 
570
         * for this release, we will allow SSL certs with an email address
 
571
         * to be used for email
 
572
         */
 
573
        if ( ( nsCertType & NS_CERT_TYPE_SSL_CLIENT ) &&
 
574
            cert->emailAddr && cert->emailAddr[0]) {
 
575
            nsCertType |= NS_CERT_TYPE_EMAIL;
 
576
        }
 
577
        /*
 
578
         * for this release, we will allow SSL intermediate CAs to be
 
579
         * email intermediate CAs too.
 
580
         */
 
581
        if ( nsCertType & NS_CERT_TYPE_SSL_CA ) {
 
582
            nsCertType |= NS_CERT_TYPE_EMAIL_CA;
 
583
        }
 
584
        /*
 
585
         * allow a cert with the extended key usage of EMail Protect
 
586
         * to be used for email or as an email CA, if basic constraints
 
587
         * indicates that it is a CA.
 
588
         */
 
589
        if (findOIDinOIDSeqByTagNum(extKeyUsage, 
 
590
                                    SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) ==
 
591
            SECSuccess) {
 
592
            if (basicConstraintPresent == PR_TRUE &&
 
593
                (basicConstraint.isCA)) {
 
594
                nsCertType |= NS_CERT_TYPE_EMAIL_CA;
 
595
            } else {
 
596
                nsCertType |= NS_CERT_TYPE_EMAIL;
 
597
            }
 
598
        }
 
599
        if (findOIDinOIDSeqByTagNum(extKeyUsage, 
 
600
                                    SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) ==
 
601
            SECSuccess){
 
602
            if (basicConstraintPresent == PR_TRUE &&
 
603
                (basicConstraint.isCA)) {
 
604
                nsCertType |= NS_CERT_TYPE_SSL_CA;
 
605
            } else {
 
606
                nsCertType |= NS_CERT_TYPE_SSL_SERVER;
 
607
            }
 
608
        }
 
609
        /* Treat certs with step-up OID as also having SSL server type. */
 
610
        if (findOIDinOIDSeqByTagNum(extKeyUsage, 
 
611
                                    SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) ==
 
612
            SECSuccess){
 
613
            if (basicConstraintPresent == PR_TRUE &&
 
614
                (basicConstraint.isCA)) {
 
615
                nsCertType |= NS_CERT_TYPE_SSL_CA;
 
616
            } else {
 
617
                nsCertType |= NS_CERT_TYPE_SSL_SERVER;
 
618
            }
 
619
        }
 
620
        if (findOIDinOIDSeqByTagNum(extKeyUsage,
 
621
                                    SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) ==
 
622
            SECSuccess){
 
623
            if (basicConstraintPresent == PR_TRUE &&
 
624
                (basicConstraint.isCA)) {
 
625
                nsCertType |= NS_CERT_TYPE_SSL_CA;
 
626
            } else {
 
627
                nsCertType |= NS_CERT_TYPE_SSL_CLIENT;
 
628
            }
 
629
        }
 
630
        if (findOIDinOIDSeqByTagNum(extKeyUsage,
 
631
                                    SEC_OID_EXT_KEY_USAGE_CODE_SIGN) ==
 
632
            SECSuccess) {
 
633
            if (basicConstraintPresent == PR_TRUE &&
 
634
                (basicConstraint.isCA)) {
 
635
                nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
 
636
            } else {
 
637
                nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING;
 
638
            }
 
639
        }
 
640
        if (findOIDinOIDSeqByTagNum(extKeyUsage,
 
641
                                    SEC_OID_EXT_KEY_USAGE_TIME_STAMP) ==
 
642
            SECSuccess) {
 
643
            nsCertType |= EXT_KEY_USAGE_TIME_STAMP;
 
644
        }
 
645
        if (findOIDinOIDSeqByTagNum(extKeyUsage,
 
646
                                    SEC_OID_OCSP_RESPONDER) == 
 
647
            SECSuccess) {
 
648
            nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
 
649
        }
 
650
    } else {
 
651
        /* if no extension, then allow any ssl or email (no ca or object
 
652
         * signing)
 
653
         */
 
654
        nsCertType = NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER |
 
655
            NS_CERT_TYPE_EMAIL;
 
656
 
 
657
        /* if the basic constraint extension says the cert is a CA, then
 
658
           allow SSL CA and EMAIL CA and Status Responder */
 
659
        if ((basicConstraintPresent == PR_TRUE)
 
660
            && (basicConstraint.isCA)) {
 
661
                nsCertType |= NS_CERT_TYPE_SSL_CA;
 
662
                nsCertType |= NS_CERT_TYPE_EMAIL_CA;
 
663
                nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
 
664
        } else if (CERT_IsCACert(cert, NULL) == PR_TRUE) {
 
665
                nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
 
666
        }
 
667
 
 
668
        /* if the cert is a fortezza CA cert, then allow SSL CA and EMAIL CA */
 
669
        if (fortezzaIsCA(cert)) {
 
670
                nsCertType |= NS_CERT_TYPE_SSL_CA;
 
671
                nsCertType |= NS_CERT_TYPE_EMAIL_CA;
 
672
        }
 
673
    }
 
674
 
 
675
    if (encodedExtKeyUsage.data != NULL) {
 
676
        PORT_Free(encodedExtKeyUsage.data);
 
677
    }
 
678
    if (extKeyUsage != NULL) {
 
679
        CERT_DestroyOidSequence(extKeyUsage);
 
680
    }
 
681
    /* Assert that it is safe to cast &cert->nsCertType to "PRInt32 *" */
 
682
    PORT_Assert(sizeof(cert->nsCertType) == sizeof(PRInt32));
 
683
    PR_AtomicSet((PRInt32 *)&cert->nsCertType, nsCertType);
 
684
    return(SECSuccess);
 
685
}
 
686
 
 
687
/*
 
688
 * cert_GetKeyID() - extract or generate the subjectKeyID from a certificate
 
689
 */
 
690
SECStatus
 
691
cert_GetKeyID(CERTCertificate *cert)
 
692
{
 
693
    SECItem tmpitem;
 
694
    SECStatus rv;
 
695
    SECKEYPublicKey *key;
 
696
    
 
697
    cert->subjectKeyID.len = 0;
 
698
 
 
699
    /* see of the cert has a key identifier extension */
 
700
    rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
 
701
    if ( rv == SECSuccess ) {
 
702
        cert->subjectKeyID.data = (unsigned char*) PORT_ArenaAlloc(cert->arena, tmpitem.len);
 
703
        if ( cert->subjectKeyID.data != NULL ) {
 
704
            PORT_Memcpy(cert->subjectKeyID.data, tmpitem.data, tmpitem.len);
 
705
            cert->subjectKeyID.len = tmpitem.len;
 
706
            cert->keyIDGenerated = PR_FALSE;
 
707
        }
 
708
        
 
709
        PORT_Free(tmpitem.data);
 
710
    }
 
711
    
 
712
    /* if the cert doesn't have a key identifier extension and the cert is
 
713
     * a V1 fortezza certificate, use the cert's 8 byte KMID as the
 
714
     * key identifier.  */
 
715
    key = CERT_KMIDPublicKey(cert);
 
716
 
 
717
    if (key != NULL) {
 
718
        
 
719
        if (key->keyType == fortezzaKey) {
 
720
 
 
721
            cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, 8);
 
722
            if ( cert->subjectKeyID.data != NULL ) {
 
723
                PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8);
 
724
                cert->subjectKeyID.len = 8;
 
725
                cert->keyIDGenerated = PR_FALSE;
 
726
            }
 
727
        }
 
728
                
 
729
        SECKEY_DestroyPublicKey(key);
 
730
    }
 
731
 
 
732
    /* if the cert doesn't have a key identifier extension, then generate one*/
 
733
    if ( cert->subjectKeyID.len == 0 ) {
 
734
        /*
 
735
         * pkix says that if the subjectKeyID is not present, then we should
 
736
         * use the SHA-1 hash of the DER-encoded publicKeyInfo from the cert
 
737
         */
 
738
        cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH);
 
739
        if ( cert->subjectKeyID.data != NULL ) {
 
740
            rv = PK11_HashBuf(SEC_OID_SHA1,cert->subjectKeyID.data,
 
741
                              cert->derPublicKey.data,
 
742
                              cert->derPublicKey.len);
 
743
            if ( rv == SECSuccess ) {
 
744
                cert->subjectKeyID.len = SHA1_LENGTH;
 
745
            }
 
746
        }
 
747
    }
 
748
 
 
749
    if ( cert->subjectKeyID.len == 0 ) {
 
750
        return(SECFailure);
 
751
    }
 
752
    return(SECSuccess);
 
753
 
 
754
}
 
755
 
 
756
static PRBool
 
757
cert_IsRootCert(CERTCertificate *cert)
 
758
{
 
759
    SECStatus rv;
 
760
    SECItem tmpitem;
 
761
 
 
762
    /* cache the authKeyID extension, if present */
 
763
    cert->authKeyID = CERT_FindAuthKeyIDExten(cert->arena, cert);
 
764
 
 
765
    /* it MUST be self-issued to be a root */
 
766
    if (cert->derIssuer.len == 0 ||
 
767
        !SECITEM_ItemsAreEqual(&cert->derIssuer, &cert->derSubject))
 
768
    {
 
769
        return PR_FALSE;
 
770
    }
 
771
 
 
772
    /* check the authKeyID extension */
 
773
    if (cert->authKeyID) {
 
774
        /* authority key identifier is present */
 
775
        if (cert->authKeyID->keyID.len > 0) {
 
776
            /* the keyIdentifier field is set, look for subjectKeyID */
 
777
            rv = CERT_FindSubjectKeyIDExtension(cert, &tmpitem);
 
778
            if (rv == SECSuccess) {
 
779
                PRBool match;
 
780
                /* also present, they MUST match for it to be a root */
 
781
                match = SECITEM_ItemsAreEqual(&cert->authKeyID->keyID,
 
782
                                              &tmpitem);
 
783
                PORT_Free(tmpitem.data);
 
784
                if (!match) return PR_FALSE; /* else fall through */
 
785
            } else {
 
786
                /* the subject key ID is required when AKI is present */
 
787
                return PR_FALSE;
 
788
            }
 
789
        }
 
790
        if (cert->authKeyID->authCertIssuer) {
 
791
            SECItem *caName;
 
792
            caName = (SECItem *)CERT_GetGeneralNameByType(
 
793
                                          cert->authKeyID->authCertIssuer,
 
794
                                          certDirectoryName, PR_TRUE);
 
795
            if (caName) {
 
796
                if (!SECITEM_ItemsAreEqual(&cert->derIssuer, caName)) {
 
797
                    return PR_FALSE;
 
798
                } /* else fall through */
 
799
            } /* else ??? could not get general name as directory name? */
 
800
        }
 
801
        if (cert->authKeyID->authCertSerialNumber.len > 0) {
 
802
            if (!SECITEM_ItemsAreEqual(&cert->serialNumber,
 
803
                                 &cert->authKeyID->authCertSerialNumber)) {
 
804
                return PR_FALSE;
 
805
            } /* else fall through */
 
806
        }
 
807
        /* all of the AKI fields that were present passed the test */
 
808
        return PR_TRUE;
 
809
    }
 
810
    /* else the AKI was not present, so this is a root */
 
811
    return PR_TRUE;
 
812
}
 
813
 
 
814
/*
 
815
 * take a DER certificate and decode it into a certificate structure
 
816
 */
 
817
CERTCertificate *
 
818
CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
 
819
                         char *nickname)
 
820
{
 
821
    CERTCertificate *cert;
 
822
    PRArenaPool *arena;
 
823
    void *data;
 
824
    int rv;
 
825
    int len;
 
826
    char *tmpname;
 
827
    
 
828
    /* make a new arena */
 
829
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
830
    
 
831
    if ( !arena ) {
 
832
        return 0;
 
833
    }
 
834
 
 
835
    /* allocate the certificate structure */
 
836
    cert = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
 
837
    
 
838
    if ( !cert ) {
 
839
        goto loser;
 
840
    }
 
841
    
 
842
    cert->arena = arena;
 
843
    
 
844
    if ( copyDER ) {
 
845
        /* copy the DER data for the cert into this arena */
 
846
        data = (void *)PORT_ArenaAlloc(arena, derSignedCert->len);
 
847
        if ( !data ) {
 
848
            goto loser;
 
849
        }
 
850
        cert->derCert.data = (unsigned char *)data;
 
851
        cert->derCert.len = derSignedCert->len;
 
852
        PORT_Memcpy(data, derSignedCert->data, derSignedCert->len);
 
853
    } else {
 
854
        /* point to passed in DER data */
 
855
        cert->derCert = *derSignedCert;
 
856
    }
 
857
 
 
858
    /* decode the certificate info */
 
859
    rv = SEC_QuickDERDecodeItem(arena, cert, SEC_SignedCertificateTemplate,
 
860
                    &cert->derCert);
 
861
 
 
862
    if ( rv ) {
 
863
        goto loser;
 
864
    }
 
865
 
 
866
    if (cert_HasUnknownCriticalExten (cert->extensions) == PR_TRUE) {
 
867
        cert->options.bits.hasUnsupportedCriticalExt = PR_TRUE;
 
868
    }
 
869
 
 
870
    /* generate and save the database key for the cert */
 
871
    rv = CERT_KeyFromIssuerAndSN(arena, &cert->derIssuer, &cert->serialNumber,
 
872
                        &cert->certKey);
 
873
    if ( rv ) {
 
874
        goto loser;
 
875
    }
 
876
 
 
877
    /* set the nickname */
 
878
    if ( nickname == NULL ) {
 
879
        cert->nickname = NULL;
 
880
    } else {
 
881
        /* copy and install the nickname */
 
882
        len = PORT_Strlen(nickname) + 1;
 
883
        cert->nickname = (char*)PORT_ArenaAlloc(arena, len);
 
884
        if ( cert->nickname == NULL ) {
 
885
            goto loser;
 
886
        }
 
887
 
 
888
        PORT_Memcpy(cert->nickname, nickname, len);
 
889
    }
 
890
 
 
891
    /* set the email address */
 
892
    cert->emailAddr = cert_GetCertificateEmailAddresses(cert);
 
893
    
 
894
    /* initialize the subjectKeyID */
 
895
    rv = cert_GetKeyID(cert);
 
896
    if ( rv != SECSuccess ) {
 
897
        goto loser;
 
898
    }
 
899
 
 
900
    /* initialize keyUsage */
 
901
    rv = GetKeyUsage(cert);
 
902
    if ( rv != SECSuccess ) {
 
903
        goto loser;
 
904
    }
 
905
 
 
906
    /* initialize the certType */
 
907
    rv = cert_GetCertType(cert);
 
908
    if ( rv != SECSuccess ) {
 
909
        goto loser;
 
910
    }
 
911
 
 
912
    /* determine if this is a root cert */
 
913
    cert->isRoot = cert_IsRootCert(cert);
 
914
 
 
915
    tmpname = CERT_NameToAscii(&cert->subject);
 
916
    if ( tmpname != NULL ) {
 
917
        cert->subjectName = PORT_ArenaStrdup(cert->arena, tmpname);
 
918
        PORT_Free(tmpname);
 
919
    }
 
920
    
 
921
    tmpname = CERT_NameToAscii(&cert->issuer);
 
922
    if ( tmpname != NULL ) {
 
923
        cert->issuerName = PORT_ArenaStrdup(cert->arena, tmpname);
 
924
        PORT_Free(tmpname);
 
925
    }
 
926
    
 
927
    cert->referenceCount = 1;
 
928
    cert->slot = NULL;
 
929
    cert->pkcs11ID = CK_INVALID_HANDLE;
 
930
    cert->dbnickname = NULL;
 
931
    
 
932
    return(cert);
 
933
    
 
934
loser:
 
935
 
 
936
    if ( arena ) {
 
937
        PORT_FreeArena(arena, PR_FALSE);
 
938
    }
 
939
    
 
940
    return(0);
 
941
}
 
942
 
 
943
CERTCertificate *
 
944
__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
 
945
                         char *nickname)
 
946
{
 
947
    return CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname);
 
948
}
 
949
 
 
950
 
 
951
/*
 
952
** Amount of time that a certifiate is allowed good before it is actually
 
953
** good. This is used for pending certificates, ones that are about to be
 
954
** valid. The slop is designed to allow for some variance in the clocks
 
955
** of the machine checking the certificate.
 
956
*/
 
957
#define PENDING_SLOP (24L*60L*60L)              /* seconds per day */
 
958
static PRInt32 pendingSlop = PENDING_SLOP;      /* seconds */
 
959
 
 
960
PRInt32
 
961
CERT_GetSlopTime(void)
 
962
{
 
963
    return pendingSlop;                 /* seconds */
 
964
}
 
965
 
 
966
SECStatus
 
967
CERT_SetSlopTime(PRInt32 slop)          /* seconds */
 
968
{
 
969
    if (slop < 0)
 
970
        return SECFailure;
 
971
    pendingSlop = slop;
 
972
    return SECSuccess;
 
973
}
 
974
 
 
975
SECStatus
 
976
CERT_GetCertTimes(CERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
 
977
{
 
978
    SECStatus rv;
 
979
 
 
980
    if (!c || !notBefore || !notAfter) {
 
981
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
982
        return SECFailure;
 
983
    }
 
984
    
 
985
    /* convert DER not-before time */
 
986
    rv = DER_DecodeTimeChoice(notBefore, &c->validity.notBefore);
 
987
    if (rv) {
 
988
        return(SECFailure);
 
989
    }
 
990
    
 
991
    /* convert DER not-after time */
 
992
    rv = DER_DecodeTimeChoice(notAfter, &c->validity.notAfter);
 
993
    if (rv) {
 
994
        return(SECFailure);
 
995
    }
 
996
 
 
997
    return(SECSuccess);
 
998
}
 
999
 
 
1000
/*
 
1001
 * Check the validity times of a certificate
 
1002
 */
 
1003
SECCertTimeValidity
 
1004
CERT_CheckCertValidTimes(CERTCertificate *c, PRTime t, PRBool allowOverride)
 
1005
{
 
1006
    PRTime notBefore, notAfter, llPendingSlop, tmp1;
 
1007
    SECStatus rv;
 
1008
 
 
1009
    if (!c) {
 
1010
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1011
        return(secCertTimeUndetermined);
 
1012
    }
 
1013
    /* if cert is already marked OK, then don't bother to check */
 
1014
    if ( allowOverride && c->timeOK ) {
 
1015
        return(secCertTimeValid);
 
1016
    }
 
1017
 
 
1018
    rv = CERT_GetCertTimes(c, &notBefore, &notAfter);
 
1019
    
 
1020
    if (rv) {
 
1021
        return(secCertTimeExpired); /*XXX is this the right thing to do here?*/
 
1022
    }
 
1023
    
 
1024
    LL_I2L(llPendingSlop, pendingSlop);
 
1025
    /* convert to micro seconds */
 
1026
    LL_UI2L(tmp1, PR_USEC_PER_SEC);
 
1027
    LL_MUL(llPendingSlop, llPendingSlop, tmp1);
 
1028
    LL_SUB(notBefore, notBefore, llPendingSlop);
 
1029
    if ( LL_CMP( t, <, notBefore ) ) {
 
1030
        PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE);
 
1031
        return(secCertTimeNotValidYet);
 
1032
    }
 
1033
    if ( LL_CMP( t, >, notAfter) ) {
 
1034
        PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE);
 
1035
        return(secCertTimeExpired);
 
1036
    }
 
1037
 
 
1038
    return(secCertTimeValid);
 
1039
}
 
1040
 
 
1041
SECStatus
 
1042
SEC_GetCrlTimes(CERTCrl *date, PRTime *notBefore, PRTime *notAfter)
 
1043
{
 
1044
    int rv;
 
1045
    
 
1046
    /* convert DER not-before time */
 
1047
    rv = DER_DecodeTimeChoice(notBefore, &date->lastUpdate);
 
1048
    if (rv) {
 
1049
        return(SECFailure);
 
1050
    }
 
1051
    
 
1052
    /* convert DER not-after time */
 
1053
    if (date->nextUpdate.data) {
 
1054
        rv = DER_DecodeTimeChoice(notAfter, &date->nextUpdate);
 
1055
        if (rv) {
 
1056
            return(SECFailure);
 
1057
        }
 
1058
    }
 
1059
    else {
 
1060
        LL_I2L(*notAfter, 0L);
 
1061
    }
 
1062
    return(SECSuccess);
 
1063
}
 
1064
 
 
1065
/* These routines should probably be combined with the cert
 
1066
 * routines using an common extraction routine.
 
1067
 */
 
1068
SECCertTimeValidity
 
1069
SEC_CheckCrlTimes(CERTCrl *crl, PRTime t) {
 
1070
    PRTime notBefore, notAfter, llPendingSlop, tmp1;
 
1071
    SECStatus rv;
 
1072
 
 
1073
    rv = SEC_GetCrlTimes(crl, &notBefore, &notAfter);
 
1074
    
 
1075
    if (rv) {
 
1076
        return(secCertTimeExpired); 
 
1077
    }
 
1078
 
 
1079
    LL_I2L(llPendingSlop, pendingSlop);
 
1080
    /* convert to micro seconds */
 
1081
    LL_I2L(tmp1, PR_USEC_PER_SEC);
 
1082
    LL_MUL(llPendingSlop, llPendingSlop, tmp1);
 
1083
    LL_SUB(notBefore, notBefore, llPendingSlop);
 
1084
    if ( LL_CMP( t, <, notBefore ) ) {
 
1085
        return(secCertTimeNotValidYet);
 
1086
    }
 
1087
 
 
1088
    /* If next update is omitted and the test for notBefore passes, then
 
1089
       we assume that the crl is up to date.
 
1090
     */
 
1091
    if ( LL_IS_ZERO(notAfter) ) {
 
1092
        return(secCertTimeValid);
 
1093
    }
 
1094
 
 
1095
    if ( LL_CMP( t, >, notAfter) ) {
 
1096
        return(secCertTimeExpired);
 
1097
    }
 
1098
 
 
1099
    return(secCertTimeValid);
 
1100
}
 
1101
 
 
1102
PRBool
 
1103
SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old) {
 
1104
    PRTime newNotBefore, newNotAfter;
 
1105
    PRTime oldNotBefore, oldNotAfter;
 
1106
    SECStatus rv;
 
1107
 
 
1108
    /* problems with the new CRL? reject it */
 
1109
    rv = SEC_GetCrlTimes(inNew, &newNotBefore, &newNotAfter);
 
1110
    if (rv) return PR_FALSE;
 
1111
 
 
1112
    /* problems with the old CRL? replace it */
 
1113
    rv = SEC_GetCrlTimes(old, &oldNotBefore, &oldNotAfter);
 
1114
    if (rv) return PR_TRUE;
 
1115
 
 
1116
    /* Question: what about the notAfter's? */
 
1117
    return ((PRBool)LL_CMP(oldNotBefore, <, newNotBefore));
 
1118
}
 
1119
   
 
1120
/*
 
1121
 * return required key usage and cert type based on cert usage 
 
1122
 */
 
1123
SECStatus
 
1124
CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage,
 
1125
                                 PRBool ca,
 
1126
                                 unsigned int *retKeyUsage,
 
1127
                                 unsigned int *retCertType)
 
1128
{
 
1129
    unsigned int requiredKeyUsage = 0;
 
1130
    unsigned int requiredCertType = 0;
 
1131
    
 
1132
    if ( ca ) {
 
1133
        switch ( usage ) {
 
1134
          case certUsageSSLServerWithStepUp:
 
1135
            requiredKeyUsage = KU_NS_GOVT_APPROVED | KU_KEY_CERT_SIGN;
 
1136
            requiredCertType = NS_CERT_TYPE_SSL_CA;
 
1137
            break;
 
1138
          case certUsageSSLClient:
 
1139
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1140
            requiredCertType = NS_CERT_TYPE_SSL_CA;
 
1141
            break;
 
1142
          case certUsageSSLServer:
 
1143
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1144
            requiredCertType = NS_CERT_TYPE_SSL_CA;
 
1145
            break;
 
1146
          case certUsageSSLCA:
 
1147
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1148
            requiredCertType = NS_CERT_TYPE_SSL_CA;
 
1149
            break;
 
1150
          case certUsageEmailSigner:
 
1151
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1152
            requiredCertType = NS_CERT_TYPE_EMAIL_CA;
 
1153
            break;
 
1154
          case certUsageEmailRecipient:
 
1155
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1156
            requiredCertType = NS_CERT_TYPE_EMAIL_CA;
 
1157
            break;
 
1158
          case certUsageObjectSigner:
 
1159
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1160
            requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA;
 
1161
            break;
 
1162
          case certUsageAnyCA:
 
1163
          case certUsageVerifyCA:
 
1164
          case certUsageStatusResponder:
 
1165
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1166
            requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING_CA |
 
1167
                NS_CERT_TYPE_EMAIL_CA |
 
1168
                    NS_CERT_TYPE_SSL_CA;
 
1169
            break;
 
1170
          default:
 
1171
            PORT_Assert(0);
 
1172
            goto loser;
 
1173
        }
 
1174
    } else {
 
1175
        switch ( usage ) {
 
1176
          case certUsageSSLClient:
 
1177
            requiredKeyUsage = KU_DIGITAL_SIGNATURE;
 
1178
            requiredCertType = NS_CERT_TYPE_SSL_CLIENT;
 
1179
            break;
 
1180
          case certUsageSSLServer:
 
1181
            requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT;
 
1182
            requiredCertType = NS_CERT_TYPE_SSL_SERVER;
 
1183
            break;
 
1184
          case certUsageSSLServerWithStepUp:
 
1185
            requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT |
 
1186
                KU_NS_GOVT_APPROVED;
 
1187
            requiredCertType = NS_CERT_TYPE_SSL_SERVER;
 
1188
            break;
 
1189
          case certUsageSSLCA:
 
1190
            requiredKeyUsage = KU_KEY_CERT_SIGN;
 
1191
            requiredCertType = NS_CERT_TYPE_SSL_CA;
 
1192
            break;
 
1193
          case certUsageEmailSigner:
 
1194
            requiredKeyUsage = KU_DIGITAL_SIGNATURE;
 
1195
            requiredCertType = NS_CERT_TYPE_EMAIL;
 
1196
            break;
 
1197
          case certUsageEmailRecipient:
 
1198
            requiredKeyUsage = KU_KEY_AGREEMENT_OR_ENCIPHERMENT;
 
1199
            requiredCertType = NS_CERT_TYPE_EMAIL;
 
1200
            break;
 
1201
          case certUsageObjectSigner:
 
1202
            requiredKeyUsage = KU_DIGITAL_SIGNATURE;
 
1203
            requiredCertType = NS_CERT_TYPE_OBJECT_SIGNING;
 
1204
            break;
 
1205
          case certUsageStatusResponder:
 
1206
            requiredKeyUsage = KU_DIGITAL_SIGNATURE;
 
1207
            requiredCertType = EXT_KEY_USAGE_STATUS_RESPONDER;
 
1208
            break;
 
1209
          default:
 
1210
            PORT_Assert(0);
 
1211
            goto loser;
 
1212
        }
 
1213
    }
 
1214
 
 
1215
    if ( retKeyUsage != NULL ) {
 
1216
        *retKeyUsage = requiredKeyUsage;
 
1217
    }
 
1218
    if ( retCertType != NULL ) {
 
1219
        *retCertType = requiredCertType;
 
1220
    }
 
1221
 
 
1222
    return(SECSuccess);
 
1223
loser:
 
1224
    return(SECFailure);
 
1225
}
 
1226
 
 
1227
/*
 
1228
 * check the key usage of a cert against a set of required values
 
1229
 */
 
1230
SECStatus
 
1231
CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage)
 
1232
{
 
1233
    unsigned int certKeyUsage;
 
1234
 
 
1235
    if (!cert) {
 
1236
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1237
        return SECFailure;
 
1238
    }
 
1239
    /* choose between key agreement or key encipherment based on key
 
1240
     * type in cert
 
1241
     */
 
1242
    if ( requiredUsage & KU_KEY_AGREEMENT_OR_ENCIPHERMENT ) {
 
1243
        KeyType keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
 
1244
        /* turn off the special bit */
 
1245
        requiredUsage &= (~KU_KEY_AGREEMENT_OR_ENCIPHERMENT);
 
1246
 
 
1247
        switch (keyType) {
 
1248
        case rsaKey:
 
1249
            requiredUsage |= KU_KEY_ENCIPHERMENT;
 
1250
            break;
 
1251
        case dsaKey:
 
1252
            requiredUsage |= KU_DIGITAL_SIGNATURE;
 
1253
            break;
 
1254
        case fortezzaKey:
 
1255
        case keaKey:
 
1256
        case dhKey:
 
1257
            requiredUsage |= KU_KEY_AGREEMENT;
 
1258
            break;
 
1259
        case ecKey:
 
1260
            /* Accept either signature or agreement. */
 
1261
            if (!(cert->keyUsage & (KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)))
 
1262
                 goto loser;
 
1263
            break;
 
1264
        default:
 
1265
            goto loser;
 
1266
        }
 
1267
    }
 
1268
 
 
1269
    certKeyUsage = cert->keyUsage;
 
1270
    if (certKeyUsage & KU_NON_REPUDIATION)
 
1271
        certKeyUsage |= KU_DIGITAL_SIGNATURE;
 
1272
    if ( (certKeyUsage & requiredUsage) == requiredUsage ) 
 
1273
        return SECSuccess;
 
1274
 
 
1275
loser:
 
1276
    PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
 
1277
    return SECFailure;
 
1278
}
 
1279
 
 
1280
 
 
1281
CERTCertificate *
 
1282
CERT_DupCertificate(CERTCertificate *c)
 
1283
{
 
1284
    if (c) {
 
1285
#ifdef NSS_CLASSIC
 
1286
        CERT_LockCertRefCount(c);
 
1287
        ++c->referenceCount;
 
1288
        CERT_UnlockCertRefCount(c);
 
1289
#else
 
1290
        NSSCertificate *tmp = STAN_GetNSSCertificate(c);
 
1291
        nssCertificate_AddRef(tmp);
 
1292
#endif
 
1293
    }
 
1294
    return c;
 
1295
}
 
1296
 
 
1297
/*
 
1298
 * Allow use of default cert database, so that apps(such as mozilla) don't
 
1299
 * have to pass the handle all over the place.
 
1300
 */
 
1301
static CERTCertDBHandle *default_cert_db_handle = 0;
 
1302
 
 
1303
void
 
1304
CERT_SetDefaultCertDB(CERTCertDBHandle *handle)
 
1305
{
 
1306
    default_cert_db_handle = handle;
 
1307
    
 
1308
    return;
 
1309
}
 
1310
 
 
1311
CERTCertDBHandle *
 
1312
CERT_GetDefaultCertDB(void)
 
1313
{
 
1314
    return(default_cert_db_handle);
 
1315
}
 
1316
 
 
1317
/* XXX this would probably be okay/better as an xp routine? */
 
1318
static void
 
1319
sec_lower_string(char *s)
 
1320
{
 
1321
    if ( s == NULL ) {
 
1322
        return;
 
1323
    }
 
1324
    
 
1325
    while ( *s ) {
 
1326
        *s = PORT_Tolower(*s);
 
1327
        s++;
 
1328
    }
 
1329
    
 
1330
    return;
 
1331
}
 
1332
 
 
1333
/*
 
1334
** Add a domain name to the list of names that the user has explicitly
 
1335
** allowed (despite cert name mismatches) for use with a server cert.
 
1336
*/
 
1337
SECStatus
 
1338
CERT_AddOKDomainName(CERTCertificate *cert, const char *hn)
 
1339
{
 
1340
    CERTOKDomainName *domainOK;
 
1341
    int        newNameLen;
 
1342
 
 
1343
    if (!hn || !(newNameLen = strlen(hn))) {
 
1344
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1345
        return SECFailure;
 
1346
    }
 
1347
    domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena, 
 
1348
                                  (sizeof *domainOK) + newNameLen);
 
1349
    if (!domainOK) 
 
1350
        return SECFailure;      /* error code is already set. */
 
1351
 
 
1352
    PORT_Strcpy(domainOK->name, hn);
 
1353
    sec_lower_string(domainOK->name);
 
1354
 
 
1355
    /* put at head of list. */
 
1356
    domainOK->next = cert->domainOK;
 
1357
    cert->domainOK = domainOK;
 
1358
    return SECSuccess;
 
1359
}
 
1360
 
 
1361
/* returns SECSuccess if hn matches pattern cn,
 
1362
** returns SECFailure with SSL_ERROR_BAD_CERT_DOMAIN if no match,
 
1363
** returns SECFailure with some other error code if another error occurs.
 
1364
**
 
1365
** may modify cn, so caller must pass a modifiable copy.
 
1366
*/
 
1367
static SECStatus
 
1368
cert_TestHostName(char * cn, const char * hn)
 
1369
{
 
1370
    int regvalid = PORT_RegExpValid(cn);
 
1371
    if (regvalid != NON_SXP) {
 
1372
        SECStatus rv;
 
1373
        /* cn is a regular expression, try to match the shexp */
 
1374
        int match = PORT_RegExpCaseSearch(hn, cn);
 
1375
 
 
1376
        if ( match == 0 ) {
 
1377
            rv = SECSuccess;
 
1378
        } else {
 
1379
            PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
 
1380
            rv = SECFailure;
 
1381
        }
 
1382
        return rv;
 
1383
    } 
 
1384
    /* cn is not a regular expression */
 
1385
 
 
1386
    /* compare entire hn with cert name */
 
1387
    if (PORT_Strcasecmp(hn, cn) == 0) {
 
1388
        return SECSuccess;
 
1389
    }
 
1390
            
 
1391
    PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
 
1392
    return SECFailure;
 
1393
}
 
1394
 
 
1395
 
 
1396
SECStatus
 
1397
cert_VerifySubjectAltName(CERTCertificate *cert, const char *hn)
 
1398
{
 
1399
    PRArenaPool *     arena          = NULL;
 
1400
    CERTGeneralName * nameList       = NULL;
 
1401
    CERTGeneralName * current;
 
1402
    char *            cn;
 
1403
    int               cnBufLen;
 
1404
    unsigned int      hnLen;
 
1405
    int               DNSextCount    = 0;
 
1406
    int               IPextCount     = 0;
 
1407
    PRBool            isIPaddr;
 
1408
    SECStatus         rv             = SECFailure;
 
1409
    SECItem           subAltName;
 
1410
    PRNetAddr         netAddr;
 
1411
    char              cnbuf[128];
 
1412
 
 
1413
    subAltName.data = NULL;
 
1414
    hnLen    = strlen(hn);
 
1415
    cn       = cnbuf;
 
1416
    cnBufLen = sizeof cnbuf;
 
1417
 
 
1418
    rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, 
 
1419
                                &subAltName);
 
1420
    if (rv != SECSuccess) {
 
1421
        goto finish;
 
1422
    }
 
1423
    isIPaddr = (PR_SUCCESS == PR_StringToNetAddr(hn, &netAddr));
 
1424
    rv = SECFailure;
 
1425
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
1426
    if (!arena) 
 
1427
        goto finish;
 
1428
 
 
1429
    nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName);
 
1430
    if (!current)
 
1431
        goto finish;
 
1432
 
 
1433
    do {
 
1434
        switch (current->type) {
 
1435
        case certDNSName:
 
1436
            if (!isIPaddr) {
 
1437
                /* DNS name current->name.other.data is not null terminated.
 
1438
                ** so must copy it.  
 
1439
                */
 
1440
                int cnLen = current->name.other.len;
 
1441
                if (cnLen + 1 > cnBufLen) {
 
1442
                    cnBufLen = cnLen + 1;
 
1443
                    cn = (char *)PORT_ArenaAlloc(arena, cnBufLen);
 
1444
                    if (!cn)
 
1445
                        goto finish;
 
1446
                }
 
1447
                PORT_Memcpy(cn, current->name.other.data, cnLen);
 
1448
                cn[cnLen] = 0;
 
1449
                rv = cert_TestHostName(cn ,hn);
 
1450
                if (rv == SECSuccess)
 
1451
                    goto finish;
 
1452
            }
 
1453
            DNSextCount++;
 
1454
            break;
 
1455
        case certIPAddress:
 
1456
            if (isIPaddr) {
 
1457
                int match = 0;
 
1458
                PRIPv6Addr v6Addr;
 
1459
                if (current->name.other.len == 4 &&         /* IP v4 address */
 
1460
                    netAddr.inet.family == PR_AF_INET) {
 
1461
                    match = !memcmp(&netAddr.inet.ip, 
 
1462
                                    current->name.other.data, 4);
 
1463
                } else if (current->name.other.len == 16 && /* IP v6 address */
 
1464
                    netAddr.ipv6.family == PR_AF_INET6) {
 
1465
                    match = !memcmp(&netAddr.ipv6.ip,
 
1466
                                     current->name.other.data, 16);
 
1467
                } else if (current->name.other.len == 16 && /* IP v6 address */
 
1468
                    netAddr.inet.family == PR_AF_INET) {
 
1469
                    /* convert netAddr to ipv6, then compare. */
 
1470
                    /* ipv4 must be in Network Byte Order on input. */
 
1471
                    PR_ConvertIPv4AddrToIPv6(netAddr.inet.ip, &v6Addr);
 
1472
                    match = !memcmp(&v6Addr, current->name.other.data, 16);
 
1473
                } else if (current->name.other.len == 4 &&  /* IP v4 address */
 
1474
                    netAddr.inet.family == PR_AF_INET6) {
 
1475
                    /* convert netAddr to ipv6, then compare. */
 
1476
                    PRUint32 ipv4 = (current->name.other.data[0] << 24) |
 
1477
                                    (current->name.other.data[1] << 16) |
 
1478
                                    (current->name.other.data[2] <<  8) |
 
1479
                                     current->name.other.data[3];
 
1480
                    /* ipv4 must be in Network Byte Order on input. */
 
1481
                    PR_ConvertIPv4AddrToIPv6(PR_htonl(ipv4), &v6Addr);
 
1482
                    match = !memcmp(&netAddr.ipv6.ip, &v6Addr, 16);
 
1483
                } 
 
1484
                if (match) {
 
1485
                    rv = SECSuccess;
 
1486
                    goto finish;
 
1487
                }
 
1488
            }
 
1489
            IPextCount++;
 
1490
            break;
 
1491
        default:
 
1492
            break;
 
1493
        }
 
1494
        current = CERT_GetNextGeneralName(current);
 
1495
    } while (current != nameList);
 
1496
 
 
1497
    if ((!isIPaddr && !DNSextCount) || (isIPaddr && !IPextCount)) {
 
1498
        /* no relevant value in the extension was found. */
 
1499
        PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
 
1500
    } else {
 
1501
        PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
 
1502
    }
 
1503
    rv = SECFailure;
 
1504
 
 
1505
finish:
 
1506
 
 
1507
    /* Don't free nameList, it's part of the arena. */
 
1508
    if (arena) {
 
1509
        PORT_FreeArena(arena, PR_FALSE);
 
1510
    }
 
1511
 
 
1512
    if (subAltName.data) {
 
1513
        SECITEM_FreeItem(&subAltName, PR_FALSE);
 
1514
    }
 
1515
 
 
1516
    return rv;
 
1517
}
 
1518
 
 
1519
 
 
1520
/* Make sure that the name of the host we are connecting to matches the
 
1521
 * name that is incoded in the common-name component of the certificate
 
1522
 * that they are using.
 
1523
 */
 
1524
SECStatus
 
1525
CERT_VerifyCertName(CERTCertificate *cert, const char *hn)
 
1526
{
 
1527
    char *    cn;
 
1528
    SECStatus rv;
 
1529
    CERTOKDomainName *domainOK;
 
1530
 
 
1531
    if (!hn || !strlen(hn)) {
 
1532
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1533
        return SECFailure;
 
1534
    }
 
1535
 
 
1536
    /* if the name is one that the user has already approved, it's OK. */
 
1537
    for (domainOK = cert->domainOK; domainOK; domainOK = domainOK->next) {
 
1538
        if (0 == PORT_Strcasecmp(hn, domainOK->name)) {
 
1539
            return SECSuccess;
 
1540
        }
 
1541
    }
 
1542
 
 
1543
    /* Per RFC 2818, if the SubjectAltName extension is present, it must
 
1544
    ** be used as the cert's identity.
 
1545
    */
 
1546
    rv = cert_VerifySubjectAltName(cert, hn);
 
1547
    if (rv == SECSuccess || PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
 
1548
        return rv;
 
1549
 
 
1550
    /* try the cert extension first, then the common name */
 
1551
    cn = CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
 
1552
    if ( !cn ) {
 
1553
        cn = CERT_GetCommonName(&cert->subject);
 
1554
    }
 
1555
    if ( cn ) {
 
1556
        rv = cert_TestHostName(cn, hn);
 
1557
        PORT_Free(cn);
 
1558
    } else 
 
1559
        PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
 
1560
    return rv;
 
1561
}
 
1562
 
 
1563
PRBool
 
1564
CERT_CompareCerts(CERTCertificate *c1, CERTCertificate *c2)
 
1565
{
 
1566
    SECComparison comp;
 
1567
    
 
1568
    comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert);
 
1569
    if ( comp == SECEqual ) { /* certs are the same */
 
1570
        return(PR_TRUE);
 
1571
    } else {
 
1572
        return(PR_FALSE);
 
1573
    }
 
1574
}
 
1575
 
 
1576
static SECStatus
 
1577
StringsEqual(char *s1, char *s2) {
 
1578
    if ( ( s1 == NULL ) || ( s2 == NULL ) ) {
 
1579
        if ( s1 != s2 ) { /* only one is null */
 
1580
            return(SECFailure);
 
1581
        }
 
1582
        return(SECSuccess); /* both are null */
 
1583
    }
 
1584
        
 
1585
    if ( PORT_Strcmp( s1, s2 ) != 0 ) {
 
1586
        return(SECFailure); /* not equal */
 
1587
    }
 
1588
 
 
1589
    return(SECSuccess); /* strings are equal */
 
1590
}
 
1591
 
 
1592
 
 
1593
PRBool
 
1594
CERT_CompareCertsForRedirection(CERTCertificate *c1, CERTCertificate *c2)
 
1595
{
 
1596
    SECComparison comp;
 
1597
    char *c1str, *c2str;
 
1598
    SECStatus eq;
 
1599
    
 
1600
    comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert);
 
1601
    if ( comp == SECEqual ) { /* certs are the same */
 
1602
        return(PR_TRUE);
 
1603
    }
 
1604
        
 
1605
    /* check if they are issued by the same CA */
 
1606
    comp = SECITEM_CompareItem(&c1->derIssuer, &c2->derIssuer);
 
1607
    if ( comp != SECEqual ) { /* different issuer */
 
1608
        return(PR_FALSE);
 
1609
    }
 
1610
 
 
1611
    /* check country name */
 
1612
    c1str = CERT_GetCountryName(&c1->subject);
 
1613
    c2str = CERT_GetCountryName(&c2->subject);
 
1614
    eq = StringsEqual(c1str, c2str);
 
1615
    PORT_Free(c1str);
 
1616
    PORT_Free(c2str);
 
1617
    if ( eq != SECSuccess ) {
 
1618
        return(PR_FALSE);
 
1619
    }
 
1620
 
 
1621
    /* check locality name */
 
1622
    c1str = CERT_GetLocalityName(&c1->subject);
 
1623
    c2str = CERT_GetLocalityName(&c2->subject);
 
1624
    eq = StringsEqual(c1str, c2str);
 
1625
    PORT_Free(c1str);
 
1626
    PORT_Free(c2str);
 
1627
    if ( eq != SECSuccess ) {
 
1628
        return(PR_FALSE);
 
1629
    }
 
1630
        
 
1631
    /* check state name */
 
1632
    c1str = CERT_GetStateName(&c1->subject);
 
1633
    c2str = CERT_GetStateName(&c2->subject);
 
1634
    eq = StringsEqual(c1str, c2str);
 
1635
    PORT_Free(c1str);
 
1636
    PORT_Free(c2str);
 
1637
    if ( eq != SECSuccess ) {
 
1638
        return(PR_FALSE);
 
1639
    }
 
1640
 
 
1641
    /* check org name */
 
1642
    c1str = CERT_GetOrgName(&c1->subject);
 
1643
    c2str = CERT_GetOrgName(&c2->subject);
 
1644
    eq = StringsEqual(c1str, c2str);
 
1645
    PORT_Free(c1str);
 
1646
    PORT_Free(c2str);
 
1647
    if ( eq != SECSuccess ) {
 
1648
        return(PR_FALSE);
 
1649
    }
 
1650
 
 
1651
#ifdef NOTDEF   
 
1652
    /* check orgUnit name */
 
1653
    /*
 
1654
     * We need to revisit this and decide which fields should be allowed to be
 
1655
     * different
 
1656
     */
 
1657
    c1str = CERT_GetOrgUnitName(&c1->subject);
 
1658
    c2str = CERT_GetOrgUnitName(&c2->subject);
 
1659
    eq = StringsEqual(c1str, c2str);
 
1660
    PORT_Free(c1str);
 
1661
    PORT_Free(c2str);
 
1662
    if ( eq != SECSuccess ) {
 
1663
        return(PR_FALSE);
 
1664
    }
 
1665
#endif
 
1666
 
 
1667
    return(PR_TRUE); /* all fields but common name are the same */
 
1668
}
 
1669
 
 
1670
 
 
1671
/* CERT_CertChainFromCert and CERT_DestroyCertificateList moved
 
1672
   to certhigh.c */
 
1673
 
 
1674
 
 
1675
CERTIssuerAndSN *
 
1676
CERT_GetCertIssuerAndSN(PRArenaPool *arena, CERTCertificate *cert)
 
1677
{
 
1678
    CERTIssuerAndSN *result;
 
1679
    SECStatus rv;
 
1680
 
 
1681
    if ( arena == NULL ) {
 
1682
        arena = cert->arena;
 
1683
    }
 
1684
    
 
1685
    result = (CERTIssuerAndSN*)PORT_ArenaZAlloc(arena, sizeof(*result));
 
1686
    if (result == NULL) {
 
1687
        PORT_SetError (SEC_ERROR_NO_MEMORY);
 
1688
        return NULL;
 
1689
    }
 
1690
 
 
1691
    rv = SECITEM_CopyItem(arena, &result->derIssuer, &cert->derIssuer);
 
1692
    if (rv != SECSuccess)
 
1693
        return NULL;
 
1694
 
 
1695
    rv = CERT_CopyName(arena, &result->issuer, &cert->issuer);
 
1696
    if (rv != SECSuccess)
 
1697
        return NULL;
 
1698
 
 
1699
    rv = SECITEM_CopyItem(arena, &result->serialNumber, &cert->serialNumber);
 
1700
    if (rv != SECSuccess)
 
1701
        return NULL;
 
1702
 
 
1703
    return result;
 
1704
}
 
1705
 
 
1706
char *
 
1707
CERT_MakeCANickname(CERTCertificate *cert)
 
1708
{
 
1709
    char *firstname = NULL;
 
1710
    char *org = NULL;
 
1711
    char *nickname = NULL;
 
1712
    int count;
 
1713
    CERTCertificate *dummycert;
 
1714
    CERTCertDBHandle *handle;
 
1715
    
 
1716
    handle = cert->dbhandle;
 
1717
    
 
1718
    nickname = CERT_GetNickName(cert, handle, cert->arena);
 
1719
    if (nickname == NULL) {
 
1720
        firstname = CERT_GetCommonName(&cert->subject);
 
1721
        if ( firstname == NULL ) {
 
1722
            firstname = CERT_GetOrgUnitName(&cert->subject);
 
1723
        }
 
1724
 
 
1725
        org = CERT_GetOrgName(&cert->issuer);
 
1726
        if (org == NULL) {
 
1727
            org = CERT_GetDomainComponentName(&cert->issuer);
 
1728
            if (org == NULL) {
 
1729
                if (firstname) {
 
1730
                    org = firstname;
 
1731
                    firstname = NULL;
 
1732
                } else {
 
1733
                    org = PORT_Strdup("Unknown CA");
 
1734
                }
 
1735
            }
 
1736
        }
 
1737
 
 
1738
        /* can only fail if PORT_Strdup fails, in which case
 
1739
         * we're having memory problems. */
 
1740
        if (org == NULL) {
 
1741
            goto loser;
 
1742
        }
 
1743
 
 
1744
    
 
1745
        count = 1;
 
1746
        while ( 1 ) {
 
1747
 
 
1748
            if ( firstname ) {
 
1749
                if ( count == 1 ) {
 
1750
                    nickname = PR_smprintf("%s - %s", firstname, org);
 
1751
                } else {
 
1752
                    nickname = PR_smprintf("%s - %s #%d", firstname, org, count);
 
1753
                }
 
1754
            } else {
 
1755
                if ( count == 1 ) {
 
1756
                    nickname = PR_smprintf("%s", org);
 
1757
                } else {
 
1758
                    nickname = PR_smprintf("%s #%d", org, count);
 
1759
                }
 
1760
            }
 
1761
            if ( nickname == NULL ) {
 
1762
                goto loser;
 
1763
            }
 
1764
 
 
1765
            /* look up the nickname to make sure it isn't in use already */
 
1766
            dummycert = CERT_FindCertByNickname(handle, nickname);
 
1767
 
 
1768
            if ( dummycert == NULL ) {
 
1769
                goto done;
 
1770
            }
 
1771
        
 
1772
            /* found a cert, destroy it and loop */
 
1773
            CERT_DestroyCertificate(dummycert);
 
1774
 
 
1775
            /* free the nickname */
 
1776
            PORT_Free(nickname);
 
1777
 
 
1778
            count++;
 
1779
        }
 
1780
    }
 
1781
loser:
 
1782
    if ( nickname ) {
 
1783
        PORT_Free(nickname);
 
1784
    }
 
1785
 
 
1786
    nickname = "";
 
1787
    
 
1788
done:
 
1789
    if ( firstname ) {
 
1790
        PORT_Free(firstname);
 
1791
    }
 
1792
    if ( org ) {
 
1793
        PORT_Free(org);
 
1794
    }
 
1795
    
 
1796
    return(nickname);
 
1797
}
 
1798
 
 
1799
/* CERT_Import_CAChain moved to certhigh.c */
 
1800
 
 
1801
void
 
1802
CERT_DestroyCrl (CERTSignedCrl *crl)
 
1803
{
 
1804
    SEC_DestroyCrl (crl);
 
1805
}
 
1806
 
 
1807
 
 
1808
 
 
1809
/*
 
1810
 * Does a cert belong to a CA?  We decide based on perm database trust
 
1811
 * flags, Netscape Cert Type Extension, and KeyUsage Extension.
 
1812
 */
 
1813
PRBool
 
1814
CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype)
 
1815
{
 
1816
    CERTCertTrust *trust;
 
1817
    SECStatus rv;
 
1818
    unsigned int type;
 
1819
    PRBool ret;
 
1820
 
 
1821
    ret = PR_FALSE;
 
1822
    type = 0;
 
1823
 
 
1824
    if ( cert->trust && (cert->trust->sslFlags|cert->trust->emailFlags|
 
1825
                                cert->trust->objectSigningFlags)) {
 
1826
        trust = cert->trust;
 
1827
        if ( ( ( trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||
 
1828
           ( ( trust->sslFlags & CERTDB_TRUSTED_CA ) == CERTDB_TRUSTED_CA ) ) {
 
1829
            ret = PR_TRUE;
 
1830
            type |= NS_CERT_TYPE_SSL_CA;
 
1831
        }
 
1832
        
 
1833
        if ( ( ( trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||
 
1834
          ( ( trust->emailFlags & CERTDB_TRUSTED_CA ) == CERTDB_TRUSTED_CA ) ) {
 
1835
            ret = PR_TRUE;
 
1836
            type |= NS_CERT_TYPE_EMAIL_CA;
 
1837
        }
 
1838
        
 
1839
        if ( ( ( trust->objectSigningFlags & CERTDB_VALID_CA ) 
 
1840
                                                == CERTDB_VALID_CA ) ||
 
1841
          ( ( trust->objectSigningFlags & CERTDB_TRUSTED_CA ) 
 
1842
                                                == CERTDB_TRUSTED_CA ) ) {
 
1843
            ret = PR_TRUE;
 
1844
            type |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
 
1845
        }
 
1846
    } else {
 
1847
        if ( cert->nsCertType &
 
1848
            ( NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA |
 
1849
             NS_CERT_TYPE_OBJECT_SIGNING_CA ) ) {
 
1850
            ret = PR_TRUE;
 
1851
            type = (cert->nsCertType & NS_CERT_TYPE_CA);
 
1852
        } else {
 
1853
            CERTBasicConstraints constraints;
 
1854
            rv = CERT_FindBasicConstraintExten(cert, &constraints);
 
1855
            if ( rv == SECSuccess ) {
 
1856
                if ( constraints.isCA ) {
 
1857
                    ret = PR_TRUE;
 
1858
                    type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
 
1859
                }
 
1860
            } 
 
1861
        } 
 
1862
 
 
1863
        /* finally check if it's a FORTEZZA V1 CA */
 
1864
        if (ret == PR_FALSE) {
 
1865
            if (fortezzaIsCA(cert)) {
 
1866
                ret = PR_TRUE;
 
1867
                type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
 
1868
            }
 
1869
        }
 
1870
    }
 
1871
 
 
1872
    /* the isRoot flag trumps all */
 
1873
    if (cert->isRoot) {
 
1874
        ret = PR_TRUE;
 
1875
        /* set only these by default, same as above */
 
1876
        type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA);
 
1877
    }
 
1878
 
 
1879
    if ( rettype != NULL ) {
 
1880
        *rettype = type;
 
1881
    }
 
1882
    
 
1883
    return(ret);
 
1884
}
 
1885
 
 
1886
PRBool
 
1887
CERT_IsCADERCert(SECItem *derCert, unsigned int *type) {
 
1888
    CERTCertificate *cert;
 
1889
    PRBool isCA;
 
1890
 
 
1891
    /* This is okay -- only looks at extensions */
 
1892
    cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
 
1893
    if (cert == NULL) return PR_FALSE;
 
1894
 
 
1895
    isCA = CERT_IsCACert(cert,type);
 
1896
    CERT_DestroyCertificate (cert);
 
1897
    return isCA;
 
1898
}
 
1899
 
 
1900
PRBool
 
1901
CERT_IsRootDERCert(SECItem *derCert)
 
1902
{
 
1903
    CERTCertificate *cert;
 
1904
    PRBool isRoot;
 
1905
 
 
1906
    /* This is okay -- only looks at extensions */
 
1907
    cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
 
1908
    if (cert == NULL) return PR_FALSE;
 
1909
 
 
1910
    isRoot = cert->isRoot;
 
1911
    CERT_DestroyCertificate (cert);
 
1912
    return isRoot;
 
1913
}
 
1914
 
 
1915
CERTCompareValidityStatus
 
1916
CERT_CompareValidityTimes(CERTValidity* val_a, CERTValidity* val_b)
 
1917
{
 
1918
    PRTime notBeforeA, notBeforeB, notAfterA, notAfterB;
 
1919
 
 
1920
    if (!val_a || !val_b)
 
1921
    {
 
1922
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1923
        return certValidityUndetermined;
 
1924
    }
 
1925
 
 
1926
    if ( SECSuccess != DER_DecodeTimeChoice(&notBeforeA, &val_a->notBefore) ||
 
1927
         SECSuccess != DER_DecodeTimeChoice(&notBeforeB, &val_b->notBefore) ||
 
1928
         SECSuccess != DER_DecodeTimeChoice(&notAfterA, &val_a->notAfter) ||
 
1929
         SECSuccess != DER_DecodeTimeChoice(&notAfterB, &val_b->notAfter) ) {
 
1930
        return certValidityUndetermined;
 
1931
    }
 
1932
 
 
1933
    /* sanity check */
 
1934
    if (LL_CMP(notBeforeA,>,notAfterA) || LL_CMP(notBeforeB,>,notAfterB)) {
 
1935
        PORT_SetError(SEC_ERROR_INVALID_TIME);
 
1936
        return certValidityUndetermined;
 
1937
    }
 
1938
 
 
1939
    if (LL_CMP(notAfterA,!=,notAfterB)) {
 
1940
        /* one cert validity goes farther into the future, select it */
 
1941
        return LL_CMP(notAfterA,<,notAfterB) ?
 
1942
            certValidityChooseB : certValidityChooseA;
 
1943
    }
 
1944
    /* the two certs have the same expiration date */
 
1945
    PORT_Assert(LL_CMP(notAfterA, == , notAfterB));
 
1946
    /* do they also have the same start date ? */
 
1947
    if (LL_CMP(notBeforeA,==,notBeforeB)) {
 
1948
        return certValidityEqual;
 
1949
    }
 
1950
    /* choose cert with the later start date */
 
1951
    return LL_CMP(notBeforeA,<,notBeforeB) ?
 
1952
        certValidityChooseB : certValidityChooseA;
 
1953
}
 
1954
 
 
1955
/*
 
1956
 * is certa newer than certb?  If one is expired, pick the other one.
 
1957
 */
 
1958
PRBool
 
1959
CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb)
 
1960
{
 
1961
    PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
 
1962
    SECStatus rv;
 
1963
    PRBool newerbefore, newerafter;
 
1964
    
 
1965
    rv = CERT_GetCertTimes(certa, &notBeforeA, &notAfterA);
 
1966
    if ( rv != SECSuccess ) {
 
1967
        return(PR_FALSE);
 
1968
    }
 
1969
    
 
1970
    rv = CERT_GetCertTimes(certb, &notBeforeB, &notAfterB);
 
1971
    if ( rv != SECSuccess ) {
 
1972
        return(PR_TRUE);
 
1973
    }
 
1974
 
 
1975
    newerbefore = PR_FALSE;
 
1976
    if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
 
1977
        newerbefore = PR_TRUE;
 
1978
    }
 
1979
 
 
1980
    newerafter = PR_FALSE;
 
1981
    if ( LL_CMP(notAfterA, >, notAfterB) ) {
 
1982
        newerafter = PR_TRUE;
 
1983
    }
 
1984
    
 
1985
    if ( newerbefore && newerafter ) {
 
1986
        return(PR_TRUE);
 
1987
    }
 
1988
    
 
1989
    if ( ( !newerbefore ) && ( !newerafter ) ) {
 
1990
        return(PR_FALSE);
 
1991
    }
 
1992
 
 
1993
    /* get current time */
 
1994
    now = PR_Now();
 
1995
 
 
1996
    if ( newerbefore ) {
 
1997
        /* cert A was issued after cert B, but expires sooner */
 
1998
        /* if A is expired, then pick B */
 
1999
        if ( LL_CMP(notAfterA, <, now ) ) {
 
2000
            return(PR_FALSE);
 
2001
        }
 
2002
        return(PR_TRUE);
 
2003
    } else {
 
2004
        /* cert B was issued after cert A, but expires sooner */
 
2005
        /* if B is expired, then pick A */
 
2006
        if ( LL_CMP(notAfterB, <, now ) ) {
 
2007
            return(PR_TRUE);
 
2008
        }
 
2009
        return(PR_FALSE);
 
2010
    }
 
2011
}
 
2012
 
 
2013
void
 
2014
CERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts)
 
2015
{
 
2016
    unsigned int i;
 
2017
    
 
2018
    if ( certs ) {
 
2019
        for ( i = 0; i < ncerts; i++ ) {
 
2020
            if ( certs[i] ) {
 
2021
                CERT_DestroyCertificate(certs[i]);
 
2022
            }
 
2023
        }
 
2024
 
 
2025
        PORT_Free(certs);
 
2026
    }
 
2027
    
 
2028
    return;
 
2029
}
 
2030
 
 
2031
char *
 
2032
CERT_FixupEmailAddr(char *emailAddr)
 
2033
{
 
2034
    char *retaddr;
 
2035
    char *str;
 
2036
 
 
2037
    if ( emailAddr == NULL ) {
 
2038
        return(NULL);
 
2039
    }
 
2040
    
 
2041
    /* copy the string */
 
2042
    str = retaddr = PORT_Strdup(emailAddr);
 
2043
    if ( str == NULL ) {
 
2044
        return(NULL);
 
2045
    }
 
2046
    
 
2047
    /* make it lower case */
 
2048
    while ( *str ) {
 
2049
        *str = tolower( *str );
 
2050
        str++;
 
2051
    }
 
2052
    
 
2053
    return(retaddr);
 
2054
}
 
2055
 
 
2056
/*
 
2057
 * NOTE - don't allow encode of govt-approved or invisible bits
 
2058
 */
 
2059
SECStatus
 
2060
CERT_DecodeTrustString(CERTCertTrust *trust, char *trusts)
 
2061
{
 
2062
    unsigned int i;
 
2063
    unsigned int *pflags;
 
2064
    
 
2065
    if (!trust) {
 
2066
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
2067
        return SECFailure;
 
2068
    }
 
2069
    trust->sslFlags = 0;
 
2070
    trust->emailFlags = 0;
 
2071
    trust->objectSigningFlags = 0;
 
2072
    if (!trusts) {
 
2073
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
2074
        return SECFailure;
 
2075
    }
 
2076
 
 
2077
    pflags = &trust->sslFlags;
 
2078
    
 
2079
    for (i=0; i < PORT_Strlen(trusts); i++) {
 
2080
        switch (trusts[i]) {
 
2081
          case 'p':
 
2082
              *pflags = *pflags | CERTDB_VALID_PEER;
 
2083
              break;
 
2084
 
 
2085
          case 'P':
 
2086
              *pflags = *pflags | CERTDB_TRUSTED | CERTDB_VALID_PEER;
 
2087
              break;
 
2088
 
 
2089
          case 'w':
 
2090
              *pflags = *pflags | CERTDB_SEND_WARN;
 
2091
              break;
 
2092
 
 
2093
          case 'c':
 
2094
              *pflags = *pflags | CERTDB_VALID_CA;
 
2095
              break;
 
2096
 
 
2097
          case 'T':
 
2098
              *pflags = *pflags | CERTDB_TRUSTED_CLIENT_CA | CERTDB_VALID_CA;
 
2099
              break;
 
2100
 
 
2101
          case 'C' :
 
2102
              *pflags = *pflags | CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
 
2103
              break;
 
2104
 
 
2105
          case 'u':
 
2106
              *pflags = *pflags | CERTDB_USER;
 
2107
              break;
 
2108
 
 
2109
          case 'i':
 
2110
              *pflags = *pflags | CERTDB_INVISIBLE_CA;
 
2111
              break;
 
2112
          case 'g':
 
2113
              *pflags = *pflags | CERTDB_GOVT_APPROVED_CA;
 
2114
              break;
 
2115
 
 
2116
          case ',':
 
2117
              if ( pflags == &trust->sslFlags ) {
 
2118
                  pflags = &trust->emailFlags;
 
2119
              } else {
 
2120
                  pflags = &trust->objectSigningFlags;
 
2121
              }
 
2122
              break;
 
2123
          default:
 
2124
              return SECFailure;
 
2125
        }
 
2126
    }
 
2127
 
 
2128
    return SECSuccess;
 
2129
}
 
2130
 
 
2131
static void
 
2132
EncodeFlags(char *trusts, unsigned int flags)
 
2133
{
 
2134
    if (flags & CERTDB_VALID_CA)
 
2135
        if (!(flags & CERTDB_TRUSTED_CA) &&
 
2136
            !(flags & CERTDB_TRUSTED_CLIENT_CA))
 
2137
            PORT_Strcat(trusts, "c");
 
2138
    if (flags & CERTDB_VALID_PEER)
 
2139
        if (!(flags & CERTDB_TRUSTED))
 
2140
            PORT_Strcat(trusts, "p");
 
2141
    if (flags & CERTDB_TRUSTED_CA)
 
2142
        PORT_Strcat(trusts, "C");
 
2143
    if (flags & CERTDB_TRUSTED_CLIENT_CA)
 
2144
        PORT_Strcat(trusts, "T");
 
2145
    if (flags & CERTDB_TRUSTED)
 
2146
        PORT_Strcat(trusts, "P");
 
2147
    if (flags & CERTDB_USER)
 
2148
        PORT_Strcat(trusts, "u");
 
2149
    if (flags & CERTDB_SEND_WARN)
 
2150
        PORT_Strcat(trusts, "w");
 
2151
    if (flags & CERTDB_INVISIBLE_CA)
 
2152
        PORT_Strcat(trusts, "I");
 
2153
    if (flags & CERTDB_GOVT_APPROVED_CA)
 
2154
        PORT_Strcat(trusts, "G");
 
2155
    return;
 
2156
}
 
2157
 
 
2158
char *
 
2159
CERT_EncodeTrustString(CERTCertTrust *trust)
 
2160
{
 
2161
    char tmpTrustSSL[32];
 
2162
    char tmpTrustEmail[32];
 
2163
    char tmpTrustSigning[32];
 
2164
    char *retstr = NULL;
 
2165
 
 
2166
    if ( trust ) {
 
2167
        tmpTrustSSL[0] = '\0';
 
2168
        tmpTrustEmail[0] = '\0';
 
2169
        tmpTrustSigning[0] = '\0';
 
2170
    
 
2171
        EncodeFlags(tmpTrustSSL, trust->sslFlags);
 
2172
        EncodeFlags(tmpTrustEmail, trust->emailFlags);
 
2173
        EncodeFlags(tmpTrustSigning, trust->objectSigningFlags);
 
2174
    
 
2175
        retstr = PR_smprintf("%s,%s,%s", tmpTrustSSL, tmpTrustEmail,
 
2176
                             tmpTrustSigning);
 
2177
    }
 
2178
    
 
2179
    return(retstr);
 
2180
}
 
2181
 
 
2182
/* in 3.4, this will only set trust */
 
2183
SECStatus
 
2184
CERT_SaveImportedCert(CERTCertificate *cert, SECCertUsage usage,
 
2185
                      PRBool caOnly, char *nickname)
 
2186
{
 
2187
    SECStatus rv;
 
2188
    PRBool saveit;
 
2189
    CERTCertTrust trust;
 
2190
    PRBool isCA;
 
2191
    unsigned int certtype;
 
2192
    
 
2193
    isCA = CERT_IsCACert(cert, NULL);
 
2194
    if ( caOnly && ( !isCA ) ) {
 
2195
        return(SECSuccess);
 
2196
    }
 
2197
    /* In NSS 3.4, certs are given zero trust upon import.  However, this
 
2198
    * function needs to set up default CA trust (CERTDB_VALID_CA), or
 
2199
    * PKCS#12 imported certs will not show up correctly.  In the case of a
 
2200
    * CA cert with zero trust, continue with this function.  But if the cert
 
2201
    * does already have some trust bits, exit and do not change them.
 
2202
    */
 
2203
    if (isCA && cert->trust && 
 
2204
        (cert->trust->sslFlags |
 
2205
         cert->trust->emailFlags |
 
2206
         cert->trust->objectSigningFlags)) {
 
2207
        return(SECSuccess);
 
2208
    }
 
2209
 
 
2210
    saveit = PR_TRUE;
 
2211
    
 
2212
    PORT_Memset((void *)&trust, 0, sizeof(trust));
 
2213
 
 
2214
    certtype = cert->nsCertType;
 
2215
 
 
2216
    /* if no CA bits in cert type, then set all CA bits */
 
2217
    if ( isCA && ( ! ( certtype & NS_CERT_TYPE_CA ) ) ) {
 
2218
        certtype |= NS_CERT_TYPE_CA;
 
2219
    }
 
2220
 
 
2221
    /* if no app bits in cert type, then set all app bits */
 
2222
    if ( ( !isCA ) && ( ! ( certtype & NS_CERT_TYPE_APP ) ) ) {
 
2223
        certtype |= NS_CERT_TYPE_APP;
 
2224
    }
 
2225
 
 
2226
    switch ( usage ) {
 
2227
      case certUsageEmailSigner:
 
2228
      case certUsageEmailRecipient:
 
2229
        if ( isCA ) {
 
2230
            if ( certtype & NS_CERT_TYPE_EMAIL_CA ) {
 
2231
                trust.emailFlags = CERTDB_VALID_CA;
 
2232
            }
 
2233
        } else {
 
2234
            if ( !cert->emailAddr || !cert->emailAddr[0] ) {
 
2235
                saveit = PR_FALSE;
 
2236
            }
 
2237
            
 
2238
            if ( certtype & NS_CERT_TYPE_EMAIL ) {
 
2239
                trust.emailFlags = CERTDB_VALID_PEER;
 
2240
                if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) {
 
2241
                    /* don't save it if KeyEncipherment is not allowed */
 
2242
                    saveit = PR_FALSE;
 
2243
                }
 
2244
            }
 
2245
        }
 
2246
        break;
 
2247
      case certUsageUserCertImport:
 
2248
        if ( isCA ) {
 
2249
            if ( certtype & NS_CERT_TYPE_SSL_CA ) {
 
2250
                trust.sslFlags = CERTDB_VALID_CA;
 
2251
            }
 
2252
            
 
2253
            if ( certtype & NS_CERT_TYPE_EMAIL_CA ) {
 
2254
                trust.emailFlags = CERTDB_VALID_CA;
 
2255
            }
 
2256
            
 
2257
            if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
 
2258
                trust.objectSigningFlags = CERTDB_VALID_CA;
 
2259
            }
 
2260
            
 
2261
        } else {
 
2262
            if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) {
 
2263
                trust.sslFlags = CERTDB_VALID_PEER;
 
2264
            }
 
2265
            
 
2266
            if ( certtype & NS_CERT_TYPE_EMAIL ) {
 
2267
                trust.emailFlags = CERTDB_VALID_PEER;
 
2268
            }
 
2269
            
 
2270
            if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) {
 
2271
                trust.objectSigningFlags = CERTDB_VALID_PEER;
 
2272
            }
 
2273
        }
 
2274
        break;
 
2275
      case certUsageAnyCA:
 
2276
        trust.sslFlags = CERTDB_VALID_CA;
 
2277
        break;
 
2278
      case certUsageSSLCA:
 
2279
        trust.sslFlags = CERTDB_VALID_CA | 
 
2280
                        CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
 
2281
        break;
 
2282
      default:  /* XXX added to quiet warnings; no other cases needed? */
 
2283
        break;
 
2284
    }
 
2285
 
 
2286
    if ( saveit ) {
 
2287
        rv = CERT_ChangeCertTrust(cert->dbhandle, cert, &trust);
 
2288
        if ( rv != SECSuccess ) {
 
2289
            goto loser;
 
2290
        }
 
2291
    }
 
2292
 
 
2293
    rv = SECSuccess;
 
2294
    goto done;
 
2295
 
 
2296
loser:
 
2297
    rv = SECFailure;
 
2298
done:
 
2299
 
 
2300
    return(rv);
 
2301
}
 
2302
 
 
2303
SECStatus
 
2304
CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage,
 
2305
                 unsigned int ncerts, SECItem **derCerts,
 
2306
                 CERTCertificate ***retCerts, PRBool keepCerts,
 
2307
                 PRBool caOnly, char *nickname)
 
2308
{
 
2309
    unsigned int i;
 
2310
    CERTCertificate **certs = NULL;
 
2311
    SECStatus rv;
 
2312
    unsigned int fcerts = 0;
 
2313
 
 
2314
    if ( ncerts ) {
 
2315
        certs = PORT_ZNewArray(CERTCertificate*, ncerts);
 
2316
        if ( certs == NULL ) {
 
2317
            return(SECFailure);
 
2318
        }
 
2319
    
 
2320
        /* decode all of the certs into the temporary DB */
 
2321
        for ( i = 0, fcerts= 0; i < ncerts; i++) {
 
2322
            certs[fcerts] = CERT_NewTempCertificate(certdb,
 
2323
                                                    derCerts[i],
 
2324
                                                    NULL,
 
2325
                                                    PR_FALSE,
 
2326
                                                    PR_TRUE);
 
2327
            if (certs[fcerts]) fcerts++;
 
2328
        }
 
2329
 
 
2330
        if ( keepCerts ) {
 
2331
            for ( i = 0; i < fcerts; i++ ) {
 
2332
                char* canickname = NULL;
 
2333
                PRBool freeNickname = PR_FALSE;
 
2334
 
 
2335
                SECKEY_UpdateCertPQG(certs[i]);
 
2336
                
 
2337
                if ( CERT_IsCACert(certs[i], NULL) ) {
 
2338
                    canickname = CERT_MakeCANickname(certs[i]);
 
2339
                    if ( canickname != NULL ) {
 
2340
                        freeNickname = PR_TRUE;
 
2341
                    }
 
2342
                }
 
2343
 
 
2344
                if(CERT_IsCACert(certs[i], NULL) && (fcerts > 1)) {
 
2345
                    /* if we are importing only a single cert and specifying
 
2346
                     * a nickname, we want to use that nickname if it a CA,
 
2347
                     * otherwise if there are more than one cert, we don't
 
2348
                     * know which cert it belongs to. But we still may try
 
2349
                     * the individual canickname from the cert itself.
 
2350
                     */
 
2351
                    rv = CERT_AddTempCertToPerm(certs[i], canickname, NULL);
 
2352
                } else {
 
2353
                    rv = CERT_AddTempCertToPerm(certs[i],
 
2354
                                                nickname?nickname:canickname, NULL);
 
2355
                }
 
2356
                if (rv == SECSuccess) {
 
2357
                    CERT_SaveImportedCert(certs[i], usage, caOnly, NULL);
 
2358
                }
 
2359
 
 
2360
                if (PR_TRUE == freeNickname) {
 
2361
                    PORT_Free(canickname);
 
2362
                }
 
2363
                /* don't care if it fails - keep going */
 
2364
            }
 
2365
        }
 
2366
    }
 
2367
 
 
2368
    if ( retCerts ) {
 
2369
        *retCerts = certs;
 
2370
    } else {
 
2371
        if (certs) {
 
2372
            CERT_DestroyCertArray(certs, fcerts);
 
2373
        }
 
2374
    }
 
2375
 
 
2376
    return ((fcerts || !ncerts) ? SECSuccess : SECFailure);
 
2377
}
 
2378
 
 
2379
/*
 
2380
 * a real list of certificates - need to convert CERTCertificateList
 
2381
 * stuff and ASN 1 encoder/decoder over to using this...
 
2382
 */
 
2383
CERTCertList *
 
2384
CERT_NewCertList(void)
 
2385
{
 
2386
    PRArenaPool *arena = NULL;
 
2387
    CERTCertList *ret = NULL;
 
2388
    
 
2389
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
2390
    if ( arena == NULL ) {
 
2391
        goto loser;
 
2392
    }
 
2393
    
 
2394
    ret = (CERTCertList *)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
 
2395
    if ( ret == NULL ) {
 
2396
        goto loser;
 
2397
    }
 
2398
    
 
2399
    ret->arena = arena;
 
2400
    
 
2401
    PR_INIT_CLIST(&ret->list);
 
2402
    
 
2403
    return(ret);
 
2404
 
 
2405
loser:
 
2406
    if ( arena != NULL ) {
 
2407
        PORT_FreeArena(arena, PR_FALSE);
 
2408
    }
 
2409
    
 
2410
    return(NULL);
 
2411
}
 
2412
 
 
2413
void
 
2414
CERT_DestroyCertList(CERTCertList *certs)
 
2415
{
 
2416
    PRCList *node;
 
2417
 
 
2418
    while( !PR_CLIST_IS_EMPTY(&certs->list) ) {
 
2419
        node = PR_LIST_HEAD(&certs->list);
 
2420
        CERT_DestroyCertificate(((CERTCertListNode *)node)->cert);
 
2421
        PR_REMOVE_LINK(node);
 
2422
    }
 
2423
    
 
2424
    PORT_FreeArena(certs->arena, PR_FALSE);
 
2425
    
 
2426
    return;
 
2427
}
 
2428
 
 
2429
void
 
2430
CERT_RemoveCertListNode(CERTCertListNode *node)
 
2431
{
 
2432
    CERT_DestroyCertificate(node->cert);
 
2433
    PR_REMOVE_LINK(&node->links);
 
2434
    return;
 
2435
}
 
2436
 
 
2437
 
 
2438
SECStatus
 
2439
CERT_AddCertToListTailWithData(CERTCertList *certs, 
 
2440
                                CERTCertificate *cert, void *appData)
 
2441
{
 
2442
    CERTCertListNode *node;
 
2443
    
 
2444
    node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
 
2445
                                                sizeof(CERTCertListNode));
 
2446
    if ( node == NULL ) {
 
2447
        goto loser;
 
2448
    }
 
2449
    
 
2450
    PR_INSERT_BEFORE(&node->links, &certs->list);
 
2451
    /* certs->count++; */
 
2452
    node->cert = cert;
 
2453
    node->appData = appData;
 
2454
    return(SECSuccess);
 
2455
    
 
2456
loser:
 
2457
    return(SECFailure);
 
2458
}
 
2459
 
 
2460
SECStatus
 
2461
CERT_AddCertToListTail(CERTCertList *certs, CERTCertificate *cert)
 
2462
{
 
2463
    return CERT_AddCertToListTailWithData(certs, cert, NULL);
 
2464
}
 
2465
 
 
2466
SECStatus
 
2467
CERT_AddCertToListHeadWithData(CERTCertList *certs, 
 
2468
                                        CERTCertificate *cert, void *appData)
 
2469
{
 
2470
    CERTCertListNode *node;
 
2471
    CERTCertListNode *head;
 
2472
    
 
2473
    head = CERT_LIST_HEAD(certs);
 
2474
 
 
2475
    if (head == NULL) return CERT_AddCertToListTail(certs,cert);
 
2476
 
 
2477
    node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
 
2478
                                                sizeof(CERTCertListNode));
 
2479
    if ( node == NULL ) {
 
2480
        goto loser;
 
2481
    }
 
2482
    
 
2483
    PR_INSERT_BEFORE(&node->links, &head->links);
 
2484
    /* certs->count++; */
 
2485
    node->cert = cert;
 
2486
    node->appData = appData;
 
2487
    return(SECSuccess);
 
2488
    
 
2489
loser:
 
2490
    return(SECFailure);
 
2491
}
 
2492
 
 
2493
SECStatus
 
2494
CERT_AddCertToListHead(CERTCertList *certs, CERTCertificate *cert)
 
2495
{
 
2496
    return CERT_AddCertToListHeadWithData(certs, cert, NULL);
 
2497
}
 
2498
 
 
2499
/*
 
2500
 * Sort callback function to determine if cert a is newer than cert b.
 
2501
 * Not valid certs are considered older than valid certs.
 
2502
 */
 
2503
PRBool
 
2504
CERT_SortCBValidity(CERTCertificate *certa,
 
2505
                    CERTCertificate *certb,
 
2506
                    void *arg)
 
2507
{
 
2508
    PRTime sorttime;
 
2509
    PRTime notBeforeA, notAfterA, notBeforeB, notAfterB;
 
2510
    SECStatus rv;
 
2511
    PRBool newerbefore, newerafter;
 
2512
    PRBool aNotValid = PR_FALSE, bNotValid = PR_FALSE;
 
2513
 
 
2514
    sorttime = *(PRTime *)arg;
 
2515
    
 
2516
    rv = CERT_GetCertTimes(certa, &notBeforeA, &notAfterA);
 
2517
    if ( rv != SECSuccess ) {
 
2518
        return(PR_FALSE);
 
2519
    }
 
2520
    
 
2521
    rv = CERT_GetCertTimes(certb, &notBeforeB, &notAfterB);
 
2522
    if ( rv != SECSuccess ) {
 
2523
        return(PR_TRUE);
 
2524
    }
 
2525
    newerbefore = PR_FALSE;
 
2526
    if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
 
2527
        newerbefore = PR_TRUE;
 
2528
    }
 
2529
    newerafter = PR_FALSE;
 
2530
    if ( LL_CMP(notAfterA, >, notAfterB) ) {
 
2531
        newerafter = PR_TRUE;
 
2532
    }
 
2533
 
 
2534
    /* check if A is valid at sorttime */
 
2535
    if ( CERT_CheckCertValidTimes(certa, sorttime, PR_FALSE)
 
2536
        != secCertTimeValid ) {
 
2537
        aNotValid = PR_TRUE;
 
2538
    }
 
2539
 
 
2540
    /* check if B is valid at sorttime */
 
2541
    if ( CERT_CheckCertValidTimes(certb, sorttime, PR_FALSE)
 
2542
        != secCertTimeValid ) {
 
2543
        bNotValid = PR_TRUE;
 
2544
    }
 
2545
 
 
2546
    /* a is valid, b is not */
 
2547
    if ( bNotValid && ( ! aNotValid ) ) {
 
2548
        return(PR_TRUE);
 
2549
    }
 
2550
 
 
2551
    /* b is valid, a is not */
 
2552
    if ( aNotValid && ( ! bNotValid ) ) {
 
2553
        return(PR_FALSE);
 
2554
    }
 
2555
    
 
2556
    /* a and b are either valid or not valid */
 
2557
    if ( newerbefore && newerafter ) {
 
2558
        return(PR_TRUE);
 
2559
    }
 
2560
    
 
2561
    if ( ( !newerbefore ) && ( !newerafter ) ) {
 
2562
        return(PR_FALSE);
 
2563
    }
 
2564
 
 
2565
    if ( newerbefore ) {
 
2566
        /* cert A was issued after cert B, but expires sooner */
 
2567
        return(PR_TRUE);
 
2568
    } else {
 
2569
        /* cert B was issued after cert A, but expires sooner */
 
2570
        return(PR_FALSE);
 
2571
    }
 
2572
}
 
2573
 
 
2574
 
 
2575
SECStatus
 
2576
CERT_AddCertToListSorted(CERTCertList *certs,
 
2577
                         CERTCertificate *cert,
 
2578
                         CERTSortCallback f,
 
2579
                         void *arg)
 
2580
{
 
2581
    CERTCertListNode *node;
 
2582
    CERTCertListNode *head;
 
2583
    PRBool ret;
 
2584
    
 
2585
    node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
 
2586
                                                sizeof(CERTCertListNode));
 
2587
    if ( node == NULL ) {
 
2588
        goto loser;
 
2589
    }
 
2590
    
 
2591
    head = CERT_LIST_HEAD(certs);
 
2592
    
 
2593
    while ( !CERT_LIST_END(head, certs) ) {
 
2594
 
 
2595
        /* if cert is already in the list, then don't add it again */
 
2596
        if ( cert == head->cert ) {
 
2597
            /*XXX*/
 
2598
            /* don't keep a reference */
 
2599
            CERT_DestroyCertificate(cert);
 
2600
            goto done;
 
2601
        }
 
2602
        
 
2603
        ret = (* f)(cert, head->cert, arg);
 
2604
        /* if sort function succeeds, then insert before current node */
 
2605
        if ( ret ) {
 
2606
            PR_INSERT_BEFORE(&node->links, &head->links);
 
2607
            goto done;
 
2608
        }
 
2609
 
 
2610
        head = CERT_LIST_NEXT(head);
 
2611
    }
 
2612
    /* if we get to the end, then just insert it at the tail */
 
2613
    PR_INSERT_BEFORE(&node->links, &certs->list);
 
2614
 
 
2615
done:    
 
2616
    /* certs->count++; */
 
2617
    node->cert = cert;
 
2618
    return(SECSuccess);
 
2619
    
 
2620
loser:
 
2621
    return(SECFailure);
 
2622
}
 
2623
 
 
2624
/* This routine is here because pcertdb.c still has a call to it.
 
2625
 * The SMIME profile code in pcertdb.c should be split into high (find
 
2626
 * the email cert) and low (store the profile) code.  At that point, we
 
2627
 * can move this to certhigh.c where it belongs.
 
2628
 *
 
2629
 * remove certs from a list that don't have keyUsage and certType
 
2630
 * that match the given usage.
 
2631
 */
 
2632
SECStatus
 
2633
CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage,
 
2634
                           PRBool ca)
 
2635
{
 
2636
    unsigned int requiredKeyUsage;
 
2637
    unsigned int requiredCertType;
 
2638
    CERTCertListNode *node, *savenode;
 
2639
    SECStatus rv;
 
2640
    
 
2641
    if (certList == NULL) goto loser;
 
2642
 
 
2643
    rv = CERT_KeyUsageAndTypeForCertUsage(usage, ca, &requiredKeyUsage,
 
2644
                                          &requiredCertType);
 
2645
    if ( rv != SECSuccess ) {
 
2646
        goto loser;
 
2647
    }
 
2648
 
 
2649
    node = CERT_LIST_HEAD(certList);
 
2650
        
 
2651
    while ( !CERT_LIST_END(node, certList) ) {
 
2652
 
 
2653
        PRBool bad = (PRBool)(!node->cert);
 
2654
 
 
2655
        /* bad key usage ? */
 
2656
        if ( !bad && 
 
2657
             CERT_CheckKeyUsage(node->cert, requiredKeyUsage) != SECSuccess ) {
 
2658
            bad = PR_TRUE;
 
2659
        }
 
2660
        /* bad cert type ? */
 
2661
        if ( !bad ) {
 
2662
            unsigned int certType = 0;
 
2663
            if ( ca ) {
 
2664
                /* This function returns a more comprehensive cert type that
 
2665
                 * takes trust flags into consideration.  Should probably
 
2666
                 * fix the cert decoding code to do this.
 
2667
                 */
 
2668
                (void)CERT_IsCACert(node->cert, &certType);
 
2669
            } else {
 
2670
                certType = node->cert->nsCertType;
 
2671
            }
 
2672
            if ( !( certType & requiredCertType ) ) {
 
2673
                bad = PR_TRUE;
 
2674
            }
 
2675
        }
 
2676
 
 
2677
        if ( bad ) {
 
2678
            /* remove the node if it is bad */
 
2679
            savenode = CERT_LIST_NEXT(node);
 
2680
            CERT_RemoveCertListNode(node);
 
2681
            node = savenode;
 
2682
        } else {
 
2683
            node = CERT_LIST_NEXT(node);
 
2684
        }
 
2685
    }
 
2686
    return(SECSuccess);
 
2687
    
 
2688
loser:
 
2689
    return(SECFailure);
 
2690
}
 
2691
 
 
2692
PRBool CERT_IsUserCert(CERTCertificate* cert)
 
2693
{
 
2694
    if ( cert->trust &&
 
2695
        ((cert->trust->sslFlags & CERTDB_USER ) ||
 
2696
         (cert->trust->emailFlags & CERTDB_USER ) ||
 
2697
         (cert->trust->objectSigningFlags & CERTDB_USER )) ) {
 
2698
        return PR_TRUE;
 
2699
    } else {
 
2700
        return PR_FALSE;
 
2701
    }
 
2702
}
 
2703
 
 
2704
SECStatus
 
2705
CERT_FilterCertListForUserCerts(CERTCertList *certList)
 
2706
{
 
2707
    CERTCertListNode *node, *freenode;
 
2708
    CERTCertificate *cert;
 
2709
 
 
2710
    if (!certList) {
 
2711
        return SECFailure;
 
2712
    }
 
2713
 
 
2714
    node = CERT_LIST_HEAD(certList);
 
2715
    
 
2716
    while ( ! CERT_LIST_END(node, certList) ) {
 
2717
        cert = node->cert;
 
2718
        if ( PR_TRUE != CERT_IsUserCert(cert) ) {
 
2719
            /* Not a User Cert, so remove this cert from the list */
 
2720
            freenode = node;
 
2721
            node = CERT_LIST_NEXT(node);
 
2722
            CERT_RemoveCertListNode(freenode);
 
2723
        } else {
 
2724
            /* Is a User cert, so leave it in the list */
 
2725
            node = CERT_LIST_NEXT(node);
 
2726
        }
 
2727
    }
 
2728
 
 
2729
    return(SECSuccess);
 
2730
}
 
2731
 
 
2732
static PZLock *certRefCountLock = NULL;
 
2733
 
 
2734
/*
 
2735
 * Acquire the cert reference count lock
 
2736
 * There is currently one global lock for all certs, but I'm putting a cert
 
2737
 * arg here so that it will be easy to make it per-cert in the future if
 
2738
 * that turns out to be necessary.
 
2739
 */
 
2740
void
 
2741
CERT_LockCertRefCount(CERTCertificate *cert)
 
2742
{
 
2743
    if ( certRefCountLock == NULL ) {
 
2744
        nss_InitLock(&certRefCountLock, nssILockRefLock);
 
2745
        PORT_Assert(certRefCountLock != NULL);
 
2746
    }
 
2747
    
 
2748
    PZ_Lock(certRefCountLock);
 
2749
    return;
 
2750
}
 
2751
 
 
2752
/*
 
2753
 * Free the cert reference count lock
 
2754
 */
 
2755
void
 
2756
CERT_UnlockCertRefCount(CERTCertificate *cert)
 
2757
{
 
2758
    PRStatus prstat;
 
2759
 
 
2760
    PORT_Assert(certRefCountLock != NULL);
 
2761
    
 
2762
    prstat = PZ_Unlock(certRefCountLock);
 
2763
    
 
2764
    PORT_Assert(prstat == PR_SUCCESS);
 
2765
 
 
2766
    return;
 
2767
}
 
2768
 
 
2769
static PZLock *certTrustLock = NULL;
 
2770
 
 
2771
/*
 
2772
 * Acquire the cert trust lock
 
2773
 * There is currently one global lock for all certs, but I'm putting a cert
 
2774
 * arg here so that it will be easy to make it per-cert in the future if
 
2775
 * that turns out to be necessary.
 
2776
 */
 
2777
void
 
2778
CERT_LockCertTrust(CERTCertificate *cert)
 
2779
{
 
2780
    if ( certTrustLock == NULL ) {
 
2781
        nss_InitLock(&certTrustLock, nssILockCertDB);
 
2782
        PORT_Assert(certTrustLock != NULL);
 
2783
    }
 
2784
    
 
2785
    PZ_Lock(certTrustLock);
 
2786
    return;
 
2787
}
 
2788
 
 
2789
/*
 
2790
 * Free the cert trust lock
 
2791
 */
 
2792
void
 
2793
CERT_UnlockCertTrust(CERTCertificate *cert)
 
2794
{
 
2795
    PRStatus prstat;
 
2796
 
 
2797
    PORT_Assert(certTrustLock != NULL);
 
2798
    
 
2799
    prstat = PZ_Unlock(certTrustLock);
 
2800
    
 
2801
    PORT_Assert(prstat == PR_SUCCESS);
 
2802
 
 
2803
    return;
 
2804
}
 
2805
 
 
2806
 
 
2807
/*
 
2808
 * Get the StatusConfig data for this handle
 
2809
 */
 
2810
CERTStatusConfig *
 
2811
CERT_GetStatusConfig(CERTCertDBHandle *handle)
 
2812
{
 
2813
  return handle->statusConfig;
 
2814
}
 
2815
 
 
2816
/*
 
2817
 * Set the StatusConfig data for this handle.  There
 
2818
 * should not be another configuration set.
 
2819
 */
 
2820
void
 
2821
CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig)
 
2822
{
 
2823
  PORT_Assert(handle->statusConfig == NULL);
 
2824
  handle->statusConfig = statusConfig;
 
2825
}
 
2826
 
 
2827
/*
 
2828
 * Code for dealing with subjKeyID to cert mappings.
 
2829
 */
 
2830
 
 
2831
static PLHashTable *gSubjKeyIDHash = NULL;
 
2832
static PRLock      *gSubjKeyIDLock = NULL;
 
2833
 
 
2834
static void *cert_AllocTable(void *pool, PRSize size)
 
2835
{
 
2836
    return PORT_Alloc(size);
 
2837
}
 
2838
 
 
2839
static void cert_FreeTable(void *pool, void *item)
 
2840
{
 
2841
    PORT_Free(item);
 
2842
}
 
2843
 
 
2844
static PLHashEntry* cert_AllocEntry(void *pool, const void *key)
 
2845
{
 
2846
    return PORT_New(PLHashEntry);
 
2847
}
 
2848
 
 
2849
static void cert_FreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
 
2850
{
 
2851
    SECITEM_FreeItem((SECItem*)(he->value), PR_TRUE);
 
2852
    if (flag == HT_FREE_ENTRY) {
 
2853
        SECITEM_FreeItem((SECItem*)(he->key), PR_TRUE);
 
2854
        PORT_Free(he);
 
2855
    }
 
2856
}
 
2857
 
 
2858
static PLHashAllocOps cert_AllocOps = {
 
2859
    cert_AllocTable, cert_FreeTable, cert_AllocEntry, cert_FreeEntry
 
2860
};
 
2861
 
 
2862
SECStatus
 
2863
cert_CreateSubjectKeyIDHashTable(void)
 
2864
{
 
2865
    gSubjKeyIDHash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
 
2866
                                    SECITEM_HashCompare,
 
2867
                                    &cert_AllocOps, NULL);
 
2868
    if (!gSubjKeyIDHash) {
 
2869
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
2870
        return SECFailure;
 
2871
    }
 
2872
    gSubjKeyIDLock = PR_NewLock();
 
2873
    if (!gSubjKeyIDLock) {
 
2874
        PL_HashTableDestroy(gSubjKeyIDHash);
 
2875
        gSubjKeyIDHash = NULL;
 
2876
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
2877
        return SECFailure;
 
2878
    }
 
2879
    return SECSuccess;
 
2880
 
 
2881
}
 
2882
 
 
2883
SECStatus
 
2884
cert_AddSubjectKeyIDMapping(SECItem *subjKeyID, CERTCertificate *cert)
 
2885
{
 
2886
    SECItem *newKeyID, *oldVal, *newVal;
 
2887
    SECStatus rv = SECFailure;
 
2888
 
 
2889
    if (!gSubjKeyIDLock) {
 
2890
        /* If one is created, then both are there.  So only check for one. */
 
2891
        return SECFailure;
 
2892
    }
 
2893
 
 
2894
    newVal = SECITEM_DupItem(&cert->derCert);
 
2895
    if (!newVal) {
 
2896
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
2897
        goto done;
 
2898
    }
 
2899
    newKeyID = SECITEM_DupItem(subjKeyID);
 
2900
    if (!newKeyID) {
 
2901
        SECITEM_FreeItem(newVal, PR_TRUE);
 
2902
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
2903
        goto done;
 
2904
    }
 
2905
 
 
2906
    PR_Lock(gSubjKeyIDLock);
 
2907
    /* The hash table implementation does not free up the memory 
 
2908
     * associated with the key of an already existing entry if we add a 
 
2909
     * duplicate, so we would wind up leaking the previously allocated 
 
2910
     * key if we don't remove before adding.
 
2911
     */
 
2912
    oldVal = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
 
2913
    if (oldVal) {
 
2914
        PL_HashTableRemove(gSubjKeyIDHash, subjKeyID);
 
2915
    }
 
2916
 
 
2917
    rv = (PL_HashTableAdd(gSubjKeyIDHash, newKeyID, newVal)) ? SECSuccess :
 
2918
                                                               SECFailure;
 
2919
    PR_Unlock(gSubjKeyIDLock);
 
2920
done:
 
2921
    return rv;
 
2922
}
 
2923
 
 
2924
SECStatus
 
2925
cert_RemoveSubjectKeyIDMapping(SECItem *subjKeyID)
 
2926
{
 
2927
    SECStatus rv;
 
2928
    if (!gSubjKeyIDLock)
 
2929
        return SECFailure;
 
2930
 
 
2931
    PR_Lock(gSubjKeyIDLock);
 
2932
    rv = (PL_HashTableRemove(gSubjKeyIDHash, subjKeyID)) ? SECSuccess :
 
2933
                                                           SECFailure;
 
2934
    PR_Unlock(gSubjKeyIDLock);
 
2935
    return rv;
 
2936
}
 
2937
 
 
2938
SECStatus
 
2939
cert_DestroySubjectKeyIDHashTable(void)
 
2940
{
 
2941
    if (gSubjKeyIDHash) {
 
2942
        PR_Lock(gSubjKeyIDLock);
 
2943
        PL_HashTableDestroy(gSubjKeyIDHash);
 
2944
        gSubjKeyIDHash = NULL;
 
2945
        PR_Unlock(gSubjKeyIDLock);
 
2946
        PR_DestroyLock(gSubjKeyIDLock);
 
2947
        gSubjKeyIDLock = NULL;
 
2948
    }
 
2949
    return SECSuccess;
 
2950
}
 
2951
 
 
2952
SECItem*
 
2953
cert_FindDERCertBySubjectKeyID(SECItem *subjKeyID)
 
2954
{
 
2955
    SECItem   *val;
 
2956
 
 
2957
    if (!gSubjKeyIDLock)
 
2958
        return NULL;
 
2959
 
 
2960
    PR_Lock(gSubjKeyIDLock);
 
2961
    val = (SECItem*)PL_HashTableLookup(gSubjKeyIDHash, subjKeyID);
 
2962
    if (val) {
 
2963
        val = SECITEM_DupItem(val);
 
2964
    }
 
2965
    PR_Unlock(gSubjKeyIDLock);
 
2966
    return val;
 
2967
}
 
2968
 
 
2969
CERTCertificate*
 
2970
CERT_FindCertBySubjectKeyID(CERTCertDBHandle *handle, SECItem *subjKeyID)
 
2971
{
 
2972
    CERTCertificate *cert = NULL;
 
2973
    SECItem *derCert;
 
2974
 
 
2975
    derCert = cert_FindDERCertBySubjectKeyID(subjKeyID);
 
2976
    if (derCert) {
 
2977
        cert = CERT_FindCertByDERCert(handle, derCert);
 
2978
        SECITEM_FreeItem(derCert, PR_TRUE);
 
2979
    }
 
2980
    return cert;
 
2981
}