⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chk_cert.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
			   the DNS name portion */
			status = sNetParseURL( &urlInfo, constrainedString, 
								   constrainedStringLength, URL_TYPE_NONE );
			if( cryptStatusError( status ) )
				{
				/* Exactly what to do in the case of a URL parse error is
				   uncertain.  As usual no-one on the PKIX list has any idea 
				   what the appropriate behaviour is here.  The best option 
				   seems to be to fail closed, otherwise anyone who creates 
				   a URL that the certificate software can't parse but 
				   that's still accepted by other apps (who in general will 
				   bend over backwards to try and accept almost any 
				   malformed URI, if they didn't do this then half the 
				   Internet would stop working) would be able to bypass the
				   name constraint.  The handling is complicated by the 
				   fact that to report a failure at this point we need to 
				   report a match for excluded subtrees but a non-match for 
				   permitted subtrees.  Since it's more likely that we'll 
				   encounter a permitted-subtrees whitelist (who in their 
				   right mind would trust something as flaky as PKI software 
				   to reliably apply an excluded-subtrees blacklist?  Even
				   something as trivial as "ex%41mple.com", let alone 
				   "ex%u0041mple.com", "exAmple.com", or 
				   "ex%EF%BC%A1mpple.com", is likely to trivially fool all 
				   certificate software in existence, so permitted-subtrees 
				   will never work anyway) we report the constraint as being 
				   not matched which will reject the certificate for 
				   permitted-subtrees.  In addition we throw an exception in 
				   debug mode */
				assert( DEBUG_WARN );
				return( FALSE );
				}

			/* Adjust the constrained string info to contain only the DNS 
			   name portion of the URI */
			constrainedString = urlInfo.host;
			startPos = urlInfo.hostLen - stringLength;
			if( startPos < 0 || startPos > MAX_INTLENGTH_SHORT )
				return( FALSE );
			ENSURES_B( startPos + stringLength <= urlInfo.hostLen );

			/* URIs have a special-case requirement where the absence of a
			   wildcard-match indicator (the leading dot) indicates that the
			   constraining DNS name is for a standalone host and not a 
			   portion of the constrained string's DNS name.  This means
			   that the DNS-name portion of the URI must be an exact match
			   for the constraining string */
			if( !isWildcardMatch && startPos != 0 )
				return( FALSE );
			}
		}

	/* Check whether the constraining string is a suffix of the constrained
	   string.  For DNS name constraints the rule for RFC 3280 became 
	   "adding to the LHS" as for other constraints, in RFC 2459 it was
	   another special case where it had to be a subdomain as if an 
	   implicit "." was present */
	return( !strCompare( constrainedString + startPos, string, 
						 stringLength ) ? TRUE : FALSE );
	}

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static BOOLEAN matchAltnameComponent( const ATTRIBUTE_LIST *constrainedAttribute,
									  const ATTRIBUTE_LIST *attribute,
									  IN_ATTRIBUTE \
										const CRYPT_ATTRIBUTE_TYPE attributeType )
	{
	assert( isReadPtr( constrainedAttribute, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isReadPtr( attribute, sizeof( ATTRIBUTE_LIST ) ) );

	REQUIRES( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \
			  attributeType == CRYPT_CERTINFO_RFC822NAME || \
			  attributeType == CRYPT_CERTINFO_DNSNAME || \
			  attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );

	/* If the attribute being matched is a DN, use a DN-specific match */
	if( attributeType == CRYPT_CERTINFO_DIRECTORYNAME )
		{
		return( compareDN( constrainedAttribute->value, attribute->value, 
						   TRUE ) );
		}

	/* It's a string name, use a substring match with attribute type-specific
	   special cases */
	return( wildcardMatch( constrainedAttribute, attribute, 
					( attributeType == CRYPT_CERTINFO_RFC822NAME ) ? \
						MATCH_EMAIL : \
					( attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER ) ? \
						MATCH_URI : \
						MATCH_NONE ) );
	}

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static BOOLEAN checkAltnameConstraints( const ATTRIBUTE_LIST *subjectAttributes,
										const ATTRIBUTE_LIST *issuerAttributes,
										IN_ATTRIBUTE \
											const CRYPT_ATTRIBUTE_TYPE attributeType,
										const BOOLEAN isExcluded )
	{
	const ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;
	int iterationCount;

	assert( isReadPtr( subjectAttributes, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_LIST ) ) );

	REQUIRES( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \
			  attributeType == CRYPT_CERTINFO_RFC822NAME || \
			  attributeType == CRYPT_CERTINFO_DNSNAME || \
			  attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );

	/* Check for the presence of constrained or constraining altName 
	   components.  If either are absent, there are no constraints to 
	   apply */
	attributeListPtr = findAttributeField( issuerAttributes,
									isExcluded ? \
										CRYPT_CERTINFO_EXCLUDEDSUBTREES : \
										CRYPT_CERTINFO_PERMITTEDSUBTREES,
									attributeType );
	if( attributeListPtr == NULL )
		return( TRUE );

	for( constrainedAttributeListPtr = \
			findAttributeField( subjectAttributes, 
								CRYPT_CERTINFO_SUBJECTALTNAME, attributeType ), \
			iterationCount = 0; 
		constrainedAttributeListPtr != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MAX;
		constrainedAttributeListPtr = \
			findNextFieldInstance( constrainedAttributeListPtr ), \
			iterationCount++ )
		{
		const ATTRIBUTE_LIST *attributeListCursor;
		int innerIterationCount;
		BOOLEAN isMatch = FALSE;

		/* Step through the constraining attributes checking if any match 
		   the constrained attribute.  If it's an excluded subtree then none 
		   can match, if it's a permitted subtree then at least one must 
		   match */
		for( attributeListCursor = attributeListPtr, \
				innerIterationCount = 0;
			 attributeListCursor != NULL && !isMatch && \
				innerIterationCount < FAILSAFE_ITERATIONS_MAX;
			 attributeListCursor = 
				findNextFieldInstance( attributeListCursor ), \
				innerIterationCount++ )
			{
			isMatch = matchAltnameComponent( constrainedAttributeListPtr,
											 attributeListCursor,
											 attributeType );
			}
		ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MAX );
		if( isExcluded == isMatch )
			return( FALSE );
		}
	ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_MAX );

	return( TRUE );
	}

/****************************************************************************
*																			*
*						Check for Constraint Violations						*
*																			*
****************************************************************************/

/* Check name constraints placed by an issuer, checked if complianceLevel >=
   CRYPT_COMPLIANCELEVEL_PKIX_FULL */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
int checkNameConstraints( const CERT_INFO *subjectCertInfoPtr,
						  const ATTRIBUTE_LIST *issuerAttributes,
						  const BOOLEAN isExcluded,
						  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
							CRYPT_ATTRIBUTE_TYPE *errorLocus,
						  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
							CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
	const CRYPT_ATTRIBUTE_TYPE constraintType = isExcluded ? \
		CRYPT_CERTINFO_EXCLUDEDSUBTREES : CRYPT_CERTINFO_PERMITTEDSUBTREES;
	ATTRIBUTE_LIST *attributeListPtr;
	BOOLEAN isMatch = FALSE;

	assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	/* If this is a PKIX path-kludge CA certificate then the name 
	   constraints don't apply to it (PKIX section 4.2.1.11).  This is 
	   required in order to allow extra certificates to be kludged into the 
	   path without violating the constraint.  For example with the chain:

		Issuer	Subject		Constraint
		------	-------		----------
		Root	CA			permitted = "EE"
		CA'		CA'
		CA		EE

	   the kludge certificate CA' must be excluded from name constraint 
	   restrictions in order for the path to be valid.  Obviously this is 
	   only necessary for constraints set by the immediate parent but PKIX 
	   says it's for constraints set by all certificates in the chain (!!), 
	   thus making the pathkludge certificate exempt from any name 
	   constraints and not just the one that would cause problems */
	if( isPathKludge( subjectCertInfoPtr ) )
		return( CRYPT_OK );

	/* Check the subject DN if constraints exist.  If it's an excluded 
	   subtree then none can match, if it's a permitted subtree then at 
	   least one must match */
	attributeListPtr = findAttributeField( issuerAttributes, constraintType, 
										   CRYPT_CERTINFO_DIRECTORYNAME );
	if( attributeListPtr != NULL )
		{
		int iterationCount;

		for( iterationCount = 0;
			 attributeListPtr != NULL && !isMatch && \
				iterationCount < FAILSAFE_ITERATIONS_MAX;
			 iterationCount++ )
			{
			isMatch = compareDN( subjectCertInfoPtr->subjectName,
								 attributeListPtr->value, TRUE );
			attributeListPtr = findNextFieldInstance( attributeListPtr );
			}
		ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );
		if( isExcluded == isMatch )
			{
			setErrorValues( CRYPT_CERTINFO_SUBJECTNAME, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* DN constraints apply to both the main subject DN and any other DNs 
	   that may be present as subject altNames, so after we've checked the 
	   main DN we check any altName DNs as well */
	if( !checkAltnameConstraints( subjectAttributes, issuerAttributes,
								  CRYPT_CERTINFO_DIRECTORYNAME, isExcluded ) )
		{
		setErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* Compare the Internet-related names if constraints exist.  We don't
	   have to check for the special case of an email address in the DN 
	   since the certificate import code transparently maps this to the 
	   appropriate altName component */
	if( !checkAltnameConstraints( subjectAttributes, issuerAttributes,
								  CRYPT_CERTINFO_RFC822NAME, isExcluded ) || \
		!checkAltnameConstraints( subjectAttributes, issuerAttributes,
								  CRYPT_CERTINFO_DNSNAME, isExcluded ) || \
		!checkAltnameConstraints( subjectAttributes, issuerAttributes,
								  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, 
								  isExcluded ) )
		{
		setErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

/* Check policy constraints placed by an issuer, checked if complianceLevel 
   >= CRYPT_COMPLIANCELEVEL_PKIX_FULL */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
int checkPolicyConstraints( const CERT_INFO *subjectCertInfoPtr,
							const ATTRIBUTE_LIST *issuerAttributes,
							IN_ENUM_OPT( POLICY ) const POLICY_TYPE policyType,
							OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
								CRYPT_ATTRIBUTE_TYPE *errorLocus,
							OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
								CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_LIST *attributeListPtr = \
					findAttributeField( issuerAttributes, 
										CRYPT_CERTINFO_CERTPOLICYID, 
										CRYPT_ATTRIBUTE_NONE );
	const ATTRIBUTE_LIST *constrainedAttributeListPtr = \
					findAttributeField( subjectCertInfoPtr->attributes, 
										CRYPT_CERTINFO_CERTPOLICYID, 
										CRYPT_ATTRIBUTE_NONE );
	ATTRIBUTE_LIST *attributeCursor;
	BOOLEAN subjectHasPolicy, issuerHasPolicy;
	BOOLEAN subjectHasAnyPolicy, issuerHasAnyPolicy;
	int iterationCount;

	assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	ENSURES( policyType >= POLICY_NONE && policyType < POLICY_LAST );

	/* If there's a policy mapping present then neither the issuer nor 
	   subject domain policies can be the wildcard anyPolicy (PKIX section 
	   4.2.1.6) */
	if( containsAnyPolicy( issuerAttributes, 
						   CRYPT_CERTINFO_ISSUERDOMAINPOLICY ) || \
		containsAnyPolicy( issuerAttributes, 
						   CRYPT_CERTINFO_SUBJECTDOMAINPOLICY ) )
		{
		setErrorValues( CRYPT_CERTINFO_POLICYMAPPINGS, 
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -