📄 dbxdbx.c
字号:
/* Insert the cert object information */
return( dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
certData : NULL, certDataLength, boundDate,
updateType ) );
}
int addCRL( DBMS_INFO *dbmsInfo, const CRYPT_CERTIFICATE iCryptCRL,
const CRYPT_CERTIFICATE iCryptRevokeCert,
const DBMS_UPDATE_TYPE updateType )
{
BYTE certData[ MAX_CERT_SIZE ];
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char nameID[ DBXKEYID_BUFFER_SIZE ], issuerID[ DBXKEYID_BUFFER_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
time_t expiryDate = 0;
int certDataLength, status;
assert( ( isCertStore( dbmsInfo ) && \
checkHandleRange( iCryptRevokeCert ) ) || \
( !isCertStore( dbmsInfo ) && \
iCryptRevokeCert == CRYPT_UNUSED ) );
/* Get the ID information for the current CRL entry */
status = getKeyID( issuerID, iCryptCRL,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iCryptCRL, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_CRLENTRY );
certDataLength = msgData.length;
}
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
{
/* If it's a cert store we also need to obtain the cert ID, the name
ID of the issuer, and the cert expiry date from the cert being
revoked */
status = getKeyID( certID, iCryptRevokeCert,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
status = getKeyID( nameID, iCryptRevokeCert,
CRYPT_IATTRIBUTE_ISSUER );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, &expiryDate, sizeof( time_t ) );
status = krnlSendMessage( iCryptRevokeCert,
IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDTO );
}
}
if( cryptStatusError( status ) )
/* Convert any low-level cert-specific error into something generic
that makes a bit more sense to the caller */
return( CRYPT_ARGERROR_NUM1 );
/* Set up the cert object data to write. Cert stores contain extra info
which is needed to build a CRL so we have to vary the SQL string
depending on the keyset type */
if( !hasBinaryBlobs( dbmsInfo ) )
{
char encodedCertData[ MAX_ENCODED_CERT_SIZE ];
base64encode( encodedCertData, certData, certDataLength,
CRYPT_CERTTYPE_NONE );
if( isCertStore( dbmsInfo ) )
dbmsFormatSQL( sqlBuffer,
"INSERT INTO CRLs VALUES (?, '$', '$', '$', '$')",
nameID, issuerID, certID, encodedCertData );
else
dbmsFormatSQL( sqlBuffer,
"INSERT INTO CRLs VALUES ('$', '$')",
issuerID, encodedCertData );
}
else
{
if( isCertStore( dbmsInfo ) )
dbmsFormatSQL( sqlBuffer,
"INSERT INTO CRLs VALUES (?, '$', '$', '$', ?)",
nameID, issuerID, certID );
else
dbmsFormatSQL( sqlBuffer,
"INSERT INTO CRLs VALUES ('$', ?)",
issuerID );
}
/* Insert the entry */
return( dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
certData : NULL, certDataLength, expiryDate,
updateType ) );
}
static int setItemFunction( KEYSET_INFO *keysetInfo,
const CRYPT_HANDLE iCryptHandle,
const KEYMGMT_ITEM_TYPE itemType,
const char *password, const int passwordLength,
const int flags )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
BOOLEAN seenNonDuplicate = FALSE;
int type, status;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO || \
itemType == KEYMGMT_ITEM_REQUEST || \
itemType == KEYMGMT_ITEM_PKIUSER );
assert( password == NULL ); assert( passwordLength == 0 );
/* Make sure that we've been given a cert, cert chain, or CRL. We can't
do any more specific checking against the itemType because if it's
coming from outside cryptlib it'll just be passed in as a generic cert
object with no distinction between object subtypes */
status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
&type, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
if( isCertStore( dbmsInfo ) )
{
/* The only item that can be inserted directly into a CA cert
store is a CA request or PKI user info */
if( type != CRYPT_CERTTYPE_CERTREQUEST && \
type != CRYPT_CERTTYPE_REQUEST_CERT && \
type != CRYPT_CERTTYPE_REQUEST_REVOCATION && \
type != CRYPT_CERTTYPE_PKIUSER )
return( CRYPT_ARGERROR_NUM1 );
if( itemType == KEYMGMT_ITEM_PKIUSER )
return( caAddPKIUser( dbmsInfo, iCryptHandle ) );
/* It's a cert request being added to a CA certificate store */
assert( itemType == KEYMGMT_ITEM_REQUEST );
return( caAddCertRequest( dbmsInfo, iCryptHandle, type,
( flags & KEYMGMT_FLAG_UPDATE ) ? \
TRUE : FALSE ) );
}
if( type != CRYPT_CERTTYPE_CERTIFICATE && \
type != CRYPT_CERTTYPE_CERTCHAIN && \
type != CRYPT_CERTTYPE_CRL )
return( CRYPT_ARGERROR_NUM1 );
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO );
/* Lock the cert or CRL for our exclusive use and select the first
sub-item (cert in a cert chain, entry in a CRL), update the keyset
with the cert(s)/CRL entries, and unlock it to allow others access */
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
do
{
/* Add the certificate or CRL */
if( type == CRYPT_CERTTYPE_CRL )
status = addCRL( dbmsInfo, iCryptHandle, CRYPT_UNUSED,
DBMS_UPDATE_NORMAL );
else
status = addCert( dbmsInfo, iCryptHandle,
CRYPT_CERTTYPE_CERTIFICATE, CERTADD_NORMAL,
DBMS_UPDATE_NORMAL );
/* An item being added may already be present, however we can't fail
immediately because what's being added may be a chain containing
further certs or a CRL containing further entries, so we keep
track of whether we've successfully added at least one item and
clear data duplicate errors */
if( status == CRYPT_OK )
seenNonDuplicate = TRUE;
else
if( status == CRYPT_ERROR_DUPLICATE )
status = CRYPT_OK;
}
while( cryptStatusOK( status ) && \
krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORNEXT,
CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusOK( status ) && !seenNonDuplicate )
/* We reached the end of the chain/CRL without finding anything we
could add, return a data duplicate error */
status = CRYPT_ERROR_DUPLICATE;
return( status );
}
/* Delete a record from the database */
static int deleteItemFunction( KEYSET_INFO *keysetInfo,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
char keyIDbuffer[ CRYPT_MAX_TEXTSIZE * 2 ];
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
assert( !isCertStore( dbmsInfo ) );
/* Delete the key from the database */
makeKeyID( keyIDbuffer, keyIDtype, keyID, keyIDlength );
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE $ = '$'",
getKeyName( keyIDtype ), keyIDbuffer );
return( dbmsStaticUpdate( sqlBuffer ) );
}
/* Return status info for the keyset */
static BOOLEAN isBusyFunction( KEYSET_INFO *keysetInfo )
{
return( ( keysetInfo->keysetDBMS->flags & \
( DBMS_FLAG_UPDATEACTIVE | DBMS_FLAG_QUERYACTIVE ) ) ? \
TRUE : FALSE );
}
/* Open a connection to a database */
static int initFunction( KEYSET_INFO *keysetInfo, const char *name,
const CRYPT_KEYOPT_TYPE options )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
int status;
/* Perform a database back-end specific open */
status = dbmsOpen( name, ( options == CRYPT_KEYOPT_READONLY ) ? \
options : CRYPT_KEYOPT_NONE );
if( cryptStatusError( status ) )
{
endDbxSession( keysetInfo );
return( status );
}
/* If we're being asked to create a new database, create it and exit */
if( options == CRYPT_KEYOPT_CREATE )
{
status = createDatabase( dbmsInfo );
if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
NULL, NULL, NULL, NULL, 0,
DBMS_UPDATE_NORMAL );
if( cryptStatusError( status ) )
{
dbmsClose();
endDbxSession( keysetInfo );
}
return( status );
}
/* Check to see whether it's a cert store. We do this by checking for
the presence of the cert store creation entry in the log, this is
always present with an action value of CRYPT_CERTACTION_CREATE */
status = dbmsStaticQuery(
"SELECT certData FROM certLog WHERE action = "
TEXT_CERTACTION_CREATE,
DBMS_QUERY_CHECK );
if( cryptStatusOK( status ) )
{
/* It's a cert store, if we're opening it as a non-cert-store it has
to be in read-only mode. We return an error rather than quietly
changing the access mode to read-only both to make it explicit to
the user at open time that they can't make changes and because we
need to have the read-only flag set when we open the database to
optimise the buffering and locking strategy, setting it at this
point is too late */
if( !isCertStore( dbmsInfo ) )
{
if( options != CRYPT_KEYOPT_READONLY )
{
dbmsClose();
endDbxSession( keysetInfo );
status = CRYPT_ERROR_PERMISSION;
}
/* Remember that even though it's not functioning as a cert
store, we can still perform some extended queries on it based
on fields that are only present in cert stores */
dbmsInfo->flags |= DBMS_FLAG_CERTSTORE_FIELDS;
return( status );
}
/* If this isn't a read-only open then record a connection to the
store */
if( options != CRYPT_KEYOPT_READONLY )
{
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,
NULL, NULL, NULL, NULL, 0,
DBMS_UPDATE_NORMAL );
if( cryptStatusError( status ) )
{
dbmsClose();
endDbxSession( keysetInfo );
}
}
return( status );
}
/* It's not a cert store, if we're expecting to open it as one tell the
caller */
if( isCertStore( dbmsInfo ) )
{
dbmsClose();
endDbxSession( keysetInfo );
return( CRYPT_ARGERROR_NUM1 );
}
/* Since the failure of the query above will set the extended error
information, we have to explicitly clear it here to avoid making the
(invisible) query side-effects visible to the user */
dbmsInfo->errorCode = 0;
memset( dbmsInfo->errorMessage, 0, MAX_ERRMSG_SIZE );
return( CRYPT_OK );
}
/* Close the connection to a database */
static void shutdownFunction( KEYSET_INFO *keysetInfo )
{
DBMS_INFO *dbmsInfo = keysetInfo->keysetDBMS;
/* If it's a cert store opened in read/write mode, record a closed
connection to the store */
if( isCertStore( dbmsInfo ) && \
keysetInfo->options != CRYPT_KEYOPT_READONLY )
updateCertLog( dbmsInfo, CRYPT_CERTACTION_DISCONNECT, NULL, NULL,
NULL, NULL, 0, DBMS_UPDATE_NORMAL );
/* If we're in the middle of a query, cancel it */
if( dbmsInfo->flags & DBMS_FLAG_QUERYACTIVE )
dbmsStaticQuery( NULL, DBMS_QUERY_CANCEL );
dbmsClose();
endDbxSession( keysetInfo );
}
/* Set up the function pointers to the keyset methods */
int setAccessMethodDBMS( KEYSET_INFO *keysetInfo,
const CRYPT_KEYSET_TYPE type )
{
int status = CRYPT_ERROR;
/* Set up the lower-level interface functions */
status = initDbxSession( keysetInfo, type );
if( cryptStatusError( status ) )
return( status );
/* Set the access method pointers */
keysetInfo->initFunction = initFunction;
keysetInfo->shutdownFunction = shutdownFunction;
keysetInfo->getItemFunction = getItemFunction;
keysetInfo->setItemFunction = setItemFunction;
keysetInfo->deleteItemFunction = deleteItemFunction;
keysetInfo->getFirstItemFunction = getFirstItemFunction;
keysetInfo->getNextItemFunction = getNextItemFunction;
if( type == CRYPT_KEYSET_ODBC_STORE || \
type == CRYPT_KEYSET_DATABASE_STORE || \
type == CRYPT_KEYSET_PLUGIN_STORE )
initDBMSCA( keysetInfo );
keysetInfo->isBusyFunction = isBusyFunction;
return( CRYPT_OK );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -