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

📄 dbx_wr.c

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

#include <stdarg.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "dbms.h"
  #include "asn1.h"
  #include "rpc.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../keyset/keyset.h"
  #include "../keyset/dbms.h"
  #include "../misc/asn1.h"
  #include "../misc/rpc.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/dbms.h"
  #include "misc/asn1.h"
  #include "misc/rpc.h"
#endif /* Compiler-specific includes */

#ifdef USE_DBMS

/* Get a commonName or commonName-equivalent from a certificate */

static int getCommonName( CRYPT_CERTIFICATE iCryptCert, char *CN,
						  const char *OU, const char *O )
	{
	RESOURCE_DATA msgData;
	char buffer[ MAX_ATTRIBUTE_SIZE ], *strPtr;
	int status;

	/* First, we try for a CN */
	setMessageData( &msgData, CN, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_COMMONNAME );
	if( cryptStatusOK( status ) )
		{
		CN[ msgData.length ] = '\0';
		return( CRYPT_OK );
		}

	/* If that fails, we try for either a pseudonym or givenName + surname.
	   Since these are part of the vast collection of oddball DN attributes
	   that aren't handled directly, we have to get the encoded DN form and
	   look for them by OID */
	setMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE - 1 );
	status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_DN );
	if( cryptStatusError( status ) )
		return( status );
	buffer[ msgData.length ] = '\0';

	/* Look for a pseudonym */
	strPtr = strstr( buffer, "oid.2.5.4.65=" );
	if( strPtr != NULL )
		{
		int length;

		strPtr += 13;	/* Skip type indicator */
		for( length = 0; strPtr[ length ] != '\0' && \
						 strPtr[ length ] != ',' && \
						 strPtr[ length ] != '+'; length++ );
		if( length > 0 && strPtr[ length ] == '+' && \
						  strPtr[ length - 1 ] == ' ' )
			length--;	/* Strip trailing space */
		if( length <= CRYPT_MAX_TEXTSIZE )
			{
			memcpy( CN, strPtr, length );
			CN[ length ] = '\0';
			return( CRYPT_OK );
			}
		}

	/* Look for givenName + surname */
	strPtr = strstr( buffer, "G=" );
	if( strPtr != NULL )
		{
		char *surnameStrPtr;
		int length, surnameLength;

		strPtr += 2;	/* Skip type indicator */
		for( length = 0; \
			 strPtr[ length ] != '\0' && \
				strPtr[ length ] != ',' && \
				strPtr[ length ] != '+'; \
			 length++ );
		if( length > 0 && strPtr[ length ] == '+' && \
						  strPtr[ length - 1 ] == ' ' )
			length--;	/* Strip trailing space */
		surnameStrPtr = strstr( buffer, "S=" );
		if( surnameStrPtr != NULL )
			{
			surnameStrPtr += 2;	/* Skip type indicator */
			for( surnameLength = 0; \
				 surnameStrPtr[ surnameLength ] != '\0' && \
					surnameStrPtr[ surnameLength ] != ',' && \
					surnameStrPtr[ length ] != '+'; \
				 surnameLength++ );
			if( surnameLength > 0 && \
				surnameStrPtr[ surnameLength ] == '+' && \
				surnameStrPtr[ surnameLength - 1 ] == ' ' )
				surnameLength--;	/* Strip trailing space */
			if( length + surnameLength <= CRYPT_MAX_TEXTSIZE )
				{
				memcpy( CN, strPtr, length );
				memcpy( CN + length, surnameStrPtr, surnameLength );
				CN[ length + surnameLength ] = '\0';
				return( CRYPT_OK );
				}
			}
		}

	/* It's possible (although highly unlikely) that a certificate won't 
	   have a usable CN-equivalent in some form, in which case we use the OU
	   instead.  If that also fails, we use the O.  This gets a bit messy, 
	   but duplicating the OU / O into the CN seems to be the best way to 
	   handle this */
	strcpy( CN, *OU ? OU : O );

	return( CRYPT_OK );
	}

/* Add a certificate object (cert, cert request, PKI user) to a database.  
   Normally existing rows would be overwritten if we added duplicate entries, 
   but the UNIQUE constraint on the indices will catch this */

int addCert( DBMS_INFO *dbmsInfo, const CRYPT_HANDLE iCryptHandle,
			 const CRYPT_CERTTYPE_TYPE certType, const CERTADD_TYPE addType,
			 const DBMS_UPDATE_TYPE updateType )
	{
	RESOURCE_DATA msgData;
	BYTE certData[ MAX_CERT_SIZE ];
	char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
	char nameID[ DBXKEYID_BUFFER_SIZE ], issuerID[ DBXKEYID_BUFFER_SIZE ];
	char keyID[ DBXKEYID_BUFFER_SIZE ], certID[ DBXKEYID_BUFFER_SIZE ];
	char C[ CRYPT_MAX_TEXTSIZE + 1 ], SP[ CRYPT_MAX_TEXTSIZE + 1 ],
		 L[ CRYPT_MAX_TEXTSIZE + 1 ], O[ CRYPT_MAX_TEXTSIZE + 1 ],
		 OU[ CRYPT_MAX_TEXTSIZE + 1 ], CN[ CRYPT_MAX_TEXTSIZE + 1 ],
		 uri[ CRYPT_MAX_TEXTSIZE + 1 ];
	time_t boundDate = 0;
	int certDataLength, status;

	assert( certType == CRYPT_CERTTYPE_CERTIFICATE || \
			certType == CRYPT_CERTTYPE_REQUEST_CERT || \
			certType == CRYPT_CERTTYPE_PKIUSER );

	*C = *SP = *L = *O = *OU = *CN = *uri = '\0';

	/* Extract the DN and altName (URI) components.  This changes the 
	   currently selected DN components, but this is OK since we've got 
	   the cert locked and the prior state will be restored when we unlock 
	   it */
	krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_SUBJECTNAME );
	setMessageData( &msgData, C, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_COUNTRYNAME );
	if( cryptStatusOK( status ) )
		C[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setMessageData( &msgData, SP, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							&msgData, CRYPT_CERTINFO_STATEORPROVINCENAME );
		if( cryptStatusOK( status ) )
			SP[ msgData.length ] = '\0';
		}
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setMessageData( &msgData, L, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							&msgData, CRYPT_CERTINFO_LOCALITYNAME );
		if( cryptStatusOK( status ) )
			L[ msgData.length ] = '\0';
		}
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setMessageData( &msgData, O, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							&msgData, CRYPT_CERTINFO_ORGANIZATIONNAME );
		if( cryptStatusOK( status ) )
			O[ msgData.length ] = '\0';
		}
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setMessageData( &msgData, OU, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							&msgData, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
		if( cryptStatusOK( status ) )
			OU[ msgData.length ] = '\0';
		}
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		/* The handling of the CN (or CN-equivalent) is somewhat complex so 
		   we use a separate function for this */
		status = getCommonName( iCryptHandle, CN, OU, O );
		}
	if( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \
		( certType != CRYPT_CERTTYPE_PKIUSER ) )
		{
		static const int value = CRYPT_CERTINFO_SUBJECTALTNAME;

		/* Get the URI for this cert, in order of likelihood of occurrence */
		setMessageData( &msgData, uri, CRYPT_MAX_TEXTSIZE );
		krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
						 ( void * ) &value, CRYPT_ATTRIBUTE_CURRENT );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CERTINFO_RFC822NAME );
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			setMessageData( &msgData, uri, CRYPT_MAX_TEXTSIZE );
			status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, 
									  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
			}
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			setMessageData( &msgData, uri, CRYPT_MAX_TEXTSIZE );
			status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_CERTINFO_DNSNAME );
			}
		if( cryptStatusOK( status ) )
			{
			int i;

			/* Force the URI (as stored) to lowercase to make case-
			   insensitive matching easier.  In most cases we could ask the 
			   back-end to do this, but this complicates indexing and 
			   there's no reason why we can't do it here */
			for( i = 0; i < msgData.length; i++ )
				uri[ i ] = toLower( uri[ i ] );
			uri[ msgData.length ] = '\0';
			}
		}
	if( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \
		( certType == CRYPT_CERTTYPE_CERTIFICATE ) )
		{
		setMessageData( &msgData, &boundDate, sizeof( time_t ) );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
							&msgData, CRYPT_CERTINFO_VALIDTO );
		}
	else
		if( status == CRYPT_ERROR_NOTFOUND )
			status = CRYPT_OK;
	if( cryptStatusError( status ) )
		/* Convert any low-level cert-specific error into something generic
		   that makes a bit more sense to the caller */
		return( CRYPT_ARGERROR_NUM1 );

	/* Get the ID information and cert data for the cert */
	if( certType == CRYPT_CERTTYPE_CERTIFICATE )
		{
		status = getKeyID( nameID, iCryptHandle, CRYPT_IATTRIBUTE_SUBJECT );
		if( !cryptStatusError( status ) )
			status = getKeyID( issuerID, iCryptHandle,
							   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( !cryptStatusError( status ) )
			{
			status = getCertKeyID( keyID, iCryptHandle );
			if( !cryptStatusError( status ) )
				status = CRYPT_OK;	/* getCertKeyID() returns a length */
			}
		}
	if( certType == CRYPT_CERTTYPE_PKIUSER )
		{
		char encKeyID[ 128 ];

		/* Get the PKI user ID.  We can't read this directly since it's
		   returned in text form for use by end users so we have to read the
		   encoded form, decode it, and then turn the decoded binary value
		   into a key ID.  We identify the result as a keyID,
		   (== subjectKeyIdentifier, which it isn't really) but we need to
		   use this to ensure that it's hashed/expanded out to the correct
		   size */
		setMessageData( &msgData, encKeyID, 128 );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CERTINFO_PKIUSER_ID );
		if( cryptStatusOK( status ) )
			{
			BYTE binaryKeyID[ 128 ];
			int length;

			status = length = decodePKIUserValue( binaryKeyID, encKeyID, 
												  msgData.length );
			if( !cryptStatusError( status ) )
				{
				status = CRYPT_OK;	/* decodePKIUserValue() returns a length */
				makeKeyID( keyID, DBXKEYID_BUFFER_SIZE, CRYPT_IKEYID_KEYID,
						   binaryKeyID, length );
				}
			}
		if( cryptStatusOK( status ) )
			{
			status = getKeyID( nameID, iCryptHandle, CRYPT_IATTRIBUTE_SUBJECT );
			if( !cryptStatusError( status ) )
				status = CRYPT_OK;	/* getKeyID() returns a length */
			}
		}
	if( cryptStatusOK( status ) )
		{
		status = getKeyID( certID, iCryptHandle,
						   CRYPT_CERTINFO_FINGERPRINT_SHA );
		if( !cryptStatusError( status ) )
			status = CRYPT_OK;	/* getKeyID() returns a length */
		}
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, certData, MAX_CERT_SIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_CRT_EXPORT,
					&msgData, ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \
					CRYPT_ICERTFORMAT_DATA : CRYPT_CERTFORMAT_CERTIFICATE );
		certDataLength = msgData.length;
		}
	if( cryptStatusError( status ) )
		/* Convert any low-level cert-specific error into something generic
		   that makes a bit more sense to the caller */

⌨️ 快捷键说明

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