📄 dbxdca.c
字号:
{
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 = '--$'",
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 */
static int caIssueCRL( DBMS_INFO *dbmsInfo, CRYPT_CERTIFICATE *iCryptCRL,
const CRYPT_CONTEXT caKey )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
BYTE crlEntry[ MAX_CERT_SIZE ];
BOOLEAN crlEntryAdded = FALSE;
char crlEntryBuffer[ MAX_QUERY_RESULT_SIZE ];
char *crlEntryPtr = crlEntryBuffer;
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char nameID[ DBXKEYID_BUFFER_SIZE ];
char *operationString;
int operationStatus = CRYPT_OK, status;
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( isWritePtr( iCryptCRL, CRYPT_CERTIFICATE * ) );
assert( checkHandleRange( caKey ) );
/* Extract the information we need to build the CRL from the CA cert */
status = 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 = ( char * ) 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 */
dbmsFormatSQL( sqlBuffer,
"SELECT certData FROM CRLs WHERE nameID = '$'",
nameID );
status = dbmsStaticQuery( sqlBuffer, 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, 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 */
while( status != CRYPT_ERROR_COMPLETE )
{
int crlEntryLength;
status = dbmsQuery( NULL, crlEntryPtr, &crlEntryLength, 0,
DBMS_QUERY_CONTINUE );
if( cryptStatusOK( status ) && !hasBinaryBlobs( dbmsInfo ) )
{
crlEntryLength = base64decode( crlEntry, crlEntryBuffer,
crlEntryLength, CRYPT_CERTFORMAT_NONE );
if( crlEntryLength <= 0 )
status = CRYPT_ERROR_BADDATA;
}
if( cryptStatusError( status ) && status != CRYPT_ERROR_COMPLETE && \
cryptStatusOK( operationStatus ) )
{
operationStatus = status;
operationString = "Some CRL entries couldn't be read from the "
"certificate store";
}
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
/* Add the entry to the CRL */
setMessageData( &msgData, crlEntry, crlEntryLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_CRLENTRY );
if( cryptStatusOK( status ) )
crlEntryAdded = TRUE;
else
if( cryptStatusOK( operationStatus ) )
{
operationStatus = status;
operationString = "Some CRL entries couldn't be added "
"to the CRL";
}
}
}
if( cryptStatusError( operationStatus ) )
{
/* If nothing could be added to the CRL, something is wrong, don't
try and continue */
if( !crlEntryAdded )
{
operationString = "No CRL entries could be added to the CRL";
updateCertErrorLogMsg( dbmsInfo, status, operationString );
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 ) )
{
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 );
}
/****************************************************************************
* *
* Cert Issue Functions *
* *
****************************************************************************/
/* Check that the request we've been passed is in order */
static BOOLEAN checkRequest( const CRYPT_CERTIFICATE iCertRequest,
const CRYPT_CERTACTION_TYPE action )
{
int certType, value, status;
/* Make sure that the request type is consistent with the operation
being performed */
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) )
return( FALSE );
switch( action )
{
case CRYPT_CERTACTION_CERT_CREATION:
case CRYPT_CERTACTION_ISSUE_CERT:
if( certType != CRYPT_CERTTYPE_CERTREQUEST && \
certType != CRYPT_CERTTYPE_REQUEST_CERT )
return( FALSE );
break;
case CRYPT_CERTACTION_REVOKE_CERT:
if( certType != CRYPT_CERTTYPE_REQUEST_REVOCATION )
return( FALSE );
break;
case CRYPT_CERTACTION_NONE:
/* We're performing a straight add of a request to the store,
any request type is permitted */
break;
default:
assert( NOTREACHED );
return( FALSE );
}
/* Make sure that the request is completed and valid. We don't check
the signature on revocation requests since they aren't signed, and
have to be careful with CRMF requests, which can be unsigned for
encryption-only keys */
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_IMMUTABLE );
if( cryptStatusError( status ) || !value )
return( FALSE );
if( certType == CRYPT_CERTTYPE_REQUEST_CERT && \
cryptStatusOK( \
krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_SELFSIGNED ) ) && \
!value )
{
/* It's an unsigned CRMF request, make sure that it really is an
encryption-only key */
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
&value, CRYPT_CERTINFO_KEYUSAGE );
if( cryptStatusOK( status ) && \
( value & ( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION ) ) )
return( FALSE );
}
else
if( certType != CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
status = krnlSendMessage( iCertRequest, IMESSAGE_CRT_SIGCHECK,
NULL, CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( FALSE );
}
/* Check that required parameters are present. This is necessary for
CRMF requests where every single parameter is optional, for our use
we require that a cert request contains at least a subject DN and
public key and a revocation request contains at least an issuer DN and
serial number */
if( certType == CRYPT_CERTTYPE_REQUEST_CERT )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( FALSE );
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SPKI );
if( cryptStatusError( status ) )
return( FALSE );
}
if( certType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
return( FALSE );
}
return( TRUE );
}
/* 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 requestTypeData[ MAX_CERT_SIZE ];
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
int requestTypeLength, status;
/* Get the certID of the request that resulted in the cert creation */
status = getKeyID( certID, iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( 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 */
dbmsFormatSQL( sqlBuffer,
"SELECT reqCertID FROM certLog WHERE certID = '$'",
certID );
status = dbmsQuery( sqlBuffer, requestTypeData, &requestTypeLength,
0, DBMS_QUERY_NORMAL );
if( cryptStatusOK( status ) )
memcpy( certID, requestTypeData,
min( requestTypeLength, MAX_ENCODED_DBXKEYID_SIZE ) );
}
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 backends will return the action as text and some as a binary
numeric value, rather than relying on the backend glue code to
perform the appropriate conversion we just check for either value
type */
dbmsFormatSQL( sqlBuffer,
"SELECT action FROM certLog WHERE certID = '$'",
certID );
status = dbmsQuery( sqlBuffer, requestTypeData, &requestTypeLength, 0,
DBMS_QUERY_NORMAL );
if( cryptStatusOK( status ) )
switch( requestTypeData[ 0 ] )
{
case CRYPT_CERTACTION_REQUEST_CERT:
case TEXTCH_CERTACTION_REQUEST_CERT:
status = CERTADD_PARTIAL;
break;
case CRYPT_CERTACTION_REQUEST_RENEWAL:
case TEXTCH_CERTACTION_REQUEST_RENEWAL:
status = CERTADD_PARTIAL_RENEWAL;
break;
default:
status = CRYPT_ERROR_NOTFOUND;
}
return( status );
}
/* 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:
-- -> std CERTADD_PARTIAL Completion of partial
-- -> ++ CERTADD_PARTIAL_RENEWAL First half of renewal
++ -> 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 status;
assert( addType == CERTADD_PARTIAL || \
addType == CERTADD_PARTIAL_RENEWAL || \
addType == CERTADD_RENEWAL_COMPLETE );
status = getKeyID( certID, iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -