Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: nss/lib/certdb/stanpcertdb.c

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

Powered by Google App Engine
This is Rietveld 408576698