📄 lib_dbms.c
字号:
if( stateInfo == NULL )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REQUEST );
assert( options == KEYMGMT_FLAG_NONE );
if( keyIDlength > MAX_SQL_QUERY_SIZE - 64 )
return( CRYPT_ARGERROR_STR1 );
/* If we're cancelling an existing query, pass it on down */
if( keyIDlength == 6 && !strnicmp( keyID, "cancel", keyIDlength ) )
{
status = performStaticQuery( &keysetInfo->keysetDBMS, NULL,
DBMS_QUERY_CANCEL );
keysetInfo->queryInProgress = FALSE;
return( status );
}
assert( keysetInfo->queryInProgress == FALSE );
/* Rewrite the user-supplied portion of the query using the actual
column names and append it to the SELECT statement */
strcpy( sqlBuffer, ( itemType == KEYMGMT_ITEM_REQUEST ) ? \
"SELECT certData FROM certRequests WHERE " : \
( itemType == KEYMGMT_ITEM_PKIUSER ) ? \
"SELECT certData FROM pkiUsers WHERE " : \
"SELECT certData FROM certificates WHERE " );
formatQuery( sqlBuffer + 40, keyID, keyIDlength,
MAX_SQL_QUERY_SIZE - 41 );
status = performStaticQuery( &keysetInfo->keysetDBMS, sqlBuffer,
DBMS_QUERY_START );
if( cryptStatusOK( status ) )
keysetInfo->queryInProgress = TRUE;
return( status );
}
else
{
/* Set up the fields for a query to access the record */
makeKeyID( keyIDbuffer, keyIDtype, keyID, keyIDlength );
keyName = getKeyName( keyIDtype );
}
/* Fetch the first data item */
return( getItemData( keysetInfo, iCertificate, stateInfo, keyName,
( stateInfo == NULL ) ? NULL : keyIDbuffer,
itemType, options ) );
}
static int getNextItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_CERTIFICATE *iCertificate,
int *stateInfo, const int options )
{
/* If we're fetching the next cert in a sequence based on externally-held
state information, set the key ID to the nameID of the previous cert's
issuer */
if( stateInfo != NULL )
{
char keyIDbuffer[ CRYPT_MAX_TEXTSIZE * 2 ];
const int status = getKeyID( keyIDbuffer, *stateInfo,
CRYPT_IATTRIBUTE_ISSUER );
if( cryptStatusError( status ) )
return( status );
return( getItemData( keysetInfo, iCertificate, stateInfo, "nameID",
keyIDbuffer, KEYMGMT_ITEM_PUBLICKEY, options ) );
}
/* Fetch the next data item in an ongoing query */
return( getItemData( keysetInfo, iCertificate, NULL, NULL,
NULL, KEYMGMT_ITEM_NONE, options ) );
}
/* Retrieve a key record from the database */
static int getItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_HANDLE *iCryptHandle,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
void *auxInfo, int *auxInfoLength,
const int flags )
{
int status;
assert( auxInfo == NULL ); assert( *auxInfoLength == 0 );
/* If this is a CA management item fetch, fetch the data from the CA cert
store */
if( itemType == KEYMGMT_ITEM_REQUEST || \
itemType == KEYMGMT_ITEM_PKIUSER )
{
int dummy;
/* This is just a standard single-cert read from a non-certificate
table rather than the standard cert table so we call the get
first cert function directly (rather than going via the indirect-
cert-import code). Since it's a direct call, we need to provide
a dummy return variable for the state information which is
normally handled by the indirect-cert-import code */
return( getFirstItemFunction( keysetInfo, iCryptHandle, &dummy,
keyIDtype, keyID, keyIDlength,
itemType, 0 ) );
}
/* If we're doing a check only, just check whether the item is present
without fetching any data */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
{
char keyIDbuffer[ CRYPT_MAX_TEXTSIZE ];
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
const char *keyName;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO );
assert( keyIDlength == KEYID_SIZE );
assert( keyIDtype == CRYPT_IKEYID_ISSUERID || \
keyIDtype == CRYPT_IKEYID_CERTID );
/* Check whether this item is present. We don't care about the
result, all we want to know is whether it's there or not, so we
just do a check rather than a fetch of any data */
makeKeyID( keyIDbuffer, keyIDtype, keyID, KEYID_SIZE );
keyName = getKeyName( keyIDtype );
formatSQL( sqlBuffer, ( itemType == KEYMGMT_ITEM_REVOCATIONINFO ) ? \
"SELECT certData FROM CRLs WHERE $ = '$'" : \
"SELECT certData FROM certificates WHERE $ = '$'",
keyName, keyIDbuffer );
return( performStaticQuery( &keysetInfo->keysetDBMS, sqlBuffer,
DBMS_QUERY_CHECK ) );
}
/* Import the cert by doing an indirect read, which fetches either a
single cert or an entire chain if it's present */
status = iCryptImportCertIndirect( iCryptHandle, keysetInfo->objectHandle,
keyIDtype, keyID, keyIDlength,
flags & KEYMGMT_MASK_CERTOPTIONS );
return( status );
}
/* Add a certificate object to a database. Normally RDBMS' would allow
existing rows to be overwritten, but the UNIQUE constraint on the index
will catch this */
static int addCert( KEYSET_INFO *keysetInfo, const CRYPT_HANDLE iCryptHandle,
const CRYPT_CERTTYPE_TYPE certType,
const CERTADD_TYPE addType,
const DBMS_UPDATE_TYPE updateType )
{
RESOURCE_DATA msgData;
BYTE certData[ MAX_CERT_SIZE ];
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char nameID[ MAX_ENCODED_DBXKEYID_SIZE ];
char issuerID[ MAX_ENCODED_DBXKEYID_SIZE ];
char keyID[ MAX_ENCODED_DBXKEYID_SIZE ];
char certID[ MAX_ENCODED_DBXKEYID_SIZE ];
char C[ CRYPT_MAX_TEXTSIZE + 1 ], SP[ CRYPT_MAX_TEXTSIZE + 1 ],
L[ CRYPT_MAX_TEXTSIZE + 1 ], O[ CRYPT_MAX_TEXTSIZE + 1 ],
OU[ CRYPT_MAX_TEXTSIZE + 1 ], CN[ CRYPT_MAX_TEXTSIZE + 1 ],
email[ CRYPT_MAX_TEXTSIZE + 1 ];
time_t boundDate = 0;
int certDataLength, status;
assert( certType == CRYPT_CERTTYPE_CERTIFICATE || \
certType == CRYPT_CERTTYPE_REQUEST_CERT || \
certType == CRYPT_CERTTYPE_PKIUSER );
*C = *SP = *L = *O = *OU = *CN = *email = '\0';
/* Extract the DN and altName components. This changes the currently
selected DN components, but this is OK since we've got the cert
locked and the prior state will be restored when we unlock it */
krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_SUBJECTNAME );
setResourceData( &msgData, C, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_COUNTRYNAME );
if( cryptStatusOK( status ) )
C[ msgData.length ] = '\0';
if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, SP, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_STATEORPROVINCENAME );
if( cryptStatusOK( status ) )
SP[ msgData.length ] = '\0';
}
if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, L, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_LOCALITYNAME );
if( cryptStatusOK( status ) )
L[ msgData.length ] = '\0';
}
if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, O, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_ORGANIZATIONNAME );
if( cryptStatusOK( status ) )
O[ msgData.length ] = '\0';
}
if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, OU, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
if( cryptStatusOK( status ) )
OU[ msgData.length ] = '\0';
}
if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
{
setResourceData( &msgData, CN, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_COMMONNAME );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* Some certs don't have CN components, so we use the OU instead.
If that also fails, we use the O. This gets a bit messy, but
duplicating the OU/O into the CN seems to be the best way to
handle this */
strcpy( CN, *OU ? OU : O );
msgData.length = strlen( CN );
status = CRYPT_OK;
}
if( cryptStatusOK( status ) )
CN[ msgData.length ] = '\0';
}
if( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \
( certType != CRYPT_CERTTYPE_PKIUSER ) )
{
setResourceData( &msgData, email, CRYPT_MAX_TEXTSIZE );
krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_SUBJECTALTNAME );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_RFC822NAME );
if( cryptStatusOK( status ) )
email[ msgData.length ] = '\0';
}
if( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \
( certType == CRYPT_CERTTYPE_CERTIFICATE ) )
{
setResourceData( &msgData, &boundDate, sizeof( time_t ) );
status = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDTO );
}
else
if( status == CRYPT_ERROR_NOTFOUND )
status = CRYPT_OK;
if( cryptStatusError( status ) )
/* Convert any low-level cert-specific error into something generic
which makes a bit more sense to the caller */
return( CRYPT_ARGERROR_NUM1 );
/* Get the ID information and cert data for the cert */
if( certType == CRYPT_CERTTYPE_CERTIFICATE )
{
status = getKeyID( nameID, iCryptHandle, CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusOK( status ) )
status = getKeyID( issuerID, iCryptHandle,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) )
status = getCertKeyID( keyID, iCryptHandle );
}
if( certType == CRYPT_CERTTYPE_PKIUSER )
{
char encKeyID[ 64 ];
/* Get the PKI user ID. We can't read this directly since it's
returned in text form for use by end users so we have to read the
encoded form, decode it, and then turn the decoded binary value
into a key ID. The value isn't strictly speaking a certID but it
isn't a keyID (== subjectKeyIdentifier, which is hashed) either */
setResourceData( &msgData, encKeyID, 1024 );
status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_PKIUSER_ID );
if( cryptStatusOK( status ) )
{
BYTE binaryKeyID[ 64 ];
int length;
length = decodeUserValue( binaryKeyID, encKeyID, msgData.length );
makeKeyID( keyID, CRYPT_IKEYID_CERTID, binaryKeyID, length );
}
}
if( cryptStatusOK( status ) )
status = getKeyID( certID, iCryptHandle, CRYPT_IATTRIBUTE_CERTID );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \
CRYPT_IATTRIBUTE_ENC_OBJDATA : CRYPT_IATTRIBUTE_ENC_CERT );
certDataLength = msgData.length;
}
if( cryptStatusError( status ) )
/* Convert any low-level cert-specific error into something generic
which makes a bit more sense to the caller */
return( CRYPT_ARGERROR_NUM1 );
/* If this is a partial add (in which we add a cert item which is in the
initial stages of the creation process where, although the item may
be physically present in the store it can't be accessed directly), we
set the first byte to 0xFF to indicate this. In addition we set the
first two bytes of the IDs which have uniqueness constraints to an
out-of-band value to prevent a clash with the finished entry when we
complete the issue process and replace the partial version with the
full version */
if( addType == CERTADD_PARTIAL || addType == CERTADD_PARTIAL_RENEWAL )
{
const char ch = ( addType == CERTADD_PARTIAL ) ? '-' : '+';
certData[ 0 ] = 0xFF;
issuerID[ 0 ] = issuerID[ 1 ] = ch;
keyID[ 0 ] = keyID[ 1 ] = ch;
certID[ 0 ] = certID[ 1 ] = ch;
}
/* Set up the cert object data to write */
if( !keysetInfo->keysetDBMS.hasBinaryBlobs )
{
char encodedCertData[ MAX_ENCODED_CERT_SIZE ];
base64encode( encodedCertData, certData, certDataLength,
CRYPT_CERTTYPE_NONE );
if( certType == CRYPT_CERTTYPE_CERTIFICATE )
formatSQL( sqlBuffer,
"INSERT INTO certificates VALUES ("
"'$', '$', '$', '$', '$', '$', '$', ?, '$', '$', '$', '$', '$')",
C, SP, L, O, OU, CN, email, nameID, issuerID, keyID,
certID, encodedCertData );
else
if( certType == CRYPT_CERTTYPE_REQUEST_CERT )
formatSQL( sqlBuffer,
"INSERT INTO certRequests VALUES ("
"'" TEXT_CERTTYPE_REQUEST_CERT "', "
"'$', '$', '$', '$', '$', '$', '$', '$', '$')",
C, SP, L, O, OU, CN, email, certID, encodedCertData );
else
formatSQL( sqlBuffer,
"INSERT INTO pkiUsers VALUES ("
"'$', '$', '$', '$', '$', '$', '$', '$', '$')",
C, SP, L, O, OU, CN, keyID, certID, encodedCertData );
}
else
{
memcpy( keysetInfo->keysetDBMS.boundCertData, certData, certDataLeng
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -