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

📄 ca_issue.c

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

#include <stdarg.h>
#include <stdio.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

/****************************************************************************
*																			*
*								Cert Issue Functions						*
*																			*
****************************************************************************/

/* Get the issue type (new request, renewal, etc) for a particular cert
   request or certificate */

static int getCertIssueType( DBMS_INFO *dbmsInfo,
							 const CRYPT_CERTIFICATE iCertificate,
							 const BOOLEAN isCert )
	{
	BYTE certData[ MAX_QUERY_RESULT_SIZE ];
	char certID[ DBXKEYID_BUFFER_SIZE ];
	int certIDlength, length, status;

	/* Get the certID of the request that resulted in the cert creation */
	status = certIDlength = getKeyID( certID, iCertificate, 
									  CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( !cryptStatusError( status ) && isCert )
		{
		/* If it's a cert we have to apply an extra level of indirection to
		   get the request that resulted in its creation */
		status = dbmsQuery(
			"SELECT reqCertID FROM certLog WHERE certID = ?",
							certData, &length, certID, certIDlength, 0, 
							DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
		if( cryptStatusOK( status ) )
			{
			if( length > MAX_ENCODED_DBXKEYID_SIZE )
				length = MAX_ENCODED_DBXKEYID_SIZE;
			memcpy( certID, certData, length );
			certIDlength = length;
			}
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Find out whether this was a cert update by checking whether it was
	   added as a standard or renewal request, then set the update type
	   appropriately.  The comparison for the action type is a bit odd since
	   some back-ends will return the action as text and some as a binary
	   numeric value, rather than relying on the back-end glue code to
	   perform the appropriate conversion we just check for either value
	   type */
	status = dbmsQuery(
		"SELECT action FROM certLog WHERE certID = ?",
						certData, &length, certID, certIDlength, 0, 
						DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
	if( cryptStatusError( status ) )
		return( status );
	switch( certData[ 0 ] )
		{
		case CRYPT_CERTACTION_REQUEST_CERT:
		case TEXTCH_CERTACTION_REQUEST_CERT:
			return( CERTADD_PARTIAL );

		case CRYPT_CERTACTION_REQUEST_RENEWAL:
		case TEXTCH_CERTACTION_REQUEST_RENEWAL:
			return( CERTADD_PARTIAL_RENEWAL );

		default:
			assert( NOTREACHED );
		}
	return( CRYPT_ERROR_NOTFOUND );
	}

/* Replace one cert (usually a partially-issued one) with another (usually
   its completed form).  The types of operations and their corresponding
   add-type values are:

	ESC1 -> std		CERTADD_PARTIAL				Completion of partial
	ESC1 -> ESC2	CERTADD_PARTIAL_RENEWAL		First half of renewal
	ESC2 -> std		CERTADD_RENEWAL_COMPLETE	Second half of renewal */

static int completeCert( DBMS_INFO *dbmsInfo,
						 const CRYPT_CERTIFICATE iCertificate,
						 const CERTADD_TYPE addType )
	{
	char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
	char certID[ DBXKEYID_BUFFER_SIZE ];
	int length, status;

	assert( addType == CERTADD_PARTIAL || \
			addType == CERTADD_PARTIAL_RENEWAL || \
			addType == CERTADD_RENEWAL_COMPLETE );

	status = length = getKeyID( certID, iCertificate,
								CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( cryptStatusError( status ) )
		return( status );
	status = addCert( dbmsInfo, iCertificate, CRYPT_CERTTYPE_CERTIFICATE,
					  ( addType == CERTADD_PARTIAL_RENEWAL ) ? \
						CERTADD_PARTIAL_RENEWAL : CERTADD_NORMAL,
					  DBMS_UPDATE_BEGIN );
	if( cryptStatusOK( status ) )
		{
		char specialCertID[ DBXKEYID_BUFFER_SIZE ];

		/* Turn the general certID into the form required for special-case
		   cert data */
		memcpy( specialCertID, certID, length + 1 );
		memcpy( specialCertID,
				( addType == CERTADD_RENEWAL_COMPLETE ) ? \
				KEYID_ESC2 : KEYID_ESC1, KEYID_ESC_SIZE );
		specialCertID[ MAX_ENCODED_DBXKEYID_SIZE ] = '\0';
		dbmsFormatSQL( sqlBuffer,
			"DELETE FROM certificates WHERE certID = '$'",
					   specialCertID );
		status = dbmsUpdate( sqlBuffer, NULL, 0, 0,
							 ( addType == CERTADD_PARTIAL_RENEWAL ) ? \
							 DBMS_UPDATE_COMMIT : DBMS_UPDATE_CONTINUE );
		}
	if( cryptStatusOK( status ) )
		{
		if( addType != CERTADD_PARTIAL_RENEWAL )
			status = updateCertLog( dbmsInfo,
									CRYPT_CERTACTION_CERT_CREATION_COMPLETE,
									NULL, NULL, certID, NULL, 0,
									DBMS_UPDATE_COMMIT );
		}
	else
		/* Something went wrong, abort the transaction */
		dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );

	/* If the operation failed, record the details */
	if( cryptStatusError( status ) )
		updateCertErrorLog( dbmsInfo, status,
							"Certificate creation - completion operation "
							"failed", NULL, NULL, certID, NULL, 0 );

	return( status );
	}

/* Complete a certificate renewal operation by revoking the cert to be
   replaced and replacing it with the newly-issued cert */

int completeCertRenewal( DBMS_INFO *dbmsInfo,
						 const CRYPT_CERTIFICATE iReplaceCertificate )
	{
	CRYPT_CERTIFICATE iOrigCertificate;
	char keyID[ DBXKEYID_BUFFER_SIZE ];
	int dummy, length, status;

	/* Extract the key ID from the new cert and use it to fetch the existing
	   cert issued for the same key */
	status = length = getCertKeyID( keyID, iReplaceCertificate );
	if( !cryptStatusError( status ) )
		status = getItemData( dbmsInfo, &iOrigCertificate, &dummy,
							  CRYPT_IKEYID_KEYID, keyID, length,
							  KEYMGMT_ITEM_PUBLICKEY, KEYMGMT_FLAG_NONE );
	if( status == CRYPT_ERROR_NOTFOUND )
		/* If the original cert fetch fails with a notfound error this is OK
		   since we may be resuming from a point where the revocation has
		   already occurred, or the cert may have already expired or been
		   otherwise replaced, so we just slide in the new cert */
		return( completeCert( dbmsInfo, iReplaceCertificate,
							  CERTADD_RENEWAL_COMPLETE ) );
	if( cryptStatusError( status ) )
		return( status );

	/* Replace the original cert with the new one */
	status = revokeCertDirect( dbmsInfo, iOrigCertificate,
							   CRYPT_CERTACTION_REVOKE_CERT );
	if( cryptStatusOK( status ) )
		status = completeCert( dbmsInfo, iReplaceCertificate,
							   CERTADD_RENEWAL_COMPLETE );
	krnlSendNotifier( iOrigCertificate, IMESSAGE_DECREFCOUNT );

	return( status );
	}

/* Issue a cert from a cert request */

int caIssueCert( DBMS_INFO *dbmsInfo, CRYPT_CERTIFICATE *iCertificate,
				 const CRYPT_CERTIFICATE caKey,
				 const CRYPT_CERTIFICATE iCertRequest,
				 const CRYPT_CERTACTION_TYPE action )
	{
	CRYPT_CERTIFICATE iLocalCertificate;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE certData[ MAX_CERT_SIZE ];
	char issuerID[ DBXKEYID_BUFFER_SIZE ], certID[ DBXKEYID_BUFFER_SIZE ];
	char reqCertID[ DBXKEYID_BUFFER_SIZE ];
	CERTADD_TYPE addType = CERTADD_NORMAL;
	int certDataLength, issueType, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isHandleRangeValid( iCertRequest ) );
	assert( action == CRYPT_CERTACTION_ISSUE_CERT || \
			action == CRYPT_CERTACTION_CERT_CREATION );

	/* Clear return value */
	if( iCertificate != NULL )
		*iCertificate = CRYPT_ERROR;

	/* Extract the information that we need from the cert request */
	status = issueType = getCertIssueType( dbmsInfo, iCertRequest, FALSE );
	if( !cryptStatusError( status ) )
		status = getKeyID( reqCertID, iCertRequest,
						   CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CAMGMT_ARGERROR_REQUEST : status );

	/* We're ready to perform the cert issue transaction.  First, we turn the
	   request into a cert */
	setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( status );
	iLocalCertificate = createInfo.cryptHandle;
	status = krnlSendMessage( iLocalCertificate, IMESSAGE_SETATTRIBUTE, 
							  ( void * ) &iCertRequest,
							  CRYPT_CERTINFO_CERTREQUEST );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Sanitise the new cert of potentially dangerous attributes.  For our 
	   use we clear all CA and CA-equivalent attributes to prevent users 
	   from submitting requests that turn them into CAs */
	setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,

⌨️ 快捷键说明

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