certvfy.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:42k
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "nspr.h"
- #include "secerr.h"
- #include "secport.h"
- #include "seccomon.h"
- #include "secoid.h"
- #include "sslerr.h"
- #include "genname.h"
- #include "keyhi.h"
- #include "cert.h"
- #include "certdb.h"
- #include "cryptohi.h"
- #define PENDING_SLOP (24L*60L*60L)
- /*
- * WARNING - this function is depricated, and will go away in the near future.
- * It has been superseded by CERT_CheckCertValidTimes().
- *
- * Check the validity times of a certificate
- */
- SECStatus
- CERT_CertTimesValid(CERTCertificate *c)
- {
- int64 now, notBefore, notAfter, pendingSlop;
- SECStatus rv;
-
- /* if cert is already marked OK, then don't bother to check */
- if ( c->timeOK ) {
- return(SECSuccess);
- }
-
- /* get current UTC time */
- now = PR_Now();
- rv = CERT_GetCertTimes(c, ¬Before, ¬After);
-
- if (rv) {
- return(SECFailure);
- }
-
- LL_I2L(pendingSlop, PENDING_SLOP);
- LL_SUB(notBefore, notBefore, pendingSlop);
- if (LL_CMP(now, <, notBefore) || LL_CMP(now, >, notAfter)) {
- PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE);
- return(SECFailure);
- }
- return(SECSuccess);
- }
- /*
- * verify the signature of a signed data object with the given certificate
- */
- SECStatus
- CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
- int64 t, void *wincx)
- {
- SECItem sig;
- SECKEYPublicKey *pubKey = 0;
- SECStatus rv;
- SECCertTimeValidity validity;
- SECOidTag algid;
- /* check the certificate's validity */
- validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
- if ( validity != secCertTimeValid ) {
- return(SECFailure);
- }
- /* get cert's public key */
- pubKey = CERT_ExtractPublicKey(cert);
- if ( !pubKey ) {
- return(SECFailure);
- }
-
- /* check the signature */
- sig = sd->signature;
- DER_ConvertBitString(&sig);
- algid = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
- rv = VFY_VerifyData(sd->data.data, sd->data.len, pubKey, &sig,
- algid, wincx);
- SECKEY_DestroyPublicKey(pubKey);
- if ( rv ) {
- return(SECFailure);
- }
- return(SECSuccess);
- }
- /*
- * This must only be called on a cert that is known to have an issuer
- * with an invalid time
- */
- CERTCertificate *
- CERT_FindExpiredIssuer(CERTCertDBHandle *handle, CERTCertificate *cert)
- {
- CERTCertificate *issuerCert = NULL;
- CERTCertificate *subjectCert;
- int count;
- SECStatus rv;
- SECComparison rvCompare;
-
- subjectCert = CERT_DupCertificate(cert);
- if ( subjectCert == NULL ) {
- goto loser;
- }
-
- for ( count = 0; count < CERT_MAX_CERT_CHAIN; count++ ) {
- /* find the certificate of the issuer */
- issuerCert = CERT_FindCertByName(handle, &subjectCert->derIssuer);
-
- if ( ! issuerCert ) {
- goto loser;
- }
- rv = CERT_CertTimesValid(issuerCert);
- if ( rv == SECFailure ) {
- /* this is the invalid issuer */
- CERT_DestroyCertificate(subjectCert);
- return(issuerCert);
- }
- /* make sure that the issuer is not self signed. If it is, then
- * stop here to prevent looping.
- */
- rvCompare = SECITEM_CompareItem(&issuerCert->derSubject,
- &issuerCert->derIssuer);
- if (rvCompare == SECEqual) {
- PORT_Assert(0); /* No expired issuer! */
- goto loser;
- }
- CERT_DestroyCertificate(subjectCert);
- subjectCert = issuerCert;
- }
- loser:
- if ( issuerCert ) {
- CERT_DestroyCertificate(issuerCert);
- }
-
- if ( subjectCert ) {
- CERT_DestroyCertificate(subjectCert);
- }
-
- return(NULL);
- }
- /* Software FORTEZZA installation hack. The software fortezza installer does
- * not have access to the krl and cert.db file. Accept FORTEZZA Certs without
- * KRL's in this case.
- */
- static int dont_use_krl = 0;
- /* not a public exposed function... */
- void sec_SetCheckKRLState(int value) { dont_use_krl = value; }
- SECStatus
- SEC_CheckKRL(CERTCertDBHandle *handle,SECKEYPublicKey *key,
- CERTCertificate *rootCert, int64 t, void * wincx)
- {
- CERTSignedCrl *crl = NULL;
- SECStatus rv = SECFailure;
- SECStatus rv2;
- CERTCrlEntry **crlEntry;
- SECCertTimeValidity validity;
- CERTCertificate *issuerCert = NULL;
- if (dont_use_krl) return SECSuccess;
- /* first look up the KRL */
- crl = SEC_FindCrlByName(handle,&rootCert->derSubject, SEC_KRL_TYPE);
- if (crl == NULL) {
- PORT_SetError(SEC_ERROR_NO_KRL);
- goto done;
- }
- /* get the issuing certificate */
- issuerCert = CERT_FindCertByName(handle, &crl->crl.derName);
- if (issuerCert == NULL) {
- PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
- goto done;
- }
- /* now verify the KRL signature */
- rv2 = CERT_VerifySignedData(&crl->signatureWrap, issuerCert, t, wincx);
- if (rv2 != SECSuccess) {
- PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
- goto done;
- }
- /* Verify the date validity of the KRL */
- validity = SEC_CheckCrlTimes(&crl->crl, t);
- if (validity == secCertTimeExpired) {
- PORT_SetError(SEC_ERROR_KRL_EXPIRED);
- goto done;
- }
- /* now make sure the key in this cert is still valid */
- if (key->keyType != fortezzaKey) {
- PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
- goto done; /* This should be an assert? */
- }
- /* now make sure the key is not on the revocation list */
- for (crlEntry = crl->crl.entries; crlEntry && *crlEntry; crlEntry++) {
- if (PORT_Memcmp((*crlEntry)->serialNumber.data,
- key->u.fortezza.KMID,
- (*crlEntry)->serialNumber.len) == 0) {
- PORT_SetError(SEC_ERROR_REVOKED_KEY);
- goto done;
- }
- }
- rv = SECSuccess;
- done:
- if (issuerCert) CERT_DestroyCertificate(issuerCert);
- if (crl) SEC_DestroyCrl(crl);
- return rv;
- }
- SECStatus
- SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert,
- CERTCertificate *caCert, int64 t, void * wincx)
- {
- CERTSignedCrl *crl = NULL;
- SECStatus rv = SECSuccess;
- CERTCrlEntry **crlEntry;
- SECCertTimeValidity validity;
- /* first look up the CRL */
- crl = SEC_FindCrlByName(handle,&caCert->derSubject, SEC_CRL_TYPE);
- if (crl == NULL) {
- /* XXX for now no CRL is ok */
- goto done;
- }
- /* now verify the CRL signature */
- rv = CERT_VerifySignedData(&crl->signatureWrap, caCert, t, wincx);
- if (rv != SECSuccess) {
- PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
- rv = SECWouldBlock; /* Soft error, ask the user */
- goto done;
- }
- /* Verify the date validity of the KRL */
- validity = SEC_CheckCrlTimes(&crl->crl,t);
- if (validity == secCertTimeExpired) {
- PORT_SetError(SEC_ERROR_CRL_EXPIRED);
- rv = SECWouldBlock; /* Soft error, ask the user */
- } else if (validity == secCertTimeNotValidYet) {
- PORT_SetError(SEC_ERROR_CRL_NOT_YET_VALID);
- rv = SECWouldBlock; /* Soft error, ask the user */
- }
- /* now make sure the key is not on the revocation list */
- for (crlEntry = crl->crl.entries; crlEntry && *crlEntry; crlEntry++) {
- if (SECITEM_CompareItem(&(*crlEntry)->serialNumber,&cert->serialNumber) == SECEqual) {
- PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
- rv = SECFailure; /* cert is revoked */
- goto done;
- }
- }
- done:
- if (crl) SEC_DestroyCrl(crl);
- return rv;
- }
- /*
- * Find the issuer of a cert. Use the authorityKeyID if it exists.
- */
- CERTCertificate *
- CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage)
- {
- CERTAuthKeyID * authorityKeyID = NULL;
- CERTCertificate * issuerCert = NULL;
- SECItem * caName;
- PRArenaPool *tmpArena = NULL;
- SECItem issuerCertKey;
- SECStatus rv;
- tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-
- if ( !tmpArena ) {
- goto loser;
- }
- authorityKeyID = CERT_FindAuthKeyIDExten(tmpArena,cert);
- if ( authorityKeyID != NULL ) {
- /* has the authority key ID extension */
- if ( authorityKeyID->keyID.data != NULL ) {
- /* extension contains a key ID, so lookup based on it */
- issuerCert = CERT_FindCertByKeyID(cert->dbhandle, &cert->derIssuer,
- &authorityKeyID->keyID);
- if ( issuerCert == NULL ) {
- PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER);
- goto loser;
- }
-
- } else if ( authorityKeyID->authCertIssuer != NULL ) {
- /* no key ID, so try issuer and serial number */
- caName = (SECItem*)CERT_GetGeneralNameByType(authorityKeyID->authCertIssuer,
- certDirectoryName, PR_TRUE);
- /*
- * caName is NULL when the authCertIssuer field is not
- * being used, or other name form is used instead.
- * If the directoryName format and serialNumber fields are
- * used, we use them to find the CA cert.
- * Note:
- * By the time it gets here, we known for sure that if the
- * authCertIssuer exists, then the authCertSerialNumber
- * must also exists (CERT_DecodeAuthKeyID() ensures this).
- * We don't need to check again.
- */
- if (caName != NULL) {
- rv = CERT_KeyFromIssuerAndSN(tmpArena, caName,
- &authorityKeyID->authCertSerialNumber,
- &issuerCertKey);
- if ( rv == SECSuccess ) {
- issuerCert = CERT_FindCertByKey(cert->dbhandle,
- &issuerCertKey);
- }
-
- if ( issuerCert == NULL ) {
- PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER);
- goto loser;
- }
- }
- }
- }
- if ( issuerCert == NULL ) {
- /* if there is not authorityKeyID, then try to find the issuer */
- /* find a valid CA cert with correct usage */
- issuerCert = CERT_FindMatchingCert(cert->dbhandle,
- &cert->derIssuer,
- certOwnerCA, usage, PR_TRUE,
- validTime, PR_TRUE);
- /* if that fails, then fall back to grabbing any cert with right name*/
- if ( issuerCert == NULL ) {
- issuerCert = CERT_FindCertByName(cert->dbhandle, &cert->derIssuer);
- if ( issuerCert == NULL ) {
- PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER);
- }
- }
- }
- loser:
- if (tmpArena != NULL) {
- PORT_FreeArena(tmpArena, PR_FALSE);
- tmpArena = NULL;
- }
- return(issuerCert);
- }
- /*
- * 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;
- 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);
- }
- static void
- AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, unsigned 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;
- }
- tnode = tnode->prev;
- }
- }
- log->count++;
- }
- return;
- }
- #define EXIT_IF_NOT_LOGGING(log)
- if ( log == NULL ) {
- goto loser;
- }
- #define LOG_ERROR_OR_EXIT(log,cert,depth,arg)
- if ( log != NULL ) {
- AddToVerifyLog(log, cert, PORT_GetError(), depth, (void *)arg);
- } else {
- goto loser;
- }
- #define LOG_ERROR(log,cert,depth,arg)
- if ( log != NULL ) {
- AddToVerifyLog(log, cert, PORT_GetError(), depth, (void *)arg);
- }
- SECStatus
- CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, int64 t,
- void *wincx, CERTVerifyLog *log)
- {
- SECTrustType trustType;
- CERTBasicConstraints basicConstraint;
- CERTCertificate *issuerCert = NULL;
- CERTCertificate *subjectCert = NULL;
- CERTCertificate *badCert = NULL;
- PRBool isca;
- PRBool isFortezzaV1 = PR_FALSE;
- SECStatus rv;
- SECComparison rvCompare;
- SECStatus rvFinal = SECSuccess;
- int count;
- int currentPathLen = -1;
- int flags;
- unsigned int caCertType;
- unsigned int requiredCAKeyUsage;
- unsigned int requiredFlags;
- PRArenaPool *arena = NULL;
- CERTGeneralName *namesList = NULL;
- CERTGeneralName *subjectNameList = NULL;
- SECItem *namesIndex = NULL;
- int namesIndexLen = 10;
- int namesCount = 0;
- enum { cbd_None, cbd_User, cbd_CA } last_type = cbd_None;
- SECKEYPublicKey *key;
- 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;
- }
-
- subjectCert = CERT_DupCertificate(cert);
- if ( subjectCert == NULL ) {
- goto loser;
- }
- /* determine if the cert is fortezza. Getting the key is an easy
- * way to determine it, especially since we need to get the privillege
- * from the key anyway.
- */
- key = CERT_ExtractPublicKey(cert);
- if (key != NULL) {
- isFortezzaV1 = (PRBool)(key->keyType == fortezzaKey);
- /* find out what type of cert we are starting with */
- if (isFortezzaV1) {
- unsigned char priv = 0;;
- rv = SEC_CheckKRL(handle, key, NULL, t, wincx);
- if (rv == SECFailure) {
- /**** PORT_SetError is already set by SEC_CheckKRL **/
- SECKEY_DestroyPublicKey(key);
- /**** Bob - should we log and continue when logging? **/
- LOG_ERROR(log,subjectCert,0,0);
- goto loser;
- }
- if (key->u.fortezza.DSSpriviledge.len > 0) {
- priv = key->u.fortezza.DSSpriviledge.data[0];
- }
- last_type = (priv & 0x30) ? cbd_CA : cbd_User;
- }
-
- SECKEY_DestroyPublicKey(key);
- }
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- goto loser;
- }
- namesIndex = (SECItem *) PORT_ZAlloc(sizeof(SECItem) * namesIndexLen);
- if (namesIndex == NULL) {
- goto loser;
- }
- for ( count = 0; count < CERT_MAX_CERT_CHAIN; count++ ) {
- int subjectNameListLen;
- int i;
- /* Construct a list of names for the current and all previous certifcates
- to be verified against the name constraints extension of the issuer
- certificate. */
- subjectNameList = CERT_GetCertificateNames(subjectCert, arena);
- subjectNameListLen = CERT_GetNamesLength(subjectNameList);
- for (i = 0; i < subjectNameListLen; i++) {
- if (namesIndexLen < namesCount + i) {
- namesIndexLen = namesIndexLen * 2;
- namesIndex = (SECItem *) PORT_Realloc(namesIndex, namesIndexLen *
- sizeof(SECItem));
- if (namesIndex == NULL) {
- goto loser;
- }
- }
- rv = SECITEM_CopyItem(arena, &(namesIndex[namesCount + i]), &(subjectCert->derSubject));
- }
- namesCount += subjectNameListLen;
- namesList = cert_CombineNamesLists(namesList, subjectNameList);
- /* 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 ( PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ) {
- PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- } else {
- PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
- LOG_ERROR_OR_EXIT(log,subjectCert,count,0);
- }
- }
- }
- /*
- * XXX - fortezza may need error logging stuff added
- */
- if (isFortezzaV1) {
- unsigned char priv = 0;
- /* read the key */
- key = CERT_ExtractPublicKey(issuerCert);
- /* Cant' get Key? fail. */
- if (key == NULL) {
- PORT_SetError(SEC_ERROR_BAD_KEY);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- goto fortezzaDone;
- }
- /* if the issuer is not an old fortezza cert, we bail */
- if (key->keyType != fortezzaKey) {
- SECKEY_DestroyPublicKey(key);
- /* CA Cert not fortezza */
- PORT_SetError(SEC_ERROR_NOT_FORTEZZA_ISSUER);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- goto fortezzaDone;
- }
- /* get the privilege mask */
- if (key->u.fortezza.DSSpriviledge.len > 0) {
- priv = key->u.fortezza.DSSpriviledge.data[0];
- }
- /*
- * make sure the CA's keys are OK
- */
-
- rv = SEC_CheckKRL(handle, key, NULL, t, wincx);
- if (rv != SECSuccess) {
- SECKEY_DestroyPublicKey(key);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- goto fortezzaDone;
- /** fall through looking for more stuff **/
- } else {
- SECKEY_DestroyPublicKey(key);
- }
- switch (last_type) {
- case cbd_User:
- /* first check for subordination */
- /*rv = FortezzaSubordinateCheck(cert,issuerCert);*/
- rv = SECSuccess;
- /* now check for issuer privilege */
- if ((rv != SECSuccess) || ((priv & 0x10) == 0)) {
- /* bail */
- PORT_SetError (SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- }
- break;
- case cbd_CA:
- case cbd_None:
- if ((priv & 0x20) == 0) {
- /* bail */
- PORT_SetError (SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- }
- break;
- default:
- /* bail */ /* shouldn't ever happen */
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- }
- fortezzaDone:
- last_type = cbd_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).
- *
- * In the fortezza (V1) case, we've already checked the CA bits
- * in the key, so we're presumed to be a CA; however we really don't
- * want to bypass Basic constraint or netscape extension parsing.
- *
- * In Fortezza V2, basicConstraint will be set for every CA,PCA,PAA
- */
- 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);
- } else {
- currentPathLen = CERT_UNLIMITED_PATH_CONSTRAINT;
- }
- /* no basic constraints found, if we're fortezza, CA bit is already
- * verified (isca = PR_TRUE). otherwise, we aren't (yet) a ca
- * isca = PR_FALSE */
- isca = isFortezzaV1;
- } else {
- if ( basicConstraint.isCA == PR_FALSE ) {
- PORT_SetError (SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0);
- }
-
- /* make sure that the path len constraint is properly set.
- */
- if ( basicConstraint.pathLenConstraint ==
- CERT_UNLIMITED_PATH_CONSTRAINT ) {
- currentPathLen = CERT_UNLIMITED_PATH_CONSTRAINT;
- } else if ( currentPathLen == CERT_UNLIMITED_PATH_CONSTRAINT ) {
- /* error if the previous CA's path length constraint is
- * unlimited but its CA's path is not.
- */
- PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,basicConstraint.pathLenConstraint);
- } else if (basicConstraint.pathLenConstraint > currentPathLen) {
- currentPathLen = basicConstraint.pathLenConstraint;
- } else {
- PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
- LOG_ERROR_OR_EXIT(log,issuerCert,count+1,basicConstraint.pathLenConstraint);
- }
- isca = PR_TRUE;
- }
-
- /* 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) {
- 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;
- LOG_ERROR(log,subjectCert,count,0);
- }
- if ( issuerCert->trust ) {
- /*
- * check the trust parms of the issuer
- */
- 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(issuerCert->trust, trustType);
-
- if ( (flags & CERTDB_VALID_CA) ||
- (certUsage == certUsageStatusResponder)) {
- if ( ( flags & requiredFlags ) == requiredFlags ||
- certUsage == certUsageStatusResponder ) {
- /* we found a trusted one, so return */
- rv = rvFinal;
- goto done;
- }
- }
- }
- /*
- * 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 ( isca ) {
- /*
- * 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 ( issuerCert->nsCertType & NS_CERT_TYPE_CA ) {
- if ( issuerCert->nsCertType & caCertType ) {
- isca = PR_TRUE;
- } else {
- isca = PR_FALSE;
- }
- }
- } else {
- if ( issuerCert->nsCertType & caCertType ) {
- isca = PR_TRUE;
- } else {
- isca = 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 entire chain is within the name space of the current issuer
- * certificate.
- */
- badCert = CERT_CompareNameSpace(issuerCert, namesList, namesIndex, arena, handle);
- if (badCert != NULL) {
- PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
- LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
- goto loser;
- }
- /* make sure that the issuer is not self signed. If it is, then
- * stop here to prevent looping.
- */
- rvCompare = SECITEM_CompareItem(&issuerCert->derSubject,
- &issuerCert->derIssuer);
- if (rvCompare == SECEqual) {
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
- LOG_ERROR(log, issuerCert, count+1, 0);
- goto loser;
- }
- CERT_DestroyCertificate(subjectCert);
- subjectCert = issuerCert;
- }
- subjectCert = NULL;
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- LOG_ERROR(log,issuerCert,count,0);
- loser:
- rv = SECFailure;
- done:
- if (namesIndex != NULL) {
- PORT_Free(namesIndex);
- }
- if ( issuerCert ) {
- CERT_DestroyCertificate(issuerCert);
- }
-
- if ( subjectCert ) {
- CERT_DestroyCertificate(subjectCert);
- }
- if ( arena != NULL ) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return rv;
- }
-
- /*
- * verify a certificate by checking if its valid and that we
- * trust the issuer.
- * Note that this routine does not verify the signature of the certificate.
- */
- SECStatus
- CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, int64 t,
- void *wincx, CERTVerifyLog *log)
- {
- SECStatus rv;
- unsigned int requiredKeyUsage;
- unsigned int requiredCertType;
- unsigned int flags;
- unsigned int certType;
- PRBool allowOverride;
- SECCertTimeValidity validity;
- CERTStatusConfig *statusConfig;
-
- /* 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);
- }
-
- /* 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:
- 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);
- }
- /* check trust flags to see if this cert is directly trusted */
- if ( cert->trust ) { /* the cert is in the DB */
- switch ( certUsage ) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- flags = cert->trust->sslFlags;
-
- /* is the cert directly trusted or not trusted ? */
- if ( flags & CERTDB_VALID_PEER ) {/*the trust record is valid*/
- if ( flags & CERTDB_TRUSTED ) { /* trust this cert */
- goto winner;
- } else { /* don't trust this cert */
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- LOG_ERROR_OR_EXIT(log,cert,0,flags);
- }
- }
- break;
- case certUsageSSLServerWithStepUp:
- /* XXX - step up certs can't be directly trusted */
- break;
- case certUsageSSLCA:
- break;
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- flags = cert->trust->emailFlags;
-
- /* is the cert directly trusted or not trusted ? */
- if ( ( flags & ( CERTDB_VALID_PEER | CERTDB_TRUSTED ) ) ==
- ( CERTDB_VALID_PEER | CERTDB_TRUSTED ) ) {
- goto winner;
- }
- break;
- case certUsageObjectSigner:
- flags = cert->trust->objectSigningFlags;
- /* is the cert directly trusted or not trusted ? */
- if ( flags & CERTDB_VALID_PEER ) {/*the trust record is valid*/
- if ( flags & CERTDB_TRUSTED ) { /* trust this cert */
- goto winner;
- } else { /* don't trust this cert */
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- LOG_ERROR_OR_EXIT(log,cert,0,flags);
- }
- }
- break;
- case certUsageVerifyCA:
- case certUsageStatusResponder:
- flags = cert->trust->sslFlags;
- /* is the cert directly trusted or not trusted ? */
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
- goto winner;
- }
- flags = cert->trust->emailFlags;
- /* is the cert directly trusted or not trusted ? */
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
- goto winner;
- }
- flags = cert->trust->objectSigningFlags;
- /* is the cert directly trusted or not trusted ? */
- if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) ==
- ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) {
- goto winner;
- }
- break;
- case certUsageAnyCA:
- case certUsageProtectedObjectSigner:
- case certUsageUserCertImport:
- /* XXX to make the compiler happy. Should these be
- * explicitly handled?
- */
- break;
- }
- }
- 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 reponder 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, which
- * is all done inside VerifyCertChain) by bypassing this code.
- */
- statusConfig = CERT_GetStatusConfig(handle);
- if (certUsage != certUsageStatusResponder && statusConfig != NULL) {
- if (statusConfig->statusChecker != NULL) {
- rv = (* statusConfig->statusChecker)(handle, cert,
- t, wincx);
- if (rv != SECSuccess) {
- LOG_ERROR_OR_EXIT(log,cert,0,0);
- }
- }
- }
- winner:
- 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_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, int64 validTime, PRBool validOnly)
- {
- CERTCertList *certList = NULL;
- CERTCertificate *cert = NULL;
- 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;
- }
-
- node = CERT_LIST_HEAD(certList);
-
- while ( !CERT_LIST_END(node, certList) ) {
- cert = node->cert;
- /* looking for a trusted CA cert */
- if ( ( owner == certOwnerCA ) && preferTrusted &&
- ( requiredTrustType != trustTypeNone ) ) {
- if ( cert->trust == NULL ) {
- flags = 0;
- } else {
- flags = SEC_GET_TRUST_FLAGS(cert->trust, requiredTrustType);
- }
- 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;
- }
- /* 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);
- }
- 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;
- int64 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);
- }
- }
-
- 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(PRArenaPool *arena, CERTCertificate *cert,
- char *expiredString, char *notYetGoodString)
- {
- SECCertTimeValidity validity;
- char *nickname, *tmpstr;
-
- 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 {
- nickname = PORT_ArenaStrdup(arena, cert->nickname);
- }
-
- if ( nickname == NULL ) {
- goto loser;
- }
- } 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 {
- /* not yet valid */
- tmpstr = PR_smprintf("%s%s", cert->nickname,
- notYetGoodString);
- }
- 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);
- }
- /*
- * 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;
- PRArenaPool *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;
- }
- names->totallen += PORT_Strlen(*nn);
-
- nn++;
- node = CERT_LIST_NEXT(node);
- }
- return(names);
- loser:
- 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] = ' ';
- 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] = ' ';
- 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, int64 time, SECCertUsage usage)
- {
- CERTCertList *chain;
- if (cert != NULL) {
- chain = CERT_NewCertList();
- cert = CERT_DupCertificate(cert);
- while (SECITEM_CompareItem(&cert->derIssuer, &cert->derSubject)
- != SECEqual) {
- CERT_AddCertToListTail(chain, cert);
- cert = CERT_FindCertIssuer(cert, time, usage);
- }
- CERT_AddCertToListTail(chain, cert);
- return chain;
- }
- return NULL;
- }