📄 ca_misc.c
字号:
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 + -