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

📄 chk_cert.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						  Certificate Checking Routines						*
*						Copyright Peter Gutmann 1997-2005					*
*																			*
****************************************************************************/

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "cert.h"
  #include "certattr.h"
  #include "asn1.h"
  #include "asn1_ext.h"
#elif defined( INC_CHILD )
  #include "cert.h"
  #include "certattr.h"
  #include "../misc/asn1.h"
  #include "../misc/asn1_ext.h"
#else
  #include "cert/cert.h"
  #include "cert/certattr.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Check whether a policy is the wildcard anyPolicy */

static BOOLEAN isAnyPolicy( const ATTRIBUTE_LIST *attributeListPtr )
	{
	return( ( attributeListPtr->valueLength == sizeofOID( OID_ANYPOLICY ) && \
			  !memcmp( attributeListPtr->value, OID_ANYPOLICY, 
					   sizeofOID( OID_ANYPOLICY ) ) ) ? TRUE : FALSE );
	}

/* Check whether a set of policies contains an instance of the anyPolicy
   wildcard */

static BOOLEAN containsAnyPolicy( const ATTRIBUTE_LIST *attributeListPtr,
								  const CRYPT_ATTRIBUTE_TYPE attributeType )
	{
	for( attributeListPtr = findAttributeField( attributeListPtr, \
								attributeType, CRYPT_ATTRIBUTE_NONE ); \
		 attributeListPtr != NULL; \
		 attributeListPtr = findNextFieldInstance( attributeListPtr ) )
		if( isAnyPolicy( attributeListPtr ) )
			return( TRUE );

	return( FALSE );
	}

/* Check the type of policy present in a cert */

static BOOLEAN checkPolicyType( const ATTRIBUTE_LIST *attributeListPtr,
								BOOLEAN *hasPolicy, BOOLEAN *hasAnyPolicy,
								const BOOLEAN inhibitAnyPolicy )
	{
	/* Clear return values */
	*hasPolicy = *hasAnyPolicy = FALSE;

	/* Make sure that there's a policy present, and that it's a specific 
	   policy if an explicit policy is required (the ability to disallow the 
	   wildcard policy via inhibitAnyPolicy was introduced in RFC 3280 along 
	   with the introduction of anyPolicy) */
	if( attributeListPtr == NULL )
		return( FALSE );
	while( attributeListPtr != NULL )
		{
		assert( attributeListPtr->fieldID == CRYPT_CERTINFO_CERTPOLICYID );

		if( isAnyPolicy( attributeListPtr ) )
			*hasAnyPolicy = TRUE;
		else
			*hasPolicy = TRUE;
		attributeListPtr = findNextFieldInstance( attributeListPtr );
		}
	if( inhibitAnyPolicy )
		{
		/* The wildcard anyPolicy isn't valid for the subject, if there's no
		   other policy set this is an error, otherwise we continue without
		   the wildcard match allowed */
		if( !*hasPolicy )
			return( FALSE );
		*hasAnyPolicy = FALSE;
		}

	return( TRUE );
	}

/* Check whether disallowed CA-only attributes are present in a (non-CA) 
   attribute list.  We report the error as a constraint derived from the CA
   flag rather than the attribute itself, since it's the absence of the flag 
   that renders the presence of the attribute invalid */

static BOOLEAN invalidAttributePresent( const ATTRIBUTE_LIST *attributeListPtr,
										const CRYPT_ATTRIBUTE_TYPE attributeType,
										const BOOLEAN isIssuer,
										CRYPT_ATTRIBUTE_TYPE *errorLocus, 
										CRYPT_ERRTYPE_TYPE *errorType )
	{
	BOOLEAN attributePresent;

	/* In some cases only a particular field of an attribute is invalid 
	   rather than the entire attribute.  We use a per-field check if this 
	   is the case (the specific exclusion of path-length constraints in
	   basicConstraints was introduced in RFC 3280) */
	if( attributeType == CRYPT_CERTINFO_PATHLENCONSTRAINT )
		attributePresent = \
				findAttributeField( attributeListPtr,
									CRYPT_CERTINFO_PATHLENCONSTRAINT, 
									CRYPT_ATTRIBUTE_NONE ) != NULL ? \
				TRUE : FALSE;
	else
		attributePresent = \
				checkAttributePresent( attributeListPtr, 
									   CRYPT_CERTINFO_NAMECONSTRAINTS );
	if( attributePresent )
		{
		setErrorValues( CRYPT_CERTINFO_CA, isIssuer ? \
							CRYPT_ERRTYPE_ISSUERCONSTRAINT : \
							CRYPT_ERRTYPE_CONSTRAINT );
		}
	return( attributePresent );
	}

static BOOLEAN invalidAttributesPresent( const ATTRIBUTE_LIST *attibuteListPtr,
										 const BOOLEAN isIssuer,
										 CRYPT_ATTRIBUTE_TYPE *errorLocus, 
										 CRYPT_ERRTYPE_TYPE *errorType )
	{
	return( invalidAttributePresent( attibuteListPtr,
									 CRYPT_CERTINFO_NAMECONSTRAINTS,
									 FALSE, errorLocus, errorType ) || \
			invalidAttributePresent( attibuteListPtr,
									 CRYPT_CERTINFO_POLICYCONSTRAINTS,
									 FALSE, errorLocus, errorType ) || \
			invalidAttributePresent( attibuteListPtr,
									 CRYPT_CERTINFO_INHIBITANYPOLICY,
									 FALSE, errorLocus, errorType ) || \
			invalidAttributePresent( attibuteListPtr,
									 CRYPT_CERTINFO_POLICYMAPPINGS,
									 FALSE, errorLocus, errorType ) || \
			invalidAttributePresent( attibuteListPtr,
									 CRYPT_CERTINFO_PATHLENCONSTRAINT,
									 FALSE, errorLocus, errorType ) ? \
			TRUE : FALSE );
	}

/* Check whether a cert is a PKIX path-kludge cert, which allows extra certs 
   to be kludged into the path without violating any constraints */

static BOOLEAN isPathKludge( const CERT_INFO *certInfoPtr )
	{
	const ATTRIBUTE_LIST *attributeListPtr;

	/* Perform a quick-reject check for certs that haven't been identified 
	   by the cert chain processing code as path-kludge certs */
	if( !( certInfoPtr->flags & CERT_FLAG_PATHKLUDGE ) )
		return( FALSE );

	/* Only CA path-kludge certs are exempt from constraint enforcement.  
	   Non-CA path kludges shouldn't ever occur, but who knows what other 
	   weirdness future RFCs will dream up, so we perform an explicit check 
	   here */
	attributeListPtr = findAttributeField( certInfoPtr->attributes, 
										   CRYPT_CERTINFO_CA, 
										   CRYPT_ATTRIBUTE_NONE );
	return( ( attributeListPtr != NULL && attributeListPtr->intValue ) ? \
			TRUE : FALSE );
	}

/****************************************************************************
*																			*
*							Name Comparison Routines						*
*																			*
****************************************************************************/

/* Perform a wildcarded compare of two strings in attributes.  Certificates
   don't use standard ? and * regular-expression wildcards but instead 
   specify the constraint as a form of longest-suffix filter that's applied 
   to the string (with the usual pile of special-case exceptions that apply 
   to any cert-related rules), so that e.g. www.foo.com would be constrained 
   using foo.com (or more usually .foo.com to avoid erroneous matches for 
   strings like www.barfoo.com) */

typedef enum {
	MATCH_NONE,		/* No special-case matching rules */
	MATCH_EMAIL,	/* Match using email address mailbox exception */
	MATCH_URI,		/* Match only DNS name portion of URI */
	MATCH_LAST		/* Last valid match rule type */
	} MATCH_TYPE;

static BOOLEAN wildcardMatch( const ATTRIBUTE_LIST *constrainedAttribute,
							  const ATTRIBUTE_LIST *attribute,
							  const MATCH_TYPE matchType )
	{
	const char *string = attribute->value;
	const char *constrainedString = constrainedAttribute->value;
	const BOOLEAN isWildcardMatch = ( *string == '.' ) ? TRUE : FALSE;
	int startPos;

	/* Determine the start position of the constraining string within the
	   constrained string: 

		xxxxxyyyyy	- Constrained string
			 yyyyy	- Constraining string
			^
			|
		startPos
	   
	   If the constraining string is longer than the constrained string 
	   (making startPos negative), it can never match */
	startPos = constrainedAttribute->valueLength - attribute->valueLength;
	if( startPos < 0 )
		return( FALSE );

	/* Handle special-case match requirements (PKIX section 4.2.1.11) */
	switch( matchType )
		{
		case MATCH_EMAIL:
			/* Email addresses have a special-case requirement where the 
			   absence of a wildcard-match indicator (the leading dot)
			   indicates that the mailbox has to be located directly on the 
			   constraining hostname rather than merely within that domain, 
			   i.e. user@foo.bar.com is a valid match for .bar.com, but not 
			   for bar.com, which would require user@bar.com to match */
			if( !isWildcardMatch && \
				( startPos < 1 || constrainedString[ startPos - 1 ] != '@' ) )
				return( FALSE );
			break;

		case MATCH_URI:
			{
			URL_INFO urlInfo;
			int status;

			/* URIs can contain trailing location information that isn't 
			   regarded as part of the URI for matching purposes, so before 
			   performing the match we have to parse the URL and only use 
			   the DNS name portion */
			status = sNetParseURL( &urlInfo, constrainedString, 
								   constrainedAttribute->valueLength );
			if( cryptStatusError( status ) )
				return( FALSE );

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

			/* 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, attribute->value, 
						 attribute->valueLength ) ? TRUE : FALSE );
	}

static BOOLEAN matchAltnameComponent( const ATTRIBUTE_LIST *constrainedAttribute,
									  const ATTRIBUTE_LIST *attribute,
									  const CRYPT_ATTRIBUTE_TYPE attributeType )
	{
	/* 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 ) );
	}

static BOOLEAN checkAltnameConstraints( const ATTRIBUTE_LIST *subjectAttributes,
										const ATTRIBUTE_LIST *issuerAttributes,
										const CRYPT_ATTRIBUTE_TYPE attributeType,
										const BOOLEAN isExcluded )
	{
	const ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;

	/* 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 ); 
		constrainedAttributeListPtr != NULL;
		constrainedAttributeListPtr = \
			findNextFieldInstance( constrainedAttributeListPtr ) )
		{
		const ATTRIBUTE_LIST *attributeListCursor;
		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;
			 attributeListCursor != NULL && !isMatch;
			 attributeListCursor = 
				findNextFieldInstance( attributeListCursor ) )
			isMatch = matchAltnameComponent( constrainedAttributeListPtr,
											 attributeListCursor,
											 attributeType );
		if( isExcluded == isMatch )
			return( FALSE );
		}

	return( TRUE );
	}

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

⌨️ 快捷键说明

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