📄 ca_rev.c
字号:
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iLocalCRL, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_CRLENTRY );
certDataLength = msgData.length;
}
if( cryptStatusError( status ) )
{
/* If we created the necessary objects locally rather than having
them passed in by the caller, we have to clean them up again
before we exit */
if( iCertificate == CRYPT_UNUSED )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
}
return( status );
}
/* Update the cert store. This is the ugliest CA operation since it
updates every table, luckily it's performed only rarely. If this is
a reversal operation or revocation of a cert to be replaced, which is
a direct follow-on to a certificate creation, there's no corresponding
request present so we don't have to update the requests table */
status = addCRL( dbmsInfo, iLocalCRL, iLocalCertificate,
DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, action, NULL, reqCertIDptr,
subjCertID, certData, certDataLength,
DBMS_UPDATE_CONTINUE );
if( cryptStatusOK( status ) && reqPresent )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certRequests WHERE certID = '$'",
reqCertID );
status = dbmsUpdate( sqlBuffer, NULL, 0, 0, DBMS_UPDATE_CONTINUE );
}
if( cryptStatusOK( status ) )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
if( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '" KEYID_ESC1 "$'",
subjCertID + 2 );
else
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '$'",
subjCertID );
status = dbmsUpdate( sqlBuffer, NULL, 0, 0, DBMS_UPDATE_COMMIT );
}
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
if( iCertificate == CRYPT_UNUSED )
{
/* If we created the necessary objects locally rather than having
them passed in by the caller, we have to clean them up again
before we exit */
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
}
/* If the operation failed, record the details and if it was a direct
revocation done invisibly as part of an internal cert management
operation, try again with a straight delete */
if( cryptStatusError( status ) )
{
updateCertErrorLog( dbmsInfo, status,
( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE ) ? \
"Certificate issue reversal operation failed, "
"performing straight delete" : \
( action == CRYPT_CERTACTION_REVOKE_CERT && \
iCertificate != CRYPT_UNUSED ) ? \
"Revocation of certificate to be replaced "
"failed, performing straight delete" :
"Certificate revocation operation failed",
NULL, reqCertIDptr, NULL, NULL, 0 );
if( !reqPresent )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
assert( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE || \
action == CRYPT_CERTACTION_REVOKE_CERT );
if( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '" KEYID_ESC1 "$'",
subjCertID + 2 );
else
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '$'",
subjCertID );
status = dbmsStaticUpdate( sqlBuffer );
if( cryptStatusError( status ) )
updateCertErrorLogMsg( dbmsInfo, status, "Fallback "
"straight delete failed" );
}
}
return( status );
}
/* Create a CRL from revocation entries in the certificate store */
int caIssueCRL( DBMS_INFO *dbmsInfo, CRYPT_CERTIFICATE *iCryptCRL,
const CRYPT_CONTEXT caKey )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
BYTE crlEntry[ MAX_QUERY_RESULT_SIZE ];
BOOLEAN crlEntryAdded = FALSE;
char crlEntryBuffer[ MAX_QUERY_RESULT_SIZE ];
void *crlEntryPtr = crlEntryBuffer;
char nameID[ DBXKEYID_BUFFER_SIZE ];
char *operationString;
int operationStatus = CRYPT_OK, errorCount = 0, length, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isWritePtr( iCryptCRL, sizeof( CRYPT_CERTIFICATE * ) ) );
assert( isHandleRangeValid( caKey ) );
/* Extract the information that we need to build the CRL from the CA
cert */
status = length = getKeyID( nameID, caKey, CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
/* Create the CRL object to hold the entries */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
/* If we have binary blob support, fetch the data directly into the
certificate buffer */
if( hasBinaryBlobs( dbmsInfo ) )
crlEntryPtr = crlEntry;
/* Submit a query to fetch every CRL entry for this CA. We don't have
to do a date check since the presence of revocation entries for
expired certs is controlled by whether the CA's policy involves
removing entries for expired certs or not */
status = dbmsQuery(
"SELECT certData FROM CRLs WHERE nameID = ?",
NULL, 0, nameID, length, 0, DBMS_CACHEDQUERY_NONE,
DBMS_QUERY_START );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Rumble through the cert store fetching every entry and adding it to
the CRL. We only stop once we've run out of entries or we hit too
many errors, which ensures that some minor error at some point won't
prevent the CRL from being issued, however if there was a problem
somewhere we create a log entry to record it */
do
{
RESOURCE_DATA msgData;
int crlEntryLength;
/* Read the CRL entry data */
status = dbmsQuery( NULL, crlEntryPtr, &crlEntryLength, NULL, 0, 0,
DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CONTINUE );
if( status == CRYPT_ERROR_COMPLETE )
{
/* We've got all the entries, complete the query and exit */
dbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE,
DBMS_QUERY_CANCEL );
break;
}
if( cryptStatusOK( status ) && !hasBinaryBlobs( dbmsInfo ) )
{
crlEntryLength = base64decode( crlEntry, MAX_CERT_SIZE,
crlEntryBuffer, crlEntryLength,
CRYPT_CERTFORMAT_NONE );
if( cryptStatusError( crlEntryLength ) )
{
assert( NOTREACHED );
status = crlEntryLength;
}
}
if( cryptStatusError( status ) )
{
/* Remember the error details for later if necessary */
if( cryptStatusOK( operationStatus ) )
{
operationStatus = status;
operationString = "Some CRL entries couldn't be read from "
"the certificate store";
}
errorCount++;
continue;
}
/* Add the entry to the CRL */
setMessageData( &msgData, crlEntry, crlEntryLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_CRLENTRY );
if( cryptStatusError( status ) )
{
/* Remember the error details for later if necessary */
if( cryptStatusOK( operationStatus ) )
{
operationStatus = status;
operationString = "Some CRL entries couldn't be added to "
"the CRL";
}
errorCount++;
continue;
}
crlEntryAdded = TRUE;
}
while( status != CRYPT_ERROR_COMPLETE && errorCount < 10 );
if( cryptStatusError( operationStatus ) )
{
/* If nothing could be added to the CRL, something is wrong, don't
try and continue */
if( !crlEntryAdded )
{
updateCertErrorLogMsg( dbmsInfo, status, "No CRL entries could "
"be added to the CRL" );
return( status );
}
/* At least some entries could be added to the CRL, record that there
was a problem but continue */
updateCertErrorLogMsg( dbmsInfo, operationStatus, operationString );
}
/* We've got all the CRL entries, sign the CRL and return it to the
caller */
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CRT_SIGN,
NULL, caKey );
if( cryptStatusError( status ) )
{
if( status == CRYPT_ARGERROR_VALUE )
status = CAMGMT_ARGERROR_CAKEY; /* Map to correct error code */
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
updateCertErrorLogMsg( dbmsInfo, operationStatus,
"CRL creation failed" );
}
else
{
*iCryptCRL = createInfo.cryptHandle;
updateCertLog( dbmsInfo, CRYPT_CERTACTION_ISSUE_CRL, NULL, NULL,
NULL, NULL, 0, DBMS_UPDATE_NORMAL );
}
return( status );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -