comparison nss/lib/certdb/stanpcertdb.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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
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.data);
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 *issuerAndSN)
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, PRTime 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 const SECItem *name, PRTime sorttime,
716 PRBool validOnly)
717 {
718 NSSCryptoContext *cc;
719 NSSCertificate **tSubjectCerts, **pSubjectCerts;
720 NSSCertificate **ci;
721 CERTCertificate *cert;
722 NSSDER subject;
723 PRBool myList = PR_FALSE;
724 cc = STAN_GetDefaultCryptoContext();
725 NSSITEM_FROM_SECITEM(&subject, name);
726 /* Collect both temp and perm certs for the subject */
727 tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc,
728 &subject,
729 NULL,
730 0,
731 NULL);
732 pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle,
733 &subject,
734 NULL,
735 0,
736 NULL);
737 if (!tSubjectCerts && !pSubjectCerts) {
738 return NULL;
739 }
740 if (certList == NULL) {
741 certList = CERT_NewCertList();
742 myList = PR_TRUE;
743 if (!certList) goto loser;
744 }
745 /* Iterate over the matching temp certs. Add them to the list */
746 ci = tSubjectCerts;
747 while (ci && *ci) {
748 cert = STAN_GetCERTCertificateOrRelease(*ci);
749 /* *ci may be invalid at this point, don't reference it again */
750 if (cert) {
751 /* NOTE: add_to_subject_list adopts the incoming cert. */
752 add_to_subject_list(certList, cert, validOnly, sorttime);
753 }
754 ci++;
755 }
756 /* Iterate over the matching perm certs. Add them to the list */
757 ci = pSubjectCerts;
758 while (ci && *ci) {
759 cert = STAN_GetCERTCertificateOrRelease(*ci);
760 /* *ci may be invalid at this point, don't reference it again */
761 if (cert) {
762 /* NOTE: add_to_subject_list adopts the incoming cert. */
763 add_to_subject_list(certList, cert, validOnly, sorttime);
764 }
765 ci++;
766 }
767 /* all the references have been adopted or freed at this point, just
768 * free the arrays now */
769 nss_ZFreeIf(tSubjectCerts);
770 nss_ZFreeIf(pSubjectCerts);
771 return certList;
772 loser:
773 /* need to free the references in tSubjectCerts and pSubjectCerts! */
774 nssCertificateArray_Destroy(tSubjectCerts);
775 nssCertificateArray_Destroy(pSubjectCerts);
776 if (myList && certList != NULL) {
777 CERT_DestroyCertList(certList);
778 }
779 return NULL;
780 }
781
782 void
783 CERT_DestroyCertificate(CERTCertificate *cert)
784 {
785 if ( cert ) {
786 /* don't use STAN_GetNSSCertificate because we don't want to
787 * go to the trouble of translating the CERTCertificate into
788 * an NSSCertificate just to destroy it. If it hasn't been done
789 * yet, don't do it at all.
790 */
791 NSSCertificate *tmp = cert->nssCertificate;
792 if (tmp) {
793 /* delete the NSSCertificate */
794 NSSCertificate_Destroy(tmp);
795 } else if (cert->arena) {
796 PORT_FreeArena(cert->arena, PR_FALSE);
797 }
798 }
799 return;
800 }
801
802 int
803 CERT_GetDBContentVersion(CERTCertDBHandle *handle)
804 {
805 /* should read the DB content version from the pkcs #11 device */
806 return 0;
807 }
808
809 SECStatus
810 certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr,
811 SECItem *emailProfile, SECItem *profileTime)
812 {
813 PRTime oldtime;
814 PRTime newtime;
815 SECStatus rv = SECFailure;
816 PRBool saveit;
817 SECItem oldprof, oldproftime;
818 SECItem *oldProfile = NULL;
819 SECItem *oldProfileTime = NULL;
820 PK11SlotInfo *slot = NULL;
821 NSSCertificate *c;
822 NSSCryptoContext *cc;
823 nssSMIMEProfile *stanProfile = NULL;
824 PRBool freeOldProfile = PR_FALSE;
825
826 c = STAN_GetNSSCertificate(cert);
827 if (!c) return SECFailure;
828 cc = c->object.cryptoContext;
829 if (cc != NULL) {
830 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
831 if (stanProfile) {
832 PORT_Assert(stanProfile->profileData);
833 SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData);
834 oldProfile = &oldprof;
835 SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime);
836 oldProfileTime = &oldproftime;
837 }
838 } else {
839 oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr,
840 &cert->derSubject, &oldProfileTime);
841 freeOldProfile = PR_TRUE;
842 }
843
844 saveit = PR_FALSE;
845
846 /* both profileTime and emailProfile have to exist or not exist */
847 if ( emailProfile == NULL ) {
848 profileTime = NULL;
849 } else if ( profileTime == NULL ) {
850 emailProfile = NULL;
851 }
852
853 if ( oldProfileTime == NULL ) {
854 saveit = PR_TRUE;
855 } else {
856 /* there was already a profile for this email addr */
857 if ( profileTime ) {
858 /* we have an old and new profile - save whichever is more recent*/
859 if ( oldProfileTime->len == 0 ) {
860 /* always replace if old entry doesn't have a time */
861 oldtime = LL_MININT;
862 } else {
863 rv = DER_UTCTimeToTime(&oldtime, oldProfileTime);
864 if ( rv != SECSuccess ) {
865 goto loser;
866 }
867 }
868
869 rv = DER_UTCTimeToTime(&newtime, profileTime);
870 if ( rv != SECSuccess ) {
871 goto loser;
872 }
873
874 if ( LL_CMP(newtime, >, oldtime ) ) {
875 /* this is a newer profile, save it and cert */
876 saveit = PR_TRUE;
877 }
878 } else {
879 saveit = PR_TRUE;
880 }
881 }
882
883
884 if (saveit) {
885 if (cc) {
886 if (stanProfile) {
887 /* stanProfile is already stored in the crypto context,
888 * overwrite the data
889 */
890 NSSArena *arena = stanProfile->object.arena;
891 stanProfile->profileTime = nssItem_Create(arena,
892 NULL,
893 profileTime->len,
894 profileTime->data);
895 stanProfile->profileData = nssItem_Create(arena,
896 NULL,
897 emailProfile->len,
898 emailProfile->data);
899 } else if (profileTime && emailProfile) {
900 PRStatus nssrv;
901 NSSItem profTime, profData;
902 NSSITEM_FROM_SECITEM(&profTime, profileTime);
903 NSSITEM_FROM_SECITEM(&profData, emailProfile);
904 stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData);
905 if (!stanProfile) goto loser;
906 nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile);
907 rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
908 }
909 } else {
910 rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr,
911 &cert->derSubject, emailProfile, profileTime);
912 }
913 } else {
914 rv = SECSuccess;
915 }
916
917 loser:
918 if (oldProfile && freeOldProfile) {
919 SECITEM_FreeItem(oldProfile,PR_TRUE);
920 }
921 if (oldProfileTime && freeOldProfile) {
922 SECITEM_FreeItem(oldProfileTime,PR_TRUE);
923 }
924 if (stanProfile) {
925 nssSMIMEProfile_Destroy(stanProfile);
926 }
927 if (slot) {
928 PK11_FreeSlot(slot);
929 }
930
931 return(rv);
932 }
933
934 /*
935 *
936 * Manage S/MIME profiles
937 *
938 */
939
940 SECStatus
941 CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile,
942 SECItem *profileTime)
943 {
944 const char *emailAddr;
945 SECStatus rv;
946
947 if (!cert) {
948 return SECFailure;
949 }
950
951 if (cert->slot && !PK11_IsInternal(cert->slot)) {
952 /* this cert comes from an external source, we need to add it
953 to the cert db before creating an S/MIME profile */
954 PK11SlotInfo* internalslot = PK11_GetInternalKeySlot();
955 if (!internalslot) {
956 return SECFailure;
957 }
958 rv = PK11_ImportCert(internalslot, cert,
959 CK_INVALID_HANDLE, NULL, PR_FALSE);
960
961 PK11_FreeSlot(internalslot);
962 if (rv != SECSuccess ) {
963 return SECFailure;
964 }
965 }
966
967 if (cert->slot && cert->isperm && CERT_IsUserCert(cert) &&
968 (!emailProfile || !emailProfile->len)) {
969 /* Don't clobber emailProfile for user certs. */
970 return SECSuccess;
971 }
972
973 for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL;
974 emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) {
975 rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime);
976 if (rv != SECSuccess) {
977 return SECFailure;
978 }
979 }
980 return SECSuccess;
981
982 }
983
984
985 SECItem *
986 CERT_FindSMimeProfile(CERTCertificate *cert)
987 {
988 PK11SlotInfo *slot = NULL;
989 NSSCertificate *c;
990 NSSCryptoContext *cc;
991 SECItem *rvItem = NULL;
992
993 if (!cert || !cert->emailAddr || !cert->emailAddr[0]) {
994 PORT_SetError(SEC_ERROR_INVALID_ARGS);
995 return NULL;
996 }
997 c = STAN_GetNSSCertificate(cert);
998 if (!c) return NULL;
999 cc = c->object.cryptoContext;
1000 if (cc != NULL) {
1001 nssSMIMEProfile *stanProfile;
1002 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
1003 if (stanProfile) {
1004 rvItem = SECITEM_AllocItem(NULL, NULL,
1005 stanProfile->profileData->size);
1006 if (rvItem) {
1007 rvItem->data = stanProfile->profileData->data;
1008 }
1009 nssSMIMEProfile_Destroy(stanProfile);
1010 }
1011 return rvItem;
1012 }
1013 rvItem =
1014 PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL);
1015 if (slot) {
1016 PK11_FreeSlot(slot);
1017 }
1018 return rvItem;
1019 }
1020
1021 /*
1022 * deprecated functions that are now just stubs.
1023 */
1024 /*
1025 * Close the database
1026 */
1027 void
1028 __CERT_ClosePermCertDB(CERTCertDBHandle *handle)
1029 {
1030 PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL);
1031 return;
1032 }
1033
1034 SECStatus
1035 CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname,
1036 PRBool readOnly)
1037 {
1038 PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL);
1039 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1040 return SECFailure;
1041 }
1042
1043 SECItem *
1044 SECKEY_HashPassword(char *pw, SECItem *salt)
1045 {
1046 PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL);
1047 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1048 return NULL;
1049 }
1050
1051 SECStatus
1052 __CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle,
1053 SECItem *derSubject,
1054 void *cb, void *cbarg)
1055 {
1056 PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL);
1057 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1058 return SECFailure;
1059 }
1060
1061
1062 SECStatus
1063 __CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname,
1064 void *cb, void *cbarg)
1065 {
1066 PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL);
1067 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1068 return SECFailure;
1069 }
1070
1071
1072
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)