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

📄 ca_misc.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
	if( reqCertID == NULL )
		{
		if( subjCertID == NULL )
			param1ptr = encodedCertData;
		else
			{
			param1ptr = subjCertID;
			param2ptr = encodedCertData;
			}
		}
	else
		{
		param1ptr = reqCertID;
		if( subjCertID == NULL )
			param2ptr = encodedCertData;
		else
			{
			param2ptr = subjCertID;
			param3ptr = encodedCertData;
			}
		}

	/* If we're not worried about the certID, we just insert a nonce value
	   which is used to meet the constraints for a unique entry.  In order
	   to ensure that it doesn't clash with a real certID, we set the first
	   four characters to an out-of-band value */
	if( certID == NULL )
		{
		RESOURCE_DATA msgData;
		BYTE nonce[ KEYID_SIZE ];
		int status;

		certIDptr = certIDbuffer;
		setMessageData( &msgData, nonce, KEYID_SIZE );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusOK( status ) )
			{
			status = base64encode( certIDptr, DBXKEYID_BUFFER_SIZE, nonce, 
								   DBXKEYID_SIZE, CRYPT_CERTTYPE_NONE );
			certIDptr[ MAX_ENCODED_DBXKEYID_SIZE ] = '\0';
			}
		if( cryptStatusError( status ) )
			{
			/* Normally this is a should-never-occur error, however if 
			   cryptlib has been shut down from another thread the kernel
			   will fail all non shutdown-related calls with a permission 
			   error.  To avoid false alarms, we mask out failures due to
			   permission errors */
			assert( ( status == CRYPT_ERROR_PERMISSION ) || NOTREACHED );
			return( status );
			}
		memset( certIDptr, '-', 4 );
		}

	/* Update the cert log */
	sPrintf( actionString, "%d", action );
	if( data != NULL && !hasBinaryBlobs( dbmsInfo ) )
		{
		dataPtrLength = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE, 
									  data, dataLength, CRYPT_CERTTYPE_NONE );
		if( cryptStatusError( dataPtrLength ) )
			{
			assert( NOTREACHED );
			return( dataPtrLength );
			}
		encodedCertData[ dataPtrLength ] = '\0';
		dataPtr = encodedCertData;
		}
	dbmsFormatSQL( sqlBuffer, sqlFormatBuffer, actionString, certIDptr,
				   param1ptr, param2ptr, param3ptr );
	return( dbmsUpdate( sqlBuffer, dataPtr, dataPtrLength, boundDate, 
						updateType ) );
	}

int updateCertErrorLog( DBMS_INFO *dbmsInfo, const int errorStatus,
						const char *errorString, const char *certID,
						const char *reqCertID, const char *subjCertID,
						const void *data, const int dataLength )
	{
	STREAM stream;
	BYTE errorData[ MAX_CERT_SIZE ];
	const int errorStringLength = strlen( errorString );
	int errorDataLength, status;

	/* Encode the error information:
		SEQUENCE {
			errorStatus	INTEGER,
			errorString	UTF8String,
			certData	ANY OPTIONAL
			} */
	sMemOpen( &stream, errorData, MAX_CERT_SIZE );
	writeSequence( &stream, sizeofShortInteger( -errorStatus ) + \
							( int ) sizeofObject( errorStringLength ) + \
							dataLength );
	writeShortInteger( &stream, -errorStatus, DEFAULT_TAG );
	status = writeCharacterString( &stream, errorString, errorStringLength,
								   BER_STRING_UTF8 );
	if( dataLength > 0 )
		status = swrite( &stream, data, dataLength );
	errorDataLength = stell( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		sMemOpen( &stream, errorData, MAX_CERT_SIZE );
		writeSequence( &stream, ( 1 + 1 + 1 ) + ( 1 + 1 + 31 ) );
		writeShortInteger( &stream, -( CRYPT_ERROR_FAILED ), DEFAULT_TAG );
		writeCharacterString( &stream, "Error writing error information", 31,
							  BER_STRING_UTF8 );
		errorDataLength = stell( &stream );
		sMemDisconnect( &stream );
		}

	/* Update the cert log with the error information as the data value */
	return( updateCertLog( dbmsInfo, CRYPT_CERTACTION_ERROR, certID,
						   reqCertID, subjCertID, errorData,
						   errorDataLength, DBMS_UPDATE_NORMAL ) );
	}

int updateCertErrorLogMsg( DBMS_INFO *dbmsInfo, const int errorStatus,
						   const char *errorString )
	{
	return( updateCertErrorLog( dbmsInfo, errorStatus, errorString,
								NULL, NULL, NULL, NULL, 0 ) );
	}

/****************************************************************************
*																			*
*							Miscellaneous CA Functions						*
*																			*
****************************************************************************/

/* Get the PKI user that originally authorised the issuing of a cert */

int caGetIssuingUser( DBMS_INFO *dbmsInfo, CRYPT_CERTIFICATE *iPkiUser,
					  const char *initialCertID, 
					  const int initialCertIDlength )
	{
	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isWritePtr( iPkiUser, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( isReadPtr( initialCertID, MAX_ENCODED_DBXKEYID_SIZE ) );
	assert( initialCertIDlength >= MAX_ENCODED_DBXKEYID_SIZE );

	return( getIssuingUser( dbmsInfo, iPkiUser, initialCertID, 
							initialCertIDlength ) );
	}

/* Perform a cleanup operation on the certificate store, removing incomplete,
   expired, and otherwise leftover certificates */

static int caCleanup( DBMS_INFO *dbmsInfo,
					  const CRYPT_CERTACTION_TYPE action )
	{
	BYTE prevCertData[ 128 ];
	char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
	const time_t currentTime = getTime();
	int errorCount, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( action == CRYPT_CERTACTION_EXPIRE_CERT || \
			action == CRYPT_CERTACTION_CLEANUP );

	/* If the time is screwed up we can't perform time-based cleanup 
	   actions */
	if( action == CRYPT_CERTACTION_EXPIRE_CERT && \
		currentTime < MIN_TIME_VALUE )
		return( CRYPT_ERROR_FAILED );

	/* Rumble through the cert store either deleting leftover requests or
	   expiring every cert which is no longer current.  Since we're cleaning
	   up the cert store we try and continue even if an error occurs, at
	   least up to a limit */
	memset( prevCertData, 0, 8 );
	errorCount = 0;
	do
		{
		char certID[ MAX_QUERY_RESULT_SIZE ];
		int certIDlength;

		/* Find the cert ID of the next expired cert or next cert request
		   (revocation requests are handled later by completing the
		   revocation).  Note that the select requires that the database
		   glue code be capable of returning a single result and then 
		   finishing the query, for some back-ends there may be a need to 
		   explicitly cancel the query after the first result is returned if 
		   the database returns an entire result set */
		if( action == CRYPT_CERTACTION_EXPIRE_CERT )
			status = dbmsQuery(
						"SELECT certID FROM certificates WHERE validTo < ?",
								certID, &certIDlength, NULL, 0, currentTime,
								DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
		else
			status = dbmsQuery(
						"SELECT certID FROM certRequests WHERE type = "
							TEXT_CERTTYPE_REQUEST_CERT,
								certID, &certIDlength, NULL, 0, 0, 
								DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
		if( cryptStatusError( status ) || \
			certIDlength > MAX_ENCODED_DBXKEYID_SIZE )
			{
			errorCount++;
			continue;
			}
		if( !memcmp( prevCertData, certID, certIDlength ) )
			/* We're stuck in a loop fetching the same value over and over,
			   make an emergency exit */
			break;
		memcpy( prevCertData, certID, certIDlength );

		/* Clean up/expire the cert.  Since CRYPT_CERTACTION_CLEANUP is a
		   composite action that encompasses a whole series of operations,
		   we replace it with a more specific action code */
		certID[ certIDlength ] = '\0';
		status = updateCertLog( dbmsInfo,
								( action == CRYPT_CERTACTION_CLEANUP ) ? \
								CRYPT_CERTACTION_RESTART_CLEANUP : action,
								NULL, NULL, certID, NULL, 0,
								DBMS_UPDATE_BEGIN );
		if( cryptStatusOK( status ) )
			{
			dbmsFormatSQL( sqlBuffer,
					   ( action == CRYPT_CERTACTION_EXPIRE_CERT ) ? \
				"DELETE FROM certificates WHERE certID = '$'" : \
				"DELETE FROM certRequests WHERE certID = '$'",
						   certID );
			status = dbmsUpdate( sqlBuffer, NULL, 0, 0, DBMS_UPDATE_COMMIT );
			}
		else
			{
			/* Something went wrong, abort the transaction */
			dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
			errorCount++;
			}
		}
	while( status != CRYPT_ERROR_NOTFOUND && errorCount < 10 );

	/* If we ran into a problem, perform a fallback general delete of
	   entries that caused the problem */
	if( status != CRYPT_ERROR_NOTFOUND )
		{
		if( action == CRYPT_CERTACTION_EXPIRE_CERT )
			{
			updateCertErrorLogMsg( dbmsInfo, status, "Expire operation "
								   "failed, performing fallback straight "
								   "delete" );
			status = dbmsUpdate(
						"DELETE FROM certificates WHERE validTo < ?",
								 NULL, 0, currentTime, DBMS_UPDATE_NORMAL );
			}
		else
			{
			updateCertErrorLogMsg( dbmsInfo, status, "Cert request "
								   "cleanup operation failed, performing "
								   "fallback straight delete" );
			status = dbmsStaticUpdate(
						"DELETE FROM certRequests WHERE type = "
							TEXT_CERTTYPE_REQUEST_CERT );
			}
		if( cryptStatusError( status ) )
			updateCertErrorLogMsg( dbmsInfo, status, "Fallback straight "
								   "delete failed" );
		}

	/* If it's an expiry action we've done the expired certs, now remove any
	   stale CRL entries and exit.  If there are no CRL entries in the
	   expiry period this isn't an error, so we remap the error code if
	   necessary */
	if( action == CRYPT_CERTACTION_EXPIRE_CERT )
		{
		status = dbmsUpdate(
					"DELETE FROM CRLs WHERE expiryDate < ?",
							 NULL, 0, currentTime, DBMS_UPDATE_NORMAL );
		return( ( status == CRYPT_ERROR_NOTFOUND ) ? \
				resetErrorInfo( dbmsInfo ) : status );
		}

	/* It's a restart, process any incompletely-issued certificates in the
	   same manner as the expiry/cleanup is handled.  Since we don't know at
	   what stage the issue process was interrupted, we have to make a worst-
	   case assumption and do a full reversal */
	memset( prevCertData, 0, 8 );
	errorCount = 0;
	do
		{
		CRYPT_CERTIFICATE iCertificate;

⌨️ 快捷键说明

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