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

📄 dbxdbx.c

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

	/* Insert the cert object information */
	return( dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
						certData : NULL, certDataLength, boundDate,
						updateType ) );
	}

int addCRL( DBMS_INFO *dbmsInfo, const CRYPT_CERTIFICATE iCryptCRL,
			const CRYPT_CERTIFICATE iCryptRevokeCert,
			const DBMS_UPDATE_TYPE updateType )
	{
	BYTE certData[ MAX_CERT_SIZE ];
	char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
	char nameID[ DBXKEYID_BUFFER_SIZE ], issuerID[ DBXKEYID_BUFFER_SIZE ];
	char certID[ DBXKEYID_BUFFER_SIZE ];
	time_t expiryDate = 0;
	int certDataLength, status;

	assert( ( isCertStore( dbmsInfo ) && \
			  checkHandleRange( iCryptRevokeCert ) ) || \
			( !isCertStore( dbmsInfo ) && \
			  iCryptRevokeCert == CRYPT_UNUSED ) );

	/* Get the ID information for the current CRL entry */
	status = getKeyID( issuerID, iCryptCRL,
					   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, certData, MAX_CERT_SIZE );
		status = krnlSendMessage( iCryptCRL, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_CRLENTRY );
		certDataLength = msgData.length;
		}
	if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
		{
		/* If it's a cert store we also need to obtain the cert ID, the name
		   ID of the issuer, and the cert expiry date from the cert being
		   revoked */
		status = getKeyID( certID, iCryptRevokeCert,
						   CRYPT_CERTINFO_FINGERPRINT_SHA );
		if( cryptStatusOK( status ) )
			status = getKeyID( nameID, iCryptRevokeCert,
							   CRYPT_IATTRIBUTE_ISSUER );
		if( cryptStatusOK( status ) )
			{
			RESOURCE_DATA msgData;

			setMessageData( &msgData, &expiryDate, sizeof( time_t ) );
			status = krnlSendMessage( iCryptRevokeCert,
									  IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_CERTINFO_VALIDTO );
			}
		}
	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 );

	/* Set up the cert object data to write.  Cert stores contain extra info
	   which is needed to build a CRL so we have to vary the SQL string
	   depending on the keyset type */
	if( !hasBinaryBlobs( dbmsInfo ) )
		{
		char encodedCertData[ MAX_ENCODED_CERT_SIZE ];

		base64encode( encodedCertData, certData, certDataLength,
					  CRYPT_CERTTYPE_NONE );
		if( isCertStore( dbmsInfo ) )
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO CRLs VALUES (?, '$', '$', '$', '$')",
						   nameID, issuerID, certID, encodedCertData );
		else
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO CRLs VALUES ('$', '$')",
						   issuerID, encodedCertData );
		}
	else
		{
		if( isCertStore( dbmsInfo ) )
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO CRLs VALUES (?, '$', '$', '$', ?)",
						   nameID, issuerID, certID );
		else
			dbmsFormatSQL( sqlBuffer,
			"INSERT INTO CRLs VALUES ('$', ?)",
						   issuerID );
		}

	/* Insert the entry */
	return( dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
						certData : NULL, certDataLength, expiryDate, 
						updateType ) );
	}

static int setItemFunction( KEYSET_INFO *keysetInfo,
							const CRYPT_HANDLE iCryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const char *password, const int passwordLength,
							const int flags )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
	BOOLEAN seenNonDuplicate = FALSE;
	int type, status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_REVOCATIONINFO || \
			itemType == KEYMGMT_ITEM_REQUEST || \
			itemType == KEYMGMT_ITEM_PKIUSER );
	assert( password == NULL ); assert( passwordLength == 0 );

	/* Make sure that we've been given a cert, cert chain, or CRL.  We can't 
	   do any more specific checking against the itemType because if it's 
	   coming from outside cryptlib it'll just be passed in as a generic cert 
	   object with no distinction between object subtypes */
	status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
							  &type, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_NUM1 );
	if( isCertStore( dbmsInfo ) )
		{
		/* The only item that can be inserted directly into a CA cert
		   store is a CA request or PKI user info */
		if( type != CRYPT_CERTTYPE_CERTREQUEST && \
			type != CRYPT_CERTTYPE_REQUEST_CERT && \
			type != CRYPT_CERTTYPE_REQUEST_REVOCATION && \
			type != CRYPT_CERTTYPE_PKIUSER )
			return( CRYPT_ARGERROR_NUM1 );

		if( itemType == KEYMGMT_ITEM_PKIUSER )
			return( caAddPKIUser( dbmsInfo, iCryptHandle ) );

		/* It's a cert request being added to a CA certificate store */
		assert( itemType == KEYMGMT_ITEM_REQUEST );
		return( caAddCertRequest( dbmsInfo, iCryptHandle, type,
								  ( flags & KEYMGMT_FLAG_UPDATE ) ? \
									TRUE : FALSE ) );
		}
	if( type != CRYPT_CERTTYPE_CERTIFICATE && \
		type != CRYPT_CERTTYPE_CERTCHAIN && \
		type != CRYPT_CERTTYPE_CRL )
		return( CRYPT_ARGERROR_NUM1 );

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_REVOCATIONINFO );

	/* Lock the cert or CRL for our exclusive use and select the first
	   sub-item (cert in a cert chain, entry in a CRL), update the keyset
	   with the cert(s)/CRL entries, and unlock it to allow others access */
	status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptStatusError( status ) )
		return( status );
	krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_CURSORFIRST,
					 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	do
		{
		/* Add the certificate or CRL */
		if( type == CRYPT_CERTTYPE_CRL )
			status = addCRL( dbmsInfo, iCryptHandle, CRYPT_UNUSED,
							 DBMS_UPDATE_NORMAL );
		else
			status = addCert( dbmsInfo, iCryptHandle,
							  CRYPT_CERTTYPE_CERTIFICATE, CERTADD_NORMAL,
							  DBMS_UPDATE_NORMAL );

		/* An item being added may already be present, however we can't fail
		   immediately because what's being added may be a chain containing
		   further certs or a CRL containing further entries, so we keep
		   track of whether we've successfully added at least one item and
		   clear data duplicate errors */
		if( status == CRYPT_OK )
			seenNonDuplicate = TRUE;
		else
			if( status == CRYPT_ERROR_DUPLICATE )
				status = CRYPT_OK;
		}
	while( cryptStatusOK( status ) && \
		   krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
							MESSAGE_VALUE_CURSORNEXT,
							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
	krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptStatusOK( status ) && !seenNonDuplicate )
		/* We reached the end of the chain/CRL without finding anything we
		   could add, return a data duplicate error */
		status = CRYPT_ERROR_DUPLICATE;

	return( status );
	}

/* Delete a record from the database */

static int deleteItemFunction( KEYSET_INFO *keysetInfo,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_KEYID_TYPE keyIDtype,
							   const void *keyID, const int keyIDlength )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
	char keyIDbuffer[ CRYPT_MAX_TEXTSIZE * 2 ];
	char sqlBuffer[ MAX_SQL_QUERY_SIZE ];

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( !isCertStore( dbmsInfo ) );

	/* Delete the key from the database */
	makeKeyID( keyIDbuffer, keyIDtype, keyID, keyIDlength );
	dbmsFormatSQL( sqlBuffer,
			"DELETE FROM certificates WHERE $ = '$'",
				   getKeyName( keyIDtype ), keyIDbuffer );
	return( dbmsStaticUpdate( sqlBuffer ) );
	}

/* Return status info for the keyset */

static BOOLEAN isBusyFunction( KEYSET_INFO *keysetInfo )
	{
	return( ( keysetInfo->keysetDBMS->flags & \
			  ( DBMS_FLAG_UPDATEACTIVE | DBMS_FLAG_QUERYACTIVE ) ) ? \
			  TRUE : FALSE );
	}

/* Open a connection to a database */

static int initFunction( KEYSET_INFO *keysetInfo, const char *name,
						 const CRYPT_KEYOPT_TYPE options )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
	int status;

	/* Perform a database back-end specific open */
	status = dbmsOpen( name, ( options == CRYPT_KEYOPT_READONLY ) ? \
					   options : CRYPT_KEYOPT_NONE );
	if( cryptStatusError( status ) )
		{
		endDbxSession( keysetInfo );
		return( status );
		}

	/* If we're being asked to create a new database, create it and exit */
	if( options == CRYPT_KEYOPT_CREATE )
		{
		status = createDatabase( dbmsInfo );
		if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
			status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
									NULL, NULL, NULL, NULL, 0,
									DBMS_UPDATE_NORMAL );
		if( cryptStatusError( status ) )
			{
			dbmsClose();
			endDbxSession( keysetInfo );
			}
		return( status );
		}

	/* Check to see whether it's a cert store.  We do this by checking for
	   the presence of the cert store creation entry in the log, this is
	   always present with an action value of CRYPT_CERTACTION_CREATE */
	status = dbmsStaticQuery(
			"SELECT certData FROM certLog WHERE action = "
				TEXT_CERTACTION_CREATE,
							  DBMS_QUERY_CHECK );
	if( cryptStatusOK( status ) )
		{
		/* It's a cert store, if we're opening it as a non-cert-store it has
		   to be in read-only mode.  We return an error rather than quietly
		   changing the access mode to read-only both to make it explicit to
		   the user at open time that they can't make changes and because we
		   need to have the read-only flag set when we open the database to
		   optimise the buffering and locking strategy, setting it at this
		   point is too late */
		if( !isCertStore( dbmsInfo ) )
			{
			if( options != CRYPT_KEYOPT_READONLY )
				{
				dbmsClose();
				endDbxSession( keysetInfo );
				status = CRYPT_ERROR_PERMISSION;
				}

			/* Remember that even though it's not functioning as a cert
			   store, we can still perform some extended queries on it based
			   on fields that are only present in cert stores */
			dbmsInfo->flags |= DBMS_FLAG_CERTSTORE_FIELDS;

			return( status );
			}

		/* If this isn't a read-only open then record a connection to the
		   store */
		if( options != CRYPT_KEYOPT_READONLY )
			{
			status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
									NULL, NULL, NULL, NULL, 0,
									DBMS_UPDATE_NORMAL );
			if( cryptStatusError( status ) )
				{
				dbmsClose();
				endDbxSession( keysetInfo );
				}
			}

		return( status );
		}

	/* It's not a cert store, if we're expecting to open it as one tell the
	   caller */
	if( isCertStore( dbmsInfo ) )
		{
		dbmsClose();
		endDbxSession( keysetInfo );
		return( CRYPT_ARGERROR_NUM1 );
		}

	/* Since the failure of the query above will set the extended error
	   information, we have to explicitly clear it here to avoid making the
	   (invisible) query side-effects visible to the user */
	dbmsInfo->errorCode = 0;
	memset( dbmsInfo->errorMessage, 0, MAX_ERRMSG_SIZE );

	return( CRYPT_OK );
	}

/* Close the connection to a database */

static void shutdownFunction( KEYSET_INFO *keysetInfo )
	{
	DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;

	/* If it's a cert store opened in read/write mode, record a closed
	   connection to the store */
	if( isCertStore( dbmsInfo ) && \
		keysetInfo->options != CRYPT_KEYOPT_READONLY )
		updateCertLog( dbmsInfo, CRYPT_CERTACTION_DISCONNECT, NULL, NULL,
					   NULL, NULL, 0, DBMS_UPDATE_NORMAL );

	/* If we're in the middle of a query, cancel it */
	if( dbmsInfo->flags & DBMS_FLAG_QUERYACTIVE )
		dbmsStaticQuery( NULL, DBMS_QUERY_CANCEL );

	dbmsClose();
	endDbxSession( keysetInfo );
	}

/* Set up the function pointers to the keyset methods */

int setAccessMethodDBMS( KEYSET_INFO *keysetInfo,
						 const CRYPT_KEYSET_TYPE type )
	{
	int status = CRYPT_ERROR;

	/* Set up the lower-level interface functions */
	status = initDbxSession( keysetInfo, type );
	if( cryptStatusError( status ) )
		return( status );

	/* Set the access method pointers */
	keysetInfo->initFunction = initFunction;
	keysetInfo->shutdownFunction = shutdownFunction;
	keysetInfo->getItemFunction = getItemFunction;
	keysetInfo->setItemFunction = setItemFunction;
	keysetInfo->deleteItemFunction = deleteItemFunction;
	keysetInfo->getFirstItemFunction = getFirstItemFunction;
	keysetInfo->getNextItemFunction = getNextItemFunction;
	if( type == CRYPT_KEYSET_ODBC_STORE || \
		type == CRYPT_KEYSET_DATABASE_STORE || \
		type == CRYPT_KEYSET_PLUGIN_STORE )
		initDBMSCA( keysetInfo );
	keysetInfo->isBusyFunction = isBusyFunction;

	return( CRYPT_OK );
	}
#endif /* USE_DBMS */

⌨️ 快捷键说明

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