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

📄 certdn.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
int writeDN( STREAM *stream, const void *dnComponentListHead, const int tag )
	{
	DN_COMPONENT *dnComponentPtr;
	const int size = preEncodeDN( ( DN_COMPONENT * ) dnComponentListHead );
	int status = CRYPT_OK;

	if( cryptStatusError( size ) )
		return( size );

	/* Write the DN */
	writeConstructed( stream, size, tag );
	for( dnComponentPtr = ( DN_COMPONENT * ) dnComponentListHead;
		 dnComponentPtr != NULL && cryptStatusOK( status );
		 dnComponentPtr = dnComponentPtr->next )
		{
		const DN_COMPONENT_INFO *dnComponentInfo = dnComponentPtr->typeInfo;
		BYTE dnString[ MAX_ATTRIBUTE_SIZE ];
		int dnStringLength, dnStringTag;

		/* Write the RDN wrapper */
		if( dnComponentPtr->encodedRDNdataSize )
			/* If it's the start of an RDN, write the RDN header */
			writeSet( stream, dnComponentPtr->encodedRDNdataSize );
		writeSequence( stream, dnComponentPtr->encodedAVAdataSize );
		swrite( stream, dnComponentInfo->oid, \
				sizeofOID( dnComponentInfo->oid ) );

		/* Convert the string to an ASN.1-compatible format and write it
		   out */
		dnStringTag = copyToAsn1String( dnString, &dnStringLength,
								MAX_ATTRIBUTE_SIZE, dnComponentPtr->value,
								dnComponentPtr->valueLength );
		if( cryptStatusError( dnStringTag ) )
			return( dnStringTag );
		if( dnStringTag == BER_STRING_IA5 && !dnComponentInfo->ia5OK )
			/* If an IA5String isn't allowed in this instance, use a
			   T61String instead */
			dnStringTag = BER_STRING_T61;
		status = writeCharacterString( stream, dnString, dnStringLength,
									   dnStringTag );
		}

	return( status );
	}

/****************************************************************************
*																			*
*								DN String Routines							*
*																			*
****************************************************************************/

/* Read a DN in string form */

typedef struct {
	const char *label, *text;
	int labelLen, textLen;			/* DN component label and value */
	BOOLEAN isContinued;			/* Whether further AVAs in this RDN */
	} DN_STRING_INFO;

#define MAX_DNSTRING_COMPONENTS 64

static BOOLEAN parseDNString( DN_STRING_INFO *dnStringInfo,
							  const char *string, const int stringLength )
	{
	int stringPos = 0, stringInfoIndex = 0, i;

	memset( dnStringInfo, 0,
			sizeof( DN_STRING_INFO ) * ( MAX_DNSTRING_COMPONENTS + 1 ) );

	/* Make sure there are no control characters in the string */
	for( i = 0; i < stringLength; i++ )
		if( ( string[ i ] & 0x7F ) < ' ' )
			return( FALSE );

	/* Verify that a DN string is of the form:

		dnString ::= assignment '\0' | assignment ',' assignment
		assignment ::= label '=' text */
	do
		{
		DN_STRING_INFO *dnStringInfoPtr = &dnStringInfo[ stringInfoIndex ];

		/* Check for label '=' ... */
		for( i = stringPos; i < stringLength; i++ )
			{
			const char ch = string[ i ];

			if( ch == '\\' )
				return( FALSE );/* No escapes in the label component */
			if( ch == '=' || ch == ',' || ch == '+' )
				break;
			}
		if( i == stringPos || i == stringLength || \
			string[ i ] == ',' || string[ i ] == '+' )
			return( FALSE );	/* No text or no '=' or spurious ',' */
		dnStringInfoPtr->label = string + stringPos;
		dnStringInfoPtr->labelLen = i - stringPos;
		stringPos = i + 1;		/* Skip text + '=' */

		/* Check for ... text { '\0' | ',' ... | '+' ... } */
		for( i = stringPos;
			 i < stringLength && \
			 !( string[ i - 1 ] != '\\' && \
				( string[ i ] == ',' || string[ i ] == '+' || \
				  string[ i ] == '=' ) ); i++ );
		if( i == stringPos || string[ i ] == '=' )
			return( FALSE );	/* No text or spurious '=' */
		dnStringInfoPtr->text = string + stringPos;
		dnStringInfoPtr->textLen = i - stringPos;
		dnStringInfoPtr->isContinued = ( i < stringLength && \
										 string[ i ] == '+' ) ? TRUE : FALSE;
		stringPos = i;			/* Skip text + optional ',' */
		if( stringPos != stringLength && \
			++stringPos == stringLength )
			/* Trailing ',' */
			return( FALSE );

		/* Strip leading and trailing whitespace on the label and text */
		for( i = 0; i < dnStringInfoPtr->labelLen && \
					dnStringInfoPtr->label[ i ] == ' '; i++ );
		dnStringInfoPtr->label += i;
		dnStringInfoPtr->labelLen -= i;
		for( i = dnStringInfoPtr->labelLen; i > 0 && \
					dnStringInfoPtr->label[ i - 1 ] == ' '; i-- );
		dnStringInfoPtr->labelLen = i;
		for( i = 0; i < dnStringInfoPtr->textLen && \
					dnStringInfoPtr->text[ i ] == ' '; i++ );
		dnStringInfoPtr->text += i;
		dnStringInfoPtr->textLen -= i;
		for( i = dnStringInfoPtr->textLen; i > 0 && \
					dnStringInfoPtr->text[ i - 1 ] == ' '; i-- );
		dnStringInfoPtr->textLen = i;
		if( dnStringInfoPtr->labelLen <= 0 || dnStringInfoPtr->textLen <= 0 )
			return( FALSE );

		if( ++stringInfoIndex >= MAX_DNSTRING_COMPONENTS )
			return( FALSE );
		}
	while( stringPos < stringLength );

	return( TRUE );
	}

int readDNstring( const char *string, const int stringLength,
				  void **dnComponentListHead )
	{
	DN_STRING_INFO dnStringInfo[ MAX_DNSTRING_COMPONENTS + 1 ];
	DN_COMPONENT *dnComponentPtr;
	int stringInfoIndex;

	/* We have to perform the text string to DN translation in two stages
	   thanks to the backwards encoding required by RFC 1779, first we parse
	   it forwards to separate out the RDN components, then we move through
	   the parsed information backwards adding it to the RDN (with special
	   handling for multi-AVA RDNs as for writeDNstring()).  Overall this
	   isn't so bad because it means we can perform a general firewall check
	   to make sure the DN string is well-formed and then leave the encoding
	   as a separate pass */
	if( !parseDNString( dnStringInfo, string, stringLength ) )
		return( CRYPT_ARGERROR_STR1 );

	/* Find the end of the DN components */
	for( stringInfoIndex = 0;
		 dnStringInfo[ stringInfoIndex + 1 ].label != NULL;
		 stringInfoIndex++ );

	do
		{
		const DN_STRING_INFO *dnStringInfoPtr;
		BOOLEAN isContinued;

		/* Find the start of the RDN */
		while( stringInfoIndex > 0 && \
			   dnStringInfo[ stringInfoIndex - 1 ].isContinued )
			stringInfoIndex--;
		dnStringInfoPtr = &dnStringInfo[ stringInfoIndex ];

		do
			{
			const DN_COMPONENT_INFO *dnComponentInfo = NULL;
			BYTE textBuffer[ MAX_ATTRIBUTE_SIZE + 1 ];
			CRYPT_ATTRIBUTE_TYPE type;
			int i, textIndex = 0, status;

			/* Look up the DN component information */
			for( i = 0; certInfoOIDs[ i ].oid != NULL; i++ )
				if( ( strlen( certInfoOIDs[ i ].name ) == \
										dnStringInfoPtr->labelLen && \
					  !strCompare( certInfoOIDs[ i ].name, dnStringInfoPtr->label,
								   dnStringInfoPtr->labelLen ) ) || \
					( certInfoOIDs[ i ].altName != NULL && \
					  strlen( certInfoOIDs[ i ].altName ) == \
										dnStringInfoPtr->labelLen && \
					  !strCompare( certInfoOIDs[ i ].altName, dnStringInfoPtr->label,
								   dnStringInfoPtr->labelLen ) ) )
					{
					dnComponentInfo = &certInfoOIDs[ i ];
					break;
					}
			if( dnComponentInfo == NULL )
				return( CRYPT_ARGERROR_STR1 );
			type = ( dnComponentInfo->type != CRYPT_ATTRIBUTE_NONE ) ?
				   dnComponentInfo->type : i + DN_OID_OFFSET;

			/* Convert the text to canonical form, removing any escapes for
			   special characters */
			for( i = 0; i < dnStringInfoPtr->textLen; i++ )
				{
				int ch = dnStringInfoPtr->text[ i ];

				if( ch == '\\' )
					{
					if( ++i >= dnStringInfoPtr->textLen )
						return( CRYPT_ARGERROR_STR1 );
					ch = dnStringInfoPtr->text[ i ];
					}
				textBuffer[ textIndex++ ] = ch;
				}

			/* Add the AVA to the DN */
			if( type == CRYPT_CERTINFO_COUNTRYNAME )
				{
				/* If it's a country code, force it to uppercase as per ISO 3166 */
				if( textIndex != 2 )
					return( CRYPT_ARGERROR_STR1 );
				textBuffer[ 0 ] = toUpper( textBuffer[ 0 ] );
				textBuffer[ 1 ] = toUpper( textBuffer[ 1 ] );
				status = insertDNstring( dnComponentListHead,
									type, textBuffer, 2,
									( dnStringInfoPtr->isContinued ) ? \
										DN_FLAG_CONTINUED | DN_FLAG_NOCHECK : \
										DN_FLAG_NOCHECK, NULL );
				}
			else
				status = insertDNstring( dnComponentListHead,
									type, textBuffer, textIndex,
									( dnStringInfoPtr->isContinued ) ? \
										DN_FLAG_CONTINUED | DN_FLAG_NOCHECK :
										DN_FLAG_NOCHECK, NULL );
			if( cryptStatusError( status ) )
				{
				deleteDN( dnComponentListHead );
				return( status );
				}

			/* Move on to the next AVA */
			isContinued = dnStringInfoPtr->isContinued;
			dnStringInfoPtr++;
			}
		while( isContinued );
		}
	while( --stringInfoIndex >= 0 );

	/* We're done, lock the DN against further updates */
	for( dnComponentPtr = *dnComponentListHead; dnComponentPtr != NULL;
		 dnComponentPtr = dnComponentPtr->next )
		dnComponentPtr->flags |= DN_FLAG_LOCKED;

	return( CRYPT_OK );
	}

/* Write a DN in string form */

int writeDNstring( STREAM *stream, const void *dnComponentListHead )
	{
	const DN_COMPONENT *dnComponentPtr = dnComponentListHead;

	if( dnComponentPtr == NULL )
		return( CRYPT_OK );

	assert( isReadPtr( dnComponentPtr, DN_COMPONENT ) );

	/* Find the end of the DN string.  We have to print the RDNs backwards
	   because of ISODE's Janet memorial backwards encoding */
	while( dnComponentPtr->next != NULL )
		dnComponentPtr = dnComponentPtr->next;

	do
		{
		const DN_COMPONENT *dnComponentCursor;
		BOOLEAN isContinued;

		/* Find the start of the RDN */
		while( dnComponentPtr->prev != NULL && \
			   ( dnComponentPtr->prev->flags & DN_FLAG_CONTINUED ) )
			dnComponentPtr = dnComponentPtr->prev;
		dnComponentCursor = dnComponentPtr;
		dnComponentPtr = dnComponentPtr->prev;

		/* Print the current RDN */
		do
			{
			const DN_COMPONENT_INFO *componentInfoPtr = \
										dnComponentCursor->typeInfo;
			int i;

			/* Print the current AVA */
			swrite( stream, componentInfoPtr->name,
					strlen( componentInfoPtr->name ) );
			sputc( stream, '=' );
			for( i = 0; i < dnComponentCursor->valueLength; i++ )
				{
				const char ch = ( ( char * ) dnComponentCursor->value )[ i ];

				if( ch == ',' || ch == '=' || ch == '+' || ch == ';' || \
					ch == '\\' || ch == '"' )
					sputc( stream, '\\' );
				sputc( stream, ch );
				}

			/* If there are more AVAs in this RDN, print a continuation
			   indicator and move on to the next AVA */
			isContinued = dnComponentCursor->flags & DN_FLAG_CONTINUED;
			if( isContinued )
				{
				swrite( stream, " + ", 3 );
				dnComponentCursor = dnComponentCursor->next;
				}
			}
		while( isContinued );

		/* If there are more components to come, print an RDN separator */
		if( dnComponentPtr != NULL )
			swrite( stream, ", ", 2 );
		}
	while( dnComponentPtr != NULL && sStatusOK( stream ) );

	return( sGetStatus( stream ) );
	}

⌨️ 快捷键说明

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