Coverage Report

Created: 2026-06-07 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/certdb/stanpcertdb.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "prtime.h"
6
7
#include "cert.h"
8
#include "certi.h"
9
#include "certdb.h"
10
#include "secitem.h"
11
#include "secder.h"
12
13
/* Call to PK11_FreeSlot below */
14
15
#include "secasn1.h"
16
#include "secerr.h"
17
#include "prmon.h"
18
#include "base64.h"
19
#include "sechash.h"
20
#include "plhash.h"
21
#include "pk11func.h" /* sigh */
22
23
#include "nsspki.h"
24
#include "pki.h"
25
#include "pkim.h"
26
#include "pki3hack.h"
27
#include "ckhelper.h"
28
#include "base.h"
29
#include "pkistore.h"
30
#include "dev3hack.h"
31
#include "dev.h"
32
#include "secmodi.h"
33
34
extern void CERT_MaybeLockCertTempPerm(const CERTCertificate *cert);
35
extern void CERT_MaybeUnlockCertTempPerm(const CERTCertificate *cert);
36
37
PRBool
38
SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject,
39
                         CERTCertDBHandle *handle)
40
0
{
41
0
    CERTCertificate *cert;
42
0
    PRBool conflict = PR_FALSE;
43
44
0
    cert = CERT_FindCertByNickname(handle, nickname);
45
46
0
    if (!cert) {
47
0
        return conflict;
48
0
    }
49
50
0
    conflict = !SECITEM_ItemsAreEqual(derSubject, &cert->derSubject);
51
0
    CERT_DestroyCertificate(cert);
52
0
    return conflict;
53
0
}
54
55
SECStatus
56
SEC_DeletePermCertificate(CERTCertificate *cert)
57
0
{
58
0
    PRStatus nssrv;
59
0
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
60
0
    NSSCertificate *c = STAN_GetNSSCertificate(cert);
61
0
    CERTCertTrust *certTrust;
62
63
0
    if (c == NULL) {
64
        /* error code is set */
65
0
        return SECFailure;
66
0
    }
67
68
0
    certTrust = nssTrust_GetCERTCertTrustForCert(c, cert);
69
0
    if (certTrust) {
70
0
        NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
71
0
        if (nssTrust) {
72
0
            nssrv = STAN_DeleteCertTrustMatchingSlot(c);
73
0
            if (nssrv != PR_SUCCESS) {
74
0
                CERT_MapStanError();
75
0
            }
76
            /* This call always returns PR_SUCCESS! */
77
0
            (void)nssTrust_Destroy(nssTrust);
78
0
        }
79
0
    }
80
81
    /* get rid of the token instances */
82
0
    nssrv = NSSCertificate_DeleteStoredObject(c, NULL);
83
84
    /* get rid of the cache entry */
85
0
    nssTrustDomain_LockCertCache(td);
86
0
    nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
87
0
    nssTrustDomain_UnlockCertCache(td);
88
89
0
    return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
90
0
}
91
92
SECStatus
93
CERT_GetCertTrust(const CERTCertificate *cert, CERTCertTrust *trust)
94
219k
{
95
219k
    SECStatus rv;
96
219k
    CERT_LockCertTrust(cert);
97
219k
    if (!cert || cert->trust == NULL) {
98
219k
        rv = SECFailure;
99
219k
    } else {
100
0
        *trust = *cert->trust;
101
0
        rv = SECSuccess;
102
0
    }
103
219k
    CERT_UnlockCertTrust(cert);
104
219k
    return (rv);
105
219k
}
106
107
extern const NSSError NSS_ERROR_NO_ERROR;
108
extern const NSSError NSS_ERROR_INTERNAL_ERROR;
109
extern const NSSError NSS_ERROR_NO_MEMORY;
110
extern const NSSError NSS_ERROR_INVALID_POINTER;
111
extern const NSSError NSS_ERROR_INVALID_ARENA;
112
extern const NSSError NSS_ERROR_INVALID_ARENA_MARK;
113
extern const NSSError NSS_ERROR_DUPLICATE_POINTER;
114
extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED;
115
extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY;
116
extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED;
117
extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
118
extern const NSSError NSS_ERROR_VALUE_TOO_LARGE;
119
extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE;
120
extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT;
121
extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT;
122
extern const NSSError NSS_ERROR_INVALID_BASE64;
123
extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT;
124
extern const NSSError NSS_ERROR_INVALID_ITEM;
125
extern const NSSError NSS_ERROR_INVALID_STRING;
126
extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
127
extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
128
extern const NSSError NSS_ERROR_INVALID_BER;
129
extern const NSSError NSS_ERROR_INVALID_ATAV;
130
extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
131
extern const NSSError NSS_ERROR_INVALID_UTF8;
132
extern const NSSError NSS_ERROR_INVALID_NSSOID;
133
extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE;
134
extern const NSSError NSS_ERROR_NOT_FOUND;
135
extern const NSSError NSS_ERROR_INVALID_PASSWORD;
136
extern const NSSError NSS_ERROR_USER_CANCELED;
137
extern const NSSError NSS_ERROR_MAXIMUM_FOUND;
138
extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND;
139
extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE;
140
extern const NSSError NSS_ERROR_HASH_COLLISION;
141
extern const NSSError NSS_ERROR_DEVICE_ERROR;
142
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
143
extern const NSSError NSS_ERROR_BUSY;
144
extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
145
extern const NSSError NSS_ERROR_PKCS11;
146
147
/* Look at the stan error stack and map it to NSS 3 errors */
148
#define STAN_MAP_ERROR(x, y) \
149
46.9k
    else if (error == (x)) { secError = y; }
150
151
/*
152
 * map Stan errors into NSS errors
153
 * This function examines the stan error stack and automatically sets
154
 * PORT_SetError(); to the appropriate SEC_ERROR value.
155
 */
156
void
157
CERT_MapStanError()
158
2.18k
{
159
2.18k
    PRInt32 *errorStack;
160
2.18k
    NSSError error, prevError;
161
2.18k
    int secError;
162
2.18k
    int i;
163
164
2.18k
    errorStack = NSS_GetErrorStack();
165
2.18k
    if (errorStack == 0) {
166
0
        PORT_SetError(0);
167
0
        return;
168
0
    }
169
2.18k
    error = prevError = CKR_GENERAL_ERROR;
170
    /* get the 'top 2' error codes from the stack */
171
10.4k
    for (i = 0; errorStack[i]; i++) {
172
8.29k
        prevError = error;
173
8.29k
        error = errorStack[i];
174
8.29k
    }
175
2.18k
    if (error == NSS_ERROR_PKCS11) {
176
        /* map it */
177
0
        secError = PK11_MapError(prevError);
178
0
    }
179
2.18k
    STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0)
180
2.18k
    STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY)
181
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA)
182
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER)
183
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA)
184
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD, SEC_ERROR_BAD_PASSWORD)
185
2.18k
    STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY)
186
2.18k
    STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO)
187
2.18k
    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND,
188
2.18k
                   SEC_ERROR_UNKNOWN_ISSUER)
189
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID)
190
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA)
191
2.18k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA)
192
193
    /* these are library failure for lack of a better error code */
194
2.18k
    STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE)
195
2.18k
    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, SEC_ERROR_LIBRARY_FAILURE)
196
1.36k
    STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE)
197
1.36k
    STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE)
198
1.36k
    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
199
1.36k
    STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
200
1.36k
    STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD,
201
1.36k
                   SEC_ERROR_LIBRARY_FAILURE)
202
1.36k
    STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE)
203
204
1.36k
    STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE)
205
206
    /* these are all invalid arguments */
207
1.36k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS)
208
1.36k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS)
209
1.36k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS)
210
1.36k
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS)
211
1.36k
    STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS)
212
0
    STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS)
213
0
    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS)
214
0
    STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS)
215
0
    STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS)
216
0
    STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS)
217
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS)
218
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS)
219
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS)
220
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS)
221
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS)
222
0
    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS)
223
0
    STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS)
224
0
    else { secError = SEC_ERROR_LIBRARY_FAILURE; }
225
2.18k
    PORT_SetError(secError);
226
2.18k
}
227
228
SECStatus
229
CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
230
                     CERTCertTrust *trust)
231
0
{
232
0
    SECStatus rv = SECSuccess;
233
0
    PRStatus ret;
234
235
0
    ret = STAN_ChangeCertTrust(cert, trust);
236
0
    if (ret != PR_SUCCESS) {
237
0
        rv = SECFailure;
238
0
        CERT_MapStanError();
239
0
    }
240
0
    return rv;
241
0
}
242
243
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
244
245
SECStatus
246
__CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
247
                         CERTCertTrust *trust)
248
0
{
249
0
    NSSUTF8 *stanNick;
250
0
    PK11SlotInfo *slot;
251
0
    NSSToken *internal;
252
0
    NSSCryptoContext *context;
253
0
    nssCryptokiObject *permInstance;
254
0
    NSSCertificate *c = STAN_GetNSSCertificate(cert);
255
0
    nssCertificateStoreTrace lockTrace = { NULL, NULL, PR_FALSE, PR_FALSE };
256
0
    nssCertificateStoreTrace unlockTrace = { NULL, NULL, PR_FALSE, PR_FALSE };
257
0
    SECStatus rv;
258
0
    PRStatus ret;
259
260
0
    if (c == NULL) {
261
0
        CERT_MapStanError();
262
0
        return SECFailure;
263
0
    }
264
265
0
    context = c->object.cryptoContext;
266
0
    if (!context) {
267
0
        PORT_SetError(SEC_ERROR_ADDING_CERT);
268
0
        return SECFailure; /* wasn't a temp cert */
269
0
    }
270
0
    stanNick = nssCertificate_GetNickname(c, NULL);
271
0
    if (stanNick && nickname && strcmp(nickname, stanNick) != 0) {
272
        /* different: take the new nickname */
273
0
        cert->nickname = NULL;
274
0
        nss_ZFreeIf(stanNick);
275
0
        stanNick = NULL;
276
0
    }
277
0
    if (!stanNick && nickname) {
278
        /* Either there was no nickname yet, or we have a new nickname */
279
0
        stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL);
280
0
    } /* else: old stanNick is identical to new nickname */
281
    /* Delete the temp instance */
282
0
    nssCertificateStore_Lock(context->certStore, &lockTrace);
283
0
    nssCertificateStore_RemoveCertLOCKED(context->certStore, c);
284
0
    nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace);
285
0
    c->object.cryptoContext = NULL;
286
287
    /* if the id has not been set explicitly yet, create one from the public
288
     * key. */
289
0
    if (c->id.data == NULL) {
290
0
        SECItem *keyID = pk11_mkcertKeyID(cert);
291
0
        if (keyID) {
292
0
            nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data);
293
0
            SECITEM_FreeItem(keyID, PR_TRUE);
294
0
        }
295
        /* if any of these failed, continue with our null c->id */
296
0
    }
297
298
    /* Import the perm instance onto the internal token */
299
0
    slot = PK11_GetInternalKeySlot();
300
0
    internal = PK11Slot_GetNSSToken(slot);
301
0
    if (!internal) {
302
0
        PK11_FreeSlot(slot);
303
0
        PORT_SetError(SEC_ERROR_NO_TOKEN);
304
0
        return SECFailure;
305
0
    }
306
0
    permInstance = nssToken_ImportCertificate(
307
0
        internal, NULL, NSSCertificateType_PKIX, &c->id, stanNick, &c->encoding,
308
0
        &c->issuer, &c->subject, &c->serial, cert->emailAddr, PR_TRUE);
309
0
    (void)nssToken_Destroy(internal);
310
0
    nss_ZFreeIf(stanNick);
311
0
    stanNick = NULL;
312
0
    PK11_FreeSlot(slot);
313
0
    if (!permInstance) {
314
0
        if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) {
315
0
            PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
316
0
        }
317
0
        return SECFailure;
318
0
    }
319
0
    nssPKIObject_AddInstance(&c->object, permInstance);
320
0
    nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
321
    /* reset the CERTCertificate fields */
322
0
    CERT_LockCertTempPerm(cert);
323
0
    cert->nssCertificate = NULL;
324
0
    CERT_UnlockCertTempPerm(cert);
325
0
    cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */
326
0
    if (!cert) {
327
0
        CERT_MapStanError();
328
0
        return SECFailure;
329
0
    }
330
0
    CERT_LockCertTempPerm(cert);
331
0
    cert->istemp = PR_FALSE;
332
0
    cert->isperm = PR_TRUE;
333
0
    CERT_UnlockCertTempPerm(cert);
334
0
    if (!trust) {
335
0
        return SECSuccess;
336
0
    }
337
0
    ret = STAN_ChangeCertTrust(cert, trust);
338
0
    rv = SECSuccess;
339
0
    if (ret != PR_SUCCESS) {
340
0
        rv = SECFailure;
341
0
        CERT_MapStanError();
342
0
    }
343
0
    return rv;
344
0
}
345
346
SECStatus
347
CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
348
                       CERTCertTrust *trust)
349
0
{
350
0
    return __CERT_AddTempCertToPerm(cert, nickname, trust);
351
0
}
352
353
CERTCertificate *
354
CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
355
                        char *nickname, PRBool isperm, PRBool copyDER)
356
93.8k
{
357
93.8k
    NSSCertificate *c;
358
93.8k
    CERTCertificate *cc;
359
93.8k
    NSSCertificate *tempCert = NULL;
360
93.8k
    nssPKIObject *pkio;
361
93.8k
    NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext();
362
93.8k
    NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain();
363
93.8k
    if (!isperm) {
364
93.8k
        NSSDER encoding;
365
93.8k
        NSSITEM_FROM_SECITEM(&encoding, derCert);
366
        /* First, see if it is already a temp cert */
367
93.8k
        c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC,
368
93.8k
                                                                 &encoding);
369
93.8k
        if (!c && handle) {
370
            /* Then, see if it is already a perm cert */
371
93.7k
            c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
372
93.7k
                                                                   &encoding);
373
93.7k
        }
374
93.8k
        if (c) {
375
            /* actually, that search ends up going by issuer/serial,
376
             * so it is still possible to return a cert with the same
377
             * issuer/serial but a different encoding, and we're
378
             * going to reject that
379
             */
380
77
            if (!nssItem_Equal(&c->encoding, &encoding, NULL)) {
381
54
                nssCertificate_Destroy(c);
382
54
                PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
383
54
                cc = NULL;
384
54
            } else {
385
23
                cc = STAN_GetCERTCertificateOrRelease(c);
386
23
                if (cc == NULL) {
387
0
                    CERT_MapStanError();
388
0
                }
389
23
            }
390
77
            return cc;
391
77
        }
392
93.8k
    }
393
93.7k
    pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor);
394
93.7k
    if (!pkio) {
395
0
        CERT_MapStanError();
396
0
        return NULL;
397
0
    }
398
93.7k
    c = nss_ZNEW(pkio->arena, NSSCertificate);
399
93.7k
    if (!c) {
400
0
        CERT_MapStanError();
401
0
        nssPKIObject_Destroy(pkio);
402
0
        return NULL;
403
0
    }
404
93.7k
    c->object = *pkio;
405
93.7k
    if (copyDER) {
406
93.7k
        nssItem_Create(c->object.arena, &c->encoding, derCert->len,
407
93.7k
                       derCert->data);
408
93.7k
    } else {
409
0
        NSSITEM_FROM_SECITEM(&c->encoding, derCert);
410
0
    }
411
    /* Forces a decoding of the cert in order to obtain the parts used
412
     * below
413
     */
414
    /* 'c' is not adopted here, if we fail loser frees what has been
415
     * allocated so far for 'c' */
416
93.7k
    cc = STAN_GetCERTCertificate(c);
417
93.7k
    if (!cc) {
418
2.18k
        CERT_MapStanError();
419
2.18k
        goto loser;
420
2.18k
    }
421
91.6k
    nssItem_Create(c->object.arena, &c->issuer, cc->derIssuer.len,
422
91.6k
                   cc->derIssuer.data);
423
91.6k
    nssItem_Create(c->object.arena, &c->subject, cc->derSubject.len,
424
91.6k
                   cc->derSubject.data);
425
    /* CERTCertificate stores serial numbers decoded.  I need the DER
426
     * here.  sigh.
427
     */
428
91.6k
    SECItem derSerial = { 0 };
429
91.6k
    CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
430
91.6k
    if (!derSerial.data)
431
0
        goto loser;
432
91.6k
    nssItem_Create(c->object.arena, &c->serial, derSerial.len,
433
91.6k
                   derSerial.data);
434
91.6k
    PORT_Free(derSerial.data);
435
436
91.6k
    if (nickname) {
437
0
        c->object.tempName =
438
0
            nssUTF8_Create(c->object.arena, nssStringType_UTF8String,
439
0
                           (NSSUTF8 *)nickname, PORT_Strlen(nickname));
440
0
    }
441
91.6k
    if (cc->emailAddr && cc->emailAddr[0]) {
442
764
        c->email = nssUTF8_Create(
443
764
            c->object.arena, nssStringType_PrintableString,
444
764
            (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr));
445
764
    }
446
447
91.6k
    tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c);
448
91.6k
    if (!tempCert) {
449
0
        CERT_MapStanError();
450
0
        goto loser;
451
0
    }
452
    /* destroy our copy */
453
91.6k
    NSSCertificate_Destroy(c);
454
    /* and use the stored entry */
455
91.6k
    c = tempCert;
456
91.6k
    cc = STAN_GetCERTCertificateOrRelease(c);
457
91.6k
    if (!cc) {
458
        /* STAN_GetCERTCertificateOrRelease destroys c on failure. */
459
0
        CERT_MapStanError();
460
0
        return NULL;
461
0
    }
462
463
91.6k
    CERT_LockCertTempPerm(cc);
464
91.6k
    cc->istemp = PR_TRUE;
465
91.6k
    cc->isperm = PR_FALSE;
466
91.6k
    CERT_UnlockCertTempPerm(cc);
467
91.6k
    return cc;
468
2.18k
loser:
469
    /* Perhaps this should be nssCertificate_Destroy(c) */
470
2.18k
    nssPKIObject_Destroy(&c->object);
471
2.18k
    return NULL;
472
91.6k
}
473
474
/* This symbol is exported for backward compatibility. */
475
CERTCertificate *
476
__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
477
                          char *nickname, PRBool isperm, PRBool copyDER)
478
0
{
479
0
    return CERT_NewTempCertificate(handle, derCert, nickname, isperm, copyDER);
480
0
}
481
482
static CERTCertificate *
483
common_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
484
                             CERTIssuerAndSN *issuerAndSN,
485
                             void *wincx)
486
0
{
487
0
    PK11SlotInfo *slot;
488
0
    CERTCertificate *cert;
489
490
0
    cert = PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, wincx);
491
0
    if (cert && slot) {
492
0
        PK11_FreeSlot(slot);
493
0
    }
494
495
0
    return cert;
496
0
}
497
498
/* maybe all the wincx's should be some const for internal token login? */
499
CERTCertificate *
500
CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
501
                           CERTIssuerAndSN *issuerAndSN)
502
0
{
503
0
    return common_FindCertByIssuerAndSN(handle, issuerAndSN, NULL);
504
0
}
505
506
/* maybe all the wincx's should be some const for internal token login? */
507
CERTCertificate *
508
CERT_FindCertByIssuerAndSNCX(CERTCertDBHandle *handle,
509
                             CERTIssuerAndSN *issuerAndSN,
510
                             void *wincx)
511
0
{
512
0
    return common_FindCertByIssuerAndSN(handle, issuerAndSN, wincx);
513
0
}
514
515
static NSSCertificate *
516
get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
517
0
{
518
0
    NSSUsage usage;
519
0
    NSSCertificate *arr[3];
520
0
    if (!ct) {
521
0
        return nssCertificate_AddRef(cp);
522
0
    } else if (!cp) {
523
0
        return nssCertificate_AddRef(ct);
524
0
    }
525
0
    arr[0] = ct;
526
0
    arr[1] = cp;
527
0
    arr[2] = NULL;
528
0
    usage.anyUsage = PR_TRUE;
529
0
    return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL);
530
0
}
531
532
CERTCertificate *
533
CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name)
534
0
{
535
0
    NSSCertificate *cp, *ct, *c;
536
0
    NSSDER subject;
537
0
    NSSUsage usage;
538
0
    NSSCryptoContext *cc;
539
0
    NSSITEM_FROM_SECITEM(&subject, name);
540
0
    usage.anyUsage = PR_TRUE;
541
0
    cc = STAN_GetDefaultCryptoContext();
542
0
    ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, NULL,
543
0
                                                       &usage, NULL);
544
0
    cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, NULL,
545
0
                                                     &usage, NULL);
546
0
    c = get_best_temp_or_perm(ct, cp);
547
0
    if (ct) {
548
0
        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
549
0
    }
550
0
    if (cp) {
551
0
        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp));
552
0
    }
553
0
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
554
0
}
555
556
CERTCertificate *
557
CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
558
0
{
559
0
    CERTCertList *list;
560
0
    CERTCertificate *cert = NULL;
561
0
    CERTCertListNode *node;
562
563
0
    list = CERT_CreateSubjectCertList(NULL, handle, name, 0, PR_FALSE);
564
0
    if (list == NULL)
565
0
        return NULL;
566
567
0
    node = CERT_LIST_HEAD(list);
568
0
    while (!CERT_LIST_END(node, list)) {
569
0
        if (node->cert &&
570
0
            SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID)) {
571
0
            cert = CERT_DupCertificate(node->cert);
572
0
            goto done;
573
0
        }
574
0
        node = CERT_LIST_NEXT(node);
575
0
    }
576
0
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
577
578
0
done:
579
0
    CERT_DestroyCertList(list);
580
0
    return cert;
581
0
}
582
583
CERTCertificate *
584
CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname)
585
0
{
586
0
    NSSCryptoContext *cc;
587
0
    NSSCertificate *c, *ct;
588
0
    CERTCertificate *cert;
589
0
    NSSUsage usage;
590
0
    usage.anyUsage = PR_TRUE;
591
0
    cc = STAN_GetDefaultCryptoContext();
592
0
    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, NULL,
593
0
                                                        &usage, NULL);
594
0
    cert = PK11_FindCertFromNickname(nickname, NULL);
595
0
    c = NULL;
596
0
    if (cert) {
597
0
        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
598
0
        CERT_DestroyCertificate(cert);
599
0
        if (ct) {
600
0
            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
601
0
        }
602
0
    } else {
603
0
        c = ct;
604
0
    }
605
0
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
606
0
}
607
608
CERTCertificate *
609
CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
610
0
{
611
0
    NSSCryptoContext *cc;
612
0
    NSSCertificate *c;
613
0
    NSSDER encoding;
614
0
    NSSITEM_FROM_SECITEM(&encoding, derCert);
615
0
    cc = STAN_GetDefaultCryptoContext();
616
0
    c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding);
617
0
    if (!c) {
618
0
        c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
619
0
                                                               &encoding);
620
0
        if (!c)
621
0
            return NULL;
622
0
    }
623
0
    return STAN_GetCERTCertificateOrRelease(c);
624
0
}
625
626
static CERTCertificate *
627
common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
628
                                             const char *name, PRBool anyUsage,
629
                                             SECCertUsage lookingForUsage,
630
                                             void *wincx)
631
0
{
632
0
    NSSCryptoContext *cc;
633
0
    NSSCertificate *c, *ct;
634
0
    CERTCertificate *cert = NULL;
635
0
    NSSUsage usage;
636
0
    CERTCertList *certlist;
637
638
0
    if (NULL == name) {
639
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
640
0
        return NULL;
641
0
    }
642
643
0
    usage.anyUsage = anyUsage;
644
645
0
    if (!anyUsage) {
646
0
        usage.nss3lookingForCA = PR_FALSE;
647
0
        usage.nss3usage = lookingForUsage;
648
0
    }
649
650
0
    cc = STAN_GetDefaultCryptoContext();
651
0
    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, NULL, &usage,
652
0
                                                        NULL);
653
0
    if (!ct && PORT_Strchr(name, '@') != NULL) {
654
0
        char *lowercaseName = CERT_FixupEmailAddr(name);
655
0
        if (lowercaseName) {
656
0
            ct = NSSCryptoContext_FindBestCertificateByEmail(
657
0
                cc, lowercaseName, NULL, &usage, NULL);
658
0
            PORT_Free(lowercaseName);
659
0
        }
660
0
    }
661
662
0
    if (anyUsage) {
663
0
        cert = PK11_FindCertFromNickname(name, wincx);
664
0
    } else {
665
0
        if (ct) {
666
            /* Does ct really have the required usage? */
667
0
            nssDecodedCert *dc;
668
0
            dc = nssCertificate_GetDecoding(ct);
669
0
            if (!dc->matchUsage(dc, &usage)) {
670
0
                CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
671
0
                ct = NULL;
672
0
            }
673
0
        }
674
675
0
        certlist = PK11_FindCertsFromNickname(name, wincx);
676
0
        if (certlist) {
677
0
            SECStatus rv =
678
0
                CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE);
679
0
            if (SECSuccess == rv && !CERT_LIST_EMPTY(certlist)) {
680
0
                cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert);
681
0
            }
682
0
            CERT_DestroyCertList(certlist);
683
0
        }
684
0
    }
685
686
0
    if (cert) {
687
0
        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
688
0
        CERT_DestroyCertificate(cert);
689
0
        if (ct) {
690
0
            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
691
0
        }
692
0
    } else {
693
0
        c = ct;
694
0
    }
695
0
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
696
0
}
697
698
CERTCertificate *
699
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
700
0
{
701
0
    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
702
0
                                                        0, NULL);
703
0
}
704
705
CERTCertificate *
706
CERT_FindCertByNicknameOrEmailAddrCX(CERTCertDBHandle *handle, const char *name,
707
                                     void *wincx)
708
0
{
709
0
    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
710
0
                                                        0, wincx);
711
0
}
712
713
CERTCertificate *
714
CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
715
                                           const char *name,
716
                                           SECCertUsage lookingForUsage)
717
0
{
718
0
    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
719
0
                                                        lookingForUsage, NULL);
720
0
}
721
722
CERTCertificate *
723
CERT_FindCertByNicknameOrEmailAddrForUsageCX(CERTCertDBHandle *handle,
724
                                             const char *name,
725
                                             SECCertUsage lookingForUsage,
726
                                             void *wincx)
727
0
{
728
0
    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
729
0
                                                        lookingForUsage, wincx);
730
0
}
731
732
static void
733
add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
734
                    PRBool validOnly, PRTime sorttime)
735
0
{
736
0
    SECStatus secrv;
737
0
    if (!validOnly ||
738
0
        CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) ==
739
0
            secCertTimeValid) {
740
0
        secrv = CERT_AddCertToListSorted(certList, cert, CERT_SortCBValidity,
741
0
                                         (void *)&sorttime);
742
0
        if (secrv != SECSuccess) {
743
0
            CERT_DestroyCertificate(cert);
744
0
        }
745
0
    } else {
746
0
        CERT_DestroyCertificate(cert);
747
0
    }
748
0
}
749
750
CERTCertList *
751
CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle,
752
                           const SECItem *name, PRTime sorttime,
753
                           PRBool validOnly)
754
0
{
755
0
    NSSCryptoContext *cc;
756
0
    NSSCertificate **tSubjectCerts, **pSubjectCerts;
757
0
    NSSCertificate **ci;
758
0
    CERTCertificate *cert;
759
0
    NSSDER subject;
760
0
    PRBool myList = PR_FALSE;
761
0
    cc = STAN_GetDefaultCryptoContext();
762
0
    NSSITEM_FROM_SECITEM(&subject, name);
763
    /* Collect both temp and perm certs for the subject */
764
0
    tSubjectCerts =
765
0
        NSSCryptoContext_FindCertificatesBySubject(cc, &subject, NULL, 0, NULL);
766
0
    pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, &subject,
767
0
                                                             NULL, 0, NULL);
768
0
    if (!tSubjectCerts && !pSubjectCerts) {
769
0
        return NULL;
770
0
    }
771
0
    if (certList == NULL) {
772
0
        certList = CERT_NewCertList();
773
0
        myList = PR_TRUE;
774
0
        if (!certList)
775
0
            goto loser;
776
0
    }
777
    /* Iterate over the matching temp certs.  Add them to the list */
778
0
    ci = tSubjectCerts;
779
0
    while (ci && *ci) {
780
0
        cert = STAN_GetCERTCertificateOrRelease(*ci);
781
        /* *ci may be invalid at this point, don't reference it again */
782
0
        if (cert) {
783
            /* NOTE: add_to_subject_list adopts the incoming cert. */
784
0
            add_to_subject_list(certList, cert, validOnly, sorttime);
785
0
        }
786
0
        ci++;
787
0
    }
788
    /* Iterate over the matching perm certs.  Add them to the list */
789
0
    ci = pSubjectCerts;
790
0
    while (ci && *ci) {
791
0
        cert = STAN_GetCERTCertificateOrRelease(*ci);
792
        /* *ci may be invalid at this point, don't reference it again */
793
0
        if (cert) {
794
            /* NOTE: add_to_subject_list adopts the incoming cert. */
795
0
            add_to_subject_list(certList, cert, validOnly, sorttime);
796
0
        }
797
0
        ci++;
798
0
    }
799
    /* all the references have been adopted or freed at this point, just
800
     * free the arrays now */
801
0
    nss_ZFreeIf(tSubjectCerts);
802
0
    nss_ZFreeIf(pSubjectCerts);
803
0
    return certList;
804
0
loser:
805
    /* need to free the references in tSubjectCerts and pSubjectCerts! */
806
0
    nssCertificateArray_Destroy(tSubjectCerts);
807
0
    nssCertificateArray_Destroy(pSubjectCerts);
808
0
    if (myList && certList != NULL) {
809
0
        CERT_DestroyCertList(certList);
810
0
    }
811
0
    return NULL;
812
0
}
813
814
void
815
CERT_DestroyCertificate(CERTCertificate *cert)
816
466k
{
817
466k
    if (cert) {
818
        /* don't use STAN_GetNSSCertificate because we don't want to
819
         * go to the trouble of translating the CERTCertificate into
820
         * an NSSCertificate just to destroy it.  If it hasn't been done
821
         * yet, don't do it at all
822
         *
823
         * cert->nssCertificate contains its own locks and refcount, but as it
824
         * may be NULL, the pointer itself must be guarded by some other lock.
825
         * Rather than creating a new global lock for only this purpose, share
826
         * an existing global lock that happens to be taken near the write in
827
         * fill_CERTCertificateFields(). The longer-term goal is to refactor
828
         * all these global locks to be certificate-scoped. */
829
465k
        CERT_MaybeLockCertTempPerm(cert);
830
465k
        NSSCertificate *tmp = cert->nssCertificate;
831
465k
        CERT_MaybeUnlockCertTempPerm(cert);
832
465k
        if (tmp) {
833
            /* delete the NSSCertificate */
834
465k
            NSSCertificate_Destroy(tmp);
835
465k
        } else if (cert->arena) {
836
0
            PORT_FreeArena(cert->arena, PR_FALSE);
837
0
        }
838
465k
    }
839
466k
    return;
840
466k
}
841
842
int
843
CERT_GetDBContentVersion(CERTCertDBHandle *handle)
844
0
{
845
    /* should read the DB content version from the pkcs #11 device */
846
0
    return 0;
847
0
}
848
849
SECStatus
850
certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr,
851
                         SECItem *emailProfile, SECItem *profileTime)
852
0
{
853
0
    PRTime oldtime;
854
0
    PRTime newtime;
855
0
    SECStatus rv = SECFailure;
856
0
    PRBool saveit;
857
0
    SECItem oldprof, oldproftime;
858
0
    SECItem *oldProfile = NULL;
859
0
    SECItem *oldProfileTime = NULL;
860
0
    PK11SlotInfo *slot = NULL;
861
0
    NSSCertificate *c;
862
0
    NSSCryptoContext *cc;
863
0
    nssSMIMEProfile *stanProfile = NULL;
864
0
    PRBool freeOldProfile = PR_FALSE;
865
866
0
    c = STAN_GetNSSCertificate(cert);
867
0
    if (!c)
868
0
        return SECFailure;
869
0
    cc = c->object.cryptoContext;
870
0
    if (cc != NULL) {
871
0
        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
872
0
        if (stanProfile) {
873
0
            PORT_Assert(stanProfile->profileData);
874
0
            SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData);
875
0
            oldProfile = &oldprof;
876
0
            SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime);
877
0
            oldProfileTime = &oldproftime;
878
0
        }
879
0
    } else {
880
0
        oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr,
881
0
                                           &cert->derSubject, &oldProfileTime);
882
0
        freeOldProfile = PR_TRUE;
883
0
    }
884
885
0
    saveit = PR_FALSE;
886
887
    /* both profileTime and emailProfile have to exist or not exist */
888
0
    if (emailProfile == NULL) {
889
0
        profileTime = NULL;
890
0
    } else if (profileTime == NULL) {
891
0
        emailProfile = NULL;
892
0
    }
893
894
0
    if (oldProfileTime == NULL) {
895
0
        saveit = PR_TRUE;
896
0
    } else {
897
        /* there was already a profile for this email addr */
898
0
        if (profileTime) {
899
            /* we have an old and new profile - save whichever is more recent*/
900
0
            if (oldProfileTime->len == 0) {
901
                /* always replace if old entry doesn't have a time */
902
0
                oldtime = LL_MININT;
903
0
            } else {
904
0
                rv = DER_UTCTimeToTime(&oldtime, oldProfileTime);
905
0
                if (rv != SECSuccess) {
906
0
                    goto loser;
907
0
                }
908
0
            }
909
910
0
            rv = DER_UTCTimeToTime(&newtime, profileTime);
911
0
            if (rv != SECSuccess) {
912
0
                goto loser;
913
0
            }
914
915
0
            if (LL_CMP(newtime, >, oldtime)) {
916
                /* this is a newer profile, save it and cert */
917
0
                saveit = PR_TRUE;
918
0
            }
919
0
        } else {
920
0
            saveit = PR_TRUE;
921
0
        }
922
0
    }
923
924
0
    if (saveit) {
925
0
        if (cc) {
926
0
            if (stanProfile && profileTime && emailProfile) {
927
                /* stanProfile is already stored in the crypto context,
928
                 * overwrite the data
929
                 */
930
0
                NSSArena *arena = stanProfile->object.arena;
931
0
                stanProfile->profileTime = nssItem_Create(
932
0
                    arena, NULL, profileTime->len, profileTime->data);
933
0
                stanProfile->profileData = nssItem_Create(
934
0
                    arena, NULL, emailProfile->len, emailProfile->data);
935
0
            } else if (profileTime && emailProfile) {
936
0
                PRStatus nssrv;
937
0
                NSSItem profTime, profData;
938
0
                NSSITEM_FROM_SECITEM(&profTime, profileTime);
939
0
                NSSITEM_FROM_SECITEM(&profData, emailProfile);
940
0
                stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData);
941
0
                if (!stanProfile)
942
0
                    goto loser;
943
0
                nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile);
944
0
                rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
945
0
            }
946
0
        } else {
947
0
            rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr,
948
0
                                       &cert->derSubject, emailProfile,
949
0
                                       profileTime);
950
0
        }
951
0
    } else {
952
0
        rv = SECSuccess;
953
0
    }
954
955
0
loser:
956
0
    if (oldProfile && freeOldProfile) {
957
0
        SECITEM_FreeItem(oldProfile, PR_TRUE);
958
0
    }
959
0
    if (oldProfileTime && freeOldProfile) {
960
0
        SECITEM_FreeItem(oldProfileTime, PR_TRUE);
961
0
    }
962
0
    if (stanProfile) {
963
0
        nssSMIMEProfile_Destroy(stanProfile);
964
0
    }
965
0
    if (slot) {
966
0
        PK11_FreeSlot(slot);
967
0
    }
968
969
0
    return (rv);
970
0
}
971
972
/*
973
 *
974
 * Manage S/MIME profiles
975
 *
976
 */
977
978
SECStatus
979
CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile,
980
                      SECItem *profileTime)
981
0
{
982
0
    const char *emailAddr;
983
0
    SECStatus rv;
984
0
    PRBool isperm = PR_FALSE;
985
986
0
    if (!cert) {
987
0
        return SECFailure;
988
0
    }
989
990
0
    if (cert->slot && !PK11_IsInternal(cert->slot)) {
991
        /* this cert comes from an external source, we need to add it
992
        to the cert db before creating an S/MIME profile */
993
0
        PK11SlotInfo *internalslot = PK11_GetInternalKeySlot();
994
0
        if (!internalslot) {
995
0
            return SECFailure;
996
0
        }
997
0
        rv = PK11_ImportCert(internalslot, cert, CK_INVALID_HANDLE, NULL,
998
0
                             PR_FALSE);
999
1000
0
        PK11_FreeSlot(internalslot);
1001
0
        if (rv != SECSuccess) {
1002
0
            return SECFailure;
1003
0
        }
1004
0
    }
1005
1006
0
    rv = CERT_GetCertIsPerm(cert, &isperm);
1007
0
    if (rv != SECSuccess) {
1008
0
        return SECFailure;
1009
0
    }
1010
0
    if (cert->slot && isperm && CERT_IsUserCert(cert) &&
1011
0
        (!emailProfile || !emailProfile->len)) {
1012
        /* Don't clobber emailProfile for user certs. */
1013
0
        return SECSuccess;
1014
0
    }
1015
1016
0
    for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL;
1017
0
         emailAddr = CERT_GetNextEmailAddress(cert, emailAddr)) {
1018
0
        rv = certdb_SaveSingleProfile(cert, emailAddr, emailProfile,
1019
0
                                      profileTime);
1020
0
        if (rv != SECSuccess) {
1021
0
            return SECFailure;
1022
0
        }
1023
0
    }
1024
0
    return SECSuccess;
1025
0
}
1026
1027
SECItem *
1028
CERT_FindSMimeProfile(CERTCertificate *cert)
1029
0
{
1030
0
    PK11SlotInfo *slot = NULL;
1031
0
    NSSCertificate *c;
1032
0
    NSSCryptoContext *cc;
1033
0
    SECItem *rvItem = NULL;
1034
1035
0
    if (!cert || !cert->emailAddr || !cert->emailAddr[0]) {
1036
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1037
0
        return NULL;
1038
0
    }
1039
0
    c = STAN_GetNSSCertificate(cert);
1040
0
    if (!c)
1041
0
        return NULL;
1042
0
    cc = c->object.cryptoContext;
1043
0
    if (cc != NULL) {
1044
0
        nssSMIMEProfile *stanProfile;
1045
0
        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
1046
0
        if (stanProfile) {
1047
0
            if (stanProfile->profileData) {
1048
0
                rvItem =
1049
0
                    SECITEM_AllocItem(NULL, NULL,
1050
0
                                      stanProfile->profileData->size);
1051
0
                if (rvItem) {
1052
0
                    PORT_Memcpy(rvItem->data,
1053
0
                                stanProfile->profileData->data,
1054
0
                                stanProfile->profileData->size);
1055
0
                }
1056
0
            }
1057
0
            nssSMIMEProfile_Destroy(stanProfile);
1058
0
        }
1059
0
        return rvItem;
1060
0
    }
1061
0
    rvItem =
1062
0
        PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL);
1063
0
    if (slot) {
1064
0
        PK11_FreeSlot(slot);
1065
0
    }
1066
0
    return rvItem;
1067
0
}
1068
1069
SECStatus
1070
CERT_GetCertIsPerm(const CERTCertificate *cert, PRBool *isperm)
1071
0
{
1072
0
    if (cert == NULL) {
1073
0
        return SECFailure;
1074
0
    }
1075
1076
0
    CERT_LockCertTempPerm(cert);
1077
0
    *isperm = cert->isperm;
1078
0
    CERT_UnlockCertTempPerm(cert);
1079
0
    return SECSuccess;
1080
0
}
1081
1082
SECStatus
1083
CERT_GetCertIsTemp(const CERTCertificate *cert, PRBool *istemp)
1084
0
{
1085
0
    if (cert == NULL) {
1086
0
        return SECFailure;
1087
0
    }
1088
1089
0
    CERT_LockCertTempPerm(cert);
1090
0
    *istemp = cert->istemp;
1091
0
    CERT_UnlockCertTempPerm(cert);
1092
0
    return SECSuccess;
1093
0
}
1094
1095
/*
1096
 * deprecated functions that are now just stubs.
1097
 */
1098
/*
1099
 * Close the database
1100
 */
1101
void
1102
__CERT_ClosePermCertDB(CERTCertDBHandle *handle)
1103
0
{
1104
0
    PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL);
1105
0
    return;
1106
0
}
1107
1108
SECStatus
1109
CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname,
1110
                        PRBool readOnly)
1111
0
{
1112
0
    PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL);
1113
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1114
0
    return SECFailure;
1115
0
}
1116
1117
SECItem *
1118
SECKEY_HashPassword(char *pw, SECItem *salt)
1119
0
{
1120
0
    PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL);
1121
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1122
0
    return NULL;
1123
0
}
1124
1125
SECStatus
1126
__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle,
1127
                                   SECItem *derSubject, void *cb, void *cbarg)
1128
0
{
1129
0
    PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL);
1130
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1131
0
    return SECFailure;
1132
0
}
1133
1134
SECStatus
1135
__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname,
1136
                                    void *cb, void *cbarg)
1137
0
{
1138
0
    PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL);
1139
0
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1140
0
    return SECFailure;
1141
0
}