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 || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; }
cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,		     PRBool checkSig, PRBool* sigerror,                     SECCertUsage certUsage, int64 t, void *wincx,                     CERTVerifyLog *log, PRBool* revoked){    SECTrustType trustType;    CERTBasicConstraints basicConstraint;    CERTCertificate *issuerCert = NULL;    CERTCertificate *subjectCert = NULL;    CERTCertificate *badCert = NULL;    PRBool isca;    PRBool isFortezzaV1 = PR_FALSE;    SECStatus rv;    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;    CERTCertificate **certsList      = NULL;    int certsListLen = 16;    int namesCount = 0;    cbd_FortezzaType last_type = cbd_None;    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 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.     */    isFortezzaV1 = (PRBool)	(CERT_GetCertKeyType(&subjectCert->subjectPublicKeyInfo) 							== fortezzaKey);    if (isFortezzaV1) {	rv = cert_VerifyFortezzaV1Cert(handle, subjectCert, &last_type, 						cbd_None, t, wincx);	if (rv == SECFailure) {	    /**** PORT_SetError is already set by cert_VerifyFortezzaV1Cert **/	    LOG_ERROR_OR_EXIT(log,subjectCert,0,0);	}    }    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if (arena == NULL) {	goto loser;    }    certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);    if (certsList == 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);	if (certsListLen <= namesCount + subjectNameListLen) {	    certsListLen = (namesCount + subjectNameListLen) * 2;	    certsList = 	        (CERTCertificate **)PORT_Realloc(certsList, 		                     certsListLen * sizeof(CERTCertificate *));	    if (certsList == NULL) {		goto loser;	    }	}	for (i = 0; i < subjectNameListLen; i++) {	    certsList[namesCount + i] = subjectCert;	}	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 (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 {		    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);		    LOG_ERROR_OR_EXIT(log,subjectCert,count,0);		}	    }	}	/*	 * XXX - fortezza may need error logging stuff added	 */	if (isFortezzaV1) {	    rv = cert_VerifyFortezzaV1Cert(handle, issuerCert, &last_type, 					last_type, t, wincx);	    if (rv == SECFailure) {		/**** PORT_SetError is already set by *		 * cert_VerifyFortezzaV1Cert **/		LOG_ERROR_OR_EXIT(log,subjectCert,0,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).	 *	 * 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 || issuerCert->isRoot;	} 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) {            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 ( 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.	*/	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;	}	/* 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;	}	CERT_DestroyCertificate(subjectCert);	subjectCert = issuerCert;    }    subjectCert = NULL;    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);    LOG_ERROR(log,issuerCert,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;}