📄 dbxdca.c
字号:
if( cryptStatusError( status ) )
return( status );
}
/* Extract the information we need from the cert request */
status = getKeyID( certID, iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iCertRequest, IMESSAGE_CRT_EXPORT,
&msgData,
( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \
CRYPT_ICERTFORMAT_DATA : CRYPT_CERTFORMAT_CERTIFICATE );
certDataLength = msgData.length;
}
if( cryptStatusOK( status ) )
{
status = getKeyID( reqCertID, iCertRequest,
CRYPT_IATTRIBUTE_AUTHCERTID );
if( cryptStatusError( status ) )
{
/* If the request is being added directly by the user, there's no
authorising certificate/PKI user info present */
reqCertIDptr = NULL;
status = CRYPT_OK;
}
}
if( cryptStatusError( status ) )
return( status );
/* Update the cert 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 cert ID */
if( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
if( !hasBinaryBlobs( dbmsInfo ) )
{
char encodedCertData[ MAX_ENCODED_CERT_SIZE ];
base64encode( encodedCertData, certData, certDataLength,
CRYPT_CERTTYPE_NONE );
dbmsFormatSQL( sqlBuffer,
"INSERT INTO certRequests VALUES ("
TEXT_CERTTYPE_REQUEST_REVOCATION ", '', '', '', '', '', '', "
"'', '$', '$')",
certID, encodedCertData );
}
else
{
dbmsFormatSQL( sqlBuffer,
"INSERT INTO certRequests VALUES ("
TEXT_CERTTYPE_REQUEST_REVOCATION ", '', '', '', '', '', '', "
"'', '$', ?)",
certID );
}
status = dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
certData : NULL, certDataLength, 0,
DBMS_UPDATE_BEGIN );
}
else
status = addCert( dbmsInfo, iCertRequest, CRYPT_CERTTYPE_REQUEST_CERT,
CERTADD_NORMAL, DBMS_UPDATE_BEGIN );
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, reqCertIDptr, NULL, certData,
certDataLength, DBMS_UPDATE_COMMIT );
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
return( status );
}
/****************************************************************************
* *
* 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 )
{
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( isWritePtr( iPkiUser, sizeof( CRYPT_CERTIFICATE ) ) );
assert( isReadPtr( initialCertID, MAX_ENCODED_DBXKEYID_SIZE ) );
return( getIssuingUser( dbmsInfo, iPkiUser, initialCertID ) );
}
/* 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 status;
assert( isWritePtr( dbmsInfo, 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( 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 */
memset( prevCertData, 0, 8 );
do
{
char certID[ MAX_QUERY_RESULT_SIZE ];
int certIDsize;
/* 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 return a single result and then finish the query, for
some backends 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, &certIDsize, currentTime,
DBMS_QUERY_NORMAL );
else
status = dbmsQuery(
"SELECT certID FROM certRequests WHERE type = "
TEXT_CERTTYPE_REQUEST_CERT,
certID, &certIDsize, 0, DBMS_QUERY_NORMAL );
if( cryptStatusError( status ) || \
certIDsize > MAX_ENCODED_DBXKEYID_SIZE )
continue;
certID[ certIDsize ] = '\0';
if( !memcmp( prevCertData, certID, MAX_ENCODED_DBXKEYID_SIZE ) )
/* We're stuck in a loop fetching the same value over and over,
make an emergency exit */
break;
memcpy( prevCertData, certID, MAX_ENCODED_DBXKEYID_SIZE );
/* 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 */
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 );
}
while( status != CRYPT_ERROR_NOTFOUND );
/* 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 ) ? CRYPT_OK : 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 );
do
{
CRYPT_CERTIFICATE iCertificate;
/* Get the next partially-issued cert */
status = getNextPartialCert( dbmsInfo, &iCertificate, prevCertData,
FALSE );
if( status == CRYPT_ERROR_DUPLICATE )
/* We're stuck in a loop fetching the same cert over and over,
exit */
break;
if( cryptStatusOK( status ) )
{
/* We found a cert to revoke, complete the revocation */
status = revokeCertDirect( dbmsInfo, iCertificate,
CRYPT_CERTACTION_CERT_CREATION_REVERSE );
krnlSendNotifier( iCertificate, IMESSAGE_DECREFCOUNT );
}
}
while( status != CRYPT_ERROR_NOTFOUND );
/* If we ran into a problem, perform a fallback general delete of
entries that caused the problem */
if( status != CRYPT_ERROR_NOTFOUND )
{
updateCertErrorLogMsg( dbmsInfo, status, "Partially-issued "
"certificate cleanup operation failed, "
"performing fallback straight delete" );
status = dbmsStaticUpdate(
"DELETE FROM certificates WHERE keyID LIKE '--%'" );
if( cryptStatusError( status ) )
updateCertErrorLogMsg( dbmsInfo, status, "Fallback straight "
"delete failed" );
}
/* Now process any partially-completed renewals */
memset( prevCertData, 0, 8 );
do
{
CRYPT_CERTIFICATE iCertificate;
/* Get the next partially-completed cert */
status = getNextPartialCert( dbmsInfo, &iCertificate, prevCertData,
TRUE );
if( status == CRYPT_ERROR_DUPLICATE )
/* We're stuck in a loop fetching the same cert over and over,
exit */
break;
if( cryptStatusOK( status ) )
{
/* We found a partially-completed cert, complete the renewal */
status = completeCertRenewal( dbmsInfo, iCertificate );
krnlSendNotifier( iCertificate, IMESSAGE_DECREFCOUNT );
}
}
while( status != CRYPT_ERROR_NOTFOUND );
/* Finally, process any pending revocations */
memset( prevCertData, 0, 8 );
do
{
CRYPT_CERTIFICATE iCertRequest;
const char *keyName = getKeyName( CRYPT_IKEYID_CERTID );
char certID[ MAX_QUERY_RESULT_SIZE ]; /* Safety margin */
int dummy, certIDsize;
/* Find the next revocation request and import it. This is slightly
ugly since we could grab it directly by fetching the data based on
the request type field, but there's no way to easily get to the
low-level import functions from here so we have to first fetch the
cert ID and then pass that down to the lower-level functions to
fetch the actual request */
status = dbmsQuery(
"SELECT certID FROM certRequests WHERE type = "
TEXT_CERTTYPE_REQUEST_REVOCATION,
certID, &certIDsize, 0, DBMS_QUERY_NORMAL );
if( cryptStatusError( status ) || \
certIDsize > MAX_ENCODED_DBXKEYID_SIZE )
continue;
certID[ certIDsize ] = '\0';
if( !memcmp( prevCertData, certID, MAX_ENCODED_DBXKEYID_SIZE ) )
/* We're stuck in a loop fetching the same value over and over,
make an emergency exit */
break;
memcpy( prevCertData, certID, MAX_ENCODED_DBXKEYID_SIZE );
status = getItemData( dbmsInfo, &iCertRequest, &dummy, keyName, certID,
KEYMGMT_ITEM_REQUEST, KEYMGMT_FLAG_NONE );
if( cryptStatusError( status ) )
continue;
/* Complete the revocation */
status = caRevokeCert( dbmsInfo, iCertRequest, CRYPT_UNUSED,
CRYPT_CERTACTION_RESTART_REVOKE_CERT );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* This is an allowable error type, just delete the entry */
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certRequests WHERE certID = '$'",
certID );
status = dbmsStaticUpdate( sqlBuffer );
updateCertErrorLog( dbmsInfo, status, "Deleted revocation "
"request for non-present certificate",
NULL, NULL, certID, NULL, 0 );
}
krnlSendNotifier( iCertRequest, IMESSAGE_DECREFCOUNT );
}
while( status != CRYPT_ERROR_NOTFOUND );
/* If we ran into a problem, perform a fallback general delete of
entries that caused the problem */
if( status != CRYPT_ERROR_NOTFOUND )
{
updateCertErrorLogMsg( dbmsInfo, status, "Revocation request "
"cleanup operation failed, performing "
"fallback straight delete" );
status = dbmsStaticUpdate(
"DELETE FROM certRequests WHERE type = "
TEXT_CERTTYPE_REQUEST_REVOCATION );
if( cryptStatusError( status ) )
updateCertErrorLogMsg( dbmsInfo, status, "Fallback straight "
"delete failed" );
return( status );
}
return( CRYPT_OK );
}
/* Perform a cert management operation */
static int certMgmtFunction( KEYSET_INFO *keysetInfo,
CRYPT_CERTIFICATE *iCertificate,
const CRYPT_CERTIFICATE caKey,
const CRYPT_CERTIFICATE request,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -