Index: lib/certhigh/certvfy.c |
=================================================================== |
--- a/lib/certhigh/certvfy.c |
+++ b/lib/certhigh/certvfy.c |
@@ -12,1833 +12,1768 @@ |
#include "cert.h" |
#include "certdb.h" |
#include "certi.h" |
#include "cryptohi.h" |
#include "pkix.h" |
/*#include "pkix_sample_modules.h" */ |
#include "pkix_pl_cert.h" |
- |
#include "nsspki.h" |
#include "pkitm.h" |
#include "pkim.h" |
#include "pki3hack.h" |
#include "base.h" |
/* |
* Check the validity times of a certificate |
*/ |
-SECStatus |
-CERT_CertTimesValid(CERTCertificate *c) |
-{ |
- SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE); |
- return (valid == secCertTimeValid) ? SECSuccess : SECFailure; |
+SECStatus CERT_CertTimesValid(CERTCertificate *c) { |
+ SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE); |
+ return (valid == secCertTimeValid) ? SECSuccess : SECFailure; |
} |
/* |
* verify the signature of a signed data object with the given DER publickey |
*/ |
-SECStatus |
-CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, |
- SECKEYPublicKey *pubKey, |
- void *wincx) |
-{ |
- SECStatus rv; |
- SECItem sig; |
- SECOidTag hashAlg = SEC_OID_UNKNOWN; |
+SECStatus CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, |
+ SECKEYPublicKey *pubKey, |
+ void *wincx) { |
+ SECStatus rv; |
+ SECItem sig; |
+ SECOidTag hashAlg = SEC_OID_UNKNOWN; |
- if ( !pubKey || !sd ) { |
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
- return SECFailure; |
+ if (!pubKey || !sd) { |
+ PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
+ return SECFailure; |
+ } |
+ |
+ /* check the signature */ |
+ sig = sd->signature; |
+ /* convert sig->len from bit counts to byte count. */ |
+ DER_ConvertBitString(&sig); |
+ |
+ rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, &sig, |
+ &sd->signatureAlgorithm, &hashAlg, wincx); |
+ if (rv == SECSuccess) { |
+ /* Are we honoring signatures for this algorithm? */ |
+ PRUint32 policyFlags = 0; |
+ rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); |
+ if (rv == SECSuccess && !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { |
+ PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); |
+ rv = SECFailure; |
} |
- |
- /* check the signature */ |
- sig = sd->signature; |
- /* convert sig->len from bit counts to byte count. */ |
- DER_ConvertBitString(&sig); |
- |
- rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, |
- &sig, &sd->signatureAlgorithm, &hashAlg, wincx); |
- if (rv == SECSuccess) { |
- /* Are we honoring signatures for this algorithm? */ |
- PRUint32 policyFlags = 0; |
- rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); |
- if (rv == SECSuccess && |
- !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { |
- PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); |
- rv = SECFailure; |
- } |
- } |
- return rv; |
+ } |
+ return rv; |
} |
/* |
* verify the signature of a signed data object with the given DER publickey |
*/ |
-SECStatus |
-CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, |
- CERTSubjectPublicKeyInfo *pubKeyInfo, |
- void *wincx) |
-{ |
- SECKEYPublicKey *pubKey; |
- SECStatus rv = SECFailure; |
+SECStatus CERT_VerifySignedDataWithPublicKeyInfo( |
+ CERTSignedData *sd, CERTSubjectPublicKeyInfo *pubKeyInfo, void *wincx) { |
+ SECKEYPublicKey *pubKey; |
+ SECStatus rv = SECFailure; |
- /* get cert's public key */ |
- pubKey = SECKEY_ExtractPublicKey(pubKeyInfo); |
- if (pubKey) { |
- rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
- SECKEY_DestroyPublicKey(pubKey); |
- } |
- return rv; |
+ /* get cert's public key */ |
+ pubKey = SECKEY_ExtractPublicKey(pubKeyInfo); |
+ if (pubKey) { |
+ rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
+ SECKEY_DestroyPublicKey(pubKey); |
+ } |
+ return rv; |
} |
/* |
* verify the signature of a signed data object with the given certificate |
*/ |
-SECStatus |
-CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert, |
- PRTime t, void *wincx) |
-{ |
- SECKEYPublicKey *pubKey = 0; |
- SECStatus rv = SECFailure; |
- SECCertTimeValidity validity; |
+SECStatus CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert, |
+ PRTime t, void *wincx) { |
+ SECKEYPublicKey *pubKey = 0; |
+ SECStatus rv = SECFailure; |
+ SECCertTimeValidity validity; |
- /* check the certificate's validity */ |
- validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE); |
- if ( validity != secCertTimeValid ) { |
- return rv; |
- } |
+ /* check the certificate's validity */ |
+ validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE); |
+ if (validity != secCertTimeValid) { |
+ return rv; |
+ } |
- /* get cert's public key */ |
- pubKey = CERT_ExtractPublicKey(cert); |
- if (pubKey) { |
- rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
- SECKEY_DestroyPublicKey(pubKey); |
- } |
- return rv; |
+ /* get cert's public key */ |
+ pubKey = CERT_ExtractPublicKey(cert); |
+ if (pubKey) { |
+ rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
+ SECKEY_DestroyPublicKey(pubKey); |
+ } |
+ return rv; |
} |
- |
-SECStatus |
-SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert, |
- CERTCertificate *caCert, PRTime t, void * wincx) |
-{ |
- return CERT_CheckCRL(cert, caCert, NULL, t, wincx); |
+SECStatus SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert, |
+ CERTCertificate *caCert, PRTime t, void *wincx) { |
+ return CERT_CheckCRL(cert, caCert, NULL, t, wincx); |
} |
/* |
* Find the issuer of a cert. Use the authorityKeyID if it exists. |
*/ |
-CERTCertificate * |
-CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage) |
-{ |
- NSSCertificate *me; |
- NSSTime *nssTime; |
- NSSTrustDomain *td; |
- NSSCryptoContext *cc; |
- NSSCertificate *chain[3]; |
- NSSUsage nssUsage; |
- PRStatus status; |
+CERTCertificate *CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, |
+ SECCertUsage usage) { |
+ NSSCertificate *me; |
+ NSSTime *nssTime; |
+ NSSTrustDomain *td; |
+ NSSCryptoContext *cc; |
+ NSSCertificate *chain[3]; |
+ NSSUsage nssUsage; |
+ PRStatus status; |
- me = STAN_GetNSSCertificate(cert); |
- if (!me) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
+ me = STAN_GetNSSCertificate(cert); |
+ if (!me) { |
+ PORT_SetError(SEC_ERROR_NO_MEMORY); |
+ return NULL; |
+ } |
+ nssTime = NSSTime_SetPRTime(NULL, validTime); |
+ nssUsage.anyUsage = PR_FALSE; |
+ nssUsage.nss3usage = usage; |
+ nssUsage.nss3lookingForCA = PR_TRUE; |
+ memset(chain, 0, 3 * sizeof(NSSCertificate *)); |
+ td = STAN_GetDefaultTrustDomain(); |
+ cc = STAN_GetDefaultCryptoContext(); |
+ (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, chain, 2, NULL, |
+ &status, td, cc); |
+ nss_ZFreeIf(nssTime); |
+ if (status == PR_SUCCESS) { |
+ PORT_Assert(me == chain[0]); |
+ /* if it's a root, the chain will only have one cert */ |
+ if (!chain[1]) { |
+ /* already has a reference from the call to BuildChain */ |
+ return cert; |
} |
- nssTime = NSSTime_SetPRTime(NULL, validTime); |
- nssUsage.anyUsage = PR_FALSE; |
- nssUsage.nss3usage = usage; |
- nssUsage.nss3lookingForCA = PR_TRUE; |
- memset(chain, 0, 3*sizeof(NSSCertificate *)); |
- td = STAN_GetDefaultTrustDomain(); |
- cc = STAN_GetDefaultCryptoContext(); |
- (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, |
- chain, 2, NULL, &status, td, cc); |
- nss_ZFreeIf(nssTime); |
- if (status == PR_SUCCESS) { |
- PORT_Assert(me == chain[0]); |
- /* if it's a root, the chain will only have one cert */ |
- if (!chain[1]) { |
- /* already has a reference from the call to BuildChain */ |
- return cert; |
- } |
- NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ |
- return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */ |
- } |
- if (chain[0]) { |
- PORT_Assert(me == chain[0]); |
- NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ |
- } |
- PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER); |
- return NULL; |
+ NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ |
+ return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */ |
+ } |
+ if (chain[0]) { |
+ PORT_Assert(me == chain[0]); |
+ NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ |
+ } |
+ PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
+ return NULL; |
} |
/* |
* return required trust flags for various cert usages for CAs |
*/ |
-SECStatus |
-CERT_TrustFlagsForCACertUsage(SECCertUsage usage, |
- unsigned int *retFlags, |
- SECTrustType *retTrustType) |
-{ |
- unsigned int requiredFlags; |
- SECTrustType trustType; |
+SECStatus CERT_TrustFlagsForCACertUsage(SECCertUsage usage, |
+ unsigned int *retFlags, |
+ SECTrustType *retTrustType) { |
+ unsigned int requiredFlags; |
+ SECTrustType trustType; |
- switch ( usage ) { |
- case certUsageSSLClient: |
- requiredFlags = CERTDB_TRUSTED_CLIENT_CA; |
- trustType = trustSSL; |
- break; |
- case certUsageSSLServer: |
- case certUsageSSLCA: |
- requiredFlags = CERTDB_TRUSTED_CA; |
- trustType = trustSSL; |
- break; |
- case certUsageSSLServerWithStepUp: |
- requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA; |
- trustType = trustSSL; |
- break; |
- case certUsageEmailSigner: |
- case certUsageEmailRecipient: |
- requiredFlags = CERTDB_TRUSTED_CA; |
- trustType = trustEmail; |
- break; |
- case certUsageObjectSigner: |
- requiredFlags = CERTDB_TRUSTED_CA; |
- trustType = trustObjectSigning; |
- break; |
- case certUsageVerifyCA: |
- case certUsageAnyCA: |
- case certUsageStatusResponder: |
- requiredFlags = CERTDB_TRUSTED_CA; |
- trustType = trustTypeNone; |
- break; |
- default: |
- PORT_Assert(0); |
- goto loser; |
- } |
- if ( retFlags != NULL ) { |
- *retFlags = requiredFlags; |
- } |
- if ( retTrustType != NULL ) { |
- *retTrustType = trustType; |
- } |
- |
- return(SECSuccess); |
+ switch (usage) { |
+ case certUsageSSLClient: |
+ requiredFlags = CERTDB_TRUSTED_CLIENT_CA; |
+ trustType = trustSSL; |
+ break; |
+ case certUsageSSLServer: |
+ case certUsageSSLCA: |
+ requiredFlags = CERTDB_TRUSTED_CA; |
+ trustType = trustSSL; |
+ break; |
+ case certUsageSSLServerWithStepUp: |
+ requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA; |
+ trustType = trustSSL; |
+ break; |
+ case certUsageEmailSigner: |
+ case certUsageEmailRecipient: |
+ requiredFlags = CERTDB_TRUSTED_CA; |
+ trustType = trustEmail; |
+ break; |
+ case certUsageObjectSigner: |
+ requiredFlags = CERTDB_TRUSTED_CA; |
+ trustType = trustObjectSigning; |
+ break; |
+ case certUsageVerifyCA: |
+ case certUsageAnyCA: |
+ case certUsageStatusResponder: |
+ requiredFlags = CERTDB_TRUSTED_CA; |
+ trustType = trustTypeNone; |
+ break; |
+ default: |
+ PORT_Assert(0); |
+ goto loser; |
+ } |
+ if (retFlags != NULL) { |
+ *retFlags = requiredFlags; |
+ } |
+ if (retTrustType != NULL) { |
+ *retTrustType = trustType; |
+ } |
+ |
+ return (SECSuccess); |
loser: |
- return(SECFailure); |
+ return (SECFailure); |
} |
-void |
-cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error, |
- unsigned int depth, void *arg) |
-{ |
- CERTVerifyLogNode *node, *tnode; |
+void cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error, |
+ unsigned int depth, void *arg) { |
+ CERTVerifyLogNode *node, *tnode; |
- PORT_Assert(log != NULL); |
- |
- node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena, |
- sizeof(CERTVerifyLogNode)); |
- if ( node != NULL ) { |
- node->cert = CERT_DupCertificate(cert); |
- node->error = error; |
- node->depth = depth; |
- node->arg = arg; |
- |
- if ( log->tail == NULL ) { |
- /* empty list */ |
- log->head = log->tail = node; |
- node->prev = NULL; |
- node->next = NULL; |
- } else if ( depth >= log->tail->depth ) { |
- /* add to tail */ |
- node->prev = log->tail; |
- log->tail->next = node; |
- log->tail = node; |
- node->next = NULL; |
- } else if ( depth < log->head->depth ) { |
- /* add at head */ |
- node->prev = NULL; |
- node->next = log->head; |
- log->head->prev = node; |
- log->head = node; |
- } else { |
- /* add in middle */ |
- tnode = log->tail; |
- while ( tnode != NULL ) { |
- if ( depth >= tnode->depth ) { |
- /* insert after tnode */ |
- node->prev = tnode; |
- node->next = tnode->next; |
- tnode->next->prev = node; |
- tnode->next = node; |
- break; |
- } |
+ PORT_Assert(log != NULL); |
- tnode = tnode->prev; |
- } |
- } |
+ node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena, |
+ sizeof(CERTVerifyLogNode)); |
+ if (node != NULL) { |
+ node->cert = CERT_DupCertificate(cert); |
+ node->error = error; |
+ node->depth = depth; |
+ node->arg = arg; |
- log->count++; |
+ if (log->tail == NULL) { |
+ /* empty list */ |
+ log->head = log->tail = node; |
+ node->prev = NULL; |
+ node->next = NULL; |
+ } else if (depth >= log->tail->depth) { |
+ /* add to tail */ |
+ node->prev = log->tail; |
+ log->tail->next = node; |
+ log->tail = node; |
+ node->next = NULL; |
+ } else if (depth < log->head->depth) { |
+ /* add at head */ |
+ node->prev = NULL; |
+ node->next = log->head; |
+ log->head->prev = node; |
+ log->head = node; |
+ } else { |
+ /* add in middle */ |
+ tnode = log->tail; |
+ while (tnode != NULL) { |
+ if (depth >= tnode->depth) { |
+ /* insert after tnode */ |
+ node->prev = tnode; |
+ node->next = tnode->next; |
+ tnode->next->prev = node; |
+ tnode->next = node; |
+ break; |
+ } |
+ |
+ tnode = tnode->prev; |
+ } |
} |
- return; |
+ |
+ log->count++; |
+ } |
+ return; |
} |
#define EXIT_IF_NOT_LOGGING(log) \ |
- if ( log == NULL ) { \ |
- goto loser; \ |
+ if (log == NULL) { \ |
+ goto loser; \ |
+ } |
+ |
+#define LOG_ERROR_OR_EXIT(log, cert, depth, arg) \ |
+ if (log != NULL) { \ |
+ cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
+ (void *)(PRWord)arg); \ |
+ } else { \ |
+ goto loser; \ |
+ } |
+ |
+#define LOG_ERROR(log, cert, depth, arg) \ |
+ if (log != NULL) { \ |
+ cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
+ (void *)(PRWord)arg); \ |
+ } |
+ |
+static SECStatus cert_VerifyCertChainOld(CERTCertDBHandle *handle, |
+ CERTCertificate *cert, PRBool checkSig, |
+ PRBool *sigerror, |
+ SECCertUsage certUsage, PRTime t, |
+ void *wincx, CERTVerifyLog *log, |
+ PRBool *revoked) { |
+ SECTrustType trustType; |
+ CERTBasicConstraints basicConstraint; |
+ CERTCertificate *issuerCert = NULL; |
+ CERTCertificate *subjectCert = NULL; |
+ CERTCertificate *badCert = NULL; |
+ PRBool isca; |
+ SECStatus rv; |
+ SECStatus rvFinal = SECSuccess; |
+ int count; |
+ int currentPathLen = 0; |
+ int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
+ unsigned int caCertType; |
+ unsigned int requiredCAKeyUsage; |
+ unsigned int requiredFlags; |
+ PLArenaPool *arena = NULL; |
+ CERTGeneralName *namesList = NULL; |
+ CERTCertificate **certsList = NULL; |
+ int certsListLen = 16; |
+ int namesCount = 0; |
+ PRBool subjectCertIsSelfIssued; |
+ CERTCertTrust issuerTrust; |
+ |
+ if (revoked) { |
+ *revoked = PR_FALSE; |
+ } |
+ |
+ if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, &requiredCAKeyUsage, |
+ &caCertType) != SECSuccess) { |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredCAKeyUsage = 0; |
+ caCertType = 0; |
+ } |
+ |
+ switch (certUsage) { |
+ case certUsageSSLClient: |
+ case certUsageSSLServer: |
+ case certUsageSSLCA: |
+ case certUsageSSLServerWithStepUp: |
+ case certUsageEmailSigner: |
+ case certUsageEmailRecipient: |
+ case certUsageObjectSigner: |
+ case certUsageVerifyCA: |
+ case certUsageAnyCA: |
+ case certUsageStatusResponder: |
+ if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
+ &trustType) != SECSuccess) { |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ /* XXX continuing with requiredFlags = 0 seems wrong. It'll |
+ * cause the following test to be true incorrectly: |
+ * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType); |
+ * if (( flags & requiredFlags ) == requiredFlags) { |
+ * rv = rvFinal; |
+ * goto done; |
+ * } |
+ * There are three other instances of this problem. |
+ */ |
+ requiredFlags = 0; |
+ trustType = trustSSL; |
+ } |
+ break; |
+ default: |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredFlags = 0; |
+ trustType = trustSSL; /* This used to be 0, but we need something |
+ * that matches the enumeration type. |
+ */ |
+ caCertType = 0; |
+ } |
+ |
+ subjectCert = CERT_DupCertificate(cert); |
+ if (subjectCert == NULL) { |
+ goto loser; |
+ } |
+ |
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
+ if (arena == NULL) { |
+ goto loser; |
+ } |
+ |
+ certsList = PORT_ZNewArray(CERTCertificate *, certsListLen); |
+ if (certsList == NULL) goto loser; |
+ |
+ /* RFC 3280 says that the name constraints will apply to the names |
+ ** in the leaf (EE) cert, whether it is self issued or not, so |
+ ** we pretend that it is not. |
+ */ |
+ subjectCertIsSelfIssued = PR_FALSE; |
+ for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) { |
+ PRBool validCAOverride = PR_FALSE; |
+ |
+ /* Construct a list of names for the current and all previous |
+ * certifcates (except leaf (EE) certs, root CAs, and self-issued |
+ * intermediate CAs) to be verified against the name constraints |
+ * extension of the issuer certificate. |
+ */ |
+ if (subjectCertIsSelfIssued == PR_FALSE) { |
+ CERTGeneralName *subjectNameList; |
+ int subjectNameListLen; |
+ int i; |
+ PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer); |
+ subjectNameList = |
+ CERT_GetConstrainedCertificateNames(subjectCert, arena, getSubjectCN); |
+ if (!subjectNameList) goto loser; |
+ subjectNameListLen = CERT_GetNamesLength(subjectNameList); |
+ if (!subjectNameListLen) goto loser; |
+ if (certsListLen <= namesCount + subjectNameListLen) { |
+ CERTCertificate **tmpCertsList; |
+ certsListLen = (namesCount + subjectNameListLen) * 2; |
+ tmpCertsList = (CERTCertificate **)PORT_Realloc( |
+ certsList, certsListLen * sizeof(CERTCertificate *)); |
+ if (tmpCertsList == NULL) { |
+ goto loser; |
+ } |
+ certsList = tmpCertsList; |
+ } |
+ for (i = 0; i < subjectNameListLen; i++) { |
+ certsList[namesCount + i] = subjectCert; |
+ } |
+ namesCount += subjectNameListLen; |
+ namesList = cert_CombineNamesLists(namesList, subjectNameList); |
} |
-#define LOG_ERROR_OR_EXIT(log,cert,depth,arg) \ |
- if ( log != NULL ) { \ |
- cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
- (void *)(PRWord)arg); \ |
- } else { \ |
- goto loser; \ |
+ /* check if the cert has an unsupported critical extension */ |
+ if (subjectCert->options.bits.hasUnsupportedCriticalExt) { |
+ PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); |
+ LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
} |
-#define LOG_ERROR(log,cert,depth,arg) \ |
- if ( log != NULL ) { \ |
- cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
- (void *)(PRWord)arg); \ |
+ /* find the certificate of the issuer */ |
+ issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage); |
+ if (!issuerCert) { |
+ PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
+ LOG_ERROR(log, subjectCert, count, 0); |
+ goto loser; |
} |
-static SECStatus |
-cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, PRBool* sigerror, |
- SECCertUsage certUsage, PRTime t, void *wincx, |
- CERTVerifyLog *log, PRBool* revoked) |
-{ |
- SECTrustType trustType; |
- CERTBasicConstraints basicConstraint; |
- CERTCertificate *issuerCert = NULL; |
- CERTCertificate *subjectCert = NULL; |
- CERTCertificate *badCert = NULL; |
- PRBool isca; |
- SECStatus rv; |
- SECStatus rvFinal = SECSuccess; |
- int count; |
- int currentPathLen = 0; |
- int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
- unsigned int caCertType; |
- unsigned int requiredCAKeyUsage; |
- unsigned int requiredFlags; |
- PLArenaPool *arena = NULL; |
- CERTGeneralName *namesList = NULL; |
- CERTCertificate **certsList = NULL; |
- int certsListLen = 16; |
- int namesCount = 0; |
- PRBool subjectCertIsSelfIssued; |
- CERTCertTrust issuerTrust; |
+ /* verify the signature on the cert */ |
+ if (checkSig) { |
+ rv = CERT_VerifySignedData(&subjectCert->signatureWrap, issuerCert, t, |
+ wincx); |
- if (revoked) { |
- *revoked = PR_FALSE; |
+ if (rv != SECSuccess) { |
+ if (sigerror) { |
+ *sigerror = PR_TRUE; |
+ } |
+ if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) { |
+ PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
+ } else { |
+ if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { |
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
+ } |
+ LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
+ } |
+ } |
} |
- if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, |
- &requiredCAKeyUsage, |
- &caCertType) |
- != SECSuccess ) { |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredCAKeyUsage = 0; |
- caCertType = 0; |
- } |
- |
- switch ( certUsage ) { |
- case certUsageSSLClient: |
- case certUsageSSLServer: |
- case certUsageSSLCA: |
- case certUsageSSLServerWithStepUp: |
- case certUsageEmailSigner: |
- case certUsageEmailRecipient: |
- case certUsageObjectSigner: |
- case certUsageVerifyCA: |
- case certUsageAnyCA: |
- case certUsageStatusResponder: |
- if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
- &trustType) != SECSuccess ) { |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- /* XXX continuing with requiredFlags = 0 seems wrong. It'll |
- * cause the following test to be true incorrectly: |
- * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType); |
- * if (( flags & requiredFlags ) == requiredFlags) { |
- * rv = rvFinal; |
- * goto done; |
- * } |
- * There are three other instances of this problem. |
- */ |
- requiredFlags = 0; |
- trustType = trustSSL; |
- } |
- break; |
- default: |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredFlags = 0; |
- trustType = trustSSL;/* This used to be 0, but we need something |
- * that matches the enumeration type. |
- */ |
- caCertType = 0; |
- } |
- |
- subjectCert = CERT_DupCertificate(cert); |
- if ( subjectCert == NULL ) { |
- goto loser; |
- } |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- goto loser; |
- } |
- |
- certsList = PORT_ZNewArray(CERTCertificate *, certsListLen); |
- if (certsList == NULL) |
- goto loser; |
- |
- /* RFC 3280 says that the name constraints will apply to the names |
- ** in the leaf (EE) cert, whether it is self issued or not, so |
- ** we pretend that it is not. |
- */ |
- subjectCertIsSelfIssued = PR_FALSE; |
- for ( count = 0; count < CERT_MAX_CERT_CHAIN; count++ ) { |
- PRBool validCAOverride = PR_FALSE; |
- |
- /* Construct a list of names for the current and all previous |
- * certifcates (except leaf (EE) certs, root CAs, and self-issued |
- * intermediate CAs) to be verified against the name constraints |
- * extension of the issuer certificate. |
- */ |
- if (subjectCertIsSelfIssued == PR_FALSE) { |
- CERTGeneralName *subjectNameList; |
- int subjectNameListLen; |
- int i; |
- PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer); |
- subjectNameList = |
- CERT_GetConstrainedCertificateNames(subjectCert, arena, |
- getSubjectCN); |
- if (!subjectNameList) |
- goto loser; |
- subjectNameListLen = CERT_GetNamesLength(subjectNameList); |
- if (!subjectNameListLen) |
- goto loser; |
- if (certsListLen <= namesCount + subjectNameListLen) { |
- CERTCertificate **tmpCertsList; |
- certsListLen = (namesCount + subjectNameListLen) * 2; |
- tmpCertsList = |
- (CERTCertificate **)PORT_Realloc(certsList, |
- certsListLen * sizeof(CERTCertificate *)); |
- if (tmpCertsList == NULL) { |
- goto loser; |
- } |
- certsList = tmpCertsList; |
- } |
- for (i = 0; i < subjectNameListLen; i++) { |
- certsList[namesCount + i] = subjectCert; |
- } |
- namesCount += subjectNameListLen; |
- namesList = cert_CombineNamesLists(namesList, subjectNameList); |
- } |
- |
- /* check if the cert has an unsupported critical extension */ |
- if ( subjectCert->options.bits.hasUnsupportedCriticalExt ) { |
- PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); |
- LOG_ERROR_OR_EXIT(log,subjectCert,count,0); |
- } |
- |
- /* find the certificate of the issuer */ |
- issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage); |
- if ( ! issuerCert ) { |
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
- LOG_ERROR(log,subjectCert,count,0); |
- goto loser; |
- } |
- |
- /* verify the signature on the cert */ |
- if ( checkSig ) { |
- rv = CERT_VerifySignedData(&subjectCert->signatureWrap, |
- issuerCert, t, wincx); |
- |
- if ( rv != SECSuccess ) { |
- if (sigerror) { |
- *sigerror = PR_TRUE; |
- } |
- if ( PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ) { |
- PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); |
- } else { |
- if (PORT_GetError() != |
- SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { |
- PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
- } |
- LOG_ERROR_OR_EXIT(log,subjectCert,count,0); |
- } |
- } |
- } |
- |
- /* If the basicConstraint extension is included in an immediate CA |
- * certificate, make sure that the isCA flag is on. If the |
- * pathLenConstraint component exists, it must be greater than the |
- * number of CA certificates we have seen so far. If the extension |
- * is omitted, we will assume that this is a CA certificate with |
- * an unlimited pathLenConstraint (since it already passes the |
- * netscape-cert-type extension checking). |
- */ |
- |
- rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint); |
- if ( rv != SECSuccess ) { |
- if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); |
- } |
- pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
- /* no basic constraints found, we aren't (yet) a CA. */ |
- isca = PR_FALSE; |
- } else { |
- if ( basicConstraint.isCA == PR_FALSE ) { |
- PORT_SetError (SEC_ERROR_CA_CERT_INVALID); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); |
- } |
- pathLengthLimit = basicConstraint.pathLenConstraint; |
- isca = PR_TRUE; |
- } |
- /* make sure that the path len constraint is properly set.*/ |
- if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) { |
- PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID); |
- LOG_ERROR_OR_EXIT(log, issuerCert, count+1, pathLengthLimit); |
- } |
- |
- /* make sure that the entire chain is within the name space of the |
- * current issuer certificate. |
- */ |
- rv = CERT_CompareNameSpace(issuerCert, namesList, certsList, |
- arena, &badCert); |
- if (rv != SECSuccess || badCert != NULL) { |
- PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE); |
- LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0); |
- goto loser; |
- } |
- |
- /* XXX - the error logging may need to go down into CRL stuff at some |
- * point |
- */ |
- /* check revoked list (issuer) */ |
- rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx); |
- if (rv == SECFailure) { |
- if (revoked) { |
- *revoked = PR_TRUE; |
- } |
- LOG_ERROR_OR_EXIT(log,subjectCert,count,0); |
- } else if (rv == SECWouldBlock) { |
- /* We found something fishy, so we intend to issue an |
- * error to the user, but the user may wish to continue |
- * processing, in which case we better make sure nothing |
- * worse has happened... so keep cranking the loop */ |
- rvFinal = SECFailure; |
- if (revoked) { |
- *revoked = PR_TRUE; |
- } |
- LOG_ERROR(log,subjectCert,count,0); |
- } |
- |
- if ( CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) { |
- /* we have some trust info, but this does NOT imply that this |
- * cert is actually trusted for any purpose. The cert may be |
- * explicitly UNtrusted. We won't know until we examine the |
- * trust bits. |
- */ |
- unsigned int flags; |
- |
- if (certUsage != certUsageAnyCA && |
- certUsage != certUsageStatusResponder) { |
- |
- /* |
- * XXX This choice of trustType seems arbitrary. |
- */ |
- if ( certUsage == certUsageVerifyCA ) { |
- if ( subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA ) { |
- trustType = trustEmail; |
- } else if ( subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA ) { |
- trustType = trustSSL; |
- } else { |
- trustType = trustObjectSigning; |
- } |
- } |
- |
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
- if (( flags & requiredFlags ) == requiredFlags) { |
- /* we found a trusted one, so return */ |
- rv = rvFinal; |
- goto done; |
- } |
- if (flags & CERTDB_VALID_CA) { |
- validCAOverride = PR_TRUE; |
- } |
- /* is it explicitly distrusted? */ |
- if ((flags & CERTDB_TERMINAL_RECORD) && |
- ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { |
- /* untrusted -- the cert is explicitly untrusted, not |
- * just that it doesn't chain to a trusted cert */ |
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags); |
- } |
- } else { |
- /* Check if we have any valid trust when cheching for |
- * certUsageAnyCA or certUsageStatusResponder. */ |
- for (trustType = trustSSL; trustType < trustTypeNone; |
- trustType++) { |
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
- if ((flags & requiredFlags) == requiredFlags) { |
- rv = rvFinal; |
- goto done; |
- } |
- if (flags & CERTDB_VALID_CA) |
- validCAOverride = PR_TRUE; |
- } |
- /* We have 2 separate loops because we want any single trust |
- * bit to allow this usage to return trusted. Only if none of |
- * the trust bits are on do we check to see if the cert is |
- * untrusted */ |
- for (trustType = trustSSL; trustType < trustTypeNone; |
- trustType++) { |
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
- /* is it explicitly distrusted? */ |
- if ((flags & CERTDB_TERMINAL_RECORD) && |
- ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { |
- /* untrusted -- the cert is explicitly untrusted, not |
- * just that it doesn't chain to a trusted cert */ |
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags); |
- } |
- } |
- } |
- } |
- |
- if (!validCAOverride) { |
- /* |
- * Make sure that if this is an intermediate CA in the chain that |
- * it was given permission by its signer to be a CA. |
- */ |
- /* |
- * if basicConstraints says it is a ca, then we check the |
- * nsCertType. If the nsCertType has any CA bits set, then |
- * it must have the right one. |
- */ |
- if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { |
- isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; |
- } |
- |
- if ( !isca ) { |
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); |
- } |
- |
- /* make sure key usage allows cert signing */ |
- if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,requiredCAKeyUsage); |
- } |
- } |
- |
- /* make sure that the issuer is not self signed. If it is, then |
- * stop here to prevent looping. |
- */ |
- if (issuerCert->isRoot) { |
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
- LOG_ERROR(log, issuerCert, count+1, 0); |
- goto loser; |
- } |
- /* The issuer cert will be the subject cert in the next loop. |
- * A cert is self-issued if its subject and issuer are equal and |
- * both are of non-zero length. |
- */ |
- subjectCertIsSelfIssued = (PRBool) |
- SECITEM_ItemsAreEqual(&issuerCert->derIssuer, |
- &issuerCert->derSubject) && |
- issuerCert->derSubject.len > 0; |
- if (subjectCertIsSelfIssued == PR_FALSE) { |
- /* RFC 3280 says only non-self-issued intermediate CA certs |
- * count in path length. |
- */ |
- ++currentPathLen; |
- } |
- |
- CERT_DestroyCertificate(subjectCert); |
- subjectCert = issuerCert; |
- issuerCert = NULL; |
- } |
- |
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
- LOG_ERROR(log,subjectCert,count,0); |
-loser: |
- rv = SECFailure; |
-done: |
- if (certsList != NULL) { |
- PORT_Free(certsList); |
- } |
- if ( issuerCert ) { |
- CERT_DestroyCertificate(issuerCert); |
- } |
- |
- if ( subjectCert ) { |
- CERT_DestroyCertificate(subjectCert); |
- } |
- |
- if ( arena != NULL ) { |
- PORT_FreeArena(arena, PR_FALSE); |
- } |
- return rv; |
-} |
- |
-SECStatus |
-cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, PRBool* sigerror, |
- SECCertUsage certUsage, PRTime t, void *wincx, |
- CERTVerifyLog *log, PRBool* revoked) |
-{ |
- if (CERT_GetUsePKIXForValidation()) { |
- return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t, |
- wincx, log, sigerror, revoked); |
- } |
- return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror, |
- certUsage, t, wincx, log, revoked); |
-} |
- |
-SECStatus |
-CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertUsage certUsage, PRTime t, |
- void *wincx, CERTVerifyLog *log) |
-{ |
- return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t, |
- wincx, log, NULL); |
-} |
- |
-/* |
- * verify that a CA can sign a certificate with the requested usage. |
- */ |
-SECStatus |
-CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertUsage certUsage, PRTime t, |
- void *wincx, CERTVerifyLog *log) |
-{ |
- SECTrustType trustType; |
- CERTBasicConstraints basicConstraint; |
- PRBool isca; |
- PRBool validCAOverride = PR_FALSE; |
- SECStatus rv; |
- SECStatus rvFinal = SECSuccess; |
- unsigned int flags; |
- unsigned int caCertType; |
- unsigned int requiredCAKeyUsage; |
- unsigned int requiredFlags; |
- CERTCertificate *issuerCert; |
- CERTCertTrust certTrust; |
- |
- |
- if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, |
- &requiredCAKeyUsage, |
- &caCertType) != SECSuccess ) { |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredCAKeyUsage = 0; |
- caCertType = 0; |
- } |
- |
- switch ( certUsage ) { |
- case certUsageSSLClient: |
- case certUsageSSLServer: |
- case certUsageSSLCA: |
- case certUsageSSLServerWithStepUp: |
- case certUsageEmailSigner: |
- case certUsageEmailRecipient: |
- case certUsageObjectSigner: |
- case certUsageVerifyCA: |
- case certUsageStatusResponder: |
- if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
- &trustType) != SECSuccess ) { |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredFlags = 0; |
- trustType = trustSSL; |
- } |
- break; |
- default: |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredFlags = 0; |
- trustType = trustSSL;/* This used to be 0, but we need something |
- * that matches the enumeration type. |
- */ |
- caCertType = 0; |
- } |
- |
- /* If the basicConstraint extension is included in an intermmediate CA |
+ /* If the basicConstraint extension is included in an immediate CA |
* certificate, make sure that the isCA flag is on. If the |
* pathLenConstraint component exists, it must be greater than the |
* number of CA certificates we have seen so far. If the extension |
* is omitted, we will assume that this is a CA certificate with |
* an unlimited pathLenConstraint (since it already passes the |
* netscape-cert-type extension checking). |
*/ |
- rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); |
- if ( rv != SECSuccess ) { |
- if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
- LOG_ERROR_OR_EXIT(log,cert,0,0); |
- } |
- /* no basic constraints found, we aren't (yet) a CA. */ |
- isca = PR_FALSE; |
- } else { |
- if ( basicConstraint.isCA == PR_FALSE ) { |
- PORT_SetError (SEC_ERROR_CA_CERT_INVALID); |
- LOG_ERROR_OR_EXIT(log,cert,0,0); |
- } |
+ rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint); |
+ if (rv != SECSuccess) { |
+ if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
+ } |
+ pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
+ /* no basic constraints found, we aren't (yet) a CA. */ |
+ isca = PR_FALSE; |
+ } else { |
+ if (basicConstraint.isCA == PR_FALSE) { |
+ PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
+ } |
+ pathLengthLimit = basicConstraint.pathLenConstraint; |
+ isca = PR_TRUE; |
+ } |
+ /* make sure that the path len constraint is properly set.*/ |
+ if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) { |
+ PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit); |
+ } |
- /* can't check path length if we don't know the previous path */ |
- isca = PR_TRUE; |
+ /* make sure that the entire chain is within the name space of the |
+ * current issuer certificate. |
+ */ |
+ rv = CERT_CompareNameSpace(issuerCert, namesList, certsList, arena, |
+ &badCert); |
+ if (rv != SECSuccess || badCert != NULL) { |
+ PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE); |
+ LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0); |
+ goto loser; |
} |
- |
- if ( CERT_GetCertTrust(cert, &certTrust) == SECSuccess ) { |
- /* we have some trust info, but this does NOT imply that this |
- * cert is actually trusted for any purpose. The cert may be |
- * explicitly UNtrusted. We won't know until we examine the |
- * trust bits. |
- */ |
- if (certUsage == certUsageStatusResponder) { |
- /* Check the special case of certUsageStatusResponder */ |
- issuerCert = CERT_FindCertIssuer(cert, t, certUsage); |
- if (issuerCert) { |
- if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) |
- != SECSuccess) { |
- PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
- CERT_DestroyCertificate(issuerCert); |
- goto loser; |
- } |
- CERT_DestroyCertificate(issuerCert); |
- } |
- /* XXX We have NOT determined that this cert is trusted. |
- * For years, NSS has treated this as trusted, |
- * but it seems incorrect. |
- */ |
- rv = rvFinal; |
- goto done; |
+ |
+ /* XXX - the error logging may need to go down into CRL stuff at some |
+ * point |
+ */ |
+ /* check revoked list (issuer) */ |
+ rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx); |
+ if (rv == SECFailure) { |
+ if (revoked) { |
+ *revoked = PR_TRUE; |
+ } |
+ LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
+ } else if (rv == SECWouldBlock) { |
+ /* We found something fishy, so we intend to issue an |
+ * error to the user, but the user may wish to continue |
+ * processing, in which case we better make sure nothing |
+ * worse has happened... so keep cranking the loop */ |
+ rvFinal = SECFailure; |
+ if (revoked) { |
+ *revoked = PR_TRUE; |
+ } |
+ LOG_ERROR(log, subjectCert, count, 0); |
+ } |
+ |
+ if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) { |
+ /* we have some trust info, but this does NOT imply that this |
+ * cert is actually trusted for any purpose. The cert may be |
+ * explicitly UNtrusted. We won't know until we examine the |
+ * trust bits. |
+ */ |
+ unsigned int flags; |
+ |
+ if (certUsage != certUsageAnyCA && |
+ certUsage != certUsageStatusResponder) { |
+ |
+ /* |
+ * XXX This choice of trustType seems arbitrary. |
+ */ |
+ if (certUsage == certUsageVerifyCA) { |
+ if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) { |
+ trustType = trustEmail; |
+ } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) { |
+ trustType = trustSSL; |
+ } else { |
+ trustType = trustObjectSigning; |
+ } |
} |
- /* |
- * check the trust params of the issuer |
- */ |
- flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType); |
- if ( ( flags & requiredFlags ) == requiredFlags) { |
- /* we found a trusted one, so return */ |
- rv = rvFinal; |
- goto done; |
- } |
- if (flags & CERTDB_VALID_CA) { |
- validCAOverride = PR_TRUE; |
- } |
- /* is it explicitly distrusted? */ |
- if ((flags & CERTDB_TERMINAL_RECORD) && |
- ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { |
- /* untrusted -- the cert is explicitly untrusted, not |
- * just that it doesn't chain to a trusted cert */ |
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
- LOG_ERROR_OR_EXIT(log,cert,0,flags); |
- } |
+ flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
+ if ((flags & requiredFlags) == requiredFlags) { |
+ /* we found a trusted one, so return */ |
+ rv = rvFinal; |
+ goto done; |
+ } |
+ if (flags & CERTDB_VALID_CA) { |
+ validCAOverride = PR_TRUE; |
+ } |
+ /* is it explicitly distrusted? */ |
+ if ((flags & CERTDB_TERMINAL_RECORD) && |
+ ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
+ /* untrusted -- the cert is explicitly untrusted, not |
+ * just that it doesn't chain to a trusted cert */ |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); |
+ } |
+ } else { |
+ /* Check if we have any valid trust when cheching for |
+ * certUsageAnyCA or certUsageStatusResponder. */ |
+ for (trustType = trustSSL; trustType < trustTypeNone; trustType++) { |
+ flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
+ if ((flags & requiredFlags) == requiredFlags) { |
+ rv = rvFinal; |
+ goto done; |
+ } |
+ if (flags & CERTDB_VALID_CA) validCAOverride = PR_TRUE; |
+ } |
+ /* We have 2 separate loops because we want any single trust |
+ * bit to allow this usage to return trusted. Only if none of |
+ * the trust bits are on do we check to see if the cert is |
+ * untrusted */ |
+ for (trustType = trustSSL; trustType < trustTypeNone; trustType++) { |
+ flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
+ /* is it explicitly distrusted? */ |
+ if ((flags & CERTDB_TERMINAL_RECORD) && |
+ ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
+ /* untrusted -- the cert is explicitly untrusted, not |
+ * just that it doesn't chain to a trusted cert */ |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); |
+ } |
+ } |
+ } |
} |
+ |
if (!validCAOverride) { |
- /* |
- * Make sure that if this is an intermediate CA in the chain that |
- * it was given permission by its signer to be a CA. |
- */ |
- /* |
- * if basicConstraints says it is a ca, then we check the |
- * nsCertType. If the nsCertType has any CA bits set, then |
- * it must have the right one. |
- */ |
- if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) { |
- isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; |
- } |
- |
- if (!isca) { |
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
- LOG_ERROR_OR_EXIT(log,cert,0,0); |
- } |
- |
- /* make sure key usage allows cert signing */ |
- if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
- LOG_ERROR_OR_EXIT(log,cert,0,requiredCAKeyUsage); |
- } |
+ /* |
+ * Make sure that if this is an intermediate CA in the chain that |
+ * it was given permission by its signer to be a CA. |
+ */ |
+ /* |
+ * if basicConstraints says it is a ca, then we check the |
+ * nsCertType. If the nsCertType has any CA bits set, then |
+ * it must have the right one. |
+ */ |
+ if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { |
+ isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; |
+ } |
+ |
+ if (!isca) { |
+ PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
+ } |
+ |
+ /* make sure key usage allows cert signing */ |
+ if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
+ LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage); |
+ } |
} |
+ |
/* make sure that the issuer is not self signed. If it is, then |
* stop here to prevent looping. |
*/ |
- if (cert->isRoot) { |
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
- LOG_ERROR(log, cert, 0, 0); |
- goto loser; |
+ if (issuerCert->isRoot) { |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
+ LOG_ERROR(log, issuerCert, count + 1, 0); |
+ goto loser; |
+ } |
+ /* The issuer cert will be the subject cert in the next loop. |
+ * A cert is self-issued if its subject and issuer are equal and |
+ * both are of non-zero length. |
+ */ |
+ subjectCertIsSelfIssued = |
+ (PRBool)SECITEM_ItemsAreEqual(&issuerCert->derIssuer, |
+ &issuerCert->derSubject) && |
+ issuerCert->derSubject.len > 0; |
+ if (subjectCertIsSelfIssued == PR_FALSE) { |
+ /* RFC 3280 says only non-self-issued intermediate CA certs |
+ * count in path length. |
+ */ |
+ ++currentPathLen; |
} |
- return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, |
- wincx, log); |
+ CERT_DestroyCertificate(subjectCert); |
+ subjectCert = issuerCert; |
+ issuerCert = NULL; |
+ } |
+ |
+ PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
+ LOG_ERROR(log, subjectCert, count, 0); |
loser: |
- rv = SECFailure; |
+ rv = SECFailure; |
done: |
- return rv; |
+ if (certsList != NULL) { |
+ PORT_Free(certsList); |
+ } |
+ if (issuerCert) { |
+ CERT_DestroyCertificate(issuerCert); |
+ } |
+ |
+ if (subjectCert) { |
+ CERT_DestroyCertificate(subjectCert); |
+ } |
+ |
+ if (arena != NULL) { |
+ PORT_FreeArena(arena, PR_FALSE); |
+ } |
+ return rv; |
} |
-#define NEXT_USAGE() { \ |
- i*=2; \ |
- certUsage++; \ |
- continue; \ |
+SECStatus cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
+ PRBool checkSig, PRBool *sigerror, |
+ SECCertUsage certUsage, PRTime t, void *wincx, |
+ CERTVerifyLog *log, PRBool *revoked) { |
+ if (CERT_GetUsePKIXForValidation()) { |
+ return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t, wincx, log, |
+ sigerror, revoked); |
+ } |
+ return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror, certUsage, t, |
+ wincx, log, revoked); |
} |
-#define VALID_USAGE() { \ |
- NEXT_USAGE(); \ |
-} |
- |
-#define INVALID_USAGE() { \ |
- if (returnedUsages) { \ |
- *returnedUsages &= (~i); \ |
- } \ |
- if (PR_TRUE == requiredUsage) { \ |
- valid = SECFailure; \ |
- } \ |
- NEXT_USAGE(); \ |
+SECStatus CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
+ PRBool checkSig, SECCertUsage certUsage, |
+ PRTime t, void *wincx, CERTVerifyLog *log) { |
+ return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t, wincx, |
+ log, NULL); |
} |
/* |
- * check the leaf cert against trust and usage. |
+ * verify that a CA can sign a certificate with the requested usage. |
+ */ |
+SECStatus CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, |
+ CERTCertificate *cert, PRBool checkSig, |
+ SECCertUsage certUsage, PRTime t, |
+ void *wincx, CERTVerifyLog *log) { |
+ SECTrustType trustType; |
+ CERTBasicConstraints basicConstraint; |
+ PRBool isca; |
+ PRBool validCAOverride = PR_FALSE; |
+ SECStatus rv; |
+ SECStatus rvFinal = SECSuccess; |
+ unsigned int flags; |
+ unsigned int caCertType; |
+ unsigned int requiredCAKeyUsage; |
+ unsigned int requiredFlags; |
+ CERTCertificate *issuerCert; |
+ CERTCertTrust certTrust; |
+ |
+ if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, &requiredCAKeyUsage, |
+ &caCertType) != SECSuccess) { |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredCAKeyUsage = 0; |
+ caCertType = 0; |
+ } |
+ |
+ switch (certUsage) { |
+ case certUsageSSLClient: |
+ case certUsageSSLServer: |
+ case certUsageSSLCA: |
+ case certUsageSSLServerWithStepUp: |
+ case certUsageEmailSigner: |
+ case certUsageEmailRecipient: |
+ case certUsageObjectSigner: |
+ case certUsageVerifyCA: |
+ case certUsageStatusResponder: |
+ if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
+ &trustType) != SECSuccess) { |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredFlags = 0; |
+ trustType = trustSSL; |
+ } |
+ break; |
+ default: |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredFlags = 0; |
+ trustType = trustSSL; /* This used to be 0, but we need something |
+ * that matches the enumeration type. |
+ */ |
+ caCertType = 0; |
+ } |
+ |
+ /* If the basicConstraint extension is included in an intermmediate CA |
+ * certificate, make sure that the isCA flag is on. If the |
+ * pathLenConstraint component exists, it must be greater than the |
+ * number of CA certificates we have seen so far. If the extension |
+ * is omitted, we will assume that this is a CA certificate with |
+ * an unlimited pathLenConstraint (since it already passes the |
+ * netscape-cert-type extension checking). |
+ */ |
+ |
+ rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); |
+ if (rv != SECSuccess) { |
+ if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
+ LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
+ } |
+ /* no basic constraints found, we aren't (yet) a CA. */ |
+ isca = PR_FALSE; |
+ } else { |
+ if (basicConstraint.isCA == PR_FALSE) { |
+ PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
+ } |
+ |
+ /* can't check path length if we don't know the previous path */ |
+ isca = PR_TRUE; |
+ } |
+ |
+ if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) { |
+ /* we have some trust info, but this does NOT imply that this |
+ * cert is actually trusted for any purpose. The cert may be |
+ * explicitly UNtrusted. We won't know until we examine the |
+ * trust bits. |
+ */ |
+ if (certUsage == certUsageStatusResponder) { |
+ /* Check the special case of certUsageStatusResponder */ |
+ issuerCert = CERT_FindCertIssuer(cert, t, certUsage); |
+ if (issuerCert) { |
+ if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) != SECSuccess) { |
+ PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
+ CERT_DestroyCertificate(issuerCert); |
+ goto loser; |
+ } |
+ CERT_DestroyCertificate(issuerCert); |
+ } |
+ /* XXX We have NOT determined that this cert is trusted. |
+ * For years, NSS has treated this as trusted, |
+ * but it seems incorrect. |
+ */ |
+ rv = rvFinal; |
+ goto done; |
+ } |
+ |
+ /* |
+ * check the trust params of the issuer |
+ */ |
+ flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType); |
+ if ((flags & requiredFlags) == requiredFlags) { |
+ /* we found a trusted one, so return */ |
+ rv = rvFinal; |
+ goto done; |
+ } |
+ if (flags & CERTDB_VALID_CA) { |
+ validCAOverride = PR_TRUE; |
+ } |
+ /* is it explicitly distrusted? */ |
+ if ((flags & CERTDB_TERMINAL_RECORD) && |
+ ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
+ /* untrusted -- the cert is explicitly untrusted, not |
+ * just that it doesn't chain to a trusted cert */ |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, flags); |
+ } |
+ } |
+ if (!validCAOverride) { |
+ /* |
+ * Make sure that if this is an intermediate CA in the chain that |
+ * it was given permission by its signer to be a CA. |
+ */ |
+ /* |
+ * if basicConstraints says it is a ca, then we check the |
+ * nsCertType. If the nsCertType has any CA bits set, then |
+ * it must have the right one. |
+ */ |
+ if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) { |
+ isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; |
+ } |
+ |
+ if (!isca) { |
+ PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
+ } |
+ |
+ /* make sure key usage allows cert signing */ |
+ if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage); |
+ } |
+ } |
+ /* make sure that the issuer is not self signed. If it is, then |
+ * stop here to prevent looping. |
+ */ |
+ if (cert->isRoot) { |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
+ LOG_ERROR(log, cert, 0, 0); |
+ goto loser; |
+ } |
+ |
+ return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, wincx, log); |
+loser: |
+ rv = SECFailure; |
+done: |
+ return rv; |
+} |
+ |
+#define NEXT_USAGE() \ |
+ { \ |
+ i *= 2; \ |
+ certUsage++; \ |
+ continue; \ |
+ } |
+ |
+#define VALID_USAGE() \ |
+ { NEXT_USAGE(); } |
+ |
+#define INVALID_USAGE() \ |
+ { \ |
+ if (returnedUsages) { \ |
+ *returnedUsages &= (~i); \ |
+ } \ |
+ if (PR_TRUE == requiredUsage) { \ |
+ valid = SECFailure; \ |
+ } \ |
+ NEXT_USAGE(); \ |
+ } |
+ |
+/* |
+ * check the leaf cert against trust and usage. |
* returns success if the cert is not distrusted. If the cert is |
* trusted, then the trusted bool will be true. |
* returns failure if the cert is distrusted. If failure, flags |
* will return the flag bits that indicated distrust. |
*/ |
-SECStatus |
-cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage, |
- unsigned int *failedFlags, PRBool *trusted) |
-{ |
- unsigned int flags; |
- CERTCertTrust trust; |
+SECStatus cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage, |
+ unsigned int *failedFlags, PRBool *trusted) { |
+ unsigned int flags; |
+ CERTCertTrust trust; |
- *failedFlags = 0; |
- *trusted = PR_FALSE; |
- |
- /* check trust flags to see if this cert is directly trusted */ |
- if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) { |
- switch ( certUsage ) { |
- case certUsageSSLClient: |
- case certUsageSSLServer: |
- flags = trust.sslFlags; |
- |
- /* is the cert directly trusted or not trusted ? */ |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ( flags & CERTDB_TRUSTED ) { /* trust this cert */ |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } else { /* don't trust this cert */ |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- break; |
- case certUsageSSLServerWithStepUp: |
- /* XXX - step up certs can't be directly trusted, only distrust */ |
- flags = trust.sslFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if (( flags & CERTDB_TRUSTED ) == 0) { |
- /* don't trust this cert */ |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- break; |
- case certUsageSSLCA: |
- flags = trust.sslFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if (( flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA) ) == 0) { |
- /* don't trust this cert */ |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- break; |
- case certUsageEmailSigner: |
- case certUsageEmailRecipient: |
- flags = trust.emailFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ( flags & CERTDB_TRUSTED ) { /* trust this cert */ |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } |
- else { /* don't trust this cert */ |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- |
- break; |
- case certUsageObjectSigner: |
- flags = trust.objectSigningFlags; |
+ *failedFlags = 0; |
+ *trusted = PR_FALSE; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ( flags & CERTDB_TRUSTED ) { /* trust this cert */ |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } else { /* don't trust this cert */ |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- break; |
- case certUsageVerifyCA: |
- case certUsageStatusResponder: |
- flags = trust.sslFlags; |
- /* is the cert directly trusted or not trusted ? */ |
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == |
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } |
- flags = trust.emailFlags; |
- /* is the cert directly trusted or not trusted ? */ |
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == |
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } |
- flags = trust.objectSigningFlags; |
- /* is the cert directly trusted or not trusted ? */ |
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == |
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { |
- *trusted = PR_TRUE; |
- return SECSuccess; |
- } |
- /* fall through to test distrust */ |
- case certUsageAnyCA: |
- case certUsageUserCertImport: |
- /* do we distrust these certs explicitly */ |
- flags = trust.sslFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- flags = trust.emailFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- /* fall through */ |
- case certUsageProtectedObjectSigner: |
- flags = trust.objectSigningFlags; |
- if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
- * authoritative */ |
- if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { |
- *failedFlags = flags; |
- return SECFailure; |
- } |
- } |
- break; |
- } |
+ /* check trust flags to see if this cert is directly trusted */ |
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess) { |
+ switch (certUsage) { |
+ case certUsageSSLClient: |
+ case certUsageSSLServer: |
+ flags = trust.sslFlags; |
+ |
+ /* is the cert directly trusted or not trusted ? */ |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if (flags & CERTDB_TRUSTED) {/* trust this cert */ |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } else {/* don't trust this cert */ |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ break; |
+ case certUsageSSLServerWithStepUp: |
+ /* XXX - step up certs can't be directly trusted, only distrust */ |
+ flags = trust.sslFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if ((flags & CERTDB_TRUSTED) == 0) { |
+ /* don't trust this cert */ |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ break; |
+ case certUsageSSLCA: |
+ flags = trust.sslFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
+ /* don't trust this cert */ |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ break; |
+ case certUsageEmailSigner: |
+ case certUsageEmailRecipient: |
+ flags = trust.emailFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if (flags & CERTDB_TRUSTED) {/* trust this cert */ |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } else {/* don't trust this cert */ |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ |
+ break; |
+ case certUsageObjectSigner: |
+ flags = trust.objectSigningFlags; |
+ |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if (flags & CERTDB_TRUSTED) {/* trust this cert */ |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } else {/* don't trust this cert */ |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ break; |
+ case certUsageVerifyCA: |
+ case certUsageStatusResponder: |
+ flags = trust.sslFlags; |
+ /* is the cert directly trusted or not trusted ? */ |
+ if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
+ (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } |
+ flags = trust.emailFlags; |
+ /* is the cert directly trusted or not trusted ? */ |
+ if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
+ (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } |
+ flags = trust.objectSigningFlags; |
+ /* is the cert directly trusted or not trusted ? */ |
+ if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
+ (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
+ *trusted = PR_TRUE; |
+ return SECSuccess; |
+ } |
+ /* fall through to test distrust */ |
+ case certUsageAnyCA: |
+ case certUsageUserCertImport: |
+ /* do we distrust these certs explicitly */ |
+ flags = trust.sslFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ flags = trust.emailFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ /* fall through */ |
+ case certUsageProtectedObjectSigner: |
+ flags = trust.objectSigningFlags; |
+ if (flags & CERTDB_TERMINAL_RECORD) {/* the trust record is |
+ * authoritative */ |
+ if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
+ *failedFlags = flags; |
+ return SECFailure; |
+ } |
+ } |
+ break; |
} |
- return SECSuccess; |
+ } |
+ return SECSuccess; |
} |
/* |
* verify a certificate by checking if it's valid and that we |
* trust the issuer. |
* |
* certificateUsage contains a bitfield of all cert usages that are |
* required for verification to succeed |
* |
* a bitfield of cert usages is returned in *returnedUsages |
* if requiredUsages is non-zero, the returned bitmap is only |
* for those required usages, otherwise it is for all usages |
* |
*/ |
-SECStatus |
-CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t, |
- void *wincx, CERTVerifyLog *log, SECCertificateUsage* returnedUsages) |
-{ |
- SECStatus rv; |
- SECStatus valid; |
- unsigned int requiredKeyUsage; |
- unsigned int requiredCertType; |
- unsigned int flags; |
- unsigned int certType; |
- PRBool allowOverride; |
- SECCertTimeValidity validity; |
- CERTStatusConfig *statusConfig; |
- PRInt32 i; |
- SECCertUsage certUsage = 0; |
- PRBool checkedOCSP = PR_FALSE; |
- PRBool checkAllUsages = PR_FALSE; |
- PRBool revoked = PR_FALSE; |
- PRBool sigerror = PR_FALSE; |
- PRBool trusted = PR_FALSE; |
+SECStatus CERT_VerifyCertificate(CERTCertDBHandle *handle, |
+ CERTCertificate *cert, PRBool checkSig, |
+ SECCertificateUsage requiredUsages, PRTime t, |
+ void *wincx, CERTVerifyLog *log, |
+ SECCertificateUsage *returnedUsages) { |
+ SECStatus rv; |
+ SECStatus valid; |
+ unsigned int requiredKeyUsage; |
+ unsigned int requiredCertType; |
+ unsigned int flags; |
+ unsigned int certType; |
+ PRBool allowOverride; |
+ SECCertTimeValidity validity; |
+ CERTStatusConfig *statusConfig; |
+ PRInt32 i; |
+ SECCertUsage certUsage = 0; |
+ PRBool checkedOCSP = PR_FALSE; |
+ PRBool checkAllUsages = PR_FALSE; |
+ PRBool revoked = PR_FALSE; |
+ PRBool sigerror = PR_FALSE; |
+ PRBool trusted = PR_FALSE; |
- if (!requiredUsages) { |
- /* there are no required usages, so the user probably wants to |
- get status for all usages */ |
- checkAllUsages = PR_TRUE; |
+ if (!requiredUsages) { |
+ /* there are no required usages, so the user probably wants to |
+ get status for all usages */ |
+ checkAllUsages = PR_TRUE; |
+ } |
+ |
+ if (returnedUsages) { |
+ *returnedUsages = 0; |
+ } else { |
+ /* we don't have a place to return status for all usages, |
+ so we can skip checks for usages that aren't required */ |
+ checkAllUsages = PR_FALSE; |
+ } |
+ valid = SECSuccess; /* start off assuming cert is valid */ |
+ |
+ /* make sure that the cert is valid at time t */ |
+ allowOverride = |
+ (PRBool)((requiredUsages & certificateUsageSSLServer) || |
+ (requiredUsages & certificateUsageSSLServerWithStepUp)); |
+ validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
+ if (validity != secCertTimeValid) { |
+ valid = SECFailure; |
+ LOG_ERROR_OR_EXIT(log, cert, 0, validity); |
+ } |
+ |
+ /* check key usage and netscape cert type */ |
+ cert_GetCertType(cert); |
+ certType = cert->nsCertType; |
+ |
+ for (i = 1; i <= certificateUsageHighest && |
+ (SECSuccess == valid || returnedUsages || log);) { |
+ PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; |
+ if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { |
+ NEXT_USAGE(); |
} |
- |
if (returnedUsages) { |
- *returnedUsages = 0; |
- } else { |
- /* we don't have a place to return status for all usages, |
- so we can skip checks for usages that aren't required */ |
- checkAllUsages = PR_FALSE; |
+ *returnedUsages |= i; /* start off assuming this usage is valid */ |
} |
- valid = SECSuccess ; /* start off assuming cert is valid */ |
- |
- /* make sure that the cert is valid at time t */ |
- allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) || |
- (requiredUsages & certificateUsageSSLServerWithStepUp)); |
- validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
- if ( validity != secCertTimeValid ) { |
- valid = SECFailure; |
- LOG_ERROR_OR_EXIT(log,cert,0,validity); |
- } |
- |
- /* check key usage and netscape cert type */ |
- cert_GetCertType(cert); |
- certType = cert->nsCertType; |
- |
- for (i=1; i<=certificateUsageHighest && |
- (SECSuccess == valid || returnedUsages || log) ; ) { |
- PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; |
- if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { |
- NEXT_USAGE(); |
- } |
- if (returnedUsages) { |
- *returnedUsages |= i; /* start off assuming this usage is valid */ |
- } |
- switch ( certUsage ) { |
- case certUsageSSLClient: |
- case certUsageSSLServer: |
- case certUsageSSLServerWithStepUp: |
- case certUsageSSLCA: |
- case certUsageEmailSigner: |
- case certUsageEmailRecipient: |
- case certUsageObjectSigner: |
- case certUsageStatusResponder: |
- rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, |
- &requiredKeyUsage, |
- &requiredCertType); |
- if ( rv != SECSuccess ) { |
- PORT_Assert(0); |
- /* EXIT_IF_NOT_LOGGING(log); XXX ??? */ |
- requiredKeyUsage = 0; |
- requiredCertType = 0; |
- INVALID_USAGE(); |
- } |
- break; |
- |
- case certUsageAnyCA: |
- case certUsageProtectedObjectSigner: |
- case certUsageUserCertImport: |
- case certUsageVerifyCA: |
- /* these usages cannot be verified */ |
- NEXT_USAGE(); |
- |
- default: |
- PORT_Assert(0); |
- requiredKeyUsage = 0; |
- requiredCertType = 0; |
- INVALID_USAGE(); |
- } |
- if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) { |
- if (PR_TRUE == requiredUsage) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
- } |
- LOG_ERROR(log,cert,0,requiredKeyUsage); |
- INVALID_USAGE(); |
- } |
- if ( !( certType & requiredCertType ) ) { |
- if (PR_TRUE == requiredUsage) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
- } |
- LOG_ERROR(log,cert,0,requiredCertType); |
- INVALID_USAGE(); |
- } |
- |
- rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted); |
- if (rv == SECFailure) { |
- if (PR_TRUE == requiredUsage) { |
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
- } |
- LOG_ERROR(log, cert, 0, flags); |
- INVALID_USAGE(); |
- } else if (trusted) { |
- VALID_USAGE(); |
- } |
- |
- if (PR_TRUE == revoked || PR_TRUE == sigerror) { |
- INVALID_USAGE(); |
- } |
- |
- rv = cert_VerifyCertChain(handle, cert, |
- checkSig, &sigerror, |
- certUsage, t, wincx, log, |
- &revoked); |
- |
- if (rv != SECSuccess) { |
- /* EXIT_IF_NOT_LOGGING(log); XXX ???? */ |
- INVALID_USAGE(); |
- } |
- |
- /* |
- * Check OCSP revocation status, but only if the cert we are checking |
- * is not a status responder itself. We only do this in the case |
- * where we checked the cert chain (above); explicit trust "wins" |
- * (avoids status checking, just as it avoids CRL checking) by |
- * bypassing this code. |
- */ |
- |
- if (PR_FALSE == checkedOCSP) { |
- checkedOCSP = PR_TRUE; /* only check OCSP once */ |
- statusConfig = CERT_GetStatusConfig(handle); |
- if (requiredUsages != certificateUsageStatusResponder && |
- statusConfig != NULL) { |
- if (statusConfig->statusChecker != NULL) { |
- rv = (* statusConfig->statusChecker)(handle, cert, |
- t, wincx); |
- if (rv != SECSuccess) { |
- LOG_ERROR(log,cert,0,0); |
- revoked = PR_TRUE; |
- INVALID_USAGE(); |
- } |
- } |
- } |
- } |
- |
- NEXT_USAGE(); |
- } |
- |
-loser: |
- return(valid); |
-} |
- |
-SECStatus |
-CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertUsage certUsage, PRTime t, |
- void *wincx, CERTVerifyLog *log) |
-{ |
- return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t, |
- CERT_VERIFYCERT_USE_DEFAULTS, wincx, log); |
-} |
- |
-SECStatus |
-cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertUsage certUsage, PRTime t, |
- PRUint32 flags, void *wincx, CERTVerifyLog *log) |
-{ |
- SECStatus rv; |
- unsigned int requiredKeyUsage; |
- unsigned int requiredCertType; |
- unsigned int failedFlags; |
- unsigned int certType; |
- PRBool trusted; |
- PRBool allowOverride; |
- SECCertTimeValidity validity; |
- CERTStatusConfig *statusConfig; |
- |
-#ifdef notdef |
- /* check if this cert is in the Evil list */ |
- rv = CERT_CheckForEvilCert(cert); |
- if ( rv != SECSuccess ) { |
- PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
- LOG_ERROR_OR_EXIT(log,cert,0,0); |
- } |
-#endif |
- |
- /* make sure that the cert is valid at time t */ |
- allowOverride = (PRBool)((certUsage == certUsageSSLServer) || |
- (certUsage == certUsageSSLServerWithStepUp)); |
- validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
- if ( validity != secCertTimeValid ) { |
- LOG_ERROR_OR_EXIT(log,cert,0,validity); |
- } |
- |
- /* check key usage and netscape cert type */ |
- cert_GetCertType(cert); |
- certType = cert->nsCertType; |
- switch ( certUsage ) { |
+ switch (certUsage) { |
case certUsageSSLClient: |
case certUsageSSLServer: |
case certUsageSSLServerWithStepUp: |
case certUsageSSLCA: |
case certUsageEmailSigner: |
case certUsageEmailRecipient: |
case certUsageObjectSigner: |
case certUsageStatusResponder: |
- rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, |
- &requiredKeyUsage, |
- &requiredCertType); |
- if ( rv != SECSuccess ) { |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredKeyUsage = 0; |
- requiredCertType = 0; |
- } |
- break; |
+ rv = CERT_KeyUsageAndTypeForCertUsage( |
+ certUsage, PR_FALSE, &requiredKeyUsage, &requiredCertType); |
+ if (rv != SECSuccess) { |
+ PORT_Assert(0); |
+ /* EXIT_IF_NOT_LOGGING(log); XXX ??? */ |
+ requiredKeyUsage = 0; |
+ requiredCertType = 0; |
+ INVALID_USAGE(); |
+ } |
+ break; |
+ |
+ case certUsageAnyCA: |
+ case certUsageProtectedObjectSigner: |
+ case certUsageUserCertImport: |
case certUsageVerifyCA: |
- case certUsageAnyCA: |
- requiredKeyUsage = KU_KEY_CERT_SIGN; |
- requiredCertType = NS_CERT_TYPE_CA; |
- if ( ! ( certType & NS_CERT_TYPE_CA ) ) { |
- certType |= NS_CERT_TYPE_CA; |
- } |
- break; |
+ /* these usages cannot be verified */ |
+ NEXT_USAGE(); |
+ |
default: |
- PORT_Assert(0); |
- EXIT_IF_NOT_LOGGING(log); |
- requiredKeyUsage = 0; |
- requiredCertType = 0; |
+ PORT_Assert(0); |
+ requiredKeyUsage = 0; |
+ requiredCertType = 0; |
+ INVALID_USAGE(); |
} |
- if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
- LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage); |
+ if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { |
+ if (PR_TRUE == requiredUsage) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
+ } |
+ LOG_ERROR(log, cert, 0, requiredKeyUsage); |
+ INVALID_USAGE(); |
} |
- if ( !( certType & requiredCertType ) ) { |
- PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
- LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType); |
+ if (!(certType & requiredCertType)) { |
+ if (PR_TRUE == requiredUsage) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
+ } |
+ LOG_ERROR(log, cert, 0, requiredCertType); |
+ INVALID_USAGE(); |
} |
- rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted); |
- if (rv == SECFailure) { |
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
- LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags); |
+ rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted); |
+ if (rv == SECFailure) { |
+ if (PR_TRUE == requiredUsage) { |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
+ } |
+ LOG_ERROR(log, cert, 0, flags); |
+ INVALID_USAGE(); |
} else if (trusted) { |
- goto done; |
+ VALID_USAGE(); |
} |
+ if (PR_TRUE == revoked || PR_TRUE == sigerror) { |
+ INVALID_USAGE(); |
+ } |
- rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage, |
- t, wincx, log); |
+ rv = cert_VerifyCertChain(handle, cert, checkSig, &sigerror, certUsage, t, |
+ wincx, log, &revoked); |
+ |
if (rv != SECSuccess) { |
- EXIT_IF_NOT_LOGGING(log); |
+ /* EXIT_IF_NOT_LOGGING(log); XXX ???? */ |
+ INVALID_USAGE(); |
} |
/* |
- * Check revocation status, but only if the cert we are checking is not a |
- * status responder itself and the caller did not ask us to skip the check. |
- * We only do this in the case where we checked the cert chain (above); |
- * explicit trust "wins" (avoids status checking, just as it avoids CRL |
- * checking, which is all done inside VerifyCertChain) by bypassing this |
- * code. |
+ * Check OCSP revocation status, but only if the cert we are checking |
+ * is not a status responder itself. We only do this in the case |
+ * where we checked the cert chain (above); explicit trust "wins" |
+ * (avoids status checking, just as it avoids CRL checking) by |
+ * bypassing this code. |
*/ |
- if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) && |
- certUsage != certUsageStatusResponder) { |
- statusConfig = CERT_GetStatusConfig(handle); |
- if (statusConfig && statusConfig->statusChecker) { |
- rv = (* statusConfig->statusChecker)(handle, cert, |
- t, wincx); |
- if (rv != SECSuccess) { |
- LOG_ERROR_OR_EXIT(log,cert,0,0); |
- } |
- } |
+ |
+ if (PR_FALSE == checkedOCSP) { |
+ checkedOCSP = PR_TRUE; /* only check OCSP once */ |
+ statusConfig = CERT_GetStatusConfig(handle); |
+ if (requiredUsages != certificateUsageStatusResponder && |
+ statusConfig != NULL) { |
+ if (statusConfig->statusChecker != NULL) { |
+ rv = (*statusConfig->statusChecker)(handle, cert, t, wincx); |
+ if (rv != SECSuccess) { |
+ LOG_ERROR(log, cert, 0, 0); |
+ revoked = PR_TRUE; |
+ INVALID_USAGE(); |
+ } |
+ } |
+ } |
} |
-done: |
- if (log && log->head) { |
- return SECFailure; |
- } |
- return(SECSuccess); |
+ NEXT_USAGE(); |
+ } |
loser: |
- rv = SECFailure; |
- |
- return(rv); |
+ return (valid); |
+} |
+ |
+SECStatus CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, |
+ PRBool checkSig, SECCertUsage certUsage, PRTime t, |
+ void *wincx, CERTVerifyLog *log) { |
+ return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t, |
+ CERT_VERIFYCERT_USE_DEFAULTS, wincx, log); |
+} |
+ |
+SECStatus cert_VerifyCertWithFlags(CERTCertDBHandle *handle, |
+ CERTCertificate *cert, PRBool checkSig, |
+ SECCertUsage certUsage, PRTime t, |
+ PRUint32 flags, void *wincx, |
+ CERTVerifyLog *log) { |
+ SECStatus rv; |
+ unsigned int requiredKeyUsage; |
+ unsigned int requiredCertType; |
+ unsigned int failedFlags; |
+ unsigned int certType; |
+ PRBool trusted; |
+ PRBool allowOverride; |
+ SECCertTimeValidity validity; |
+ CERTStatusConfig *statusConfig; |
+ |
+#ifdef notdef |
+ /* check if this cert is in the Evil list */ |
+ rv = CERT_CheckForEvilCert(cert); |
+ if (rv != SECSuccess) { |
+ PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
+ } |
+#endif |
+ |
+ /* make sure that the cert is valid at time t */ |
+ allowOverride = (PRBool)((certUsage == certUsageSSLServer) || |
+ (certUsage == certUsageSSLServerWithStepUp)); |
+ validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
+ if (validity != secCertTimeValid) { |
+ LOG_ERROR_OR_EXIT(log, cert, 0, validity); |
+ } |
+ |
+ /* check key usage and netscape cert type */ |
+ cert_GetCertType(cert); |
+ certType = cert->nsCertType; |
+ switch (certUsage) { |
+ case certUsageSSLClient: |
+ case certUsageSSLServer: |
+ case certUsageSSLServerWithStepUp: |
+ case certUsageSSLCA: |
+ case certUsageEmailSigner: |
+ case certUsageEmailRecipient: |
+ case certUsageObjectSigner: |
+ case certUsageStatusResponder: |
+ rv = CERT_KeyUsageAndTypeForCertUsage( |
+ certUsage, PR_FALSE, &requiredKeyUsage, &requiredCertType); |
+ if (rv != SECSuccess) { |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredKeyUsage = 0; |
+ requiredCertType = 0; |
+ } |
+ break; |
+ case certUsageVerifyCA: |
+ case certUsageAnyCA: |
+ requiredKeyUsage = KU_KEY_CERT_SIGN; |
+ requiredCertType = NS_CERT_TYPE_CA; |
+ if (!(certType & NS_CERT_TYPE_CA)) { |
+ certType |= NS_CERT_TYPE_CA; |
+ } |
+ break; |
+ default: |
+ PORT_Assert(0); |
+ EXIT_IF_NOT_LOGGING(log); |
+ requiredKeyUsage = 0; |
+ requiredCertType = 0; |
+ } |
+ if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage); |
+ } |
+ if (!(certType & requiredCertType)) { |
+ PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType); |
+ } |
+ |
+ rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted); |
+ if (rv == SECFailure) { |
+ PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
+ LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags); |
+ } else if (trusted) { |
+ goto done; |
+ } |
+ |
+ rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, wincx, log); |
+ if (rv != SECSuccess) { |
+ EXIT_IF_NOT_LOGGING(log); |
+ } |
+ |
+ /* |
+ * Check revocation status, but only if the cert we are checking is not a |
+ * status responder itself and the caller did not ask us to skip the check. |
+ * We only do this in the case where we checked the cert chain (above); |
+ * explicit trust "wins" (avoids status checking, just as it avoids CRL |
+ * checking, which is all done inside VerifyCertChain) by bypassing this |
+ * code. |
+ */ |
+ if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) && |
+ certUsage != certUsageStatusResponder) { |
+ statusConfig = CERT_GetStatusConfig(handle); |
+ if (statusConfig && statusConfig->statusChecker) { |
+ rv = (*statusConfig->statusChecker)(handle, cert, t, wincx); |
+ if (rv != SECSuccess) { |
+ LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
+ } |
+ } |
+ } |
+ |
+done: |
+ if (log && log->head) { |
+ return SECFailure; |
+ } |
+ return (SECSuccess); |
+ |
+loser: |
+ rv = SECFailure; |
+ |
+ return (rv); |
} |
/* |
* verify a certificate by checking if its valid and that we |
* trust the issuer. Verify time against now. |
*/ |
-SECStatus |
-CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertificateUsage requiredUsages, |
- void *wincx, SECCertificateUsage* returnedUsages) |
-{ |
- return(CERT_VerifyCertificate(handle, cert, checkSig, |
- requiredUsages, PR_Now(), wincx, NULL, returnedUsages)); |
+SECStatus CERT_VerifyCertificateNow(CERTCertDBHandle *handle, |
+ CERTCertificate *cert, PRBool checkSig, |
+ SECCertificateUsage requiredUsages, |
+ void *wincx, |
+ SECCertificateUsage *returnedUsages) { |
+ return (CERT_VerifyCertificate(handle, cert, checkSig, requiredUsages, |
+ PR_Now(), wincx, NULL, returnedUsages)); |
} |
/* obsolete, do not use for new code */ |
-SECStatus |
-CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, |
- PRBool checkSig, SECCertUsage certUsage, void *wincx) |
-{ |
- return(CERT_VerifyCert(handle, cert, checkSig, |
- certUsage, PR_Now(), wincx, NULL)); |
+SECStatus CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, |
+ PRBool checkSig, SECCertUsage certUsage, |
+ void *wincx) { |
+ return (CERT_VerifyCert(handle, cert, checkSig, certUsage, PR_Now(), wincx, |
+ NULL)); |
} |
- |
/* [ FROM pcertdb.c ] */ |
/* |
* Supported usage values and types: |
* certUsageSSLClient |
* certUsageSSLServer |
* certUsageSSLServerWithStepUp |
* certUsageEmailSigner |
* certUsageEmailRecipient |
* certUsageObjectSigner |
*/ |
-CERTCertificate * |
-CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName, |
- CERTCertOwner owner, SECCertUsage usage, |
- PRBool preferTrusted, PRTime validTime, PRBool validOnly) |
-{ |
- CERTCertList *certList = NULL; |
- CERTCertificate *cert = NULL; |
- CERTCertTrust certTrust; |
- unsigned int requiredTrustFlags; |
- SECTrustType requiredTrustType; |
- unsigned int flags; |
- |
- PRBool lookingForCA = PR_FALSE; |
- SECStatus rv; |
- CERTCertListNode *node; |
- CERTCertificate *saveUntrustedCA = NULL; |
- |
- /* if preferTrusted is set, must be a CA cert */ |
- PORT_Assert( ! ( preferTrusted && ( owner != certOwnerCA ) ) ); |
- |
- if ( owner == certOwnerCA ) { |
- lookingForCA = PR_TRUE; |
- if ( preferTrusted ) { |
- rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags, |
- &requiredTrustType); |
- if ( rv != SECSuccess ) { |
- goto loser; |
- } |
- requiredTrustFlags |= CERTDB_VALID_CA; |
- } |
+CERTCertificate *CERT_FindMatchingCert(CERTCertDBHandle *handle, |
+ SECItem *derName, CERTCertOwner owner, |
+ SECCertUsage usage, PRBool preferTrusted, |
+ PRTime validTime, PRBool validOnly) { |
+ CERTCertList *certList = NULL; |
+ CERTCertificate *cert = NULL; |
+ CERTCertTrust certTrust; |
+ unsigned int requiredTrustFlags; |
+ SECTrustType requiredTrustType; |
+ unsigned int flags; |
+ |
+ PRBool lookingForCA = PR_FALSE; |
+ SECStatus rv; |
+ CERTCertListNode *node; |
+ CERTCertificate *saveUntrustedCA = NULL; |
+ |
+ /* if preferTrusted is set, must be a CA cert */ |
+ PORT_Assert(!(preferTrusted && (owner != certOwnerCA))); |
+ |
+ if (owner == certOwnerCA) { |
+ lookingForCA = PR_TRUE; |
+ if (preferTrusted) { |
+ rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags, |
+ &requiredTrustType); |
+ if (rv != SECSuccess) { |
+ goto loser; |
+ } |
+ requiredTrustFlags |= CERTDB_VALID_CA; |
+ } |
+ } |
+ |
+ certList = |
+ CERT_CreateSubjectCertList(NULL, handle, derName, validTime, validOnly); |
+ if (certList != NULL) { |
+ rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA); |
+ if (rv != SECSuccess) { |
+ goto loser; |
} |
- certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime, |
- validOnly); |
- if ( certList != NULL ) { |
- rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA); |
- if ( rv != SECSuccess ) { |
- goto loser; |
- } |
- |
- node = CERT_LIST_HEAD(certList); |
- |
- while ( !CERT_LIST_END(node, certList) ) { |
- cert = node->cert; |
+ node = CERT_LIST_HEAD(certList); |
- /* looking for a trusted CA cert */ |
- if ( ( owner == certOwnerCA ) && preferTrusted && |
- ( requiredTrustType != trustTypeNone ) ) { |
+ while (!CERT_LIST_END(node, certList)) { |
+ cert = node->cert; |
- if ( CERT_GetCertTrust(cert, &certTrust) != SECSuccess ) { |
- flags = 0; |
- } else { |
- flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType); |
- } |
+ /* looking for a trusted CA cert */ |
+ if ((owner == certOwnerCA) && preferTrusted && |
+ (requiredTrustType != trustTypeNone)) { |
- if ( ( flags & requiredTrustFlags ) != requiredTrustFlags ) { |
- /* cert is not trusted */ |
- /* if this is the first cert to get this far, then save |
- * it, so we can use it if we can't find a trusted one |
- */ |
- if ( saveUntrustedCA == NULL ) { |
- saveUntrustedCA = cert; |
- } |
- goto endloop; |
- } |
- } |
- /* if we got this far, then this cert meets all criteria */ |
- break; |
- |
-endloop: |
- node = CERT_LIST_NEXT(node); |
- cert = NULL; |
- } |
+ if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) { |
+ flags = 0; |
+ } else { |
+ flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType); |
+ } |
- /* use the saved one if we have it */ |
- if ( cert == NULL ) { |
- cert = saveUntrustedCA; |
- } |
+ if ((flags & requiredTrustFlags) != requiredTrustFlags) { |
+ /* cert is not trusted */ |
+ /* if this is the first cert to get this far, then save |
+ * it, so we can use it if we can't find a trusted one |
+ */ |
+ if (saveUntrustedCA == NULL) { |
+ saveUntrustedCA = cert; |
+ } |
+ goto endloop; |
+ } |
+ } |
+ /* if we got this far, then this cert meets all criteria */ |
+ break; |
- /* if we found one then bump the ref count before freeing the list */ |
- if ( cert != NULL ) { |
- /* bump the ref count */ |
- cert = CERT_DupCertificate(cert); |
- } |
- |
- CERT_DestroyCertList(certList); |
+ endloop: |
+ node = CERT_LIST_NEXT(node); |
+ cert = NULL; |
} |
- return(cert); |
+ /* use the saved one if we have it */ |
+ if (cert == NULL) { |
+ cert = saveUntrustedCA; |
+ } |
+ |
+ /* if we found one then bump the ref count before freeing the list */ |
+ if (cert != NULL) { |
+ /* bump the ref count */ |
+ cert = CERT_DupCertificate(cert); |
+ } |
+ |
+ CERT_DestroyCertList(certList); |
+ } |
+ |
+ return (cert); |
loser: |
- if ( certList != NULL ) { |
- CERT_DestroyCertList(certList); |
- } |
+ if (certList != NULL) { |
+ CERT_DestroyCertList(certList); |
+ } |
- return(NULL); |
+ return (NULL); |
} |
- |
/* [ From certdb.c ] */ |
/* |
* Filter a list of certificates, removing those certs that do not have |
* one of the named CA certs somewhere in their cert chain. |
* |
* "certList" - the list of certificates to filter |
* "nCANames" - number of CA names |
* "caNames" - array of CA names in string(rfc 1485) form |
* "usage" - what use the certs are for, this is used when |
* selecting CA certs |
*/ |
-SECStatus |
-CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, |
- char **caNames, SECCertUsage usage) |
-{ |
- CERTCertificate *issuerCert = NULL; |
- CERTCertificate *subjectCert; |
- CERTCertListNode *node, *freenode; |
- CERTCertificate *cert; |
- int n; |
- char **names; |
- PRBool found; |
- PRTime time; |
- |
- if ( nCANames <= 0 ) { |
- return(SECSuccess); |
+SECStatus CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, |
+ char **caNames, SECCertUsage usage) { |
+ CERTCertificate *issuerCert = NULL; |
+ CERTCertificate *subjectCert; |
+ CERTCertListNode *node, *freenode; |
+ CERTCertificate *cert; |
+ int n; |
+ char **names; |
+ PRBool found; |
+ PRTime time; |
+ |
+ if (nCANames <= 0) { |
+ return (SECSuccess); |
+ } |
+ |
+ time = PR_Now(); |
+ |
+ node = CERT_LIST_HEAD(certList); |
+ |
+ while (!CERT_LIST_END(node, certList)) { |
+ cert = node->cert; |
+ |
+ subjectCert = CERT_DupCertificate(cert); |
+ |
+ /* traverse the CA certs for this cert */ |
+ found = PR_FALSE; |
+ while (subjectCert != NULL) { |
+ n = nCANames; |
+ names = caNames; |
+ |
+ if (subjectCert->issuerName != NULL) { |
+ while (n > 0) { |
+ if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) { |
+ found = PR_TRUE; |
+ break; |
+ } |
+ |
+ n--; |
+ names++; |
+ } |
+ } |
+ |
+ if (found) { |
+ break; |
+ } |
+ |
+ issuerCert = CERT_FindCertIssuer(subjectCert, time, usage); |
+ if (issuerCert == subjectCert) { |
+ CERT_DestroyCertificate(issuerCert); |
+ issuerCert = NULL; |
+ break; |
+ } |
+ CERT_DestroyCertificate(subjectCert); |
+ subjectCert = issuerCert; |
} |
+ CERT_DestroyCertificate(subjectCert); |
+ if (!found) { |
+ /* CA was not found, so remove this cert from the list */ |
+ freenode = node; |
+ node = CERT_LIST_NEXT(node); |
+ CERT_RemoveCertListNode(freenode); |
+ } else { |
+ /* CA was found, so leave it in the list */ |
+ node = CERT_LIST_NEXT(node); |
+ } |
+ } |
- time = PR_Now(); |
- |
- node = CERT_LIST_HEAD(certList); |
- |
- while ( ! CERT_LIST_END(node, certList) ) { |
- cert = node->cert; |
- |
- subjectCert = CERT_DupCertificate(cert); |
- |
- /* traverse the CA certs for this cert */ |
- found = PR_FALSE; |
- while ( subjectCert != NULL ) { |
- n = nCANames; |
- names = caNames; |
- |
- if (subjectCert->issuerName != NULL) { |
- while ( n > 0 ) { |
- if ( PORT_Strcmp(*names, subjectCert->issuerName) == 0 ) { |
- found = PR_TRUE; |
- break; |
- } |
- |
- n--; |
- names++; |
- } |
- } |
- |
- if ( found ) { |
- break; |
- } |
- |
- issuerCert = CERT_FindCertIssuer(subjectCert, time, usage); |
- if ( issuerCert == subjectCert ) { |
- CERT_DestroyCertificate(issuerCert); |
- issuerCert = NULL; |
- break; |
- } |
- CERT_DestroyCertificate(subjectCert); |
- subjectCert = issuerCert; |
- |
- } |
- CERT_DestroyCertificate(subjectCert); |
- if ( !found ) { |
- /* CA was not found, so remove this cert from the list */ |
- freenode = node; |
- node = CERT_LIST_NEXT(node); |
- CERT_RemoveCertListNode(freenode); |
- } else { |
- /* CA was found, so leave it in the list */ |
- node = CERT_LIST_NEXT(node); |
- } |
- } |
- |
- return(SECSuccess); |
+ return (SECSuccess); |
} |
/* |
* Given a certificate, return a string containing the nickname, and possibly |
* one of the validity strings, based on the current validity state of the |
* certificate. |
* |
* "arena" - arena to allocate returned string from. If NULL, then heap |
* is used. |
* "cert" - the cert to get nickname from |
* "expiredString" - the string to append to the nickname if the cert is |
* expired. |
* "notYetGoodString" - the string to append to the nickname if the cert is |
* not yet good. |
*/ |
-char * |
-CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert, |
- char *expiredString, char *notYetGoodString) |
-{ |
- SECCertTimeValidity validity; |
- char *nickname = NULL, *tmpstr = NULL; |
- |
- validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); |
+char *CERT_GetCertNicknameWithValidity(PLArenaPool *arena, |
+ CERTCertificate *cert, |
+ char *expiredString, |
+ char *notYetGoodString) { |
+ SECCertTimeValidity validity; |
+ char *nickname = NULL, *tmpstr = NULL; |
- /* if the cert is good, then just use the nickname directly */ |
- if ( validity == secCertTimeValid ) { |
- if ( arena == NULL ) { |
- nickname = PORT_Strdup(cert->nickname); |
- } else { |
- nickname = PORT_ArenaStrdup(arena, cert->nickname); |
- } |
- |
- if ( nickname == NULL ) { |
- goto loser; |
- } |
+ validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); |
+ |
+ /* if the cert is good, then just use the nickname directly */ |
+ if (validity == secCertTimeValid) { |
+ if (arena == NULL) { |
+ nickname = PORT_Strdup(cert->nickname); |
} else { |
- |
- /* if the cert is not valid, then tack one of the strings on the |
- * end |
- */ |
- if ( validity == secCertTimeExpired ) { |
- tmpstr = PR_smprintf("%s%s", cert->nickname, |
- expiredString); |
- } else if ( validity == secCertTimeNotValidYet ) { |
- /* not yet valid */ |
- tmpstr = PR_smprintf("%s%s", cert->nickname, |
- notYetGoodString); |
- } else { |
- /* undetermined */ |
- tmpstr = PR_smprintf("%s", |
- "(NULL) (Validity Unknown)"); |
- } |
+ nickname = PORT_ArenaStrdup(arena, cert->nickname); |
+ } |
- if ( tmpstr == NULL ) { |
- goto loser; |
- } |
+ if (nickname == NULL) { |
+ goto loser; |
+ } |
+ } else { |
- if ( arena ) { |
- /* copy the string into the arena and free the malloc'd one */ |
- nickname = PORT_ArenaStrdup(arena, tmpstr); |
- PORT_Free(tmpstr); |
- } else { |
- nickname = tmpstr; |
- } |
- if ( nickname == NULL ) { |
- goto loser; |
- } |
- } |
- return(nickname); |
+ /* if the cert is not valid, then tack one of the strings on the |
+ * end |
+ */ |
+ if (validity == secCertTimeExpired) { |
+ tmpstr = PR_smprintf("%s%s", cert->nickname, expiredString); |
+ } else if (validity == secCertTimeNotValidYet) { |
+ /* not yet valid */ |
+ tmpstr = PR_smprintf("%s%s", cert->nickname, notYetGoodString); |
+ } else { |
+ /* undetermined */ |
+ tmpstr = PR_smprintf("%s", "(NULL) (Validity Unknown)"); |
+ } |
+ |
+ if (tmpstr == NULL) { |
+ goto loser; |
+ } |
+ |
+ if (arena) { |
+ /* copy the string into the arena and free the malloc'd one */ |
+ nickname = PORT_ArenaStrdup(arena, tmpstr); |
+ PORT_Free(tmpstr); |
+ } else { |
+ nickname = tmpstr; |
+ } |
+ if (nickname == NULL) { |
+ goto loser; |
+ } |
+ } |
+ return (nickname); |
loser: |
- return(NULL); |
+ return (NULL); |
} |
/* |
* Collect the nicknames from all certs in a CertList. If the cert is not |
* valid, append a string to that nickname. |
* |
* "certList" - the list of certificates |
* "expiredString" - the string to append to the nickname of any expired cert |
* "notYetGoodString" - the string to append to the nickname of any cert |
* that is not yet valid |
*/ |
-CERTCertNicknames * |
-CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString, |
- char *notYetGoodString) |
-{ |
- CERTCertNicknames *names; |
- PLArenaPool *arena; |
- CERTCertListNode *node; |
- char **nn; |
- |
- /* allocate an arena */ |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if ( arena == NULL ) { |
- return(NULL); |
- } |
- |
- /* allocate the structure */ |
- names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); |
- if ( names == NULL ) { |
- goto loser; |
+CERTCertNicknames *CERT_NicknameStringsFromCertList(CERTCertList *certList, |
+ char *expiredString, |
+ char *notYetGoodString) { |
+ CERTCertNicknames *names; |
+ PLArenaPool *arena; |
+ CERTCertListNode *node; |
+ char **nn; |
+ |
+ /* allocate an arena */ |
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
+ if (arena == NULL) { |
+ return (NULL); |
+ } |
+ |
+ /* allocate the structure */ |
+ names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); |
+ if (names == NULL) { |
+ goto loser; |
+ } |
+ |
+ /* init the structure */ |
+ names->arena = arena; |
+ names->head = NULL; |
+ names->numnicknames = 0; |
+ names->nicknames = NULL; |
+ names->totallen = 0; |
+ |
+ /* count the certs in the list */ |
+ node = CERT_LIST_HEAD(certList); |
+ while (!CERT_LIST_END(node, certList)) { |
+ names->numnicknames++; |
+ node = CERT_LIST_NEXT(node); |
+ } |
+ |
+ /* allocate nicknames array */ |
+ names->nicknames = |
+ PORT_ArenaAlloc(arena, sizeof(char *) * names->numnicknames); |
+ if (names->nicknames == NULL) { |
+ goto loser; |
+ } |
+ |
+ /* just in case printf can't deal with null strings */ |
+ if (expiredString == NULL) { |
+ expiredString = ""; |
+ } |
+ |
+ if (notYetGoodString == NULL) { |
+ notYetGoodString = ""; |
+ } |
+ |
+ /* traverse the list of certs and collect the nicknames */ |
+ nn = names->nicknames; |
+ node = CERT_LIST_HEAD(certList); |
+ while (!CERT_LIST_END(node, certList)) { |
+ *nn = CERT_GetCertNicknameWithValidity(arena, node->cert, expiredString, |
+ notYetGoodString); |
+ if (*nn == NULL) { |
+ goto loser; |
} |
- /* init the structure */ |
- names->arena = arena; |
- names->head = NULL; |
- names->numnicknames = 0; |
- names->nicknames = NULL; |
- names->totallen = 0; |
+ names->totallen += PORT_Strlen(*nn); |
- /* count the certs in the list */ |
- node = CERT_LIST_HEAD(certList); |
- while ( ! CERT_LIST_END(node, certList) ) { |
- names->numnicknames++; |
- node = CERT_LIST_NEXT(node); |
- } |
- |
- /* allocate nicknames array */ |
- names->nicknames = PORT_ArenaAlloc(arena, |
- sizeof(char *) * names->numnicknames); |
- if ( names->nicknames == NULL ) { |
- goto loser; |
- } |
+ nn++; |
+ node = CERT_LIST_NEXT(node); |
+ } |
- /* just in case printf can't deal with null strings */ |
- if (expiredString == NULL ) { |
- expiredString = ""; |
- } |
- |
- if ( notYetGoodString == NULL ) { |
- notYetGoodString = ""; |
- } |
- |
- /* traverse the list of certs and collect the nicknames */ |
- nn = names->nicknames; |
- node = CERT_LIST_HEAD(certList); |
- while ( ! CERT_LIST_END(node, certList) ) { |
- *nn = CERT_GetCertNicknameWithValidity(arena, node->cert, |
- expiredString, |
- notYetGoodString); |
- if ( *nn == NULL ) { |
- goto loser; |
- } |
- |
- names->totallen += PORT_Strlen(*nn); |
- |
- nn++; |
- node = CERT_LIST_NEXT(node); |
- } |
- |
- return(names); |
+ return (names); |
loser: |
- PORT_FreeArena(arena, PR_FALSE); |
- return(NULL); |
+ PORT_FreeArena(arena, PR_FALSE); |
+ return (NULL); |
} |
/* |
* Extract the nickname from a nickmake string that may have either |
* expiredString or notYetGoodString appended. |
* |
* Args: |
* "namestring" - the string containing the nickname, and possibly |
* one of the validity label strings |
* "expiredString" - the expired validity label string |
* "notYetGoodString" - the not yet good validity label string |
* |
* Returns the raw nickname |
*/ |
-char * |
-CERT_ExtractNicknameString(char *namestring, char *expiredString, |
- char *notYetGoodString) |
-{ |
- int explen, nyglen, namelen; |
- int retlen; |
- char *retstr; |
- |
- namelen = PORT_Strlen(namestring); |
- explen = PORT_Strlen(expiredString); |
- nyglen = PORT_Strlen(notYetGoodString); |
- |
- if ( namelen > explen ) { |
- if ( PORT_Strcmp(expiredString, &namestring[namelen-explen]) == 0 ) { |
- retlen = namelen - explen; |
- retstr = (char *)PORT_Alloc(retlen+1); |
- if ( retstr == NULL ) { |
- goto loser; |
- } |
- |
- PORT_Memcpy(retstr, namestring, retlen); |
- retstr[retlen] = '\0'; |
- goto done; |
- } |
+char *CERT_ExtractNicknameString(char *namestring, char *expiredString, |
+ char *notYetGoodString) { |
+ int explen, nyglen, namelen; |
+ int retlen; |
+ char *retstr; |
+ |
+ namelen = PORT_Strlen(namestring); |
+ explen = PORT_Strlen(expiredString); |
+ nyglen = PORT_Strlen(notYetGoodString); |
+ |
+ if (namelen > explen) { |
+ if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) { |
+ retlen = namelen - explen; |
+ retstr = (char *)PORT_Alloc(retlen + 1); |
+ if (retstr == NULL) { |
+ goto loser; |
+ } |
+ |
+ PORT_Memcpy(retstr, namestring, retlen); |
+ retstr[retlen] = '\0'; |
+ goto done; |
+ } |
+ } |
+ |
+ if (namelen > nyglen) { |
+ if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) { |
+ retlen = namelen - nyglen; |
+ retstr = (char *)PORT_Alloc(retlen + 1); |
+ if (retstr == NULL) { |
+ goto loser; |
+ } |
+ |
+ PORT_Memcpy(retstr, namestring, retlen); |
+ retstr[retlen] = '\0'; |
+ goto done; |
+ } |
+ } |
+ |
+ /* if name string is shorter than either invalid string, then it must |
+ * be a raw nickname |
+ */ |
+ retstr = PORT_Strdup(namestring); |
+ |
+done: |
+ return (retstr); |
+ |
+loser: |
+ return (NULL); |
+} |
+ |
+CERTCertList *CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, |
+ SECCertUsage usage) { |
+ CERTCertList *chain = NULL; |
+ int count = 0; |
+ |
+ if (NULL == cert) { |
+ return NULL; |
+ } |
+ |
+ cert = CERT_DupCertificate(cert); |
+ if (NULL == cert) { |
+ PORT_SetError(SEC_ERROR_NO_MEMORY); |
+ return NULL; |
+ } |
+ |
+ chain = CERT_NewCertList(); |
+ if (NULL == chain) { |
+ PORT_SetError(SEC_ERROR_NO_MEMORY); |
+ return NULL; |
+ } |
+ |
+ while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) { |
+ if (SECSuccess != CERT_AddCertToListTail(chain, cert)) { |
+ /* return partial chain */ |
+ PORT_SetError(SEC_ERROR_NO_MEMORY); |
+ return chain; |
} |
- if ( namelen > nyglen ) { |
- if ( PORT_Strcmp(notYetGoodString, &namestring[namelen-nyglen]) == 0) { |
- retlen = namelen - nyglen; |
- retstr = (char *)PORT_Alloc(retlen+1); |
- if ( retstr == NULL ) { |
- goto loser; |
- } |
- |
- PORT_Memcpy(retstr, namestring, retlen); |
- retstr[retlen] = '\0'; |
- goto done; |
- } |
+ if (cert->isRoot) { |
+ /* return complete chain */ |
+ return chain; |
} |
- /* if name string is shorter than either invalid string, then it must |
- * be a raw nickname |
- */ |
- retstr = PORT_Strdup(namestring); |
- |
-done: |
- return(retstr); |
+ cert = CERT_FindCertIssuer(cert, time, usage); |
+ } |
-loser: |
- return(NULL); |
+ /* return partial chain */ |
+ PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
+ return chain; |
} |
- |
-CERTCertList * |
-CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage) |
-{ |
- CERTCertList *chain = NULL; |
- int count = 0; |
- |
- if (NULL == cert) { |
- return NULL; |
- } |
- |
- cert = CERT_DupCertificate(cert); |
- if (NULL == cert) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- chain = CERT_NewCertList(); |
- if (NULL == chain) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) { |
- if (SECSuccess != CERT_AddCertToListTail(chain, cert)) { |
- /* return partial chain */ |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return chain; |
- } |
- |
- if (cert->isRoot) { |
- /* return complete chain */ |
- return chain; |
- } |
- |
- cert = CERT_FindCertIssuer(cert, time, usage); |
- } |
- |
- /* return partial chain */ |
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
- return chain; |
-} |