📄 dbx_rd.c
字号:
itemType < KEYMGMT_ITEM_LAST && \
keyIDtype > CRYPT_KEYID_NONE && \
keyIDtype <= CRYPT_KEYID_LAST && \
keyValue != NULL && \
keyValueLength >= MIN_NAME_LENGTH &&
keyValueLength < MAX_ATTRIBUTE_SIZE && \
stateInfo != NULL ) );
/* As well as the standard values we can also have the
special-case value CRYPT_KEYID_LAST (see the comment in
getItemFunction() for details) which is mapped to the
database-use-only lookup value "nameID", the hashed DN */
REQUIRES( itemType == KEYMGMT_ITEM_NONE || \
itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REQUEST || \
itemType == KEYMGMT_ITEM_PKIUSER || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO );
REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX );
REQUIRES( errorInfo != NULL );
/* Clear return values */
*iCertificate = CRYPT_ERROR;
if( stateInfo != NULL )
*stateInfo = CRYPT_ERROR;
/* Make sure that we can never explicitly fetch anything with an ID that
indicates that it's physically but not logically present, for example
certificates that have been created but not fully issued yet,
certificate items that are on hold, and similar items */
if( keyValue != NULL && keyValueLength >= KEYID_ESC_SIZE && \
( !memcmp( keyValue, KEYID_ESC1, KEYID_ESC_SIZE ) || \
!memcmp( keyValue, KEYID_ESC2, KEYID_ESC_SIZE ) ) )
{
/* Eheu, litteras istas reperire non possum */
return( CRYPT_ERROR_NOTFOUND );
}
/* Perform a slight optimisation to eliminate unnecessary multi-
certificate queries: If we're querying by certID or issuerID only one
certificate can ever match so there's no need to perform a multi-
certificate query even if key usage options are specified */
if( keyIDtype == CRYPT_IKEYID_ISSUERID || \
keyIDtype == CRYPT_IKEYID_CERTID )
multiCertQuery = FALSE;
/* Set the query to begin the fetch */
if( stateInfo != NULL )
{
const char *keyName = getKeyName( keyIDtype );
const char *selectString = getSelectString( itemType );
ENSURES( keyName != NULL && selectString != NULL );
strlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );
strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, keyName );
strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, " = ?" );
queryString = sqlBuffer;
initBoundData( boundDataPtr );
setBoundData( boundDataPtr, 0, keyValue, keyValueLength );
queryType = multiCertQuery ? DBMS_QUERY_START : DBMS_QUERY_NORMAL;
}
else
{
/* It's an ongoing query, just fetch the next set of results */
queryString = NULL;
boundDataPtr = NULL;
queryType = DBMS_QUERY_CONTINUE;
}
/* Retrieve the results from the query */
for( iterationCount = 0; iterationCount < FAILSAFE_ITERATIONS_MED;
iterationCount++ )
{
/* Retrieve the certificate data and base64-decode it if necessary */
status = dbmsQuery( queryString, certDataPtr,
hasBinaryBlobs( dbmsInfo ) ? \
MAX_CERT_SIZE : MAX_SQL_QUERY_SIZE,
&certDataLength, boundDataPtr, cachedQueryType,
queryType );
if( cryptStatusError( status ) )
{
/* Convert the error code to a more appropriate value if
necessary */
return( ( multiCertQuery && ( status == CRYPT_ERROR_COMPLETE ) ) ? \
CRYPT_ERROR_NOTFOUND : status );
}
if( !hasBinaryBlobs( dbmsInfo ) )
{
status = base64decode( certificate, MAX_CERT_SIZE,
&certDataLength, certDataBuffer,
certDataLength, CRYPT_CERTFORMAT_NONE );
if( cryptStatusError( status ) )
{
retExt( status,
( status, errorInfo,
"Couldn't decode certificate from stored encoded "
"certificate data" ) );
}
}
/* We've started the fetch, from now on we're only fetching further
results */
queryString = NULL;
boundDataPtr = NULL;
if( queryType == DBMS_QUERY_START )
queryType = DBMS_QUERY_CONTINUE;
ENSURES( certDataLength >= 16 && certDataLength <= MAX_CERT_SIZE );
ENSURES( ( stateInfo != NULL && \
( queryType == DBMS_QUERY_NORMAL || \
queryType == DBMS_QUERY_CONTINUE ) ) || \
( stateInfo == NULL && queryType == DBMS_QUERY_CONTINUE ) );
/* If the first byte of the certificate data is 0xFF then this is an
item that's physically but not logically present (see the comment
above in the check for the keyValue), which means that we can't
explicitly fetch it (te audire non possum, musa sapientum fixa
est in aure) */
if( certificate[ 0 ] == 0xFF )
{
/* If it's a multi-certificate query try again with the next
result */
if( multiCertQuery )
continue;
/* It's a point query, we found something but it isn't there.
"Can't you understand English you arse, we're not at home"
-- Jeremy Black, "The Boys from Brazil" */
return( CRYPT_ERROR_NOTFOUND );
}
/* If more than one certificate is present and the requested key
usage doesn't match the one indicated in the certificate, try
again */
if( multiCertQuery && \
!checkCertUsage( certificate, certDataLength, options ) )
continue;
/* We got what we wanted, exit */
break;
}
if( iterationCount >= FAILSAFE_ITERATIONS_MED )
{
retExt_IntError( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, errorInfo,
"Couldn't find matching certificate after "
"processing %d items", FAILSAFE_ITERATIONS_MED ) );
}
/* If we've been looking through multiple certificates, cancel the
outstanding query, which will still be in progress */
if( multiCertQuery )
dbmsStaticQuery( NULL, cachedQueryType, DBMS_QUERY_CANCEL );
/* Create a certificate object from the encoded certificate data. If
we're reading revocation information the data is a single CRL entry
so we have to tell the certificate import code to treat it as a
special case of a CRL. If we're reading a request it could be one
of several types so we have to use auto-detection rather than
specifying an exact format */
setMessageCreateObjectIndirectInfo( &createInfo, certificate,
certDataLength,
( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_NONE ) ? CRYPT_CERTTYPE_CERTIFICATE : \
( itemType == KEYMGMT_ITEM_REQUEST ) ? CRYPT_CERTTYPE_NONE : \
( itemType == KEYMGMT_ITEM_PKIUSER ) ? CRYPT_CERTTYPE_PKIUSER : \
( itemType == KEYMGMT_ITEM_REVOCATIONINFO ) ? CRYPT_ICERTTYPE_REVINFO : \
CRYPT_CERTTYPE_NONE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
{
retExt( status,
( status, errorInfo,
"Couldn't recreate certificate from stored certificate "
"data" ) );
}
*iCertificate = createInfo.cryptHandle;
/* If this was a read with state held externally remember where we got
to so that we can fetch the next certificate in the sequence */
if( stateInfo != NULL )
*stateInfo = *iCertificate;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \
static int getFirstItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
OUT int *stateInfo,
IN_ENUM( KEYMGMT_ITEM ) \
const KEYMGMT_ITEM_TYPE itemType,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID const int keyIDlength,
IN_FLAGS_Z( KEYMGMT ) const int options )
{
DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
char encodedKeyID[ ( CRYPT_MAX_TEXTSIZE * 2 ) + 8 ];
int encodedKeyIDlength, status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( iCertificate == NULL || \
isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
assert( isWritePtr( stateInfo, sizeof( int ) ) );
assert( isReadPtr( keyID, keyIDlength ) );
REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
REQUIRES( itemType == KEYMGMT_ITEM_NONE || \
itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REQUEST || \
itemType == KEYMGMT_ITEM_PKIUSER || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO );
REQUIRES( keyIDtype > CRYPT_KEYID_NONE && \
keyIDtype < CRYPT_KEYID_LAST );
REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES( options >= KEYMGMT_FLAG_NONE && \
options < KEYMGMT_FLAG_MAX );
REQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* Fetch the first data item */
status = makeKeyID( encodedKeyID, CRYPT_MAX_TEXTSIZE * 2,
&encodedKeyIDlength, keyIDtype, keyID, keyIDlength );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_STR1 );
return( getItemData( dbmsInfo, iCertificate, stateInfo, itemType,
keyIDtype, encodedKeyID, encodedKeyIDlength,
options, KEYSET_ERRINFO ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int getNextItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
INOUT int *stateInfo,
IN_FLAGS_Z( KEYMGMT ) const int options )
{
DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
assert( ( stateInfo == NULL ) || \
isWritePtr( stateInfo, sizeof( int ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
REQUIRES( options >= KEYMGMT_FLAG_NONE && \
options < KEYMGMT_FLAG_MAX );
REQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* If we're fetching the next certificate in a sequence based on
externally-held state information, set the key ID to the nameID of
the previous certificate's issuer. This is a special-case ID that
isn't used outside the database keysets so we use the non-ID type
CRYPT_KEYID_LAST to signify its use */
if( stateInfo != NULL )
{
char encodedKeyID[ ENCODED_DBXKEYID_SIZE + 8 ];
int encodedKeyIDlength, status;
status = getKeyID( encodedKeyID, ENCODED_DBXKEYID_SIZE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -