Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / certdb / stanpcertdb.c
blobc2fa9de616150cd45580a5df529f39f94c797258
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "prtime.h"
39 #include "cert.h"
40 #include "mcom_db.h"
41 #include "certdb.h"
42 #include "secitem.h"
43 #include "secder.h"
45 /* Call to PK11_FreeSlot below */
47 #include "secasn1.h"
48 #include "secerr.h"
49 #include "nssilock.h"
50 #include "prmon.h"
51 #include "nsslocks.h"
52 #include "base64.h"
53 #include "sechash.h"
54 #include "plhash.h"
55 #include "pk11func.h" /* sigh */
57 #ifndef NSS_3_4_CODE
58 #define NSS_3_4_CODE
59 #endif /* NSS_3_4_CODE */
60 #include "nsspki.h"
61 #include "pki.h"
62 #include "pkim.h"
63 #include "pki3hack.h"
64 #include "ckhelper.h"
65 #include "base.h"
66 #include "pkistore.h"
67 #include "dev3hack.h"
68 #include "dev.h"
70 PRBool
71 SEC_CertNicknameConflict(char *nickname, SECItem *derSubject,
72 CERTCertDBHandle *handle)
74 CERTCertificate *cert;
75 PRBool conflict = PR_FALSE;
77 cert=CERT_FindCertByNickname(handle, nickname);
79 if (!cert) {
80 return conflict;
83 conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject);
84 CERT_DestroyCertificate(cert);
85 return conflict;
88 SECStatus
89 SEC_DeletePermCertificate(CERTCertificate *cert)
91 PRStatus nssrv;
92 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
93 NSSCertificate *c = STAN_GetNSSCertificate(cert);
95 if (c == NULL) {
96 /* error code is set */
97 return SECFailure;
100 /* get rid of the token instances */
101 nssrv = NSSCertificate_DeleteStoredObject(c, NULL);
103 /* get rid of the cache entry */
104 nssTrustDomain_LockCertCache(td);
105 nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
106 nssTrustDomain_UnlockCertCache(td);
108 return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
111 SECStatus
112 CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust)
114 SECStatus rv;
115 CERT_LockCertTrust(cert);
116 if ( cert->trust == NULL ) {
117 rv = SECFailure;
118 } else {
119 *trust = *cert->trust;
120 rv = SECSuccess;
122 CERT_UnlockCertTrust(cert);
123 return(rv);
126 #ifdef notdef
127 static char *
128 cert_parseNickname(char *nickname)
130 char *cp;
131 for (cp=nickname; *cp && *cp != ':'; cp++);
132 if (*cp == ':') return cp+1;
133 return nickname;
135 #endif
137 SECStatus
138 CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
139 CERTCertTrust *trust)
141 SECStatus rv = SECFailure;
142 PRStatus ret;
144 CERT_LockCertTrust(cert);
145 ret = STAN_ChangeCertTrust(cert, trust);
146 rv = (ret == PR_SUCCESS) ? SECSuccess : SECFailure;
147 CERT_UnlockCertTrust(cert);
148 return rv;
151 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
153 SECStatus
154 __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
155 CERTCertTrust *trust)
157 NSSUTF8 *stanNick;
158 PK11SlotInfo *slot;
159 NSSToken *internal;
160 NSSCryptoContext *context;
161 nssCryptokiObject *permInstance;
162 NSSCertificate *c = STAN_GetNSSCertificate(cert);
163 nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
164 nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
166 if (c == NULL) {
167 /* error code is set */
168 return SECFailure;
171 context = c->object.cryptoContext;
172 if (!context) {
173 PORT_SetError(SEC_ERROR_ADDING_CERT);
174 return SECFailure; /* wasn't a temp cert */
176 stanNick = nssCertificate_GetNickname(c, NULL);
177 if (stanNick && nickname && strcmp(nickname, stanNick) != 0) {
178 /* take the new nickname */
179 cert->nickname = NULL;
180 stanNick = NULL;
182 if (!stanNick && nickname) {
183 stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, c->object.arena);
185 /* Delete the temp instance */
186 nssCertificateStore_Lock(context->certStore, &lockTrace);
187 nssCertificateStore_RemoveCertLOCKED(context->certStore, c);
188 nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace);
189 nssCertificateStore_Check(&lockTrace, &unlockTrace);
190 c->object.cryptoContext = NULL;
191 /* Import the perm instance onto the internal token */
192 slot = PK11_GetInternalKeySlot();
193 internal = PK11Slot_GetNSSToken(slot);
194 permInstance = nssToken_ImportCertificate(internal, NULL,
195 NSSCertificateType_PKIX,
196 &c->id,
197 stanNick,
198 &c->encoding,
199 &c->issuer,
200 &c->subject,
201 &c->serial,
202 cert->emailAddr,
203 PR_TRUE);
204 PK11_FreeSlot(slot);
205 if (!permInstance) {
206 if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) {
207 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
209 return SECFailure;
211 nssPKIObject_AddInstance(&c->object, permInstance);
212 nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
213 /* reset the CERTCertificate fields */
214 cert->nssCertificate = NULL;
215 cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */
216 if (!cert) {
217 return SECFailure;
219 cert->istemp = PR_FALSE;
220 cert->isperm = PR_TRUE;
221 if (!trust) {
222 return SECSuccess;
224 return (STAN_ChangeCertTrust(cert, trust) == PR_SUCCESS) ?
225 SECSuccess: SECFailure;
228 SECStatus
229 CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
230 CERTCertTrust *trust)
232 return __CERT_AddTempCertToPerm(cert, nickname, trust);
235 CERTCertificate *
236 __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
237 char *nickname, PRBool isperm, PRBool copyDER)
239 PRStatus nssrv;
240 NSSCertificate *c;
241 CERTCertificate *cc;
242 NSSCertificate *tempCert = NULL;
243 nssPKIObject *pkio;
244 NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext();
245 NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain();
246 if (!isperm) {
247 NSSDER encoding;
248 NSSITEM_FROM_SECITEM(&encoding, derCert);
249 /* First, see if it is already a temp cert */
250 c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC,
251 &encoding);
252 if (!c) {
253 /* Then, see if it is already a perm cert */
254 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
255 &encoding);
257 if (c) {
258 /* actually, that search ends up going by issuer/serial,
259 * so it is still possible to return a cert with the same
260 * issuer/serial but a different encoding, and we're
261 * going to reject that
263 if (!nssItem_Equal(&c->encoding, &encoding, NULL)) {
264 nssCertificate_Destroy(c);
265 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
266 cc = NULL;
267 } else {
268 cc = STAN_GetCERTCertificateOrRelease(c);
270 return cc;
273 pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor);
274 if (!pkio) {
275 return NULL;
277 c = nss_ZNEW(pkio->arena, NSSCertificate);
278 if (!c) {
279 nssPKIObject_Destroy(pkio);
280 return NULL;
282 c->object = *pkio;
283 if (copyDER) {
284 nssItem_Create(c->object.arena, &c->encoding,
285 derCert->len, derCert->data);
286 } else {
287 NSSITEM_FROM_SECITEM(&c->encoding, derCert);
289 /* Forces a decoding of the cert in order to obtain the parts used
290 * below
292 /* 'c' is not adopted here, if we fail loser frees what has been
293 * allocated so far for 'c' */
294 cc = STAN_GetCERTCertificate(c);
295 if (!cc) {
296 goto loser;
298 nssItem_Create(c->object.arena,
299 &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
300 nssItem_Create(c->object.arena,
301 &c->subject, cc->derSubject.len, cc->derSubject.data);
302 if (PR_TRUE) {
303 /* CERTCertificate stores serial numbers decoded. I need the DER
304 * here. sigh.
306 SECItem derSerial = { 0 };
307 CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
308 if (!derSerial.data) goto loser;
309 nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data);
310 PORT_Free(derSerial.data);
312 if (nickname) {
313 c->object.tempName = nssUTF8_Create(c->object.arena,
314 nssStringType_UTF8String,
315 (NSSUTF8 *)nickname,
316 PORT_Strlen(nickname));
318 if (cc->emailAddr && cc->emailAddr[0]) {
319 c->email = nssUTF8_Create(c->object.arena,
320 nssStringType_PrintableString,
321 (NSSUTF8 *)cc->emailAddr,
322 PORT_Strlen(cc->emailAddr));
325 tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c);
326 if (!tempCert) {
327 goto loser;
329 /* destroy our copy */
330 NSSCertificate_Destroy(c);
331 /* and use the stored entry */
332 c = tempCert;
333 cc = STAN_GetCERTCertificateOrRelease(c);
334 if (!cc) {
335 /* STAN_GetCERTCertificateOrRelease destroys c on failure. */
336 return NULL;
339 cc->istemp = PR_TRUE;
340 cc->isperm = PR_FALSE;
341 return cc;
342 loser:
343 /* Perhaps this should be nssCertificate_Destroy(c) */
344 nssPKIObject_Destroy(&c->object);
345 return NULL;
348 CERTCertificate *
349 CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
350 char *nickname, PRBool isperm, PRBool copyDER)
352 return( __CERT_NewTempCertificate(handle, derCert, nickname,
353 isperm, copyDER) );
356 /* maybe all the wincx's should be some const for internal token login? */
357 CERTCertificate *
358 CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN)
360 PK11SlotInfo *slot;
361 CERTCertificate *cert;
363 cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL);
364 if (cert && slot) {
365 PK11_FreeSlot(slot);
368 return cert;
371 static NSSCertificate *
372 get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
374 NSSUsage usage;
375 NSSCertificate *arr[3];
376 if (!ct) {
377 return nssCertificate_AddRef(cp);
378 } else if (!cp) {
379 return nssCertificate_AddRef(ct);
381 arr[0] = ct;
382 arr[1] = cp;
383 arr[2] = NULL;
384 usage.anyUsage = PR_TRUE;
385 return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL);
388 CERTCertificate *
389 CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name)
391 NSSCertificate *cp, *ct, *c;
392 NSSDER subject;
393 NSSUsage usage;
394 NSSCryptoContext *cc;
395 NSSITEM_FROM_SECITEM(&subject, name);
396 usage.anyUsage = PR_TRUE;
397 cc = STAN_GetDefaultCryptoContext();
398 ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject,
399 NULL, &usage, NULL);
400 cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject,
401 NULL, &usage, NULL);
402 c = get_best_temp_or_perm(ct, cp);
403 if (ct) {
404 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
406 if (cp) {
407 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp));
409 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
412 CERTCertificate *
413 CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
415 CERTCertList *list;
416 CERTCertificate *cert = NULL;
417 CERTCertListNode *node, *head;
419 list = CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE);
420 if (list == NULL) return NULL;
422 node = head = CERT_LIST_HEAD(list);
423 if (head) {
424 do {
425 if (node->cert &&
426 SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID) ) {
427 cert = CERT_DupCertificate(node->cert);
428 goto done;
430 node = CERT_LIST_NEXT(node);
431 } while (node && head != node);
433 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
434 done:
435 if (list) {
436 CERT_DestroyCertList(list);
438 return cert;
441 CERTCertificate *
442 CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname)
444 NSSCryptoContext *cc;
445 NSSCertificate *c, *ct;
446 CERTCertificate *cert;
447 NSSUsage usage;
448 usage.anyUsage = PR_TRUE;
449 cc = STAN_GetDefaultCryptoContext();
450 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname,
451 NULL, &usage, NULL);
452 cert = PK11_FindCertFromNickname(nickname, NULL);
453 c = NULL;
454 if (cert) {
455 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
456 CERT_DestroyCertificate(cert);
457 if (ct) {
458 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
460 } else {
461 c = ct;
463 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
466 CERTCertificate *
467 CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
469 NSSCryptoContext *cc;
470 NSSCertificate *c;
471 NSSDER encoding;
472 NSSITEM_FROM_SECITEM(&encoding, derCert);
473 cc = STAN_GetDefaultCryptoContext();
474 c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding);
475 if (!c) {
476 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
477 &encoding);
478 if (!c) return NULL;
480 return STAN_GetCERTCertificateOrRelease(c);
483 CERTCertificate *
484 CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *name)
486 NSSCryptoContext *cc;
487 NSSCertificate *c, *ct;
488 CERTCertificate *cert;
489 NSSUsage usage;
491 if (NULL == name) {
492 PORT_SetError(SEC_ERROR_INVALID_ARGS);
493 return NULL;
495 usage.anyUsage = PR_TRUE;
496 cc = STAN_GetDefaultCryptoContext();
497 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name,
498 NULL, &usage, NULL);
499 if (!ct && PORT_Strchr(name, '@') != NULL) {
500 char* lowercaseName = CERT_FixupEmailAddr(name);
501 if (lowercaseName) {
502 ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName,
503 NULL, &usage, NULL);
504 PORT_Free(lowercaseName);
507 cert = PK11_FindCertFromNickname(name, NULL);
508 if (cert) {
509 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
510 CERT_DestroyCertificate(cert);
511 if (ct) {
512 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
514 } else {
515 c = ct;
517 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
520 static void
521 add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
522 PRBool validOnly, int64 sorttime)
524 SECStatus secrv;
525 if (!validOnly ||
526 CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE)
527 == secCertTimeValid) {
528 secrv = CERT_AddCertToListSorted(certList, cert,
529 CERT_SortCBValidity,
530 (void *)&sorttime);
531 if (secrv != SECSuccess) {
532 CERT_DestroyCertificate(cert);
534 } else {
535 CERT_DestroyCertificate(cert);
539 CERTCertList *
540 CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle,
541 SECItem *name, int64 sorttime, PRBool validOnly)
543 NSSCryptoContext *cc;
544 NSSCertificate **tSubjectCerts, **pSubjectCerts;
545 NSSCertificate **ci;
546 CERTCertificate *cert;
547 NSSDER subject;
548 PRBool myList = PR_FALSE;
549 cc = STAN_GetDefaultCryptoContext();
550 NSSITEM_FROM_SECITEM(&subject, name);
551 /* Collect both temp and perm certs for the subject */
552 tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc,
553 &subject,
554 NULL,
556 NULL);
557 pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle,
558 &subject,
559 NULL,
561 NULL);
562 if (!tSubjectCerts && !pSubjectCerts) {
563 return NULL;
565 if (certList == NULL) {
566 certList = CERT_NewCertList();
567 myList = PR_TRUE;
568 if (!certList) goto loser;
570 /* Iterate over the matching temp certs. Add them to the list */
571 ci = tSubjectCerts;
572 while (ci && *ci) {
573 cert = STAN_GetCERTCertificateOrRelease(*ci);
574 /* *ci may be invalid at this point, don't reference it again */
575 if (cert) {
576 /* NOTE: add_to_subject_list adopts the incoming cert. */
577 add_to_subject_list(certList, cert, validOnly, sorttime);
579 ci++;
581 /* Iterate over the matching perm certs. Add them to the list */
582 ci = pSubjectCerts;
583 while (ci && *ci) {
584 cert = STAN_GetCERTCertificateOrRelease(*ci);
585 /* *ci may be invalid at this point, don't reference it again */
586 if (cert) {
587 /* NOTE: add_to_subject_list adopts the incoming cert. */
588 add_to_subject_list(certList, cert, validOnly, sorttime);
590 ci++;
592 /* all the references have been adopted or freed at this point, just
593 * free the arrays now */
594 nss_ZFreeIf(tSubjectCerts);
595 nss_ZFreeIf(pSubjectCerts);
596 return certList;
597 loser:
598 /* need to free the references in tSubjectCerts and pSubjectCerts! */
599 nssCertificateArray_Destroy(tSubjectCerts);
600 nssCertificateArray_Destroy(pSubjectCerts);
601 if (myList && certList != NULL) {
602 CERT_DestroyCertList(certList);
604 return NULL;
607 void
608 CERT_DestroyCertificate(CERTCertificate *cert)
610 if ( cert ) {
611 /* don't use STAN_GetNSSCertificate because we don't want to
612 * go to the trouble of translating the CERTCertificate into
613 * an NSSCertificate just to destroy it. If it hasn't been done
614 * yet, don't do it at all.
616 NSSCertificate *tmp = cert->nssCertificate;
617 if (tmp) {
618 /* delete the NSSCertificate */
619 NSSCertificate_Destroy(tmp);
620 } else if (cert->arena) {
621 PORT_FreeArena(cert->arena, PR_FALSE);
624 return;
627 #ifdef notdef
628 SECStatus
629 CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb,
630 CERTCertificate *cert, SECCertUsage usage)
632 SECStatus rv;
633 CERTCertTrust trust;
634 CERTCertTrust tmptrust;
635 unsigned int certtype;
636 PRBool saveit;
638 saveit = PR_TRUE;
640 PORT_Memset((void *)&trust, 0, sizeof(trust));
642 certtype = cert->nsCertType;
644 /* if no app bits in cert type, then set all app bits */
645 if ( ! ( certtype & NS_CERT_TYPE_APP ) ) {
646 certtype |= NS_CERT_TYPE_APP;
649 switch ( usage ) {
650 case certUsageEmailSigner:
651 case certUsageEmailRecipient:
652 if ( certtype & NS_CERT_TYPE_EMAIL ) {
653 trust.emailFlags = CERTDB_VALID_PEER;
654 if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) {
655 /* don't save it if KeyEncipherment is not allowed */
656 saveit = PR_FALSE;
659 break;
660 case certUsageUserCertImport:
661 if ( certtype & NS_CERT_TYPE_EMAIL ) {
662 trust.emailFlags = CERTDB_VALID_PEER;
664 /* VALID_USER is already set if the cert was imported,
665 * in the case that the cert was already in the database
666 * through SMIME or other means, we should set the USER
667 * flags, if they are not already set.
669 if( cert->isperm ) {
670 if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) {
671 if( !(cert->trust->sslFlags & CERTDB_USER) ) {
672 trust.sslFlags |= CERTDB_USER;
676 if ( certtype & NS_CERT_TYPE_EMAIL ) {
677 if( !(cert->trust->emailFlags & CERTDB_USER) ) {
678 trust.emailFlags |= CERTDB_USER;
682 if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) {
683 if( !(cert->trust->objectSigningFlags & CERTDB_USER) ) {
684 trust.objectSigningFlags |= CERTDB_USER;
688 break;
689 default: /* XXX added to quiet warnings; no other cases needed? */
690 break;
693 if ( (trust.sslFlags | trust.emailFlags | trust.objectSigningFlags) == 0 ){
694 saveit = PR_FALSE;
697 if ( saveit && cert->isperm ) {
698 /* Cert already in the DB. Just adjust flags */
699 tmptrust = *cert->trust;
700 tmptrust.sslFlags |= trust.sslFlags;
701 tmptrust.emailFlags |= trust.emailFlags;
702 tmptrust.objectSigningFlags |= trust.objectSigningFlags;
704 rv = CERT_ChangeCertTrust(cert->dbhandle, cert,
705 &tmptrust);
706 if ( rv != SECSuccess ) {
707 goto loser;
711 rv = SECSuccess;
712 goto done;
714 loser:
715 rv = SECFailure;
716 done:
718 return(rv);
720 #endif
723 CERT_GetDBContentVersion(CERTCertDBHandle *handle)
725 /* should read the DB content version from the pkcs #11 device */
726 return 0;
729 SECStatus
730 certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr,
731 SECItem *emailProfile, SECItem *profileTime)
733 int64 oldtime;
734 int64 newtime;
735 SECStatus rv = SECFailure;
736 PRBool saveit;
737 SECItem oldprof, oldproftime;
738 SECItem *oldProfile = NULL;
739 SECItem *oldProfileTime = NULL;
740 PK11SlotInfo *slot = NULL;
741 NSSCertificate *c;
742 NSSCryptoContext *cc;
743 nssSMIMEProfile *stanProfile = NULL;
744 PRBool freeOldProfile = PR_FALSE;
746 c = STAN_GetNSSCertificate(cert);
747 if (!c) return SECFailure;
748 cc = c->object.cryptoContext;
749 if (cc != NULL) {
750 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
751 if (stanProfile) {
752 PORT_Assert(stanProfile->profileData);
753 SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData);
754 oldProfile = &oldprof;
755 SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime);
756 oldProfileTime = &oldproftime;
758 } else {
759 oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr,
760 &cert->derSubject, &oldProfileTime);
761 freeOldProfile = PR_TRUE;
764 saveit = PR_FALSE;
766 /* both profileTime and emailProfile have to exist or not exist */
767 if ( emailProfile == NULL ) {
768 profileTime = NULL;
769 } else if ( profileTime == NULL ) {
770 emailProfile = NULL;
773 if ( oldProfileTime == NULL ) {
774 saveit = PR_TRUE;
775 } else {
776 /* there was already a profile for this email addr */
777 if ( profileTime ) {
778 /* we have an old and new profile - save whichever is more recent*/
779 if ( oldProfileTime->len == 0 ) {
780 /* always replace if old entry doesn't have a time */
781 oldtime = LL_MININT;
782 } else {
783 rv = DER_UTCTimeToTime(&oldtime, oldProfileTime);
784 if ( rv != SECSuccess ) {
785 goto loser;
789 rv = DER_UTCTimeToTime(&newtime, profileTime);
790 if ( rv != SECSuccess ) {
791 goto loser;
794 if ( LL_CMP(newtime, >, oldtime ) ) {
795 /* this is a newer profile, save it and cert */
796 saveit = PR_TRUE;
798 } else {
799 saveit = PR_TRUE;
804 if (saveit) {
805 if (cc) {
806 if (stanProfile) {
807 /* stanProfile is already stored in the crypto context,
808 * overwrite the data
810 NSSArena *arena = stanProfile->object.arena;
811 stanProfile->profileTime = nssItem_Create(arena,
812 NULL,
813 profileTime->len,
814 profileTime->data);
815 stanProfile->profileData = nssItem_Create(arena,
816 NULL,
817 emailProfile->len,
818 emailProfile->data);
819 } else if (profileTime && emailProfile) {
820 PRStatus nssrv;
821 NSSItem profTime, profData;
822 NSSITEM_FROM_SECITEM(&profTime, profileTime);
823 NSSITEM_FROM_SECITEM(&profData, emailProfile);
824 stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData);
825 if (!stanProfile) goto loser;
826 nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile);
827 rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
829 } else {
830 rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr,
831 &cert->derSubject, emailProfile, profileTime);
833 } else {
834 rv = SECSuccess;
837 loser:
838 if (oldProfile && freeOldProfile) {
839 SECITEM_FreeItem(oldProfile,PR_TRUE);
841 if (oldProfileTime && freeOldProfile) {
842 SECITEM_FreeItem(oldProfileTime,PR_TRUE);
844 if (stanProfile) {
845 nssSMIMEProfile_Destroy(stanProfile);
847 if (slot) {
848 PK11_FreeSlot(slot);
851 return(rv);
856 * Manage S/MIME profiles
860 SECStatus
861 CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile,
862 SECItem *profileTime)
864 const char *emailAddr;
865 SECStatus rv;
867 if (!cert) {
868 return SECFailure;
871 if (cert->slot && !PK11_IsInternal(cert->slot)) {
872 /* this cert comes from an external source, we need to add it
873 to the cert db before creating an S/MIME profile */
874 PK11SlotInfo* internalslot = PK11_GetInternalKeySlot();
875 if (!internalslot) {
876 return SECFailure;
878 rv = PK11_ImportCert(internalslot, cert,
879 CK_INVALID_HANDLE, NULL, PR_FALSE);
881 PK11_FreeSlot(internalslot);
882 if (rv != SECSuccess ) {
883 return SECFailure;
888 for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL;
889 emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) {
890 rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime);
891 if (rv != SECSuccess) {
892 return SECFailure;
895 return SECSuccess;
900 SECItem *
901 CERT_FindSMimeProfile(CERTCertificate *cert)
903 PK11SlotInfo *slot = NULL;
904 NSSCertificate *c;
905 NSSCryptoContext *cc;
906 SECItem *rvItem = NULL;
908 if (!cert || !cert->emailAddr || !cert->emailAddr[0]) {
909 PORT_SetError(SEC_ERROR_INVALID_ARGS);
910 return NULL;
912 c = STAN_GetNSSCertificate(cert);
913 if (!c) return NULL;
914 cc = c->object.cryptoContext;
915 if (cc != NULL) {
916 nssSMIMEProfile *stanProfile;
917 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
918 if (stanProfile) {
919 rvItem = SECITEM_AllocItem(NULL, NULL,
920 stanProfile->profileData->size);
921 if (rvItem) {
922 rvItem->data = stanProfile->profileData->data;
924 nssSMIMEProfile_Destroy(stanProfile);
926 return rvItem;
928 rvItem =
929 PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL);
930 if (slot) {
931 PK11_FreeSlot(slot);
933 return rvItem;
937 * depricated functions that are now just stubs.
940 * Close the database
942 void
943 __CERT_ClosePermCertDB(CERTCertDBHandle *handle)
945 PORT_Assert("CERT_ClosePermCertDB is Depricated" == NULL);
946 return;
949 SECStatus
950 CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname,
951 PRBool readOnly)
953 PORT_Assert("CERT_OpenCertDBFilename is Depricated" == NULL);
954 return SECFailure;
957 SECItem *
958 SECKEY_HashPassword(char *pw, SECItem *salt)
960 PORT_Assert("SECKEY_HashPassword is Depricated" == NULL);
961 return NULL;
964 SECStatus
965 __CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle,
966 SECItem *derSubject,
967 void *cb, void *cbarg)
969 PORT_Assert("CERT_TraversePermCertsForSubject is Depricated" == NULL);
970 return SECFailure;
974 SECStatus
975 __CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname,
976 void *cb, void *cbarg)
978 PORT_Assert("CERT_TraversePermCertsForNickname is Depricated" == NULL);
979 return SECFailure;