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

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/certdb/stanpcertdb.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
 
 
34
#include "prtime.h"
 
35
 
 
36
#include "cert.h"
 
37
#include "mcom_db.h"
 
38
#include "certdb.h"
 
39
#include "secitem.h"
 
40
#include "secder.h"
 
41
 
 
42
/* Call to PK11_FreeSlot below */
 
43
 
 
44
#include "secasn1.h"
 
45
#include "secerr.h"
 
46
#include "nssilock.h"
 
47
#include "prmon.h"
 
48
#include "nsslocks.h"
 
49
#include "base64.h"
 
50
#include "sechash.h"
 
51
#include "plhash.h"
 
52
#include "pk11func.h" /* sigh */
 
53
 
 
54
#ifndef NSS_3_4_CODE
 
55
#define NSS_3_4_CODE
 
56
#endif /* NSS_3_4_CODE */
 
57
#include "nsspki.h"
 
58
#include "pki.h"
 
59
#include "pkim.h"
 
60
#include "pki3hack.h"
 
61
#include "ckhelper.h"
 
62
#include "base.h"
 
63
#include "pkistore.h"
 
64
#include "dev3hack.h"
 
65
#include "dev.h"
 
66
 
 
67
PRBool
 
68
SEC_CertNicknameConflict(char *nickname, SECItem *derSubject,
 
69
                         CERTCertDBHandle *handle)
 
70
{
 
71
    CERTCertificate *cert;
 
72
    PRBool conflict = PR_FALSE;
 
73
 
 
74
    cert=CERT_FindCertByNickname(handle, nickname);
 
75
 
 
76
    if (!cert) {
 
77
        return conflict;
 
78
    }
 
79
 
 
80
    conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject);
 
81
    CERT_DestroyCertificate(cert);
 
82
    return conflict;
 
83
}
 
84
 
 
85
SECStatus
 
86
SEC_DeletePermCertificate(CERTCertificate *cert)
 
87
{
 
88
    PRStatus nssrv;
 
89
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
 
90
    NSSCertificate *c = STAN_GetNSSCertificate(cert);
 
91
 
 
92
    /* get rid of the token instances */
 
93
    nssrv = NSSCertificate_DeleteStoredObject(c, NULL);
 
94
 
 
95
    /* get rid of the cache entry */
 
96
    nssTrustDomain_LockCertCache(td);
 
97
    nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
 
98
    nssTrustDomain_UnlockCertCache(td);
 
99
 
 
100
    return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
 
101
}
 
102
 
 
103
SECStatus
 
104
CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust)
 
105
{
 
106
    SECStatus rv;
 
107
    CERT_LockCertTrust(cert);
 
108
    if ( cert->trust == NULL ) {
 
109
        rv = SECFailure;
 
110
    } else {
 
111
        *trust = *cert->trust;
 
112
        rv = SECSuccess;
 
113
    }
 
114
    CERT_UnlockCertTrust(cert);
 
115
    return(rv);
 
116
}
 
117
 
 
118
#ifdef notdef
 
119
static char *
 
120
cert_parseNickname(char *nickname)
 
121
{
 
122
    char *cp;
 
123
    for (cp=nickname; *cp && *cp != ':'; cp++);
 
124
    if (*cp == ':') return cp+1;
 
125
    return nickname;
 
126
}
 
127
#endif
 
128
 
 
129
SECStatus
 
130
CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
 
131
                    CERTCertTrust *trust)
 
132
{
 
133
    SECStatus rv = SECFailure;
 
134
    PRStatus ret;
 
135
 
 
136
    CERT_LockCertTrust(cert);
 
137
    ret = STAN_ChangeCertTrust(cert, trust);
 
138
    rv = (ret == PR_SUCCESS) ? SECSuccess : SECFailure;
 
139
    CERT_UnlockCertTrust(cert);
 
140
    return rv;
 
141
}
 
142
 
 
143
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
 
144
 
 
145
SECStatus
 
146
__CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
 
147
                       CERTCertTrust *trust)
 
148
{
 
149
    NSSUTF8 *stanNick;
 
150
    PK11SlotInfo *slot;
 
151
    NSSToken *internal;
 
152
    NSSCryptoContext *context;
 
153
    nssCryptokiObject *permInstance;
 
154
    NSSCertificate *c = STAN_GetNSSCertificate(cert);
 
155
    context = c->object.cryptoContext;
 
156
    if (!context) {
 
157
        PORT_SetError(SEC_ERROR_ADDING_CERT); 
 
158
        return SECFailure; /* wasn't a temp cert */
 
159
    }
 
160
    stanNick = nssCertificate_GetNickname(c, NULL);
 
161
    if (stanNick && nickname && strcmp(nickname, stanNick) != 0) {
 
162
        /* take the new nickname */
 
163
        cert->nickname = NULL;
 
164
        stanNick = NULL;
 
165
    }
 
166
    if (!stanNick && nickname) {
 
167
        stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, c->object.arena);
 
168
    }
 
169
    /* Delete the temp instance */
 
170
    nssCertificateStore_Lock(context->certStore);
 
171
    nssCertificateStore_RemoveCertLOCKED(context->certStore, c);
 
172
    nssCertificateStore_Unlock(context->certStore);
 
173
    c->object.cryptoContext = NULL;
 
174
    /* Import the perm instance onto the internal token */
 
175
    slot = PK11_GetInternalKeySlot();
 
176
    internal = PK11Slot_GetNSSToken(slot);
 
177
    permInstance = nssToken_ImportCertificate(internal, NULL,
 
178
                                              NSSCertificateType_PKIX,
 
179
                                              &c->id,
 
180
                                              stanNick,
 
181
                                              &c->encoding,
 
182
                                              &c->issuer,
 
183
                                              &c->subject,
 
184
                                              &c->serial,
 
185
                                              cert->emailAddr,
 
186
                                              PR_TRUE);
 
187
    PK11_FreeSlot(slot);
 
188
    if (!permInstance) {
 
189
        if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) {
 
190
            PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
 
191
        }
 
192
        return SECFailure;
 
193
    }
 
194
    nssPKIObject_AddInstance(&c->object, permInstance);
 
195
    nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
 
196
    /* reset the CERTCertificate fields */
 
197
    cert->nssCertificate = NULL;
 
198
    cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */
 
199
    if (!cert) {
 
200
        return SECFailure;
 
201
    }
 
202
    cert->istemp = PR_FALSE;
 
203
    cert->isperm = PR_TRUE;
 
204
    if (!trust) {
 
205
        return SECSuccess;
 
206
    }
 
207
    return (STAN_ChangeCertTrust(cert, trust) == PR_SUCCESS) ? 
 
208
                                                        SECSuccess: SECFailure;
 
209
}
 
210
 
 
211
SECStatus
 
212
CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
 
213
                       CERTCertTrust *trust)
 
214
{
 
215
    return __CERT_AddTempCertToPerm(cert, nickname, trust);
 
216
}
 
217
 
 
218
CERTCertificate *
 
219
__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
 
220
                          char *nickname, PRBool isperm, PRBool copyDER)
 
221
{
 
222
    PRStatus nssrv;
 
223
    NSSCertificate *c;
 
224
    CERTCertificate *cc;
 
225
    NSSCertificate *tempCert;
 
226
    nssPKIObject *pkio;
 
227
    NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext();
 
228
    NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain();
 
229
    if (!isperm) {
 
230
        NSSDER encoding;
 
231
        NSSITEM_FROM_SECITEM(&encoding, derCert);
 
232
        /* First, see if it is already a temp cert */
 
233
        c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, 
 
234
                                                               &encoding);
 
235
        if (!c) {
 
236
            /* Then, see if it is already a perm cert */
 
237
            c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, 
 
238
                                                                   &encoding);
 
239
        }
 
240
        if (c) {
 
241
            /* actually, that search ends up going by issuer/serial,
 
242
             * so it is still possible to return a cert with the same
 
243
             * issuer/serial but a different encoding, and we're
 
244
             * going to reject that
 
245
             */
 
246
            if (!nssItem_Equal(&c->encoding, &encoding, NULL)) {
 
247
                nssCertificate_Destroy(c);
 
248
                PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
 
249
                cc = NULL;
 
250
            } else {
 
251
                cc = STAN_GetCERTCertificateOrRelease(c);
 
252
            }
 
253
            return cc;
 
254
        }
 
255
    }
 
256
    pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC);
 
257
    if (!pkio) {
 
258
        return NULL;
 
259
    }
 
260
    c = nss_ZNEW(pkio->arena, NSSCertificate);
 
261
    if (!c) {
 
262
        nssPKIObject_Destroy(pkio);
 
263
        return NULL;
 
264
    }
 
265
    c->object = *pkio;
 
266
    if (copyDER) {
 
267
        nssItem_Create(c->object.arena, &c->encoding, 
 
268
                       derCert->len, derCert->data);
 
269
    } else {
 
270
        NSSITEM_FROM_SECITEM(&c->encoding, derCert);
 
271
    }
 
272
    /* Forces a decoding of the cert in order to obtain the parts used
 
273
     * below
 
274
     */
 
275
    /* 'c' is not adopted here, if we fail loser frees what has been
 
276
     * allocated so far for 'c' */
 
277
    cc = STAN_GetCERTCertificate(c);
 
278
    if (!cc) {
 
279
        goto loser;
 
280
    }
 
281
    nssItem_Create(c->object.arena, 
 
282
                   &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
 
283
    nssItem_Create(c->object.arena, 
 
284
                   &c->subject, cc->derSubject.len, cc->derSubject.data);
 
285
    if (PR_TRUE) {
 
286
        /* CERTCertificate stores serial numbers decoded.  I need the DER
 
287
        * here.  sigh.
 
288
        */
 
289
        SECItem derSerial = { 0 };
 
290
        CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
 
291
        if (!derSerial.data) goto loser;
 
292
        nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data);
 
293
        PORT_Free(derSerial.data);
 
294
    }
 
295
    if (nickname) {
 
296
        c->object.tempName = nssUTF8_Create(c->object.arena, 
 
297
                                            nssStringType_UTF8String, 
 
298
                                            (NSSUTF8 *)nickname, 
 
299
                                            PORT_Strlen(nickname));
 
300
    }
 
301
    if (cc->emailAddr && cc->emailAddr[0]) {
 
302
        c->email = nssUTF8_Create(c->object.arena, 
 
303
                                  nssStringType_PrintableString, 
 
304
                                  (NSSUTF8 *)cc->emailAddr, 
 
305
                                  PORT_Strlen(cc->emailAddr));
 
306
    }
 
307
    /* this function cannot detect if the cert exists as a temp cert now, but
 
308
     * didn't when CERT_NewTemp was first called.
 
309
     */
 
310
    nssrv = NSSCryptoContext_ImportCertificate(gCC, c);
 
311
    if (nssrv != PR_SUCCESS) {
 
312
        goto loser;
 
313
    }
 
314
    /* so find the entry in the temp store */
 
315
    tempCert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(gCC,
 
316
                                                                   &c->issuer,
 
317
                                                                   &c->serial);
 
318
    /* destroy the copy */
 
319
    NSSCertificate_Destroy(c);
 
320
    if (tempCert) {
 
321
        /* and use the "official" entry */
 
322
        c = tempCert;
 
323
        cc = STAN_GetCERTCertificateOrRelease(c);
 
324
        if (!cc) {
 
325
            return NULL;
 
326
        }
 
327
    } else {
 
328
        return NULL;
 
329
    }
 
330
    cc->istemp = PR_TRUE;
 
331
    cc->isperm = PR_FALSE;
 
332
    return cc;
 
333
loser:
 
334
    nssPKIObject_Destroy(&c->object);
 
335
    return NULL;
 
336
}
 
337
 
 
338
CERTCertificate *
 
339
CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
 
340
                        char *nickname, PRBool isperm, PRBool copyDER)
 
341
{
 
342
    return( __CERT_NewTempCertificate(handle, derCert, nickname,
 
343
                                      isperm, copyDER) );
 
344
}
 
345
 
 
346
/* maybe all the wincx's should be some const for internal token login? */
 
347
CERTCertificate *
 
348
CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN)
 
349
{
 
350
    PK11SlotInfo *slot;
 
351
    CERTCertificate *cert;
 
352
 
 
353
    cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL);
 
354
    if (cert && slot) {
 
355
        PK11_FreeSlot(slot);
 
356
    }
 
357
 
 
358
    return cert;
 
359
}
 
360
 
 
361
static NSSCertificate *
 
362
get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
 
363
{
 
364
    NSSUsage usage;
 
365
    NSSCertificate *arr[3];
 
366
    if (!ct) {
 
367
        return nssCertificate_AddRef(cp);
 
368
    } else if (!cp) {
 
369
        return nssCertificate_AddRef(ct);
 
370
    }
 
371
    arr[0] = ct;
 
372
    arr[1] = cp;
 
373
    arr[2] = NULL;
 
374
    usage.anyUsage = PR_TRUE;
 
375
    return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL);
 
376
}
 
377
 
 
378
CERTCertificate *
 
379
CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name)
 
380
{
 
381
    NSSCertificate *cp, *ct, *c;
 
382
    NSSDER subject;
 
383
    NSSUsage usage;
 
384
    NSSCryptoContext *cc;
 
385
    NSSITEM_FROM_SECITEM(&subject, name);
 
386
    usage.anyUsage = PR_TRUE;
 
387
    cc = STAN_GetDefaultCryptoContext();
 
388
    ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, 
 
389
                                                       NULL, &usage, NULL);
 
390
    cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, 
 
391
                                                     NULL, &usage, NULL);
 
392
    c = get_best_temp_or_perm(ct, cp);
 
393
    if (ct) {
 
394
        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
 
395
    }
 
396
    if (cp) {
 
397
        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp));
 
398
    }
 
399
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
 
400
}
 
401
 
 
402
CERTCertificate *
 
403
CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
 
404
{
 
405
   CERTCertList *list =
 
406
                        CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE);
 
407
    CERTCertificate *cert = NULL;
 
408
    CERTCertListNode *node = CERT_LIST_HEAD(list);
 
409
 
 
410
    if (list == NULL) return NULL;
 
411
 
 
412
    for (node = CERT_LIST_HEAD(list); node ; node = CERT_LIST_NEXT(node)) {
 
413
        if (SECITEM_ItemsAreEqual(&cert->subjectKeyID, keyID) ) {
 
414
            cert = CERT_DupCertificate(node->cert);
 
415
            break;
 
416
        }
 
417
    }
 
418
    return cert;
 
419
}
 
420
 
 
421
CERTCertificate *
 
422
CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname)
 
423
{
 
424
    NSSCryptoContext *cc;
 
425
    NSSCertificate *c, *ct;
 
426
    CERTCertificate *cert;
 
427
    NSSUsage usage;
 
428
    usage.anyUsage = PR_TRUE;
 
429
    cc = STAN_GetDefaultCryptoContext();
 
430
    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, 
 
431
                                                       NULL, &usage, NULL);
 
432
    cert = PK11_FindCertFromNickname(nickname, NULL);
 
433
    c = NULL;
 
434
    if (cert) {
 
435
        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
 
436
        CERT_DestroyCertificate(cert);
 
437
        if (ct) {
 
438
            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
 
439
        }
 
440
    } else {
 
441
        c = ct;
 
442
    }
 
443
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
 
444
}
 
445
 
 
446
CERTCertificate *
 
447
CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
 
448
{
 
449
    NSSCryptoContext *cc;
 
450
    NSSCertificate *c;
 
451
    NSSDER encoding;
 
452
    NSSITEM_FROM_SECITEM(&encoding, derCert);
 
453
    cc = STAN_GetDefaultCryptoContext();
 
454
    c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding);
 
455
    if (!c) {
 
456
        c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, 
 
457
                                                               &encoding);
 
458
        if (!c) return NULL;
 
459
    }
 
460
    return STAN_GetCERTCertificateOrRelease(c);
 
461
}
 
462
 
 
463
CERTCertificate *
 
464
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *name)
 
465
{
 
466
    NSSCryptoContext *cc;
 
467
    NSSCertificate *c, *ct;
 
468
    CERTCertificate *cert;
 
469
    NSSUsage usage;
 
470
 
 
471
    if (NULL == name) {
 
472
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
473
        return NULL;
 
474
    }
 
475
    usage.anyUsage = PR_TRUE;
 
476
    cc = STAN_GetDefaultCryptoContext();
 
477
    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, 
 
478
                                                       NULL, &usage, NULL);
 
479
    if (!ct && PORT_Strchr(name, '@') != NULL) {
 
480
        char* lowercaseName = CERT_FixupEmailAddr(name);
 
481
        if (lowercaseName) {
 
482
            ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, 
 
483
                                                            NULL, &usage, NULL);
 
484
            PORT_Free(lowercaseName);
 
485
        }
 
486
    }
 
487
    cert = PK11_FindCertFromNickname(name, NULL);
 
488
    if (cert) {
 
489
        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
 
490
        CERT_DestroyCertificate(cert);
 
491
        if (ct) {
 
492
            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
 
493
        }
 
494
    } else {
 
495
        c = ct;
 
496
    }
 
497
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
 
498
}
 
499
 
 
500
static void 
 
501
add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
 
502
                    PRBool validOnly, int64 sorttime)
 
503
{
 
504
    SECStatus secrv;
 
505
    if (!validOnly ||
 
506
        CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) 
 
507
         == secCertTimeValid) {
 
508
            secrv = CERT_AddCertToListSorted(certList, cert, 
 
509
                                             CERT_SortCBValidity, 
 
510
                                             (void *)&sorttime);
 
511
            if (secrv != SECSuccess) {
 
512
                CERT_DestroyCertificate(cert);
 
513
            }
 
514
    } else {
 
515
        CERT_DestroyCertificate(cert);
 
516
    }
 
517
}
 
518
 
 
519
CERTCertList *
 
520
CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle,
 
521
                           SECItem *name, int64 sorttime, PRBool validOnly)
 
522
{
 
523
    NSSCryptoContext *cc;
 
524
    NSSCertificate **tSubjectCerts, **pSubjectCerts;
 
525
    NSSCertificate **ci;
 
526
    CERTCertificate *cert;
 
527
    NSSDER subject;
 
528
    PRBool myList = PR_FALSE;
 
529
    cc = STAN_GetDefaultCryptoContext();
 
530
    NSSITEM_FROM_SECITEM(&subject, name);
 
531
    /* Collect both temp and perm certs for the subject */
 
532
    tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc,
 
533
                                                               &subject,
 
534
                                                               NULL,
 
535
                                                               0,
 
536
                                                               NULL);
 
537
    pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle,
 
538
                                                             &subject,
 
539
                                                             NULL,
 
540
                                                             0,
 
541
                                                             NULL);
 
542
    if (!tSubjectCerts && !pSubjectCerts) {
 
543
        return NULL;
 
544
    }
 
545
    if (certList == NULL) {
 
546
        certList = CERT_NewCertList();
 
547
        myList = PR_TRUE;
 
548
        if (!certList) goto loser;
 
549
    }
 
550
    /* Iterate over the matching temp certs.  Add them to the list */
 
551
    ci = tSubjectCerts;
 
552
    while (ci && *ci) {
 
553
        cert = STAN_GetCERTCertificateOrRelease(*ci);
 
554
        /* *ci may be invalid at this point, don't reference it again */
 
555
        if (cert) {
 
556
            /* NOTE: add_to_subject_list adopts the incoming cert. */
 
557
            add_to_subject_list(certList, cert, validOnly, sorttime);
 
558
        }
 
559
        ci++;
 
560
    }
 
561
    /* Iterate over the matching perm certs.  Add them to the list */
 
562
    ci = pSubjectCerts;
 
563
    while (ci && *ci) {
 
564
        cert = STAN_GetCERTCertificateOrRelease(*ci);
 
565
        /* *ci may be invalid at this point, don't reference it again */
 
566
        if (cert) {
 
567
            /* NOTE: add_to_subject_list adopts the incoming cert. */
 
568
            add_to_subject_list(certList, cert, validOnly, sorttime);
 
569
        }
 
570
        ci++;
 
571
    }
 
572
    /* all the references have been adopted or freed at this point, just
 
573
     * free the arrays now */
 
574
    nss_ZFreeIf(tSubjectCerts);
 
575
    nss_ZFreeIf(pSubjectCerts);
 
576
    return certList;
 
577
loser:
 
578
    /* need to free the references in tSubjectCerts and pSubjectCerts! */
 
579
    nssCertificateArray_Destroy(tSubjectCerts);
 
580
    nssCertificateArray_Destroy(pSubjectCerts);
 
581
    if (myList && certList != NULL) {
 
582
        CERT_DestroyCertList(certList);
 
583
    }
 
584
    return NULL;
 
585
}
 
586
 
 
587
void
 
588
CERT_DestroyCertificate(CERTCertificate *cert)
 
589
{
 
590
    if ( cert ) {
 
591
        /* don't use STAN_GetNSSCertificate because we don't want to
 
592
         * go to the trouble of translating the CERTCertificate into
 
593
         * an NSSCertificate just to destroy it.  If it hasn't been done
 
594
         * yet, don't do it at all.
 
595
         */
 
596
        NSSCertificate *tmp = cert->nssCertificate;
 
597
        if (tmp) {
 
598
            /* delete the NSSCertificate */
 
599
            NSSCertificate_Destroy(tmp);
 
600
        } else {
 
601
            PORT_FreeArena(cert->arena, PR_FALSE);
 
602
        }
 
603
    }
 
604
    return;
 
605
}
 
606
 
 
607
#ifdef notdef
 
608
SECStatus
 
609
CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb,
 
610
                            CERTCertificate *cert, SECCertUsage usage)
 
611
{
 
612
    SECStatus rv;
 
613
    CERTCertTrust trust;
 
614
    CERTCertTrust tmptrust;
 
615
    unsigned int certtype;
 
616
    PRBool saveit;
 
617
    
 
618
    saveit = PR_TRUE;
 
619
    
 
620
    PORT_Memset((void *)&trust, 0, sizeof(trust));
 
621
 
 
622
    certtype = cert->nsCertType;
 
623
 
 
624
    /* if no app bits in cert type, then set all app bits */
 
625
    if ( ! ( certtype & NS_CERT_TYPE_APP ) ) {
 
626
        certtype |= NS_CERT_TYPE_APP;
 
627
    }
 
628
 
 
629
    switch ( usage ) {
 
630
      case certUsageEmailSigner:
 
631
      case certUsageEmailRecipient:
 
632
        if ( certtype & NS_CERT_TYPE_EMAIL ) {
 
633
             trust.emailFlags = CERTDB_VALID_PEER;
 
634
             if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) {
 
635
                /* don't save it if KeyEncipherment is not allowed */
 
636
                saveit = PR_FALSE;
 
637
            }
 
638
        }
 
639
        break;
 
640
      case certUsageUserCertImport:
 
641
        if ( certtype & NS_CERT_TYPE_EMAIL ) {
 
642
            trust.emailFlags = CERTDB_VALID_PEER;
 
643
        }
 
644
        /* VALID_USER is already set if the cert was imported, 
 
645
         * in the case that the cert was already in the database
 
646
         * through SMIME or other means, we should set the USER
 
647
         * flags, if they are not already set.
 
648
         */
 
649
        if( cert->isperm ) {
 
650
            if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) {
 
651
                if( !(cert->trust->sslFlags & CERTDB_USER) ) {
 
652
                    trust.sslFlags |= CERTDB_USER;
 
653
                }
 
654
            }
 
655
            
 
656
            if ( certtype & NS_CERT_TYPE_EMAIL ) {
 
657
                if( !(cert->trust->emailFlags & CERTDB_USER) ) {
 
658
                    trust.emailFlags |= CERTDB_USER;
 
659
                }
 
660
            }
 
661
            
 
662
            if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) {
 
663
                if( !(cert->trust->objectSigningFlags & CERTDB_USER) ) {
 
664
                    trust.objectSigningFlags |= CERTDB_USER;
 
665
                }
 
666
            }
 
667
        }
 
668
        break;
 
669
      default:  /* XXX added to quiet warnings; no other cases needed? */
 
670
        break;
 
671
    }
 
672
 
 
673
    if ( (trust.sslFlags | trust.emailFlags | trust.objectSigningFlags) == 0 ){
 
674
        saveit = PR_FALSE;
 
675
    }
 
676
 
 
677
    if ( saveit && cert->isperm ) {
 
678
        /* Cert already in the DB.  Just adjust flags */
 
679
        tmptrust = *cert->trust;
 
680
        tmptrust.sslFlags |= trust.sslFlags;
 
681
        tmptrust.emailFlags |= trust.emailFlags;
 
682
        tmptrust.objectSigningFlags |= trust.objectSigningFlags;
 
683
            
 
684
        rv = CERT_ChangeCertTrust(cert->dbhandle, cert,
 
685
                                  &tmptrust);
 
686
        if ( rv != SECSuccess ) {
 
687
            goto loser;
 
688
        }
 
689
    }
 
690
 
 
691
    rv = SECSuccess;
 
692
    goto done;
 
693
 
 
694
loser:
 
695
    rv = SECFailure;
 
696
done:
 
697
 
 
698
    return(rv);
 
699
}
 
700
#endif
 
701
 
 
702
int
 
703
CERT_GetDBContentVersion(CERTCertDBHandle *handle)
 
704
{
 
705
    /* should read the DB content version from the pkcs #11 device */
 
706
    return 0;
 
707
}
 
708
 
 
709
SECStatus
 
710
certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr, 
 
711
                                SECItem *emailProfile, SECItem *profileTime)
 
712
{
 
713
    int64 oldtime;
 
714
    int64 newtime;
 
715
    SECStatus rv = SECFailure;
 
716
    PRBool saveit;
 
717
    SECItem oldprof, oldproftime;
 
718
    SECItem *oldProfile = NULL;
 
719
    SECItem *oldProfileTime = NULL;
 
720
    PK11SlotInfo *slot = NULL;
 
721
    NSSCertificate *c;
 
722
    NSSCryptoContext *cc;
 
723
    nssSMIMEProfile *stanProfile = NULL;
 
724
    PRBool freeOldProfile = PR_FALSE;
 
725
 
 
726
    c = STAN_GetNSSCertificate(cert);
 
727
    if (!c) return SECFailure;
 
728
    cc = c->object.cryptoContext;
 
729
    if (cc != NULL) {
 
730
        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
 
731
        if (stanProfile) {
 
732
            PORT_Assert(stanProfile->profileData);
 
733
            SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData);
 
734
            oldProfile = &oldprof;
 
735
            SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime);
 
736
            oldProfileTime = &oldproftime;
 
737
        }
 
738
    } else {
 
739
        oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr, 
 
740
                                        &cert->derSubject, &oldProfileTime); 
 
741
        freeOldProfile = PR_TRUE;
 
742
    }
 
743
 
 
744
    saveit = PR_FALSE;
 
745
    
 
746
    /* both profileTime and emailProfile have to exist or not exist */
 
747
    if ( emailProfile == NULL ) {
 
748
        profileTime = NULL;
 
749
    } else if ( profileTime == NULL ) {
 
750
        emailProfile = NULL;
 
751
    }
 
752
   
 
753
    if ( oldProfileTime == NULL ) {
 
754
        saveit = PR_TRUE;
 
755
    } else {
 
756
        /* there was already a profile for this email addr */
 
757
        if ( profileTime ) {
 
758
            /* we have an old and new profile - save whichever is more recent*/
 
759
            if ( oldProfileTime->len == 0 ) {
 
760
                /* always replace if old entry doesn't have a time */
 
761
                oldtime = LL_MININT;
 
762
            } else {
 
763
                rv = DER_UTCTimeToTime(&oldtime, oldProfileTime);
 
764
                if ( rv != SECSuccess ) {
 
765
                    goto loser;
 
766
                }
 
767
            }
 
768
            
 
769
            rv = DER_UTCTimeToTime(&newtime, profileTime);
 
770
            if ( rv != SECSuccess ) {
 
771
                goto loser;
 
772
            }
 
773
        
 
774
            if ( LL_CMP(newtime, >, oldtime ) ) {
 
775
                /* this is a newer profile, save it and cert */
 
776
                saveit = PR_TRUE;
 
777
            }
 
778
        } else {
 
779
            saveit = PR_TRUE;
 
780
        }
 
781
    }
 
782
 
 
783
 
 
784
    if (saveit) {
 
785
        if (cc) {
 
786
            if (stanProfile) {
 
787
                /* stanProfile is already stored in the crypto context,
 
788
                 * overwrite the data
 
789
                 */
 
790
                NSSArena *arena = stanProfile->object.arena;
 
791
                stanProfile->profileTime = nssItem_Create(arena, 
 
792
                                                          NULL,
 
793
                                                          profileTime->len,
 
794
                                                          profileTime->data);
 
795
                stanProfile->profileData = nssItem_Create(arena, 
 
796
                                                          NULL,
 
797
                                                          emailProfile->len,
 
798
                                                          emailProfile->data);
 
799
            } else if (profileTime && emailProfile) {
 
800
                PRStatus nssrv;
 
801
                NSSDER subject;
 
802
                NSSItem profTime, profData;
 
803
                NSSItem *pprofTime, *pprofData;
 
804
                NSSITEM_FROM_SECITEM(&subject, &cert->derSubject);
 
805
                if (profileTime) {
 
806
                    NSSITEM_FROM_SECITEM(&profTime, profileTime);
 
807
                    pprofTime = &profTime;
 
808
                } else {
 
809
                    pprofTime = NULL;
 
810
                }
 
811
                if (emailProfile) {
 
812
                    NSSITEM_FROM_SECITEM(&profData, emailProfile);
 
813
                    pprofData = &profData;
 
814
                } else {
 
815
                    pprofData = NULL;
 
816
                }
 
817
                stanProfile = nssSMIMEProfile_Create(c, pprofTime, pprofData);
 
818
                if (!stanProfile) goto loser;
 
819
                nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile);
 
820
                rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
 
821
            }
 
822
        } else {
 
823
            rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr, 
 
824
                                &cert->derSubject, emailProfile, profileTime);
 
825
        }
 
826
    } else {
 
827
        rv = SECSuccess;
 
828
    }
 
829
 
 
830
loser:
 
831
    if (oldProfile && freeOldProfile) {
 
832
        SECITEM_FreeItem(oldProfile,PR_TRUE);
 
833
    }
 
834
    if (oldProfileTime && freeOldProfile) {
 
835
        SECITEM_FreeItem(oldProfileTime,PR_TRUE);
 
836
    }
 
837
    if (stanProfile) {
 
838
        nssSMIMEProfile_Destroy(stanProfile);
 
839
    }
 
840
    if (slot) {
 
841
        PK11_FreeSlot(slot);
 
842
    }
 
843
    
 
844
    return(rv);
 
845
}
 
846
 
 
847
/*
 
848
 *
 
849
 * Manage S/MIME profiles
 
850
 *
 
851
 */
 
852
 
 
853
SECStatus
 
854
CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile,
 
855
                      SECItem *profileTime)
 
856
{
 
857
    const char *emailAddr;
 
858
    SECStatus rv;
 
859
 
 
860
    if (!cert) {
 
861
        return SECFailure;
 
862
    }
 
863
 
 
864
    if (cert->slot &&  !PK11_IsInternal(cert->slot)) {
 
865
        /* this cert comes from an external source, we need to add it
 
866
        to the cert db before creating an S/MIME profile */
 
867
        PK11SlotInfo* internalslot = PK11_GetInternalKeySlot();
 
868
        if (!internalslot) {
 
869
            return SECFailure;
 
870
        }
 
871
        rv = PK11_ImportCert(internalslot, cert,
 
872
            CK_INVALID_HANDLE, NULL, PR_FALSE);
 
873
 
 
874
        PK11_FreeSlot(internalslot);
 
875
        if (rv != SECSuccess ) {
 
876
            return SECFailure;
 
877
        }
 
878
    }
 
879
 
 
880
    
 
881
    for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL;
 
882
                emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) {
 
883
        rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime);
 
884
        if (rv != SECSuccess) {
 
885
           return SECFailure;
 
886
        }
 
887
    }
 
888
    return SECSuccess;
 
889
 
 
890
}
 
891
 
 
892
 
 
893
SECItem *
 
894
CERT_FindSMimeProfile(CERTCertificate *cert)
 
895
{
 
896
    PK11SlotInfo *slot = NULL;
 
897
    NSSCertificate *c;
 
898
    NSSCryptoContext *cc;
 
899
    SECItem *rvItem = NULL;
 
900
 
 
901
    c = STAN_GetNSSCertificate(cert);
 
902
    if (!c) return NULL;
 
903
    cc = c->object.cryptoContext;
 
904
    if (cc != NULL) {
 
905
        nssSMIMEProfile *stanProfile;
 
906
        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
 
907
        if (stanProfile) {
 
908
            rvItem = SECITEM_AllocItem(NULL, NULL, 
 
909
                                       stanProfile->profileData->size);
 
910
            if (rvItem) {
 
911
                rvItem->data = stanProfile->profileData->data;
 
912
            }
 
913
            nssSMIMEProfile_Destroy(stanProfile);
 
914
        }
 
915
        return rvItem;
 
916
    }
 
917
    rvItem =
 
918
        PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL);
 
919
    if (slot) {
 
920
        PK11_FreeSlot(slot);
 
921
    }
 
922
    return rvItem;
 
923
}
 
924
 
 
925
/*
 
926
 * depricated functions that are now just stubs.
 
927
 */
 
928
/*
 
929
 * Close the database
 
930
 */
 
931
void
 
932
__CERT_ClosePermCertDB(CERTCertDBHandle *handle)
 
933
{
 
934
    PORT_Assert("CERT_ClosePermCertDB is Depricated" == NULL);
 
935
    return;
 
936
}
 
937
 
 
938
SECStatus
 
939
CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname,
 
940
                        PRBool readOnly)
 
941
{
 
942
    PORT_Assert("CERT_OpenCertDBFilename is Depricated" == NULL);
 
943
    return SECFailure;
 
944
}
 
945
 
 
946
SECItem *
 
947
SECKEY_HashPassword(char *pw, SECItem *salt)
 
948
{
 
949
    PORT_Assert("SECKEY_HashPassword is Depricated" == NULL);
 
950
    return NULL;
 
951
}
 
952
 
 
953
SECStatus
 
954
__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle,
 
955
                                 SECItem *derSubject,
 
956
                                 void *cb, void *cbarg)
 
957
{
 
958
    PORT_Assert("CERT_TraversePermCertsForSubject is Depricated" == NULL);
 
959
    return SECFailure;
 
960
}
 
961
 
 
962
 
 
963
SECStatus
 
964
__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname,
 
965
                                  void *cb, void *cbarg)
 
966
{
 
967
    PORT_Assert("CERT_TraversePermCertsForNickname is Depricated" == NULL);
 
968
    return SECFailure;
 
969
}
 
970
 
 
971
 
 
972