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

📄 dn.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:

	/* Find the position of this component in the list */
	for( listPtr = dnComponentList, iterationCount = 0; 
		 listPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
		 listPtr = listPtr->next, iterationCount++ )
		{
		assert( isReadPtr( listPtr, sizeof( DN_COMPONENT ) ) );

		if( listPtr->type == type && \
			( ( value == NULL ) || \
			  ( listPtr->valueLength == valueLength && \
				!memcmp( listPtr->value, value, valueLength ) ) ) )
			break;
		}
	ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( ( DN_COMPONENT * ) listPtr );
	}

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \
static DN_COMPONENT *findDNComponentByOID( const DN_COMPONENT *dnComponentList,
										   IN_BUFFER( oidLength ) const BYTE *oid, 
										   IN_LENGTH_OID const int oidLength )
	{
	const DN_COMPONENT *listPtr;
	int iterationCount;

	assert( isReadPtr( dnComponentList, sizeof( DN_COMPONENT ) ) );
	assert( isReadPtr( oid, oidLength ) );

	REQUIRES_N( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \
				oidLength == sizeofOID( oid ) );

	/* Find the position of this component in the list */
	for( listPtr = dnComponentList, iterationCount = 0; 
		 listPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
		 listPtr = listPtr->next, iterationCount++ )
		{
		const DN_COMPONENT_INFO *dnComponentInfo = listPtr->typeInfo;

		if( oidLength == sizeofOID( dnComponentInfo->oid ) && \
			!memcmp( dnComponentInfo->oid, oid, oidLength ) )
			break;
		}
	ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( ( DN_COMPONENT * ) listPtr );
	}

/****************************************************************************
*																			*
*								Insert/Delete DNs							*
*																			*
****************************************************************************/

/* Insert a DN component into a list.  The type can be either a 
   CRYPT_CERTINFO_xxx value, indicating that it's a standard DN component,
   or a small integer denoting a recognised but nonstandard DN component.  
   In the latter case we don't try to sort the component into the correct 
   position */

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \
static int insertDNstring( /*?*/ DN_COMPONENT **dnComponentListPtrPtr, 
						   IN_INT const int type,
						   IN_BUFFER( valueLength ) const void *value, 
						   IN_LENGTH_SHORT const int valueLength,
						   IN_FLAGS_Z( DN ) const int flags, 
						   OUT_ENUM_OPT( CRYPT_ERRTYPE_TYPE ) \
								CRYPT_ERRTYPE_TYPE *errorType )
	{
	const DN_COMPONENT_INFO *dnComponentInfo = NULL;
	DN_COMPONENT *listHeadPtr = *dnComponentListPtrPtr;
	DN_COMPONENT *newElement, *insertPoint;
	int i, iterationCount;

	assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) );
	assert( listHeadPtr == NULL || \
			isWritePtr( listHeadPtr, sizeof( DN_COMPONENT ) ) );
	assert( isReadPtr( value, valueLength ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	REQUIRES( ( type > CRYPT_CERTINFO_FIRST && \
				type < CRYPT_CERTINFO_LAST ) || \
			  ( type > 0 && type < 50 ) );
	REQUIRES( flags >= DN_FLAG_NONE && flags <= DN_FLAG_MAX );
	REQUIRES( valueLength > 0 && valueLength < MAX_INTLENGTH_SHORT );

	/* If the DN is locked against modification we can't make any further
	   updates */
	if( listHeadPtr != NULL && ( listHeadPtr->flags & DN_FLAG_LOCKED ) )
		return( CRYPT_ERROR_INITED );

	/* Find the type information for this component */
	for( i = 0; certInfoOIDs[ i ].oid != NULL && \
				i < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ); 
		 i++ )
		{
		if( certInfoOIDs[ i ].type == type )
			{
			dnComponentInfo = &certInfoOIDs[ i ];
			break;
			}
		}
	ENSURES( i < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ) );
	ENSURES( dnComponentInfo != NULL );

	/* Make sure that the length is valid.  If it's being read from an
	   encoded form we allow abnormally-long lengths (although we still keep
	   them within a sensible limit) since this is better than failing to
	   read a certificate because it contains a broken DN.  In addition if a 
	   widechar string is OK we allow a range up to the maximum byte count
	   defined by the widechar size, this is only valid for standard DN
	   components, when they're coming from the user the exact check has
	   already been performed by the kernel */
#ifdef USE_WIDECHARS
	if( valueLength > ( ( flags & DN_FLAG_NOCHECK ) ? \
							MAX_ATTRIBUTE_SIZE : \
						( dnComponentInfo->wcsOK ) ? \
							( WCSIZE * dnComponentInfo->maxLength ) : \
							dnComponentInfo->maxLength ) )
#else
	if( valueLength > ( ( flags & DN_FLAG_NOCHECK ) ? \
							MAX_ATTRIBUTE_SIZE : dnComponentInfo->maxLength ) )
#endif /* USE_WIDECHARS */
		{
		if( errorType != NULL )
			*errorType = CRYPT_ERRTYPE_ATTR_SIZE;
		return( CRYPT_ARGERROR_NUM1 );
		}

	/* Find the correct place in the list to insert the new element */
	if( listHeadPtr != NULL )
		{
		DN_COMPONENT *prevElement = NULL;

		/* If it's being read from an external certificate item just append 
		   it to the end of the list */
		if( flags & DN_FLAG_NOCHECK )
			{
			for( insertPoint = listHeadPtr, iterationCount = 0; 
				 insertPoint->next != NULL && \
					iterationCount < FAILSAFE_ITERATIONS_MED;
				 insertPoint = insertPoint->next, iterationCount++ );
			ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
			}
		else
			{
			const int newValueSortOrder = dnSortOrder( type );

			/* Make sure that the sort order for the new value is valid */
			if( cryptStatusError( newValueSortOrder ) )
				return( newValueSortOrder );
			
			for( insertPoint = listHeadPtr, iterationCount = 0; 
				 insertPoint != NULL && \
					newValueSortOrder >= dnSortOrder( insertPoint->type ) && \
					iterationCount < FAILSAFE_ITERATIONS_MED; 
				 insertPoint = insertPoint->next, iterationCount++ )
				{
				/* Make sure that this component isn't already present.  For 
				   now we only allow a single DN component of any type to 
				   keep things simple for the user, if it's necessary to 
				   allow multiple components of the same type then we'll 
				   need to check the value and valueLength as well */
				if( insertPoint->type == type )
					{
					if( errorType != NULL )
						*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
					return( CRYPT_ERROR_INITED );
					}

				prevElement = insertPoint;
				}
			ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
			insertPoint = prevElement;
			}
		}
	else
		{
		/* It's an empty list, insert the new element at the start */
		insertPoint = NULL;
		}

	/* Allocate memory for the new element and copy over the information */
	if( ( newElement = ( DN_COMPONENT * ) \
				clAlloc( "insertDNstring", sizeof( DN_COMPONENT ) + \
										   valueLength ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	initVarStruct( newElement, DN_COMPONENT, valueLength );
	newElement->type = type;
	newElement->typeInfo = dnComponentInfo;
	memcpy( newElement->value, value, valueLength );
	newElement->valueLength = valueLength;
	newElement->flags = flags;

	/* If it's a country code, force it to uppercase as per ISO 3166 */
	if( type == CRYPT_CERTINFO_COUNTRYNAME )
		{
		BYTE *dnStrPtr = newElement->value;

		/* Note: When the code is run under BoundsChecker 6.x the toUpper() 
		   conversion will produce garbage on any call after the first one 
		   resulting in the following checks failing */
		dnStrPtr[ 0 ] = toUpper( dnStrPtr[ 0 ] );
		dnStrPtr[ 1 ] = toUpper( dnStrPtr[ 1 ] );
		if( flags & DN_FLAG_NOCHECK )
			{
			/* 'UK' isn't an ISO 3166 country code but may be found in some
			   certificates.  If we find this we quietly convert it to the
			   correct value */
			if( !memcmp( dnStrPtr, "UK", 2 ) )
				memcpy( dnStrPtr, "GB", 2 );
			}
		else
			{
			/* Make sure that the country code is valid */
			if( !checkCountryCode( dnStrPtr ) )
				{
				endVarStruct( newElement, DN_COMPONENT );
				clFree( "insertDNstring", newElement );
				if( errorType != NULL )
					*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				return( CRYPT_ERROR_INVALID );
				}
			}
		}

	/* Link it into the list */
	insertDoubleListElement( ( DN_COMPONENT ** ) dnComponentListPtrPtr, 
							 insertPoint, newElement );

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
int insertDNComponent( INOUT_PTR void **dnComponentListPtrPtr,
					   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE componentType,
					   IN_BUFFER( valueLength ) const void *value, 
					   IN_LENGTH_SHORT const int valueLength,
					   OUT_ENUM_OPT( CRYPT_ERRTYPE_TYPE ) \
							CRYPT_ERRTYPE_TYPE *errorType )
	{
	assert( isWritePtr( dnComponentListPtrPtr, 
						sizeof( DN_COMPONENT_INFO * ) ) );
	assert( isReadPtr( value, valueLength ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	REQUIRES( componentType > CRYPT_CERTINFO_FIRST && \
			  componentType < CRYPT_CERTINFO_LAST );
	REQUIRES( valueLength > 0 && valueLength < MAX_INTLENGTH_SHORT );

	return( insertDNstring( ( DN_COMPONENT ** ) dnComponentListPtrPtr, 
							componentType, value, valueLength, 0, 
							errorType ) );
	}

/* Delete a DN component from a list */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int deleteComponent( /*?*/ DN_COMPONENT **dnComponentListPtrPtr, 
							INOUT DN_COMPONENT *theElement )
	{
	assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) );
	assert( isWritePtr( theElement, sizeof( DN_COMPONENT ) ) );

	/* Remove the item from the list */
	deleteDoubleListElement( dnComponentListPtrPtr, theElement );

	/* Clear all data in the list item and free the memory */
	endVarStruct( theElement, DN_COMPONENT );
	clFree( "deleteComponent", theElement );

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int deleteDNComponent( INOUT_PTR void **dnComponentListPtrPtr, 
					   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,
					   IN_BUFFER_OPT( valueLength ) const void *value, 
					   IN_LENGTH_SHORT const int valueLength )
	{
	DN_COMPONENT *listHeadPtr = *dnComponentListPtrPtr;
	DN_COMPONENT *itemToDelete;

	assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) );
	assert( listHeadPtr == NULL || \
			isWritePtr( listHeadPtr, sizeof( DN_COMPONENT ) ) );
	assert( ( value == NULL && valueLength == 0 ) ||
			isReadPtr( value, valueLength ) );
			/* We may be doing the delete purely by type */

	REQUIRES( type > CRYPT_CERTINFO_FIRST && type < CRYPT_CERTINFO_LAST );
	REQUIRES( valueLength >= 0 && valueLength < MAX_INTLENGTH_SHORT );

	/* If the DN is locked against modification we can't make any further
	   updates */
	if( listHeadPtr != NULL && ( listHeadPtr->flags & DN_FLAG_LOCKED ) )
		return( CRYPT_ERROR_PERMISSION );

	/* Find the component in the list and delete it */
	itemToDelete = findDNComponent( listHeadPtr, type, value, valueLength );
	if( itemToDelete == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	return( deleteComponent( ( DN_COMPONENT ** ) dnComponentListPtrPtr, 
							 itemToDelete ) );
	}

/* Delete a DN */

STDC_NONNULL_ARG( ( 1 ) ) \
void deleteDN( void **dnComponentListPtrPtr )
	{
	DN_COMPONENT *listPtr;
	int iterationCount;

	assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) );

	/* Destroy all DN items */
	for( listPtr = *dnComponentListPtrPtr, iterationCount = 0;
		 listPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
		 iterationCount++ )
		{
		DN_COMPONENT *itemToFree = listPtr;

		/* Another gcc bug, this time in gcc 4.x for 64-bit architectures 
		   (confirmed for x86-64 and ppc64) in which it removes an empty-
		   list check in deleteDoubleListElement() (in fact the emitted 
		   code bears only a passing resemblance to the actual source code). 
		   The only possible workaround seems to be to omit the call to 
		   deleteComponent() and just delete the item directly */
		listPtr = listPtr->next;
#if defined( __GNUC__ ) && ( __GNUC__ == 4 )
		endVarStruct( itemToFree, DN_COMPONENT );
		clFree( "deleteComponent", itemToFree );
#else
		( void ) deleteComponent( &itemToFree, itemToFree );
#endif /* gcc 4.x on 64-bit architectures bug workaround */

⌨️ 快捷键说明

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