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

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

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

Powered by Google App Engine
This is Rietveld 408576698