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

📄 dbxdbx.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
		dbmsFormatSQL( sqlBuffer,
			"SELECT certData FROM $ WHERE ",
					   getTableName( itemType ) );
		sqlLength = strlen( sqlBuffer );
		dbmsFormatQuery( sqlBuffer + sqlLength, keyID, keyIDlength,
						 ( MAX_SQL_QUERY_SIZE - 1 ) - sqlLength );
		return( dbmsStaticQuery( sqlBuffer, DBMS_QUERY_START ) );
		}

	/* Fetch the first data item */
	makeKeyID( keyIDbuffer, keyIDtype, keyID, keyIDlength );
	return( getItemData( dbmsInfo, iCertificate, stateInfo,
						 getKeyName( keyIDtype ), keyIDbuffer, itemType,
						 options ) );
	}

static int getNextItemFunction( KEYSET_INFO *keysetInfo,
								CRYPT_CERTIFICATE *iCertificate,
								int *stateInfo, const int options )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;

	/* If we're fetching the next cert in a sequence based on externally-held
	   state information, set the key ID to the nameID of the previous cert's
	   issuer */
	if( stateInfo != NULL )
		{
		char keyIDbuffer[ CRYPT_MAX_TEXTSIZE * 2 ];
		const int status = getKeyID( keyIDbuffer, *stateInfo,
									 CRYPT_IATTRIBUTE_ISSUER );
		if( cryptStatusError( status ) )
			return( status );
		return( getItemData( dbmsInfo, iCertificate, stateInfo, "nameID",
							 keyIDbuffer, KEYMGMT_ITEM_PUBLICKEY, options ) );
		}

	/* Fetch the next data item in an ongoing query */
	return( getItemData( dbmsInfo, iCertificate, NULL, NULL,
						 NULL, KEYMGMT_ITEM_NONE, options ) );
	}

/* Retrieve a key record from the database */

static int getItemFunction( KEYSET_INFO *keysetInfo,
							CRYPT_HANDLE *iCryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype,
							const void *keyID,  const int keyIDlength,
							void *auxInfo, int *auxInfoLength,
							const int flags )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
	int status;

	assert( auxInfo == NULL ); assert( *auxInfoLength == 0 );

	/* There are some query types that can only be satisfied by a cert store
	   since a standard database doesn't contain the necessary fields.
	   Before we do anything else we make sure that we can resolve the query 
	   using the current database type */
	if( !( dbmsInfo->flags & DBMS_FLAG_CERTSTORE_FIELDS ) )
		{
		/* A standard database doesn't contain a cert ID in the revocation
		   information since the CRL it's populated from only contains an
		   issuerAndSerialNumber, so we can't resolve queries for revocation
		   info using a cert ID */
		if( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \
			keyIDtype == CRYPT_IKEYID_CERTID )
			return( CRYPT_ERROR_NOTFOUND );
		}

	/* If this is a CA management item fetch, fetch the data from the CA cert
	   store */
	if( itemType == KEYMGMT_ITEM_REQUEST || \
		itemType == KEYMGMT_ITEM_PKIUSER || \
		( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \
		  !( flags & KEYMGMT_FLAG_CHECK_ONLY ) ) )
		{
		int dummy;

		/* If we're getting the issuing PKI user, which means that the key ID
		   that's being queried on is that of an issued cert that the user 
		   owns rather than that of the user themselves, fetch the user info 
		   via a special function */
		if( itemType == KEYMGMT_ITEM_PKIUSER && \
			( flags & KEYMGMT_FLAG_GETISSUER ) )
			{
			char keyIDbuffer[ DBXKEYID_BUFFER_SIZE ];

			assert( keyIDtype == CRYPT_IKEYID_CERTID );
			assert( isCertStore( dbmsInfo ) );

			/* The information required to locate the PKI user from one of 
			   their certs is only present in a cert store */
			if( !isCertStore( dbmsInfo ) )
				return( CRYPT_ERROR_NOTFOUND );

			/* Get the PKI user based on the cert */
			makeKeyID( keyIDbuffer, CRYPT_IKEYID_CERTID, keyID, 
					   keyIDlength );
			return( caGetIssuingUser( dbmsInfo, iCryptHandle, 
									  keyIDbuffer ) );
			}

		/* This is just a standard read from a non-certificate table rather
		   than the cert table so we call the get first cert function directly
		   (rather than going via the indirect-cert-import code).  Since it's
		   a direct call, we need to provide a dummy return variable for the
		   state information which is normally handled by the indirect-cert-
		   import code */
		return( getFirstItemFunction( keysetInfo, iCryptHandle, &dummy,
									  keyIDtype, keyID, keyIDlength,
									  itemType, KEYMGMT_FLAG_NONE ) );
		}

	/* If we're doing a check only, just check whether the item is present
	   without fetching any data */
	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
		{
		char keyIDbuffer[ DBXKEYID_BUFFER_SIZE ];
		char sqlBuffer[ MAX_SQL_QUERY_SIZE ];

		assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
				itemType == KEYMGMT_ITEM_REVOCATIONINFO );
		assert( keyIDlength == KEYID_SIZE );
		assert( keyIDtype == CRYPT_IKEYID_ISSUERID || \
				keyIDtype == CRYPT_IKEYID_CERTID );

		/* Check whether this item is present.  We don't care about the
		   result, all we want to know is whether it's there or not, so we
		   just do a check rather than a fetch of any data */
		makeKeyID( keyIDbuffer, keyIDtype, keyID, KEYID_SIZE );
		dbmsFormatSQL( sqlBuffer,
			"SELECT certData FROM $ WHERE $ = '$'",
					   getTableName( itemType ), getKeyName( keyIDtype ),
					   keyIDbuffer );
		return( dbmsStaticQuery( sqlBuffer, DBMS_QUERY_CHECK ) );
		}

	/* Import the cert by doing an indirect read, which fetches either a
	   single cert or an entire chain if it's present */
	status = iCryptImportCertIndirect( iCryptHandle, keysetInfo->objectHandle,
									   keyIDtype, keyID, keyIDlength,
									   flags & KEYMGMT_MASK_CERTOPTIONS );
	return( status );
	}

/* Add a certificate object to a database.  Normally RDBMS' would allow
   existing rows to be overwritten, 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 ],
		 email[ 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 = *email = '\0';

	/* Extract the DN and altName 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 )
		{
		setMessageData( &msgData, CN, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, 
							&msgData, CRYPT_CERTINFO_COMMONNAME );
		if( cryptStatusOK( status ) )
			CN[ msgData.length ] = '\0';
		else
			if( status == CRYPT_ERROR_NOTFOUND )
				/* It's possible (although highly unlikely) that a
				   certificate won't have a CN, 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 );
		}
	if( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \
		( certType != CRYPT_CERTTYPE_PKIUSER ) )
		{
		static const int value = CRYPT_CERTINFO_SUBJECTALTNAME;

		setMessageData( &msgData, email, CRYPT_MAX_TEXTSIZE );
		krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, 
						 ( void * ) &value, CRYPT_CERTINFO_CURRENT_FIELD );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, 
							&msgData, CRYPT_CERTINFO_RFC822NAME );
		if( cryptStatusOK( status ) )
			email[ 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( cryptStatusOK( status ) )
			status = getKeyID( issuerID, iCryptHandle,
							   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( cryptStatusOK( status ) )
			status = getCertKeyID( keyID, iCryptHandle );
		}
	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;

			length = decodePKIUserValue( binaryKeyID, encKeyID, msgData.length );
			makeKeyID( keyID, CRYPT_IKEYID_KEYID, binaryKeyID, length );
			}
		if( cryptStatusOK( status ) )
			status = getKeyID( nameID, iCryptHandle, CRYPT_IATTRIBUTE_SUBJECT );
		}
	if( cryptStatusOK( status ) )
		status = getKeyID( certID, iCryptHandle, 
						   CRYPT_CERTINFO_FINGERPRINT_SHA );
	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 */
		return( CRYPT_ARGERROR_NUM1 );

	/* If this is a partial add (in which we add a cert item which is in the
	   initial stages of the creation process where, although the item may
	   be physically present in the store it can't be accessed directly), we
	   set the first byte to 0xFF to indicate this.  In addition we set the
	   first two bytes of the IDs that have uniqueness constraints to an
	   out-of-band value to prevent a clash with the finished entry when we
	   complete the issue process and replace the partial version with the
	   full version */
	if( addType == CERTADD_PARTIAL || addType == CERTADD_PARTIAL_RENEWAL )
		{
		const char ch = ( addType == CERTADD_PARTIAL ) ? '-' : '+';

		certData[ 0 ] = 0xFF;
		issuerID[ 0 ] = issuerID[ 1 ] = ch;
		keyID[ 0 ] = keyID[ 1 ] = ch;
		certID[ 0 ] = certID[ 1 ] = ch;
		}

	/* Set up the cert object data to write */
	if( !hasBinaryBlobs( dbmsInfo ) )
		{
		char encodedCertData[ MAX_ENCODED_CERT_SIZE ];

		base64encode( encodedCertData, certData, certDataLength,
					  CRYPT_CERTTYPE_NONE );
		if( certType == CRYPT_CERTTYPE_CERTIFICATE )
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO certificates VALUES ('$', '$', '$', '$', '$', '$', "
											 "'$', ?, '$', '$', '$', '$', '$')",
						   C, SP, L, O, OU, CN, email, nameID, issuerID,
						   keyID, certID, encodedCertData );
		else
			if( certType == CRYPT_CERTTYPE_REQUEST_CERT )
				dbmsFormatSQL( sqlBuffer,
			"INSERT INTO certRequests VALUES ('" TEXT_CERTTYPE_REQUEST_CERT "', "
											 "'$', '$', '$', '$', '$', '$', "
											 "'$', '$', '$')",
							   C, SP, L, O, OU, CN, email, certID,
							   encodedCertData );
			else
				dbmsFormatSQL( sqlBuffer,
			"INSERT INTO pkiUsers VALUES ('$', '$', '$', '$', '$', '$', "
										 "'$', '$', '$', '$')",
							   C, SP, L, O, OU, CN, nameID, keyID, certID,
							   encodedCertData );
		}
	else
		{
		if( certType == CRYPT_CERTTYPE_CERTIFICATE )
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO certificates VALUES ('$', '$', '$', '$', '$', '$', "
											 "'$', ?, '$', '$', '$', '$', ?)",
						   C, SP, L, O, OU, CN, email, nameID, issuerID,
						   keyID, certID );
		else
			if( certType == CRYPT_CERTTYPE_REQUEST_CERT )
				dbmsFormatSQL( sqlBuffer,
			"INSERT INTO certRequests VALUES ('" TEXT_CERTTYPE_REQUEST_CERT "', "
											 "'$', '$', '$', '$', '$', '$', "
											 "'$', '$', ?)",
							   C, SP, L, O, OU, CN, email, certID );
			else
				dbmsFormatSQL( sqlBuffer,
			"INSERT INTO pkiUsers VALUES ('$', '$', '$', '$', '$', '$', "
										 "'$', '$', '$', ?)",
							   C, SP, L, O, OU, CN, nameID, keyID, certID );
		}

⌨️ 快捷键说明

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