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

📄 ca_add.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isReadPtr( keyID, keyIDlength ) );

	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
			  keyIDtype == CRYPT_KEYID_URI );
	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
			  keyIDlength < MAX_ATTRIBUTE_SIZE );
	REQUIRES( errorInfo != NULL );

	/* Get information on the PKI user that we're about to delete */
	status = getItemData( dbmsInfo, &iPkiUser, &dummy, 
						  KEYMGMT_ITEM_PKIUSER, keyIDtype, 
						  keyID, keyIDlength, KEYMGMT_FLAG_NONE, 
						  errorInfo );
	if( cryptStatusOK( status ) )
		{
		status = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, 
						   iPkiUser, CRYPT_CERTINFO_FINGERPRINT_SHA );
		krnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );
		}
	if( cryptStatusError( status ) )
		{
		retExtErr( status, 
				   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
					 "Couldn't get information on PKI user to be "
					 "deleted: " ) );
		}

	/* Delete the PKI user information and record the deletion */
	initBoundData( boundDataPtr );
	setBoundData( boundDataPtr, 0, certID, certIDlength );
	status = dbmsUpdate( 
			"DELETE FROM pkiUsers WHERE certID = ?", 
						 boundDataPtr, DBMS_UPDATE_BEGIN );
	if( cryptStatusOK( status ) )
		status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_DELETEUSER, 
								NULL, 0, NULL, 0, certID, certIDlength, 
								NULL, 0, DBMS_UPDATE_COMMIT );
	else
		{
		/* Something went wrong, abort the transaction */
		dbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );
		retExtErr( status, 
				   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
					 "PKI user delete operation failed: " ) );
		}

	return( status );
	}

/* Add a certificate issue or revocation request to the certificate store */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
int caAddCertRequest( INOUT DBMS_INFO *dbmsInfo, 
					  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
					  IN_ENUM( CRYPT_CERTTYPE ) \
						const CRYPT_CERTTYPE_TYPE requestType, 
					  const BOOLEAN isRenewal, 
					  INOUT ERROR_INFO *errorInfo )
	{
	BYTE certData[ MAX_CERT_SIZE + 8 ];
	char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
	char reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ], *reqCertIDptr = reqCertID;
	int certIDlength, reqCertIDlength = DUMMY_INIT;
	int certDataLength = DUMMY_INIT, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	
	REQUIRES( isHandleRangeValid( iCertRequest ) );
	REQUIRES( requestType == CRYPT_CERTTYPE_CERTREQUEST || \
			  requestType == CRYPT_CERTTYPE_REQUEST_CERT || \
			  requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION );
	REQUIRES( errorInfo != NULL );

	/* Make sure that the request is OK and if it's a revocation request 
	   make sure that it refers to a certificate which is both present in 
	   the store and currently active */
	if( !checkRequest( iCertRequest, CRYPT_CERTACTION_NONE ) )
		{
		retExtArg( CRYPT_ARGERROR_NUM1, 
				   ( CRYPT_ARGERROR_NUM1, errorInfo, 
					 "Certificate request information "
					 "inconsistent/invalid" ) );
		}
	if( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
		{
		status = checkRevRequest( dbmsInfo, iCertRequest );
		if( cryptStatusError( status ) )
			retExt( status, 
					( status, errorInfo, 
					  "Revocation request doesn't correspond to a currently "
					  "active certificate" ) );
		}

	/* Extract the information that we need from the certificate request */
	status = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, 
					   iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( cryptStatusOK( status ) )
		{
		status = extractCertData( iCertRequest, 
								  ( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \
									CRYPT_ICERTFORMAT_DATA : \
									CRYPT_CERTFORMAT_CERTIFICATE,
								  certData, MAX_CERT_SIZE, &certDataLength );
		}
	if( cryptStatusOK( status ) )
		{
		status = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength, 
						   iCertRequest, CRYPT_IATTRIBUTE_AUTHCERTID );
		if( cryptStatusError( status ) )
			{
			/* If the request is being added directly by the user, there's no
			   authorising certificate/PKI user information present */
			reqCertIDptr = NULL;
			reqCertIDlength = 0;
			status = CRYPT_OK;
			}
		}
	if( cryptStatusError( status ) )
		{
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't extract certificate request data to add to "
				  "certificate store" ) );
		}

	/* Check that the PKI user who authorised this certificate issue still 
	   exists.  If the CA has deleted them all further requests for 
	   certificates fail */
	if( reqCertIDptr != NULL )
		{
		CRYPT_CERTIFICATE iPkiUser;

		status = caGetIssuingUser( dbmsInfo, &iPkiUser, reqCertID, 
								   reqCertIDlength, errorInfo );
		if( cryptStatusOK( status ) )
			krnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );
		else
			{
			updateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,
								"Certificate request submitted for "
								"nonexistent PKI user", NULL, 0, 
								reqCertID, reqCertIDlength, NULL, 0, 
								NULL, 0 );
			retExt( CRYPT_ERROR_PERMISSION, 
					( CRYPT_ERROR_PERMISSION, errorInfo, 
					  "Certificate request submitted for nonexistent PKI "
					  "user" ) );
			}
		}

	/* If there's an authorising PKI user present make sure that it hasn't
	   already been used to authorise the issuance of a certificate.  This 
	   is potentially vulnerable to the following race condition:

		1: check authCertID -> OK
		2: check authCertID -> OK
		1: add
		2: add

	   In theory we could detect this by requiring the reqCertID to be 
	   unique, however a PKI user can be used to request both a certificate 
	   and a revocation for the certificate and a signing certificate can 
	   be used to request an update or revocation of both itself and one or 
	   more associated encryption certificates.  We could probably handle 
	   this via the ID-mangling used for certIDs but this makes tracing 
	   events through the audit log complex since there'll now be different 
	   effective IDs for the authorising certificate depending on what it 
	   was authorising.  
	   
	   In addition it's not certain how many further operations a 
	   certificate (rather than a PKI user) can authorise, in theory a 
	   single signing certificate can authorise at least four further 
	   operations, these being the update of itself, the update of an 
	   associated encryption certificate, and the revocation of itself and 
	   the encryption certificate.  In addition its possible that a signing 
	   certificate could be used to authorise a series of short-duration 
	   encryption certificates or a variety of other combinations of 
	   operations.

	   Because of these issues we can't use a uniqueness constraint on the
	   reqCertID to enforce a single use of issuing authorisation by the
	   database ifself but have to do a manual check here, checking 
	   specifically for the case where a PKI user authorises a certificate 
	   issue */
#if 0	/* This check is too restrictive because it blocks any further 
		   certificate issues after the first one.  This is because as soon 
		   as a single issue has been authorised for a user there'll be a 
		   request for that user logged so all further attempts to submit a 
		   request (for example for a renewal, or an encryption certificate 
		   to go with a signing one) will fail */
	if( reqCertIDptr != NULL )
		{
		initBoundData( boundDataPtr );
		setBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );
		status = dbmsQuery(
			"SELECT certID FROM certLog WHERE reqCertID = ? "
			"AND action = " TEXT_CERTACTION_REQUEST_CERT,
							NULL, 0, NULL, boundDataPtr, 
							DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );
		if( cryptStatusOK( status ) )
			{
			/* This user has already authorised the issue of a certificate, 
			   it can't be used to issue a second certificate */
			updateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,
								"Attempt to authorise additional certificate "
								"issue when a certificate for this user has "
								"already been issued", NULL, 0, 
								reqCertID, reqCertIDlength, NULL, 0, NULL, 0 );
			retExt( CRYPT_ERROR_DUPLICATE, 
					( CRYPT_ERROR_DUPLICATE, errorInfo, 
					  "Attempt to authorise additional certificate issue "
					  "when a certificate for this user has already been "
					  "issued" ) );
			}
		}
#endif /* 0 */

	/* Update the certificate store.  Since a revocation request generally 
	   won't have any fields of any significance set we have to use a 
	   special cut-down insert statement that doesn't expect to find any 
	   fields except the certificate ID */
	if( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
		{
		BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
		char encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];

		initBoundData( boundDataPtr );
		setBoundData( boundDataPtr, 0, certID, certIDlength );
		if( hasBinaryBlobs( dbmsInfo ) )
			{
			setBoundDataBlob( boundDataPtr, 1, certData, certDataLength );
			}
		else
			{
			int encodedCertDataLength;
			
			status = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE, 
								   &encodedCertDataLength, certData, 
								   certDataLength, CRYPT_CERTTYPE_NONE );
			if( cryptStatusError( status ) )
				{
				assert( DEBUG_WARN );
				return( status );
				}
			setBoundData( boundDataPtr, 1, encodedCertData, 
						  encodedCertDataLength );
			}
		status = dbmsUpdate( 
				"INSERT INTO certRequests VALUES ("
				TEXT_CERTTYPE_REQUEST_REVOCATION ", '', '', '', '', '', '', "
				"'', ?, ?)", boundDataPtr, DBMS_UPDATE_BEGIN );
		}
	else
		{
		status = addCert( dbmsInfo, iCertRequest, CRYPT_CERTTYPE_REQUEST_CERT,
						  CERTADD_NORMAL, DBMS_UPDATE_BEGIN, errorInfo );
		}
	if( cryptStatusOK( status ) )
		{
		status = updateCertLog( dbmsInfo,
						( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \
							CRYPT_CERTACTION_REQUEST_REVOCATION : \
						( isRenewal ) ? \
							CRYPT_CERTACTION_REQUEST_RENEWAL : \
							CRYPT_CERTACTION_REQUEST_CERT,
						certID, certIDlength, reqCertIDptr, reqCertIDlength, 
						NULL, 0, certData, certDataLength, 
						DBMS_UPDATE_COMMIT );
		}
	else
		{
		/* Something went wrong, abort the transaction */
		dbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );
		retExtErr( status, 
				   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
					 "Certificate request add operation failed: " ) );
		}

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

⌨️ 快捷键说明

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