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

📄 certdn.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
****************************************************************************/

/* Insert a DN component into a list.  If the type is zero then it's an
   unrecognised component type, and if it's negative it's a recognised
   component type being read from a cert produced by a non-cryptlib
   application.  In this case we don't try to sort the component into the
   correct position */

static int insertDNstring( void **dnListHead, const CRYPT_ATTRIBUTE_TYPE type,
						   const void *value, const int valueLength,
						   const int flags, CRYPT_ERRTYPE_TYPE *errorType )
	{
	const DN_COMPONENT_INFO *dnComponentInfo;
	DN_COMPONENT *listHeadPtr = *dnListHead;
	DN_COMPONENT *newElement, *insertPoint;

	/* 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 if it's a recognised
	   type */
	if( type > CRYPT_CERTINFO_FIRST && type < CRYPT_CERTINFO_LAST )
		{
		int i;

		/* It's a handled component, get the pointer to the OID */
		for( i = 0; certInfoOIDs[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )
			if( certInfoOIDs[ i ].type == type )
				{
				dnComponentInfo = &certInfoOIDs[ i ];
				break;
				}
		if( certInfoOIDs[ i ].type == CRYPT_ATTRIBUTE_NONE )
			{
			assert( NOTREACHED );
			return( CRYPT_ERROR_NOTAVAIL );
			}
		}
	else
		/* It's a non-handled component, the type is an index into the
		   component table.  At this point we run into a GCC 2.7.x compiler
		   bug (detect with '#if defined( __GNUC__ ) && ( __GNUC__ == 2 )').
		   If we use the expression '&certInfoOIDs[ type - DN_OID_OFFSET ]'
		   what we should get is:
				leal -1000(%ebp,%ebp,2),%eax
				movl certInfoOIDs(,%eax,4),%eax
		   but what we actually get is:
				leal -3000(%ebp,%ebp,2),%eax
				movl certInfoOIDs(,%eax,4),%eax
		   To fix this we need to insert some form of dummy evaluation in a
		   form which ensures that it can't be optimised away (which is
		   actually quite difficult with gcc because it optimises any simple
		   code way).  To work around this we insert a dummy expression to
		   keep the value live */
		{
#if defined( __GNUC__ ) && ( __GNUC__ == 2 )
		int i = type - DN_OID_OFFSET;
		dnComponentInfo = &certInfoOIDs[ i ];
		if( dnComponentInfo < 0 )	/* Dummy code to keep i live */
			newElement = ( i + type ) ? NULL : ( void * ) value;
#else
		dnComponentInfo = &certInfoOIDs[ type - DN_OID_OFFSET ];
#endif /* gcc 2.7.x bug workaround */
		if( type - DN_OID_OFFSET >= \
			sizeof( certInfoOIDs ) / sizeof( DN_COMPONENT_INFO ) )
			{
			assert( NOTREACHED );
			return( CRYPT_ERROR_NOTAVAIL );
			}
		}

	/* 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 cert 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 cert item, just append it to
		   the end of the list */
		if( flags & DN_FLAG_NOCHECK )
			for( insertPoint = listHeadPtr; insertPoint->next != NULL;
				 insertPoint = insertPoint->next );
		else
			{
			for( insertPoint = listHeadPtr; insertPoint != NULL && \
				 dnSortOrder( type ) >= dnSortOrder( insertPoint->type );
				 insertPoint = insertPoint->next )
				{
				/* Make sure 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 we 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;
				}
			insertPoint = prevElement;
			}
		}

	/* 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;

		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( newElement->value, "UK", 2 ) )
				memcpy( newElement->value, "GB", 2 );
			}
		else
			/* Make sure the country code is valid */
			if( !checkCountryCode( ( char * ) newElement->value ) )
				{
				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 ** ) dnListHead, insertPoint,
							 newElement );

	return( CRYPT_OK );
	}

int insertDNComponent( void **dnListHead,
					   const CRYPT_ATTRIBUTE_TYPE type,
					   const void *value, const int valueLength,
					   CRYPT_ERRTYPE_TYPE *errorType )
	{
	return( insertDNstring( dnListHead, type, value, valueLength, 0,
							errorType ) );
	}

/* Delete a DN component from a list */

static int deleteComponent( void **dnListHead, DN_COMPONENT *theElement )
	{
	DN_COMPONENT *listPrevPtr, *listNextPtr;

	if( theElement == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	assert( isWritePtr( theElement, DN_COMPONENT ) );
	listPrevPtr = theElement->prev;
	listNextPtr = theElement->next;

	/* Remove the item from the list */
	if( theElement == *dnListHead )
		*dnListHead = listNextPtr;			/* Delete from start */
	else
		listPrevPtr->next = listNextPtr;	/* Delete from middle or end */
	if( listNextPtr != NULL )
		listNextPtr->prev = listPrevPtr;

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

	return( CRYPT_OK );
	}

int deleteDNComponent( void **dnListHead,
					   const CRYPT_ATTRIBUTE_TYPE type, const void *value,
					   const int valueLength )
	{
	DN_COMPONENT *listHeadPtr = *dnListHead;

	/* 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 */
	return( deleteComponent( dnListHead, findDNComponent( listHeadPtr, type,
													value, valueLength ) ) );
	}

/* Delete a DN */

void deleteDN( void **dnListHead )
	{
	DN_COMPONENT *listPtr = *dnListHead;

	/* Mark the list as being empty */
	*dnListHead = NULL;

	/* Destroy all DN items */
	while( listPtr != NULL )
		{
		DN_COMPONENT *itemToFree = listPtr;

		listPtr = listPtr->next;
		deleteComponent( ( void ** ) &itemToFree, itemToFree );
		}
	}

/* Get the value of a DN component */

int getDNComponentValue( const void *dnListHead,
						 const CRYPT_ATTRIBUTE_TYPE type,
						 void *value, int *length, const int maxLength )
	{
	const DN_COMPONENT *dnComponent = findDNComponent( dnListHead, type,
													   NULL, 0 );

	if( dnComponent == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	*length = dnComponent->valueLength;
	if( value == NULL )
		return( CRYPT_OK );
	if( dnComponent->valueLength > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	if( checkBadPtrWrite( value, dnComponent->valueLength ) )
		return( CRYPT_ARGERROR_STR1 );
	memcpy( value, dnComponent->value, dnComponent->valueLength );
	return( CRYPT_OK );
	}

/* Compare two DNs.  Since this is used for constraint comparisons as well
   as just strict equality checks, we provide a flag which, if set, returns
   a match if the first DN is a proper substring of the second DN */

BOOLEAN compareDN( const void *dnComponentListHead1,
				   const void *dnComponentListHead2,
				   const BOOLEAN dn1substring )
	{
	DN_COMPONENT *dn1ptr = ( DN_COMPONENT * ) dnComponentListHead1;
	DN_COMPONENT *dn2ptr = ( DN_COMPONENT * ) dnComponentListHead2;

	/* Check each DN component for equality */
	while( dn1ptr != NULL && dn2ptr != NULL )
		{
		/* If the RDN types differ, the DNs don't match */
		if( dn1ptr->type != dn2ptr->type )
			return( FALSE );

		/* Compare the current RDNs.  In theory we should be using the
		   complex and arcane X.500 name comparison rules, but no-one
		   actually does this since they're almost impossible to get right.
		   Since everyone else uses memcpy()/memcmp() to handle DN
		   components, it's safe to use it here (sic faciunt omnes).  This 
		   also avoids any potential security problems arising from the 
		   complexity of the code necessary to implement the X.500 matching 
		   rules */
		if( dn1ptr->valueLength != dn2ptr->valueLength || \
			memcmp( dn1ptr->value, dn2ptr->value, dn1ptr->valueLength ) )
			return( FALSE );

		/* Move on to the next component */
		dn1ptr = dn1ptr->next;
		dn2ptr = dn2ptr->next;
		}

	/* If we've reached the end of both DNs or we're looking for a substring
	   match, the two match */
	return( ( ( dn1ptr == NULL && dn2ptr == NULL ) || dn1substring ) ? \
			TRUE : FALSE );
	}

/* Copy a DN */

int copyDN( void **dnDest, const void *dnSrc )
	{
	const DN_COMPONENT *srcPtr = dnSrc;
	DN_COMPONENT *destPtr = NULL;

	for( *dnDest = NULL; srcPtr != NULL; srcPtr = srcPtr->next )
		{
		DN_COMPONENT *newElement;

		/* Allocate memory for the new element and copy over the information */
		if( ( newElement = ( DN_COMPONENT * ) \
					clAlloc( "copyDN", \
					sizeofVarStruct( srcPtr, DN_COMPONENT ) ) ) == NULL )
			{
			deleteDN( dnDest );
			return( CRYPT_ERROR_MEMORY );
			}

⌨️ 快捷键说明

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