Index: mozilla/security/nss/lib/certdb/stanpcertdb.c |
=================================================================== |
--- mozilla/security/nss/lib/certdb/stanpcertdb.c (revision 191424) |
+++ mozilla/security/nss/lib/certdb/stanpcertdb.c (working copy) |
@@ -1,1071 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-#include "prtime.h" |
- |
-#include "cert.h" |
-#include "certi.h" |
-#include "certdb.h" |
-#include "secitem.h" |
-#include "secder.h" |
- |
-/* Call to PK11_FreeSlot below */ |
- |
-#include "secasn1.h" |
-#include "secerr.h" |
-#include "nssilock.h" |
-#include "prmon.h" |
-#include "base64.h" |
-#include "sechash.h" |
-#include "plhash.h" |
-#include "pk11func.h" /* sigh */ |
- |
-#include "nsspki.h" |
-#include "pki.h" |
-#include "pkim.h" |
-#include "pki3hack.h" |
-#include "ckhelper.h" |
-#include "base.h" |
-#include "pkistore.h" |
-#include "dev3hack.h" |
-#include "dev.h" |
- |
-PRBool |
-SEC_CertNicknameConflict(const char *nickname, SECItem *derSubject, |
- CERTCertDBHandle *handle) |
-{ |
- CERTCertificate *cert; |
- PRBool conflict = PR_FALSE; |
- |
- cert=CERT_FindCertByNickname(handle, nickname); |
- |
- if (!cert) { |
- return conflict; |
- } |
- |
- conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject); |
- CERT_DestroyCertificate(cert); |
- return conflict; |
-} |
- |
-SECStatus |
-SEC_DeletePermCertificate(CERTCertificate *cert) |
-{ |
- PRStatus nssrv; |
- NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); |
- NSSCertificate *c = STAN_GetNSSCertificate(cert); |
- CERTCertTrust *certTrust; |
- |
- if (c == NULL) { |
- /* error code is set */ |
- return SECFailure; |
- } |
- |
- certTrust = nssTrust_GetCERTCertTrustForCert(c, cert); |
- if (certTrust) { |
- NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); |
- if (nssTrust) { |
- nssrv = STAN_DeleteCertTrustMatchingSlot(c); |
- if (nssrv != PR_SUCCESS) { |
- CERT_MapStanError(); |
- } |
- /* This call always returns PR_SUCCESS! */ |
- (void) nssTrust_Destroy(nssTrust); |
- } |
- } |
- |
- /* get rid of the token instances */ |
- nssrv = NSSCertificate_DeleteStoredObject(c, NULL); |
- |
- /* get rid of the cache entry */ |
- nssTrustDomain_LockCertCache(td); |
- nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); |
- nssTrustDomain_UnlockCertCache(td); |
- |
- return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; |
-} |
- |
-SECStatus |
-CERT_GetCertTrust(CERTCertificate *cert, CERTCertTrust *trust) |
-{ |
- SECStatus rv; |
- CERT_LockCertTrust(cert); |
- if ( cert->trust == NULL ) { |
- rv = SECFailure; |
- } else { |
- *trust = *cert->trust; |
- rv = SECSuccess; |
- } |
- CERT_UnlockCertTrust(cert); |
- return(rv); |
-} |
- |
-extern const NSSError NSS_ERROR_NO_ERROR; |
-extern const NSSError NSS_ERROR_INTERNAL_ERROR; |
-extern const NSSError NSS_ERROR_NO_MEMORY; |
-extern const NSSError NSS_ERROR_INVALID_POINTER; |
-extern const NSSError NSS_ERROR_INVALID_ARENA; |
-extern const NSSError NSS_ERROR_INVALID_ARENA_MARK; |
-extern const NSSError NSS_ERROR_DUPLICATE_POINTER; |
-extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED; |
-extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY; |
-extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED; |
-extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD; |
-extern const NSSError NSS_ERROR_VALUE_TOO_LARGE; |
-extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE; |
-extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT; |
-extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT; |
-extern const NSSError NSS_ERROR_INVALID_BASE64; |
-extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT; |
-extern const NSSError NSS_ERROR_INVALID_ITEM; |
-extern const NSSError NSS_ERROR_INVALID_STRING; |
-extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER; |
-extern const NSSError NSS_ERROR_INVALID_ASN1DECODER; |
-extern const NSSError NSS_ERROR_INVALID_BER; |
-extern const NSSError NSS_ERROR_INVALID_ATAV; |
-extern const NSSError NSS_ERROR_INVALID_ARGUMENT; |
-extern const NSSError NSS_ERROR_INVALID_UTF8; |
-extern const NSSError NSS_ERROR_INVALID_NSSOID; |
-extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE; |
-extern const NSSError NSS_ERROR_NOT_FOUND; |
-extern const NSSError NSS_ERROR_INVALID_PASSWORD; |
-extern const NSSError NSS_ERROR_USER_CANCELED; |
-extern const NSSError NSS_ERROR_MAXIMUM_FOUND; |
-extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND; |
-extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; |
-extern const NSSError NSS_ERROR_HASH_COLLISION; |
-extern const NSSError NSS_ERROR_DEVICE_ERROR; |
-extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; |
-extern const NSSError NSS_ERROR_BUSY; |
-extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; |
-extern const NSSError NSS_ERROR_PKCS11; |
- |
- |
-/* Look at the stan error stack and map it to NSS 3 errors */ |
-#define STAN_MAP_ERROR(x,y) \ |
- else if (error == (x)) { \ |
- secError = y; \ |
- } \ |
- |
-/* |
- * map Stan errors into NSS errors |
- * This function examines the stan error stack and automatically sets |
- * PORT_SetError(); to the appropriate SEC_ERROR value. |
- */ |
-void |
-CERT_MapStanError() |
-{ |
- PRInt32 *errorStack; |
- NSSError error, prevError; |
- int secError; |
- int i; |
- |
- error = 0; |
- |
- errorStack = NSS_GetErrorStack(); |
- if (errorStack == 0) { |
- PORT_SetError(0); |
- return; |
- } |
- error = prevError = CKR_GENERAL_ERROR; |
- /* get the 'top 2' error codes from the stack */ |
- for (i=0; errorStack[i]; i++) { |
- prevError = error; |
- error = errorStack[i]; |
- } |
- if (error == NSS_ERROR_PKCS11) { |
- /* map it */ |
- secError = PK11_MapError(prevError); |
- } |
- STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0) |
- STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD,SEC_ERROR_BAD_PASSWORD) |
- STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY) |
- STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO) |
- STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND, |
- SEC_ERROR_UNKNOWN_ISSUER) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA) |
- |
- /* these are library failure for lack of a better error code */ |
- STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, |
- SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, |
- SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD, |
- SEC_ERROR_LIBRARY_FAILURE) |
- STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE) |
- |
- STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE) |
- |
- /* these are all invalid arguments */ |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS) |
- STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS) |
- else { |
- secError = SEC_ERROR_LIBRARY_FAILURE; |
- } |
- PORT_SetError(secError); |
-} |
- |
- |
- |
-SECStatus |
-CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, |
- CERTCertTrust *trust) |
-{ |
- SECStatus rv = SECSuccess; |
- PRStatus ret; |
- |
- ret = STAN_ChangeCertTrust(cert, trust); |
- if (ret != PR_SUCCESS) { |
- rv = SECFailure; |
- CERT_MapStanError(); |
- } |
- return rv; |
-} |
- |
-extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; |
- |
-SECStatus |
-__CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, |
- CERTCertTrust *trust) |
-{ |
- NSSUTF8 *stanNick; |
- PK11SlotInfo *slot; |
- NSSToken *internal; |
- NSSCryptoContext *context; |
- nssCryptokiObject *permInstance; |
- NSSCertificate *c = STAN_GetNSSCertificate(cert); |
- nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; |
- nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; |
- SECStatus rv; |
- PRStatus ret; |
- |
- if (c == NULL) { |
- CERT_MapStanError(); |
- return SECFailure; |
- } |
- |
- context = c->object.cryptoContext; |
- if (!context) { |
- PORT_SetError(SEC_ERROR_ADDING_CERT); |
- return SECFailure; /* wasn't a temp cert */ |
- } |
- stanNick = nssCertificate_GetNickname(c, NULL); |
- if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { |
- /* different: take the new nickname */ |
- cert->nickname = NULL; |
- nss_ZFreeIf(stanNick); |
- stanNick = NULL; |
- } |
- if (!stanNick && nickname) { |
- /* Either there was no nickname yet, or we have a new nickname */ |
- stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL); |
- } /* else: old stanNick is identical to new nickname */ |
- /* Delete the temp instance */ |
- nssCertificateStore_Lock(context->certStore, &lockTrace); |
- nssCertificateStore_RemoveCertLOCKED(context->certStore, c); |
- nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); |
- c->object.cryptoContext = NULL; |
- /* Import the perm instance onto the internal token */ |
- slot = PK11_GetInternalKeySlot(); |
- internal = PK11Slot_GetNSSToken(slot); |
- permInstance = nssToken_ImportCertificate(internal, NULL, |
- NSSCertificateType_PKIX, |
- &c->id, |
- stanNick, |
- &c->encoding, |
- &c->issuer, |
- &c->subject, |
- &c->serial, |
- cert->emailAddr, |
- PR_TRUE); |
- nss_ZFreeIf(stanNick); |
- stanNick = NULL; |
- PK11_FreeSlot(slot); |
- if (!permInstance) { |
- if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { |
- PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); |
- } |
- return SECFailure; |
- } |
- nssPKIObject_AddInstance(&c->object, permInstance); |
- nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); |
- /* reset the CERTCertificate fields */ |
- cert->nssCertificate = NULL; |
- cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */ |
- if (!cert) { |
- CERT_MapStanError(); |
- return SECFailure; |
- } |
- cert->istemp = PR_FALSE; |
- cert->isperm = PR_TRUE; |
- if (!trust) { |
- return SECSuccess; |
- } |
- ret = STAN_ChangeCertTrust(cert, trust); |
- rv = SECSuccess; |
- if (ret != PR_SUCCESS) { |
- rv = SECFailure; |
- CERT_MapStanError(); |
- } |
- return rv; |
-} |
- |
-SECStatus |
-CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, |
- CERTCertTrust *trust) |
-{ |
- return __CERT_AddTempCertToPerm(cert, nickname, trust); |
-} |
- |
-CERTCertificate * |
-CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, |
- char *nickname, PRBool isperm, PRBool copyDER) |
-{ |
- NSSCertificate *c; |
- CERTCertificate *cc; |
- NSSCertificate *tempCert = NULL; |
- nssPKIObject *pkio; |
- NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); |
- NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); |
- if (!isperm) { |
- NSSDER encoding; |
- NSSITEM_FROM_SECITEM(&encoding, derCert); |
- /* First, see if it is already a temp cert */ |
- c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, |
- &encoding); |
- if (!c) { |
- /* Then, see if it is already a perm cert */ |
- c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, |
- &encoding); |
- } |
- if (c) { |
- /* actually, that search ends up going by issuer/serial, |
- * so it is still possible to return a cert with the same |
- * issuer/serial but a different encoding, and we're |
- * going to reject that |
- */ |
- if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { |
- nssCertificate_Destroy(c); |
- PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); |
- cc = NULL; |
- } else { |
- cc = STAN_GetCERTCertificateOrRelease(c); |
- if (cc == NULL) { |
- CERT_MapStanError(); |
- } |
- } |
- return cc; |
- } |
- } |
- pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); |
- if (!pkio) { |
- CERT_MapStanError(); |
- return NULL; |
- } |
- c = nss_ZNEW(pkio->arena, NSSCertificate); |
- if (!c) { |
- CERT_MapStanError(); |
- nssPKIObject_Destroy(pkio); |
- return NULL; |
- } |
- c->object = *pkio; |
- if (copyDER) { |
- nssItem_Create(c->object.arena, &c->encoding, |
- derCert->len, derCert->data); |
- } else { |
- NSSITEM_FROM_SECITEM(&c->encoding, derCert); |
- } |
- /* Forces a decoding of the cert in order to obtain the parts used |
- * below |
- */ |
- /* 'c' is not adopted here, if we fail loser frees what has been |
- * allocated so far for 'c' */ |
- cc = STAN_GetCERTCertificate(c); |
- if (!cc) { |
- CERT_MapStanError(); |
- goto loser; |
- } |
- nssItem_Create(c->object.arena, |
- &c->issuer, cc->derIssuer.len, cc->derIssuer.data); |
- nssItem_Create(c->object.arena, |
- &c->subject, cc->derSubject.len, cc->derSubject.data); |
- if (PR_TRUE) { |
- /* CERTCertificate stores serial numbers decoded. I need the DER |
- * here. sigh. |
- */ |
- SECItem derSerial = { 0 }; |
- CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); |
- if (!derSerial.data) goto loser; |
- nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); |
- PORT_Free(derSerial.data); |
- } |
- if (nickname) { |
- c->object.tempName = nssUTF8_Create(c->object.arena, |
- nssStringType_UTF8String, |
- (NSSUTF8 *)nickname, |
- PORT_Strlen(nickname)); |
- } |
- if (cc->emailAddr && cc->emailAddr[0]) { |
- c->email = nssUTF8_Create(c->object.arena, |
- nssStringType_PrintableString, |
- (NSSUTF8 *)cc->emailAddr, |
- PORT_Strlen(cc->emailAddr)); |
- } |
- |
- tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); |
- if (!tempCert) { |
- CERT_MapStanError(); |
- goto loser; |
- } |
- /* destroy our copy */ |
- NSSCertificate_Destroy(c); |
- /* and use the stored entry */ |
- c = tempCert; |
- cc = STAN_GetCERTCertificateOrRelease(c); |
- if (!cc) { |
- /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ |
- CERT_MapStanError(); |
- return NULL; |
- } |
- |
- cc->istemp = PR_TRUE; |
- cc->isperm = PR_FALSE; |
- return cc; |
-loser: |
- /* Perhaps this should be nssCertificate_Destroy(c) */ |
- nssPKIObject_Destroy(&c->object); |
- return NULL; |
-} |
- |
-/* This symbol is exported for backward compatibility. */ |
-CERTCertificate * |
-__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, |
- char *nickname, PRBool isperm, PRBool copyDER) |
-{ |
- return CERT_NewTempCertificate(handle, derCert, nickname, |
- isperm, copyDER); |
-} |
- |
-/* maybe all the wincx's should be some const for internal token login? */ |
-CERTCertificate * |
-CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN) |
-{ |
- PK11SlotInfo *slot; |
- CERTCertificate *cert; |
- |
- cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL); |
- if (cert && slot) { |
- PK11_FreeSlot(slot); |
- } |
- |
- return cert; |
-} |
- |
-static NSSCertificate * |
-get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp) |
-{ |
- NSSUsage usage; |
- NSSCertificate *arr[3]; |
- if (!ct) { |
- return nssCertificate_AddRef(cp); |
- } else if (!cp) { |
- return nssCertificate_AddRef(ct); |
- } |
- arr[0] = ct; |
- arr[1] = cp; |
- arr[2] = NULL; |
- usage.anyUsage = PR_TRUE; |
- return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL); |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) |
-{ |
- NSSCertificate *cp, *ct, *c; |
- NSSDER subject; |
- NSSUsage usage; |
- NSSCryptoContext *cc; |
- NSSITEM_FROM_SECITEM(&subject, name); |
- usage.anyUsage = PR_TRUE; |
- cc = STAN_GetDefaultCryptoContext(); |
- ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, |
- NULL, &usage, NULL); |
- cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, |
- NULL, &usage, NULL); |
- c = get_best_temp_or_perm(ct, cp); |
- if (ct) { |
- CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); |
- } |
- if (cp) { |
- CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp)); |
- } |
- return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) |
-{ |
- CERTCertList *list; |
- CERTCertificate *cert = NULL; |
- CERTCertListNode *node, *head; |
- |
- list = CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); |
- if (list == NULL) return NULL; |
- |
- node = head = CERT_LIST_HEAD(list); |
- if (head) { |
- do { |
- if (node->cert && |
- SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID) ) { |
- cert = CERT_DupCertificate(node->cert); |
- goto done; |
- } |
- node = CERT_LIST_NEXT(node); |
- } while (node && head != node); |
- } |
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
-done: |
- if (list) { |
- CERT_DestroyCertList(list); |
- } |
- return cert; |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname) |
-{ |
- NSSCryptoContext *cc; |
- NSSCertificate *c, *ct; |
- CERTCertificate *cert; |
- NSSUsage usage; |
- usage.anyUsage = PR_TRUE; |
- cc = STAN_GetDefaultCryptoContext(); |
- ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, |
- NULL, &usage, NULL); |
- cert = PK11_FindCertFromNickname(nickname, NULL); |
- c = NULL; |
- if (cert) { |
- c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); |
- CERT_DestroyCertificate(cert); |
- if (ct) { |
- CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); |
- } |
- } else { |
- c = ct; |
- } |
- return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) |
-{ |
- NSSCryptoContext *cc; |
- NSSCertificate *c; |
- NSSDER encoding; |
- NSSITEM_FROM_SECITEM(&encoding, derCert); |
- cc = STAN_GetDefaultCryptoContext(); |
- c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); |
- if (!c) { |
- c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, |
- &encoding); |
- if (!c) return NULL; |
- } |
- return STAN_GetCERTCertificateOrRelease(c); |
-} |
- |
-static CERTCertificate * |
-common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, |
- const char *name, |
- PRBool anyUsage, |
- SECCertUsage lookingForUsage) |
-{ |
- NSSCryptoContext *cc; |
- NSSCertificate *c, *ct; |
- CERTCertificate *cert = NULL; |
- NSSUsage usage; |
- CERTCertList *certlist; |
- |
- if (NULL == name) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- usage.anyUsage = anyUsage; |
- |
- if (!anyUsage) { |
- usage.nss3lookingForCA = PR_FALSE; |
- usage.nss3usage = lookingForUsage; |
- } |
- |
- cc = STAN_GetDefaultCryptoContext(); |
- ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, |
- NULL, &usage, NULL); |
- if (!ct && PORT_Strchr(name, '@') != NULL) { |
- char* lowercaseName = CERT_FixupEmailAddr(name); |
- if (lowercaseName) { |
- ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, |
- NULL, &usage, NULL); |
- PORT_Free(lowercaseName); |
- } |
- } |
- |
- if (anyUsage) { |
- cert = PK11_FindCertFromNickname(name, NULL); |
- } |
- else { |
- if (ct) { |
- /* Does ct really have the required usage? */ |
- nssDecodedCert *dc; |
- dc = nssCertificate_GetDecoding(ct); |
- if (!dc->matchUsage(dc, &usage)) { |
- CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); |
- ct = NULL; |
- } |
- } |
- |
- certlist = PK11_FindCertsFromNickname(name, NULL); |
- if (certlist) { |
- SECStatus rv = CERT_FilterCertListByUsage(certlist, |
- lookingForUsage, |
- PR_FALSE); |
- if (SECSuccess == rv && |
- !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { |
- cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert); |
- } |
- CERT_DestroyCertList(certlist); |
- } |
- } |
- |
- if (cert) { |
- c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); |
- CERT_DestroyCertificate(cert); |
- if (ct) { |
- CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); |
- } |
- } else { |
- c = ct; |
- } |
- return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name) |
-{ |
- return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, |
- PR_TRUE, 0); |
-} |
- |
-CERTCertificate * |
-CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, |
- const char *name, |
- SECCertUsage lookingForUsage) |
-{ |
- return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, |
- PR_FALSE, |
- lookingForUsage); |
-} |
- |
-static void |
-add_to_subject_list(CERTCertList *certList, CERTCertificate *cert, |
- PRBool validOnly, int64 sorttime) |
-{ |
- SECStatus secrv; |
- if (!validOnly || |
- CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) |
- == secCertTimeValid) { |
- secrv = CERT_AddCertToListSorted(certList, cert, |
- CERT_SortCBValidity, |
- (void *)&sorttime); |
- if (secrv != SECSuccess) { |
- CERT_DestroyCertificate(cert); |
- } |
- } else { |
- CERT_DestroyCertificate(cert); |
- } |
-} |
- |
-CERTCertList * |
-CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, |
- SECItem *name, int64 sorttime, PRBool validOnly) |
-{ |
- NSSCryptoContext *cc; |
- NSSCertificate **tSubjectCerts, **pSubjectCerts; |
- NSSCertificate **ci; |
- CERTCertificate *cert; |
- NSSDER subject; |
- PRBool myList = PR_FALSE; |
- cc = STAN_GetDefaultCryptoContext(); |
- NSSITEM_FROM_SECITEM(&subject, name); |
- /* Collect both temp and perm certs for the subject */ |
- tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc, |
- &subject, |
- NULL, |
- 0, |
- NULL); |
- pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, |
- &subject, |
- NULL, |
- 0, |
- NULL); |
- if (!tSubjectCerts && !pSubjectCerts) { |
- return NULL; |
- } |
- if (certList == NULL) { |
- certList = CERT_NewCertList(); |
- myList = PR_TRUE; |
- if (!certList) goto loser; |
- } |
- /* Iterate over the matching temp certs. Add them to the list */ |
- ci = tSubjectCerts; |
- while (ci && *ci) { |
- cert = STAN_GetCERTCertificateOrRelease(*ci); |
- /* *ci may be invalid at this point, don't reference it again */ |
- if (cert) { |
- /* NOTE: add_to_subject_list adopts the incoming cert. */ |
- add_to_subject_list(certList, cert, validOnly, sorttime); |
- } |
- ci++; |
- } |
- /* Iterate over the matching perm certs. Add them to the list */ |
- ci = pSubjectCerts; |
- while (ci && *ci) { |
- cert = STAN_GetCERTCertificateOrRelease(*ci); |
- /* *ci may be invalid at this point, don't reference it again */ |
- if (cert) { |
- /* NOTE: add_to_subject_list adopts the incoming cert. */ |
- add_to_subject_list(certList, cert, validOnly, sorttime); |
- } |
- ci++; |
- } |
- /* all the references have been adopted or freed at this point, just |
- * free the arrays now */ |
- nss_ZFreeIf(tSubjectCerts); |
- nss_ZFreeIf(pSubjectCerts); |
- return certList; |
-loser: |
- /* need to free the references in tSubjectCerts and pSubjectCerts! */ |
- nssCertificateArray_Destroy(tSubjectCerts); |
- nssCertificateArray_Destroy(pSubjectCerts); |
- if (myList && certList != NULL) { |
- CERT_DestroyCertList(certList); |
- } |
- return NULL; |
-} |
- |
-void |
-CERT_DestroyCertificate(CERTCertificate *cert) |
-{ |
- if ( cert ) { |
- /* don't use STAN_GetNSSCertificate because we don't want to |
- * go to the trouble of translating the CERTCertificate into |
- * an NSSCertificate just to destroy it. If it hasn't been done |
- * yet, don't do it at all. |
- */ |
- NSSCertificate *tmp = cert->nssCertificate; |
- if (tmp) { |
- /* delete the NSSCertificate */ |
- NSSCertificate_Destroy(tmp); |
- } else if (cert->arena) { |
- PORT_FreeArena(cert->arena, PR_FALSE); |
- } |
- } |
- return; |
-} |
- |
-int |
-CERT_GetDBContentVersion(CERTCertDBHandle *handle) |
-{ |
- /* should read the DB content version from the pkcs #11 device */ |
- return 0; |
-} |
- |
-SECStatus |
-certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr, |
- SECItem *emailProfile, SECItem *profileTime) |
-{ |
- int64 oldtime; |
- int64 newtime; |
- SECStatus rv = SECFailure; |
- PRBool saveit; |
- SECItem oldprof, oldproftime; |
- SECItem *oldProfile = NULL; |
- SECItem *oldProfileTime = NULL; |
- PK11SlotInfo *slot = NULL; |
- NSSCertificate *c; |
- NSSCryptoContext *cc; |
- nssSMIMEProfile *stanProfile = NULL; |
- PRBool freeOldProfile = PR_FALSE; |
- |
- c = STAN_GetNSSCertificate(cert); |
- if (!c) return SECFailure; |
- cc = c->object.cryptoContext; |
- if (cc != NULL) { |
- stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); |
- if (stanProfile) { |
- PORT_Assert(stanProfile->profileData); |
- SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData); |
- oldProfile = &oldprof; |
- SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime); |
- oldProfileTime = &oldproftime; |
- } |
- } else { |
- oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr, |
- &cert->derSubject, &oldProfileTime); |
- freeOldProfile = PR_TRUE; |
- } |
- |
- saveit = PR_FALSE; |
- |
- /* both profileTime and emailProfile have to exist or not exist */ |
- if ( emailProfile == NULL ) { |
- profileTime = NULL; |
- } else if ( profileTime == NULL ) { |
- emailProfile = NULL; |
- } |
- |
- if ( oldProfileTime == NULL ) { |
- saveit = PR_TRUE; |
- } else { |
- /* there was already a profile for this email addr */ |
- if ( profileTime ) { |
- /* we have an old and new profile - save whichever is more recent*/ |
- if ( oldProfileTime->len == 0 ) { |
- /* always replace if old entry doesn't have a time */ |
- oldtime = LL_MININT; |
- } else { |
- rv = DER_UTCTimeToTime(&oldtime, oldProfileTime); |
- if ( rv != SECSuccess ) { |
- goto loser; |
- } |
- } |
- |
- rv = DER_UTCTimeToTime(&newtime, profileTime); |
- if ( rv != SECSuccess ) { |
- goto loser; |
- } |
- |
- if ( LL_CMP(newtime, >, oldtime ) ) { |
- /* this is a newer profile, save it and cert */ |
- saveit = PR_TRUE; |
- } |
- } else { |
- saveit = PR_TRUE; |
- } |
- } |
- |
- |
- if (saveit) { |
- if (cc) { |
- if (stanProfile) { |
- /* stanProfile is already stored in the crypto context, |
- * overwrite the data |
- */ |
- NSSArena *arena = stanProfile->object.arena; |
- stanProfile->profileTime = nssItem_Create(arena, |
- NULL, |
- profileTime->len, |
- profileTime->data); |
- stanProfile->profileData = nssItem_Create(arena, |
- NULL, |
- emailProfile->len, |
- emailProfile->data); |
- } else if (profileTime && emailProfile) { |
- PRStatus nssrv; |
- NSSItem profTime, profData; |
- NSSITEM_FROM_SECITEM(&profTime, profileTime); |
- NSSITEM_FROM_SECITEM(&profData, emailProfile); |
- stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData); |
- if (!stanProfile) goto loser; |
- nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile); |
- rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; |
- } |
- } else { |
- rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr, |
- &cert->derSubject, emailProfile, profileTime); |
- } |
- } else { |
- rv = SECSuccess; |
- } |
- |
-loser: |
- if (oldProfile && freeOldProfile) { |
- SECITEM_FreeItem(oldProfile,PR_TRUE); |
- } |
- if (oldProfileTime && freeOldProfile) { |
- SECITEM_FreeItem(oldProfileTime,PR_TRUE); |
- } |
- if (stanProfile) { |
- nssSMIMEProfile_Destroy(stanProfile); |
- } |
- if (slot) { |
- PK11_FreeSlot(slot); |
- } |
- |
- return(rv); |
-} |
- |
-/* |
- * |
- * Manage S/MIME profiles |
- * |
- */ |
- |
-SECStatus |
-CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, |
- SECItem *profileTime) |
-{ |
- const char *emailAddr; |
- SECStatus rv; |
- |
- if (!cert) { |
- return SECFailure; |
- } |
- |
- if (cert->slot && !PK11_IsInternal(cert->slot)) { |
- /* this cert comes from an external source, we need to add it |
- to the cert db before creating an S/MIME profile */ |
- PK11SlotInfo* internalslot = PK11_GetInternalKeySlot(); |
- if (!internalslot) { |
- return SECFailure; |
- } |
- rv = PK11_ImportCert(internalslot, cert, |
- CK_INVALID_HANDLE, NULL, PR_FALSE); |
- |
- PK11_FreeSlot(internalslot); |
- if (rv != SECSuccess ) { |
- return SECFailure; |
- } |
- } |
- |
- if (cert->slot && cert->isperm && CERT_IsUserCert(cert) && |
- (!emailProfile || !emailProfile->len)) { |
- /* Don't clobber emailProfile for user certs. */ |
- return SECSuccess; |
- } |
- |
- for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL; |
- emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) { |
- rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime); |
- if (rv != SECSuccess) { |
- return SECFailure; |
- } |
- } |
- return SECSuccess; |
- |
-} |
- |
- |
-SECItem * |
-CERT_FindSMimeProfile(CERTCertificate *cert) |
-{ |
- PK11SlotInfo *slot = NULL; |
- NSSCertificate *c; |
- NSSCryptoContext *cc; |
- SECItem *rvItem = NULL; |
- |
- if (!cert || !cert->emailAddr || !cert->emailAddr[0]) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- c = STAN_GetNSSCertificate(cert); |
- if (!c) return NULL; |
- cc = c->object.cryptoContext; |
- if (cc != NULL) { |
- nssSMIMEProfile *stanProfile; |
- stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); |
- if (stanProfile) { |
- rvItem = SECITEM_AllocItem(NULL, NULL, |
- stanProfile->profileData->size); |
- if (rvItem) { |
- rvItem->data = stanProfile->profileData->data; |
- } |
- nssSMIMEProfile_Destroy(stanProfile); |
- } |
- return rvItem; |
- } |
- rvItem = |
- PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL); |
- if (slot) { |
- PK11_FreeSlot(slot); |
- } |
- return rvItem; |
-} |
- |
-/* |
- * deprecated functions that are now just stubs. |
- */ |
-/* |
- * Close the database |
- */ |
-void |
-__CERT_ClosePermCertDB(CERTCertDBHandle *handle) |
-{ |
- PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL); |
- return; |
-} |
- |
-SECStatus |
-CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, |
- PRBool readOnly) |
-{ |
- PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL); |
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
- return SECFailure; |
-} |
- |
-SECItem * |
-SECKEY_HashPassword(char *pw, SECItem *salt) |
-{ |
- PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL); |
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
- return NULL; |
-} |
- |
-SECStatus |
-__CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, |
- SECItem *derSubject, |
- void *cb, void *cbarg) |
-{ |
- PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL); |
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
- return SECFailure; |
-} |
- |
- |
-SECStatus |
-__CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, |
- void *cb, void *cbarg) |
-{ |
- PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL); |
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
- return SECFailure; |
-} |
- |
- |
- |