~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/certhigh/certhigh.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is the Netscape security libraries.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Netscape
 
15
 * Communications Corporation.  Portions created by Netscape are 
 
16
 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
 
17
 * Rights Reserved.
 
18
 * 
 
19
 * Contributor(s):
 
20
 * 
 
21
 * Alternatively, the contents of this file may be used under the
 
22
 * terms of the GNU General Public License Version 2 or later (the
 
23
 * "GPL"), in which case the provisions of the GPL are applicable 
 
24
 * instead of those above.  If you wish to allow use of your 
 
25
 * version of this file only under the terms of the GPL and not to
 
26
 * allow others to use your version of this file under the MPL,
 
27
 * indicate your decision by deleting the provisions above and
 
28
 * replace them with the notice and other provisions required by
 
29
 * the GPL.  If you do not delete the provisions above, a recipient
 
30
 * may use your version of this file under either the MPL or the
 
31
 * GPL.
 
32
 */
 
33
#include "nspr.h"
 
34
#include "secerr.h"
 
35
#include "secasn1.h"
 
36
#include "seccomon.h"
 
37
#include "pk11func.h"
 
38
#include "certdb.h"
 
39
#include "certt.h"
 
40
#include "cert.h"
 
41
#include "certxutl.h"
 
42
 
 
43
#ifndef NSS_3_4_CODE
 
44
#define NSS_3_4_CODE
 
45
#endif
 
46
#include "nsspki.h"
 
47
#include "pki.h"
 
48
#include "pkit.h"
 
49
#include "pkitm.h"
 
50
#include "pki3hack.h"
 
51
 
 
52
 
 
53
PRBool
 
54
CERT_MatchNickname(char *name1, char *name2) {
 
55
    char *nickname1= NULL;
 
56
    char *nickname2 = NULL;
 
57
    char *token1;
 
58
    char *token2;
 
59
    char *token = NULL;
 
60
    int len;
 
61
 
 
62
    /* first deal with the straight comparison */
 
63
    if (PORT_Strcmp(name1, name2) == 0) {
 
64
        return PR_TRUE;
 
65
    }
 
66
    /* we need to handle the case where one name has an explicit token and the other
 
67
     * doesn't */
 
68
    token1 = PORT_Strchr(name1,':');
 
69
    token2 = PORT_Strchr(name2,':');
 
70
    if ((token1 && token2) || (!token1 && !token2)) {
 
71
        /* either both token names are specified or neither are, not match */
 
72
        return PR_FALSE;
 
73
    }
 
74
    if (token1) {
 
75
        token=name1;
 
76
        nickname1=token1;
 
77
        nickname2=name2;
 
78
    } else {
 
79
        token=name2;
 
80
        nickname1=token2;
 
81
        nickname2=name1;
 
82
    }
 
83
    len = nickname1-token;
 
84
    nickname1++;
 
85
    if (PORT_Strcmp(nickname1,nickname2) != 0) {
 
86
        return PR_FALSE;
 
87
    }
 
88
    /* compare the other token with the internal slot here */
 
89
    return PR_TRUE;
 
90
}
 
91
 
 
92
/*
 
93
 * Find all user certificates that match the given criteria.
 
94
 * 
 
95
 *      "handle" - database to search
 
96
 *      "usage" - certificate usage to match
 
97
 *      "oneCertPerName" - if set then only return the "best" cert per
 
98
 *                      name
 
99
 *      "validOnly" - only return certs that are curently valid
 
100
 *      "proto_win" - window handle passed to pkcs11
 
101
 */
 
102
CERTCertList *
 
103
CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
 
104
                          SECCertUsage usage,
 
105
                          PRBool oneCertPerName,
 
106
                          PRBool validOnly,
 
107
                          void *proto_win)
 
108
{
 
109
    CERTCertNicknames *nicknames = NULL;
 
110
    char **nnptr;
 
111
    int nn;
 
112
    CERTCertificate *cert = NULL;
 
113
    CERTCertList *certList = NULL;
 
114
    SECStatus rv;
 
115
    int64 time;
 
116
    CERTCertListNode *node = NULL;
 
117
    CERTCertListNode *freenode = NULL;
 
118
    int n;
 
119
    
 
120
    time = PR_Now();
 
121
    
 
122
    nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
 
123
                                      proto_win);
 
124
    
 
125
    if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) {
 
126
        goto loser;
 
127
    }
 
128
 
 
129
    nnptr = nicknames->nicknames;
 
130
    nn = nicknames->numnicknames;
 
131
 
 
132
    while ( nn > 0 ) {
 
133
        cert = NULL;
 
134
        /* use the pk11 call so that we pick up any certs on tokens,
 
135
         * which may require login
 
136
         */
 
137
        if ( proto_win != NULL ) {
 
138
            cert = PK11_FindCertFromNickname(*nnptr,proto_win);
 
139
        }
 
140
 
 
141
        /* Sigh, It turns out if the cert is already in the temp db, because
 
142
         * it's in the perm db, then the nickname lookup doesn't work.
 
143
         * since we already have the cert here, though, than we can just call
 
144
         * CERT_CreateSubjectCertList directly. For those cases where we didn't
 
145
         * find the cert in pkcs #11 (because we didn't have a password arg,
 
146
         * or because the nickname is for a peer, server, or CA cert, then we
 
147
         * go look the cert up.
 
148
         */
 
149
        if (cert == NULL) { 
 
150
            cert = CERT_FindCertByNickname(handle,*nnptr);
 
151
        }
 
152
 
 
153
        if ( cert != NULL ) {
 
154
           /* collect certs for this nickname, sorting them into the list */
 
155
            certList = CERT_CreateSubjectCertList(certList, handle, 
 
156
                                &cert->derSubject, time, validOnly);
 
157
 
 
158
            CERT_FilterCertListForUserCerts(certList);
 
159
        
 
160
            /* drop the extra reference */
 
161
            CERT_DestroyCertificate(cert);
 
162
        }
 
163
        
 
164
        nnptr++;
 
165
        nn--;
 
166
    }
 
167
 
 
168
    /* remove certs with incorrect usage */
 
169
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
 
170
 
 
171
    if ( rv != SECSuccess ) {
 
172
        goto loser;
 
173
    }
 
174
 
 
175
    /* remove any extra certs for each name */
 
176
    if ( oneCertPerName ) {
 
177
        PRBool *flags;
 
178
 
 
179
        nn = nicknames->numnicknames;
 
180
        nnptr = nicknames->nicknames;
 
181
        
 
182
        flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
 
183
        if ( flags == NULL ) {
 
184
            goto loser;
 
185
        }
 
186
        
 
187
        node = CERT_LIST_HEAD(certList);
 
188
        
 
189
        /* treverse all certs in the list */
 
190
        while ( !CERT_LIST_END(node, certList) ) {
 
191
 
 
192
            /* find matching nickname index */
 
193
            for ( n = 0; n < nn; n++ ) {
 
194
                if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) {
 
195
                    /* We found a match.  If this is the first one, then
 
196
                     * set the flag and move on to the next cert.  If this
 
197
                     * is not the first one then delete it from the list.
 
198
                     */
 
199
                    if ( flags[n] ) {
 
200
                        /* We have already seen a cert with this nickname,
 
201
                         * so delete this one.
 
202
                         */
 
203
                        freenode = node;
 
204
                        node = CERT_LIST_NEXT(node);
 
205
                        CERT_RemoveCertListNode(freenode);
 
206
                    } else {
 
207
                        /* keep the first cert for each nickname, but set the
 
208
                         * flag so we know to delete any others with the same
 
209
                         * nickname.
 
210
                         */
 
211
                        flags[n] = PR_TRUE;
 
212
                        node = CERT_LIST_NEXT(node);
 
213
                    }
 
214
                    break;
 
215
                }
 
216
            }
 
217
            if ( n == nn ) {
 
218
                /* if we get here it means that we didn't find a matching
 
219
                 * nickname, which should not happen.
 
220
                 */
 
221
                PORT_Assert(0);
 
222
                node = CERT_LIST_NEXT(node);
 
223
            }
 
224
        }
 
225
        PORT_Free(flags);
 
226
    }
 
227
 
 
228
    goto done;
 
229
    
 
230
loser:
 
231
    if ( certList != NULL ) {
 
232
        CERT_DestroyCertList(certList);
 
233
        certList = NULL;
 
234
    }
 
235
 
 
236
done:
 
237
    if ( nicknames != NULL ) {
 
238
        CERT_FreeNicknames(nicknames);
 
239
    }
 
240
 
 
241
    return(certList);
 
242
}
 
243
 
 
244
/*
 
245
 * Find a user certificate that matchs the given criteria.
 
246
 * 
 
247
 *      "handle" - database to search
 
248
 *      "nickname" - nickname to match
 
249
 *      "usage" - certificate usage to match
 
250
 *      "validOnly" - only return certs that are curently valid
 
251
 *      "proto_win" - window handle passed to pkcs11
 
252
 */
 
253
CERTCertificate *
 
254
CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
 
255
                         char *nickname,
 
256
                         SECCertUsage usage,
 
257
                         PRBool validOnly,
 
258
                         void *proto_win)
 
259
{
 
260
    CERTCertificate *cert = NULL;
 
261
    CERTCertList *certList = NULL;
 
262
    SECStatus rv;
 
263
    int64 time;
 
264
    
 
265
    time = PR_Now();
 
266
    
 
267
    /* use the pk11 call so that we pick up any certs on tokens,
 
268
     * which may require login
 
269
     */
 
270
    /* XXX - why is this restricted? */
 
271
    if ( proto_win != NULL ) {
 
272
        cert = PK11_FindCertFromNickname(nickname,proto_win);
 
273
    }
 
274
 
 
275
 
 
276
    /* sigh, There are still problems find smart cards from the temp
 
277
     * db. This will get smart cards working again. The real fix
 
278
     * is to make sure we can search the temp db by their token nickname.
 
279
     */
 
280
    if (cert == NULL) {
 
281
        cert = CERT_FindCertByNickname(handle,nickname);
 
282
    }
 
283
 
 
284
    if ( cert != NULL ) {
 
285
        /* collect certs for this nickname, sorting them into the list */
 
286
        certList = CERT_CreateSubjectCertList(certList, handle, 
 
287
                                        &cert->derSubject, time, validOnly);
 
288
 
 
289
        CERT_FilterCertListForUserCerts(certList);
 
290
 
 
291
        /* drop the extra reference */
 
292
        CERT_DestroyCertificate(cert);
 
293
        cert = NULL;
 
294
    }
 
295
        
 
296
    if ( certList == NULL ) {
 
297
        goto loser;
 
298
    }
 
299
    
 
300
    /* remove certs with incorrect usage */
 
301
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
 
302
 
 
303
    if ( rv != SECSuccess ) {
 
304
        goto loser;
 
305
    }
 
306
 
 
307
    if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) {
 
308
        cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
 
309
    }
 
310
    
 
311
loser:
 
312
    if ( certList != NULL ) {
 
313
        CERT_DestroyCertList(certList);
 
314
    }
 
315
 
 
316
    return(cert);
 
317
}
 
318
 
 
319
CERTCertList *
 
320
CERT_MatchUserCert(CERTCertDBHandle *handle,
 
321
                   SECCertUsage usage,
 
322
                   int nCANames, char **caNames,
 
323
                   void *proto_win)
 
324
{
 
325
    CERTCertList *certList = NULL;
 
326
    SECStatus rv;
 
327
 
 
328
    certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
 
329
                                         proto_win);
 
330
    if ( certList == NULL ) {
 
331
        goto loser;
 
332
    }
 
333
    
 
334
    rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
 
335
    if ( rv != SECSuccess ) {
 
336
        goto loser;
 
337
    }
 
338
    
 
339
    goto done;
 
340
    
 
341
loser:
 
342
    if ( certList != NULL ) {
 
343
        CERT_DestroyCertList(certList);
 
344
        certList = NULL;
 
345
    }
 
346
 
 
347
done:
 
348
 
 
349
    return(certList);
 
350
}
 
351
 
 
352
 
 
353
typedef struct stringNode {
 
354
    struct stringNode *next;
 
355
    char *string;
 
356
} stringNode;
 
357
    
 
358
static PRStatus
 
359
CollectNicknames( NSSCertificate *c, void *data)
 
360
{
 
361
    CERTCertNicknames *names;
 
362
    PRBool saveit = PR_FALSE;
 
363
    stringNode *node;
 
364
    int len;
 
365
#ifdef notdef
 
366
    NSSTrustDomain *td;
 
367
    NSSTrust *trust;
 
368
#endif
 
369
    char *stanNickname;
 
370
    char *nickname = NULL;
 
371
    
 
372
    names = (CERTCertNicknames *)data;
 
373
 
 
374
    stanNickname = nssCertificate_GetNickname(c,NULL);
 
375
    
 
376
    if ( stanNickname ) {
 
377
        if (names->what == SEC_CERT_NICKNAMES_USER) {
 
378
            saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
 
379
        }
 
380
#ifdef notdef
 
381
          else {
 
382
            td = NSSCertificate_GetTrustDomain(c);
 
383
            if (!td) {
 
384
                return PR_SUCCESS;
 
385
            }
 
386
            trust = nssTrustDomain_FindTrustForCertificate(td,c);
 
387
        
 
388
            switch(names->what) {
 
389
             case SEC_CERT_NICKNAMES_ALL:
 
390
                if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
 
391
                 (trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
 
392
                 (trust->objectSigningFlags & 
 
393
                                        (CERTDB_VALID_CA|CERTDB_VALID_PEER))) {
 
394
                    saveit = PR_TRUE;
 
395
                }
 
396
            
 
397
                break;
 
398
             case SEC_CERT_NICKNAMES_SERVER:
 
399
                if ( trust->sslFlags & CERTDB_VALID_PEER ) {
 
400
                    saveit = PR_TRUE;
 
401
                }
 
402
            
 
403
                break;
 
404
             case SEC_CERT_NICKNAMES_CA:
 
405
                if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)||
 
406
                 ((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) ||
 
407
                 ((trust->objectSigningFlags & CERTDB_VALID_CA ) 
 
408
                                                        == CERTDB_VALID_CA)) {
 
409
                    saveit = PR_TRUE;
 
410
                }
 
411
                break;
 
412
            }
 
413
        }
 
414
#endif
 
415
    }
 
416
 
 
417
    /* traverse the list of collected nicknames and make sure we don't make
 
418
     * a duplicate
 
419
     */
 
420
    if ( saveit ) {
 
421
        nickname = STAN_GetCERTCertificateName(NULL, c);
 
422
        /* nickname can only be NULL here if we are having memory 
 
423
         * alloc problems */
 
424
        if (nickname == NULL) {
 
425
            return PR_FAILURE;
 
426
        }
 
427
        node = (stringNode *)names->head;
 
428
        while ( node != NULL ) {
 
429
            if ( PORT_Strcmp(nickname, node->string) == 0 ) { 
 
430
                /* if the string matches, then don't save this one */
 
431
                saveit = PR_FALSE;
 
432
                break;
 
433
            }
 
434
            node = node->next;
 
435
        }
 
436
    }
 
437
 
 
438
    if ( saveit ) {
 
439
        
 
440
        /* allocate the node */
 
441
        node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
 
442
        if ( node == NULL ) {
 
443
            return(PR_FAILURE);
 
444
        }
 
445
 
 
446
        /* copy the string */
 
447
        len = PORT_Strlen(nickname) + 1;
 
448
        node->string = (char*)PORT_ArenaAlloc(names->arena, len);
 
449
        if ( node->string == NULL ) {
 
450
            if (nickname) PORT_Free(nickname);
 
451
            return(PR_FAILURE);
 
452
        }
 
453
        PORT_Memcpy(node->string, nickname, len);
 
454
 
 
455
        /* link it into the list */
 
456
        node->next = (stringNode *)names->head;
 
457
        names->head = (void *)node;
 
458
 
 
459
        /* bump the count */
 
460
        names->numnicknames++;
 
461
    }
 
462
    
 
463
    if (nickname) PORT_Free(nickname);
 
464
    return(PR_SUCCESS);
 
465
}
 
466
 
 
467
CERTCertNicknames *
 
468
CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
 
469
{
 
470
    PRArenaPool *arena;
 
471
    CERTCertNicknames *names;
 
472
    int i;
 
473
    stringNode *node;
 
474
    
 
475
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
476
    if ( arena == NULL ) {
 
477
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
478
        return(NULL);
 
479
    }
 
480
    
 
481
    names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
 
482
    if ( names == NULL ) {
 
483
        goto loser;
 
484
    }
 
485
 
 
486
    names->arena = arena;
 
487
    names->head = NULL;
 
488
    names->numnicknames = 0;
 
489
    names->nicknames = NULL;
 
490
    names->what = what;
 
491
    names->totallen = 0;
 
492
 
 
493
    /* make sure we are logged in */
 
494
    (void) pk11_TraverseAllSlots(NULL, NULL, wincx);
 
495
   
 
496
    NSSTrustDomain_TraverseCertificates(handle,
 
497
                                            CollectNicknames, (void *)names);
 
498
    if ( names->numnicknames ) {
 
499
        names->nicknames = (char**)PORT_ArenaAlloc(arena,
 
500
                                         names->numnicknames * sizeof(char *));
 
501
 
 
502
        if ( names->nicknames == NULL ) {
 
503
            goto loser;
 
504
        }
 
505
    
 
506
        node = (stringNode *)names->head;
 
507
        
 
508
        for ( i = 0; i < names->numnicknames; i++ ) {
 
509
            PORT_Assert(node != NULL);
 
510
            
 
511
            names->nicknames[i] = node->string;
 
512
            names->totallen += PORT_Strlen(node->string);
 
513
            node = node->next;
 
514
        }
 
515
 
 
516
        PORT_Assert(node == NULL);
 
517
    }
 
518
 
 
519
    return(names);
 
520
    
 
521
loser:
 
522
    PORT_FreeArena(arena, PR_FALSE);
 
523
    return(NULL);
 
524
}
 
525
 
 
526
void
 
527
CERT_FreeNicknames(CERTCertNicknames *nicknames)
 
528
{
 
529
    PORT_FreeArena(nicknames->arena, PR_FALSE);
 
530
    
 
531
    return;
 
532
}
 
533
 
 
534
/* [ FROM pcertdb.c ] */
 
535
 
 
536
typedef struct dnameNode {
 
537
    struct dnameNode *next;
 
538
    SECItem name;
 
539
} dnameNode;
 
540
 
 
541
void
 
542
CERT_FreeDistNames(CERTDistNames *names)
 
543
{
 
544
    PORT_FreeArena(names->arena, PR_FALSE);
 
545
    
 
546
    return;
 
547
}
 
548
 
 
549
static SECStatus
 
550
CollectDistNames( CERTCertificate *cert, SECItem *k, void *data)
 
551
{
 
552
    CERTDistNames *names;
 
553
    PRBool saveit = PR_FALSE;
 
554
    CERTCertTrust *trust;
 
555
    dnameNode *node;
 
556
    int len;
 
557
    
 
558
    names = (CERTDistNames *)data;
 
559
    
 
560
    if ( cert->trust ) {
 
561
        trust = cert->trust;
 
562
        
 
563
        /* only collect names of CAs trusted for issuing SSL clients */
 
564
        if (  trust->sslFlags &  CERTDB_TRUSTED_CLIENT_CA )  {
 
565
            saveit = PR_TRUE;
 
566
        }
 
567
    }
 
568
 
 
569
    if ( saveit ) {
 
570
        /* allocate the node */
 
571
        node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
 
572
        if ( node == NULL ) {
 
573
            return(SECFailure);
 
574
        }
 
575
 
 
576
        /* copy the name */
 
577
        node->name.len = len = cert->derSubject.len;
 
578
        node->name.type = siBuffer;
 
579
        node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);
 
580
        if ( node->name.data == NULL ) {
 
581
            return(SECFailure);
 
582
        }
 
583
        PORT_Memcpy(node->name.data, cert->derSubject.data, len);
 
584
 
 
585
        /* link it into the list */
 
586
        node->next = (dnameNode *)names->head;
 
587
        names->head = (void *)node;
 
588
 
 
589
        /* bump the count */
 
590
        names->nnames++;
 
591
    }
 
592
    
 
593
    return(SECSuccess);
 
594
}
 
595
 
 
596
/*
 
597
 * Return all of the CAs that are "trusted" for SSL.
 
598
 */
 
599
CERTDistNames *
 
600
CERT_GetSSLCACerts(CERTCertDBHandle *handle)
 
601
{
 
602
    PRArenaPool *arena;
 
603
    CERTDistNames *names;
 
604
    int i;
 
605
    SECStatus rv;
 
606
    dnameNode *node;
 
607
    
 
608
    /* allocate an arena to use */
 
609
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
610
    if ( arena == NULL ) {
 
611
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
612
        return(NULL);
 
613
    }
 
614
    
 
615
    /* allocate the header structure */
 
616
    names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
 
617
    if ( names == NULL ) {
 
618
        goto loser;
 
619
    }
 
620
 
 
621
    /* initialize the header struct */
 
622
    names->arena = arena;
 
623
    names->head = NULL;
 
624
    names->nnames = 0;
 
625
    names->names = NULL;
 
626
    
 
627
    /* collect the names from the database */
 
628
    rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
 
629
    if ( rv ) {
 
630
        goto loser;
 
631
    }
 
632
 
 
633
    /* construct the array from the list */
 
634
    if ( names->nnames ) {
 
635
        names->names = (SECItem*)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
 
636
 
 
637
        if ( names->names == NULL ) {
 
638
            goto loser;
 
639
        }
 
640
    
 
641
        node = (dnameNode *)names->head;
 
642
        
 
643
        for ( i = 0; i < names->nnames; i++ ) {
 
644
            PORT_Assert(node != NULL);
 
645
            
 
646
            names->names[i] = node->name;
 
647
            node = node->next;
 
648
        }
 
649
 
 
650
        PORT_Assert(node == NULL);
 
651
    }
 
652
 
 
653
    return(names);
 
654
    
 
655
loser:
 
656
    PORT_FreeArena(arena, PR_FALSE);
 
657
    return(NULL);
 
658
}
 
659
 
 
660
CERTDistNames *
 
661
CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
 
662
                           int nnames)
 
663
{
 
664
    CERTDistNames *dnames = NULL;
 
665
    PRArenaPool *arena;
 
666
    int i, rv;
 
667
    SECItem *names = NULL;
 
668
    CERTCertificate *cert = NULL;
 
669
    
 
670
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
671
    if (arena == NULL) goto loser;
 
672
    dnames = (CERTDistNames*)PORT_Alloc(sizeof(CERTDistNames));
 
673
    if (dnames == NULL) goto loser;
 
674
 
 
675
    dnames->arena = arena;
 
676
    dnames->nnames = nnames;
 
677
    dnames->names = names = (SECItem*)PORT_Alloc(nnames * sizeof(SECItem));
 
678
    if (names == NULL) goto loser;
 
679
    
 
680
    for (i = 0; i < nnames; i++) {
 
681
        cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
 
682
        if (cert == NULL) goto loser;
 
683
        rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
 
684
        if (rv == SECFailure) goto loser;
 
685
        CERT_DestroyCertificate(cert);
 
686
    }
 
687
    return dnames;
 
688
    
 
689
loser:
 
690
    if (cert != NULL)
 
691
        CERT_DestroyCertificate(cert);
 
692
    if (arena != NULL)
 
693
        PORT_FreeArena(arena, PR_FALSE);
 
694
    return NULL;
 
695
}
 
696
 
 
697
/* [ from pcertdb.c - calls Ascii to Name ] */
 
698
/*
 
699
 * Lookup a certificate in the database by name
 
700
 */
 
701
CERTCertificate *
 
702
CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
 
703
{
 
704
    CERTName *name;
 
705
    SECItem *nameItem;
 
706
    CERTCertificate *cert = NULL;
 
707
    PRArenaPool *arena = NULL;
 
708
    
 
709
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
710
    
 
711
    if ( arena == NULL ) {
 
712
        goto loser;
 
713
    }
 
714
    
 
715
    name = CERT_AsciiToName(nameStr);
 
716
    
 
717
    if ( name ) {
 
718
        nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name,
 
719
                                       CERT_NameTemplate);
 
720
        if ( nameItem == NULL ) {
 
721
            goto loser;
 
722
        }
 
723
 
 
724
        cert = CERT_FindCertByName(handle, nameItem);
 
725
        CERT_DestroyName(name);
 
726
    }
 
727
 
 
728
loser:
 
729
    if ( arena ) {
 
730
        PORT_FreeArena(arena, PR_FALSE);
 
731
    }
 
732
    
 
733
    return(cert);
 
734
}
 
735
 
 
736
/* From certv3.c */
 
737
 
 
738
CERTCrlDistributionPoints *
 
739
CERT_FindCRLDistributionPoints (CERTCertificate *cert)
 
740
{
 
741
    SECItem encodedExtenValue;
 
742
    SECStatus rv;
 
743
 
 
744
    encodedExtenValue.data = NULL;
 
745
    encodedExtenValue.len = 0;
 
746
 
 
747
    rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
 
748
                            &encodedExtenValue);
 
749
    if ( rv != SECSuccess ) {
 
750
        return (NULL);
 
751
    }
 
752
 
 
753
    return (CERT_DecodeCRLDistributionPoints (cert->arena,
 
754
                                              &encodedExtenValue));
 
755
}
 
756
 
 
757
/* From crl.c */
 
758
CERTSignedCrl * CERT_ImportCRL
 
759
   (CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
 
760
{
 
761
    CERTSignedCrl* retCrl = NULL;
 
762
    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
 
763
    retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
 
764
        CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
 
765
    PK11_FreeSlot(slot);
 
766
 
 
767
    return retCrl;
 
768
}
 
769
 
 
770
/* From certdb.c */
 
771
static SECStatus
 
772
cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
 
773
{
 
774
    SECStatus rv;
 
775
    SECItem *derCert;
 
776
    CERTCertificate *cert = NULL;
 
777
    CERTCertificate *newcert = NULL;
 
778
    CERTCertDBHandle *handle;
 
779
    CERTCertTrust trust;
 
780
    PRBool isca;
 
781
    char *nickname;
 
782
    unsigned int certtype;
 
783
    
 
784
    handle = CERT_GetDefaultCertDB();
 
785
    
 
786
    while (numcerts--) {
 
787
        derCert = certs;
 
788
        certs++;
 
789
 
 
790
        /* decode my certificate */
 
791
        /* This use is ok -- only looks at decoded parts, calls NewTemp later */
 
792
        newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
 
793
        if ( newcert == NULL ) {
 
794
            goto loser;
 
795
        }
 
796
 
 
797
        if (!trusted) {
 
798
            /* make sure that cert is valid */
 
799
            rv = CERT_CertTimesValid(newcert);
 
800
            if ( rv == SECFailure ) {
 
801
                goto endloop;
 
802
            }
 
803
        }
 
804
 
 
805
        /* does it have the CA extension */
 
806
        
 
807
        /*
 
808
         * Make sure that if this is an intermediate CA in the chain that
 
809
         * it was given permission by its signer to be a CA.
 
810
         */
 
811
        isca = CERT_IsCACert(newcert, &certtype);
 
812
 
 
813
        if ( !isca ) {
 
814
            if (!trusted) {
 
815
                goto endloop;
 
816
            }
 
817
            trust.sslFlags = CERTDB_VALID_CA;
 
818
            trust.emailFlags = CERTDB_VALID_CA;
 
819
            trust.objectSigningFlags = CERTDB_VALID_CA;
 
820
        } else {
 
821
            /* SSL ca's must have the ssl bit set */
 
822
            if ( ( certUsage == certUsageSSLCA ) &&
 
823
                (( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) {
 
824
                goto endloop;
 
825
            }
 
826
 
 
827
            /* it passed all of the tests, so lets add it to the database */
 
828
            /* mark it as a CA */
 
829
            PORT_Memset((void *)&trust, 0, sizeof(trust));
 
830
            switch ( certUsage ) {
 
831
              case certUsageSSLCA:
 
832
                trust.sslFlags = CERTDB_VALID_CA;
 
833
                break;
 
834
              case certUsageUserCertImport:
 
835
                if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
 
836
                    trust.sslFlags = CERTDB_VALID_CA;
 
837
                }
 
838
                if ((certtype & NS_CERT_TYPE_EMAIL_CA) 
 
839
                                                == NS_CERT_TYPE_EMAIL_CA ) {
 
840
                    trust.emailFlags = CERTDB_VALID_CA;
 
841
                }
 
842
                if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) ==
 
843
                                        NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
 
844
                     trust.objectSigningFlags = CERTDB_VALID_CA;
 
845
                }
 
846
                break;
 
847
              default:
 
848
                PORT_Assert(0);
 
849
                break;
 
850
            }
 
851
        }
 
852
        
 
853
        cert = CERT_NewTempCertificate(handle, derCert, NULL, 
 
854
                                                        PR_FALSE, PR_FALSE);
 
855
        if ( cert == NULL ) {
 
856
            goto loser;
 
857
        }
 
858
        
 
859
        /* if the cert is temp, make it perm; otherwise we're done */
 
860
        if (cert->istemp) {
 
861
            /* get a default nickname for it */
 
862
            nickname = CERT_MakeCANickname(cert);
 
863
 
 
864
            rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
 
865
 
 
866
            /* free the nickname */
 
867
            if ( nickname ) {
 
868
                PORT_Free(nickname);
 
869
            }
 
870
        } else {
 
871
            rv = SECSuccess;
 
872
        }
 
873
 
 
874
        CERT_DestroyCertificate(cert);
 
875
        cert = NULL;
 
876
        
 
877
        if ( rv != SECSuccess ) {
 
878
            goto loser;
 
879
        }
 
880
 
 
881
endloop:
 
882
        if ( newcert ) {
 
883
            CERT_DestroyCertificate(newcert);
 
884
            newcert = NULL;
 
885
        }
 
886
        
 
887
    }
 
888
 
 
889
    rv = SECSuccess;
 
890
    goto done;
 
891
loser:
 
892
    rv = SECFailure;
 
893
done:
 
894
    
 
895
    if ( newcert ) {
 
896
        CERT_DestroyCertificate(newcert);
 
897
        newcert = NULL;
 
898
    }
 
899
    
 
900
    if ( cert ) {
 
901
        CERT_DestroyCertificate(cert);
 
902
        cert = NULL;
 
903
    }
 
904
    
 
905
    return(rv);
 
906
}
 
907
 
 
908
SECStatus
 
909
CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
 
910
{
 
911
    return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
 
912
}
 
913
 
 
914
SECStatus
 
915
CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage) {
 
916
    return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
 
917
}
 
918
 
 
919
/* Moved from certdb.c */
 
920
/*
 
921
** CERT_CertChainFromCert
 
922
**
 
923
** Construct a CERTCertificateList consisting of the given certificate and all
 
924
** of the issuer certs until we either get to a self-signed cert or can't find
 
925
** an issuer.  Since we don't know how many certs are in the chain we have to
 
926
** build a linked list first as we count them.
 
927
*/
 
928
 
 
929
typedef struct certNode {
 
930
    struct certNode *next;
 
931
    CERTCertificate *cert;
 
932
} certNode;
 
933
 
 
934
CERTCertificateList *
 
935
CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
 
936
                       PRBool includeRoot)
 
937
{
 
938
#ifdef NSS_CLASSIC
 
939
    CERTCertificateList *chain = NULL;
 
940
    CERTCertificate *c;
 
941
    SECItem *p;
 
942
    int rv, len = 0;
 
943
    PRArenaPool *tmpArena, *arena;
 
944
    certNode *head, *tail, *node;
 
945
 
 
946
    /*
 
947
     * Initialize stuff so we can goto loser.
 
948
     */
 
949
    head = NULL;
 
950
    arena = NULL;
 
951
 
 
952
    /* arena for linked list */
 
953
    tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
954
    if (tmpArena == NULL) goto no_memory;
 
955
 
 
956
    /* arena for SecCertificateList */
 
957
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
958
    if (arena == NULL) goto no_memory;
 
959
 
 
960
    head = tail = (certNode*)PORT_ArenaZAlloc(tmpArena, sizeof(certNode));
 
961
    if (head == NULL) goto no_memory;
 
962
 
 
963
    /* put primary cert first in the linked list */
 
964
    head->cert = c = CERT_DupCertificate(cert);
 
965
    if (head->cert == NULL) goto loser;
 
966
    len++;
 
967
 
 
968
    /* add certs until we come to a self-signed one */
 
969
    while(SECITEM_CompareItem(&c->derIssuer, &c->derSubject) != SECEqual) {
 
970
        c = CERT_FindCertIssuer(tail->cert, PR_Now(), usage);
 
971
        if (c == NULL) {
 
972
            /* no root is found, so make sure we don't attempt to delete one
 
973
             * below
 
974
             */
 
975
            includeRoot = PR_TRUE;
 
976
            break;
 
977
        }
 
978
        
 
979
        tail->next = (certNode*)PORT_ArenaZAlloc(tmpArena, sizeof(certNode));
 
980
        tail = tail->next;
 
981
        if (tail == NULL) goto no_memory;
 
982
        
 
983
        tail->cert = c;
 
984
        len++;
 
985
    }
 
986
 
 
987
    /* now build the CERTCertificateList */
 
988
    chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
 
989
    if (chain == NULL) goto no_memory;
 
990
    chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
 
991
    if (chain->certs == NULL) goto no_memory;
 
992
    
 
993
    for(node = head, p = chain->certs; node; node = node->next, p++) {
 
994
        rv = SECITEM_CopyItem(arena, p, &node->cert->derCert);
 
995
        CERT_DestroyCertificate(node->cert);
 
996
        node->cert = NULL;
 
997
        if (rv < 0) goto loser;
 
998
    }
 
999
    if ( !includeRoot && len > 1) {
 
1000
        chain->len = len - 1;
 
1001
    } else {
 
1002
        chain->len = len;
 
1003
    }
 
1004
    
 
1005
    chain->arena = arena;
 
1006
 
 
1007
    PORT_FreeArena(tmpArena, PR_FALSE);
 
1008
    
 
1009
    return chain;
 
1010
 
 
1011
no_memory:
 
1012
    PORT_SetError(SEC_ERROR_NO_MEMORY);
 
1013
loser:
 
1014
    if (head != NULL) {
 
1015
        for (node = head; node; node = node->next) {
 
1016
            if (node->cert != NULL)
 
1017
                CERT_DestroyCertificate(node->cert);
 
1018
        }
 
1019
    }
 
1020
 
 
1021
    if (arena != NULL) {
 
1022
        PORT_FreeArena(arena, PR_FALSE);
 
1023
    }
 
1024
 
 
1025
    if (tmpArena != NULL) {
 
1026
        PORT_FreeArena(tmpArena, PR_FALSE);
 
1027
    }
 
1028
 
 
1029
    return NULL;
 
1030
#else
 
1031
    CERTCertificateList *chain = NULL;
 
1032
    NSSCertificate **stanChain;
 
1033
    NSSCertificate *stanCert;
 
1034
    PRArenaPool *arena;
 
1035
    NSSUsage nssUsage;
 
1036
    int i, len;
 
1037
 
 
1038
    stanCert = STAN_GetNSSCertificate(cert);
 
1039
    nssUsage.anyUsage = PR_FALSE;
 
1040
    nssUsage.nss3usage = usage;
 
1041
    nssUsage.nss3lookingForCA = PR_FALSE;
 
1042
    stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL,
 
1043
                                                    NULL, 0, NULL, NULL);
 
1044
    if (!stanChain) {
 
1045
        return NULL;
 
1046
    }
 
1047
 
 
1048
    len = 0;
 
1049
    stanCert = stanChain[0];
 
1050
    while (stanCert) {
 
1051
        stanCert = stanChain[++len];
 
1052
    }
 
1053
 
 
1054
    arena = PORT_NewArena(4096);
 
1055
    if (arena == NULL) {
 
1056
        goto loser;
 
1057
    }
 
1058
 
 
1059
    chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, 
 
1060
                                                 sizeof(CERTCertificateList));
 
1061
    if (!chain) goto loser;
 
1062
    chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
 
1063
    if (!chain->certs) goto loser;
 
1064
    i = 0;
 
1065
    stanCert = stanChain[i];
 
1066
    while (stanCert) {
 
1067
        SECItem derCert;
 
1068
        CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
 
1069
        if (!cCert) {
 
1070
            goto loser;
 
1071
        }
 
1072
        derCert.len = (unsigned int)stanCert->encoding.size;
 
1073
        derCert.data = (unsigned char *)stanCert->encoding.data;
 
1074
        derCert.type = siBuffer;
 
1075
        SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
 
1076
        stanCert = stanChain[++i];
 
1077
        if (!stanCert && !cCert->isRoot) {
 
1078
            /* reached the end of the chain, but the final cert is
 
1079
             * not a root.  Don't discard it.
 
1080
             */
 
1081
            includeRoot = PR_TRUE;
 
1082
        }
 
1083
        CERT_DestroyCertificate(cCert);
 
1084
    }
 
1085
    if ( !includeRoot && len > 1) {
 
1086
        chain->len = len - 1;
 
1087
    } else {
 
1088
        chain->len = len;
 
1089
    }
 
1090
    
 
1091
    chain->arena = arena;
 
1092
    nss_ZFreeIf(stanChain);
 
1093
    return chain;
 
1094
loser:
 
1095
    i = 0;
 
1096
    stanCert = stanChain[i];
 
1097
    while (stanCert) {
 
1098
        CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
 
1099
        if (cCert) {
 
1100
            CERT_DestroyCertificate(cCert);
 
1101
        }
 
1102
        stanCert = stanChain[++i];
 
1103
    }
 
1104
    nss_ZFreeIf(stanChain);
 
1105
    if (arena) {
 
1106
        PORT_FreeArena(arena, PR_FALSE);
 
1107
    }
 
1108
    return NULL;
 
1109
#endif
 
1110
}
 
1111
 
 
1112
/* Builds a CERTCertificateList holding just one DER-encoded cert, namely
 
1113
** the one for the cert passed as an argument.
 
1114
*/
 
1115
CERTCertificateList *
 
1116
CERT_CertListFromCert(CERTCertificate *cert)
 
1117
{
 
1118
    CERTCertificateList *chain = NULL;
 
1119
    int rv;
 
1120
    PRArenaPool *arena;
 
1121
 
 
1122
    /* arena for SecCertificateList */
 
1123
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
1124
    if (arena == NULL) goto no_memory;
 
1125
 
 
1126
    /* build the CERTCertificateList */
 
1127
    chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
 
1128
    if (chain == NULL) goto no_memory;
 
1129
    chain->certs = (SECItem*)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
 
1130
    if (chain->certs == NULL) goto no_memory;
 
1131
    rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
 
1132
    if (rv < 0) goto loser;
 
1133
    chain->len = 1;
 
1134
    chain->arena = arena;
 
1135
 
 
1136
    return chain;
 
1137
 
 
1138
no_memory:
 
1139
    PORT_SetError(SEC_ERROR_NO_MEMORY);
 
1140
loser:
 
1141
    if (arena != NULL) {
 
1142
        PORT_FreeArena(arena, PR_FALSE);
 
1143
    }
 
1144
    return NULL;
 
1145
}
 
1146
 
 
1147
CERTCertificateList *
 
1148
CERT_DupCertList(CERTCertificateList * oldList)
 
1149
{
 
1150
    CERTCertificateList *newList = NULL;
 
1151
    PRArenaPool         *arena   = NULL;
 
1152
    SECItem             *newItem;
 
1153
    SECItem             *oldItem;
 
1154
    int                 len      = oldList->len;
 
1155
    int                 rv;
 
1156
 
 
1157
    /* arena for SecCertificateList */
 
1158
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
1159
    if (arena == NULL) 
 
1160
        goto no_memory;
 
1161
 
 
1162
    /* now build the CERTCertificateList */
 
1163
    newList = PORT_ArenaNew(arena, CERTCertificateList);
 
1164
    if (newList == NULL) 
 
1165
        goto no_memory;
 
1166
    newList->arena = arena;
 
1167
    newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
 
1168
    if (newItem == NULL) 
 
1169
        goto no_memory;
 
1170
    newList->certs = newItem;
 
1171
    newList->len   = len;
 
1172
 
 
1173
    for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
 
1174
        rv = SECITEM_CopyItem(arena, newItem, oldItem);
 
1175
        if (rv < 0) 
 
1176
            goto loser;
 
1177
    }
 
1178
    return newList;
 
1179
 
 
1180
no_memory:
 
1181
    PORT_SetError(SEC_ERROR_NO_MEMORY);
 
1182
loser:
 
1183
    if (arena != NULL) {
 
1184
        PORT_FreeArena(arena, PR_FALSE);
 
1185
    }
 
1186
    return NULL;
 
1187
}
 
1188
 
 
1189
void
 
1190
CERT_DestroyCertificateList(CERTCertificateList *list)
 
1191
{
 
1192
    PORT_FreeArena(list->arena, PR_FALSE);
 
1193
}
 
1194