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

📄 chk_chn.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
   of certs from the issuer to the leaf is less than the constraint length, 
   with special handling for PKIX path kludge certs.

   Name constraints are a bit more difficult, the abstract description
   requires building and maintaining a (potentially enormous) name constraint
   tree which is applied to each cert in turn as it's processed, however 
   since name constraints are practically nonexistant and chains are short
   it's more efficient to walk down the cert chain when a constraint is
   encountered and check each cert in turn, which avoids having to maintain
   massive amounts of state information and is no less efficient than a
   single monolithic state comparison.  Again, there's special handling for
   PKIX path kludge certs, see chk_cert.c for details.

   Policy constraints are hardest of all because, with the complex mishmash
   of policies, policy constraints, qualifiers, and mappings it turns out
   that no-one actually knows how to apply them, and even if people could
   agree, with the de facto use of the policy extension as the kitchenSink
   extension it's uncertain how to apply the constraints to typical
   kitchenSink constructs.  The ambiguity of name constraints when applied 
   to altNames is bad enough, with a 50/50 split in PKIX about whether it 
   should be an AND or OR operation, and whether a DN constraint applies to 
   a subjectName or altName or both.  In the absence of any consensus on the
   issue the latter was fixed in the final version of RFC 2459 by somewhat 
   arbitrarily requiring an AND rather than an OR, although how many 
   implementations follow exactly this version rather than the dozen earlier 
   drafts or any other profile or interpretation is unknown.  With policy 
   constraints it's even worse and no-one seems to be able to agree on what 
   to do with them (or more specifically, the people who write the standards 
   don't seem to be aware that there are ambiguities and inconsistencies in 
   the handling of these extensions.  Anyone who doesn't believe this is 
   invited to try implementing the path-processing algorithm in RFC 3280 as 
   described by the pseudocode there).
   
   For example, the various policy constraints in effect act as conditional 
   modifiers on the critical flag of the policies extension and/or the 
   various blah-policy-set settings in the path-processing algorithm, so 
   that under various conditions imposed by the constraints the extension 
   goes from being non-critical to being (effectively) critical.  In addition 
   the constraint extensions can have their own critical flags, which means 
   that we can end up having to chain back through multiple layers of 
   interacting constraint extensions spread across multiple certs to see 
   what the current interpretation of a particular extension is.  Finally, 
   the presence of PKIX path-kludge certs can turn enforcement of constraints
   on and off at various stages of path processing, with extra special cases
   containing exceptions to the exceptions.  In addition the path-kludge
   exceptions apply to some constraint types but not to others, although the
   main body of the spec and the pseudocode path-processing algorithm 
   disagree on which ones and when they're in effect (this implementation
   assumes that the body of the spec is authoritative and the pseudocode
   represents a buggy attempt to implement the spec, rather than the other
   way round).  Since the virtual-criticality can switch itself on and off 
   across certs depending on where in the path they are, the handling of 
   policy constraints is reduced to a complete chaos if we try and interpret 
   them as required by the spec - trying to implement the logic using 
   decision tables ends up with expressions of more than a dozen variables, 
   which indicates that the issue is more or less incomprehensible.  
   However, since it's only applied at the CRYPT_COMPLIANCELEVEL_PKIX_FULL 
   compliance level it's reasonably safe since users should be expecting 
   peculiar behaviour at this level anyway. 

   The requireExplicitPolicy constraint is particularly bizarre, it 
   specifies the number of additional certificates that can be present in 
   the path before the entire path needs to have policies present.  In other 
   words unlike all other length-based constraints (pathLenConstraint, 
   inhibitPolicyMapping, inhibitAnyPolicy) this works both forwards and
   *backwards* up and down the path, making it the PKI equivalent of a COME
   FROM in that at some random point down the path a constraint placed who
   knows where can suddenly retroactively render the previously-valid path 
   invalid.  No-one seems to know why it runs backwards or what the purpose
   of the retroactive triggering after n certs is, for now we only check
   forwards down the path in the manner of all the other length-based 
   constraints.

   Massa make big magic, gunga din */

static int checkConstraints( CERT_INFO *certInfoPtr, const int startCertIndex,
							 const CERT_INFO *issuerCertInfoPtr,
							 int *errorCertIndex, const int explicitPolicy )
	{
	const ATTRIBUTE_LIST *nameConstraintPtr = NULL, *policyConstraintPtr = NULL;
	const ATTRIBUTE_LIST *inhibitPolicyPtr = NULL, *attributeListPtr;
	ATTRIBUTE_LIST pathAttributeList;
	BOOLEAN hasExcludedSubtrees = FALSE, hasPermittedSubtrees = FALSE;
	BOOLEAN hasPolicy = FALSE, hasPathLength = FALSE;
	BOOLEAN hasExplicitPolicy = FALSE, hasInhibitPolicyMap = FALSE;
	BOOLEAN hasInhibitAnyPolicy = FALSE;
	int requireExplicitPolicyLevel, inhibitPolicyMapLevel;
	int inhibitAnyPolicyLevel;
	int certIndex = startCertIndex, status = CRYPT_OK;

	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
	assert( startCertIndex >= -1 );
	assert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( certInfoPtr != issuerCertInfoPtr );

	/* Clear return value */
	*errorCertIndex = CRYPT_ERROR;

	/* Check for path constraints */
	attributeListPtr = findAttributeField( issuerCertInfoPtr->attributes,
										   CRYPT_CERTINFO_PATHLENCONSTRAINT, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		memset( &pathAttributeList, 0, sizeof( ATTRIBUTE_LIST ) );
		pathAttributeList.intValue = attributeListPtr->intValue;
		hasPathLength = TRUE;
		}

	/* Check for policy constraints */
	if( explicitPolicy && \
		checkAttributePresent( issuerCertInfoPtr->attributes, 
							   CRYPT_CERTINFO_CERTIFICATEPOLICIES ) )
		/* Policy chaining purely from the presence of a policy extension
		   is only enforced if the explicit-policy option is set */
		hasPolicy = TRUE;
	attributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
									  CRYPT_CERTINFO_POLICYCONSTRAINTS, FALSE );
	if( attributeListPtr != NULL )
		policyConstraintPtr = attributeListPtr;
	attributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
									  CRYPT_CERTINFO_INHIBITANYPOLICY, TRUE );
	if( attributeListPtr != NULL )
		inhibitPolicyPtr = attributeListPtr;

	/* Check for name constraints */
	attributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
									  CRYPT_CERTINFO_NAMECONSTRAINTS, FALSE );
	if( attributeListPtr != NULL )
		{
		nameConstraintPtr = attributeListPtr;
		hasExcludedSubtrees = findAttributeField( nameConstraintPtr, \
												  CRYPT_CERTINFO_EXCLUDEDSUBTREES, 
												  CRYPT_ATTRIBUTE_NONE ) != NULL;
		hasPermittedSubtrees = findAttributeField( nameConstraintPtr, \
												   CRYPT_CERTINFO_PERMITTEDSUBTREES, 
												   CRYPT_ATTRIBUTE_NONE ) != NULL;
		}

	/* If there aren't any critical policies or constraints present (the 
	   most common case), we're done */
	if( !hasPolicy && !hasPathLength && \
		policyConstraintPtr == NULL && inhibitPolicyPtr == NULL && \
		nameConstraintPtr == NULL )
		return( CRYPT_OK );

	/* Check whether there are requireExplicitPolicy, inhibitPolicyMapping, or 
	   inhibitAnyPolicy attributes, which act as conditional modifiers on the
	   criticality and contents of the policies extension */
	attributeListPtr = findAttributeField( policyConstraintPtr,
										   CRYPT_CERTINFO_REQUIREEXPLICITPOLICY, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		requireExplicitPolicyLevel = attributeListPtr->intValue;
		hasExplicitPolicy = TRUE;
		}
	attributeListPtr = findAttributeField( policyConstraintPtr,
										   CRYPT_CERTINFO_INHIBITPOLICYMAPPING, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		inhibitPolicyMapLevel = attributeListPtr->intValue;
		hasInhibitPolicyMap = TRUE;
		}
	if( inhibitPolicyPtr != NULL )
		{
		inhibitAnyPolicyLevel = inhibitPolicyPtr->intValue;
		hasInhibitAnyPolicy = TRUE;
		}

	/* Walk down the chain checking each cert against the issuer */
	for( certIndex = startCertIndex; \
		 cryptStatusOK( status ) && certIndex >= -1; \
		 certIndex-- )
		{
		CERT_INFO *subjectCertInfoPtr;
		POLICY_TYPE policyType;

		/* Get info for the current cert in the chain */
		status = getCertInfo( certInfoPtr, &subjectCertInfoPtr, certIndex );
		if( cryptStatusError( status ) )
			break;

		/* Check for the presence of further policy constraints.  The path 
		   length value can only ever be decremented once set, so if we find 
		   a further value for the length constraint we set the overall 
		   value to the smaller of the two */
		attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
											   CRYPT_CERTINFO_REQUIREEXPLICITPOLICY, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			if( !hasExplicitPolicy || \
				attributeListPtr->intValue < requireExplicitPolicyLevel )
				requireExplicitPolicyLevel = attributeListPtr->intValue;
			hasExplicitPolicy = TRUE;
			}
		attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
											   CRYPT_CERTINFO_INHIBITPOLICYMAPPING, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			if( !hasInhibitPolicyMap || \
				attributeListPtr->intValue < inhibitPolicyMapLevel )
				inhibitPolicyMapLevel = attributeListPtr->intValue;
			hasInhibitPolicyMap = TRUE;
			}
		attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
											   CRYPT_CERTINFO_INHIBITANYPOLICY, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			if( !hasInhibitAnyPolicy || \
				attributeListPtr->intValue < inhibitAnyPolicyLevel )
				inhibitAnyPolicyLevel = attributeListPtr->intValue;
			hasInhibitAnyPolicy = TRUE;
			}

		/* If any of the policy constraints have triggered, the policy 
		   extension is now treated as critical even if it wasn't before */
		if( ( hasExplicitPolicy && requireExplicitPolicyLevel <= 0 ) || \
			( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) )
			hasPolicy = TRUE;

		/* Determine the necessary policy check type based on the various
		   policy constraints */
		if( hasPolicy )
			{
			const BOOLEAN inhibitAnyPolicy = \
				( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) ? \
				TRUE : FALSE;

			if( hasExplicitPolicy )
				{
				if( requireExplicitPolicyLevel > 0 )
					policyType = inhibitAnyPolicy ? \
								 POLICY_NONE_SPECIFIC : POLICY_NONE;
				else
				if( requireExplicitPolicyLevel == 0 )
					policyType = inhibitAnyPolicy ? \
								 POLICY_SUBJECT_SPECIFIC : POLICY_SUBJECT;
				else
				if( requireExplicitPolicyLevel < 0 )
					policyType = inhibitAnyPolicy ? \
								 POLICY_BOTH_SPECIFIC : POLICY_BOTH;
				}

⌨️ 快捷键说明

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