📄 dbx_rd.c
字号:
&encodedKeyIDlength, *stateInfo,
CRYPT_IATTRIBUTE_ISSUER );
if( cryptStatusError( status ) )
return( status );
return( getItemData( dbmsInfo, iCertificate, stateInfo,
KEYMGMT_ITEM_PUBLICKEY, CRYPT_KEYID_LAST,
encodedKeyID, encodedKeyIDlength, options,
KEYSET_ERRINFO ) );
}
/* Fetch the next data item in an ongoing query */
return( getItemData( dbmsInfo, iCertificate, NULL, KEYMGMT_ITEM_NONE,
CRYPT_KEYID_NONE, NULL, 0, options,
KEYSET_ERRINFO ) );
}
/* Retrieve a certificate object from the database */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
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,
STDC_UNUSED void *auxInfo,
STDC_UNUSED int *auxInfoLength,
IN_FLAGS_Z( KEYMGMT ) const int flags )
{
DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
int status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( isWritePtr( iCryptHandle, sizeof( CRYPT_CERTIFICATE ) ) );
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( auxInfo == NULL && *auxInfoLength == 0 );
REQUIRES( flags >= KEYMGMT_FLAG_NONE && \
flags < KEYMGMT_FLAG_MAX );
REQUIRES( ( flags & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* There are some query types that can only be satisfied by a
certificate store since a standard database doesn't contain the
necessary fields. Before we do anything else we make sure that we
can resolve the query using the current database type */
if( !( dbmsInfo->flags & DBMS_FLAG_CERTSTORE_FIELDS ) )
{
/* A standard database doesn't contain a certificate ID in the
revocation information since the CRL that it's populated from
only contains an issuerAndSerialNumber, so we can't resolve
queries for revocation information using a certificate ID */
if( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \
keyIDtype == CRYPT_IKEYID_CERTID )
{
retExt( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO,
"Operation is only valid for certificate stores" ) );
}
}
/* If this is a CA management item fetch, fetch the data from the CA
certificate store */
if( itemType == KEYMGMT_ITEM_REQUEST || \
itemType == KEYMGMT_ITEM_PKIUSER || \
( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \
!( flags & KEYMGMT_FLAG_CHECK_ONLY ) ) )
{
int dummy;
/* If we're getting the issuing PKI user (which means that the key ID
that's being queried on is that of an issued certificate that the
PKI user owns rather than that of the PKI user themselves) fetch
the user information via a special function */
if( itemType == KEYMGMT_ITEM_PKIUSER && \
( flags & KEYMGMT_FLAG_GETISSUER ) )
{
char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
int certIDlength;
REQUIRES( keyIDtype == CRYPT_IKEYID_CERTID );
/* The information required to locate the PKI user from one of
their certificates is only present in a certificate store */
if( !isCertStore( dbmsInfo ) )
{
retExt( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO,
"Operation is only valid for certificate stores" ) );
}
/* Get the PKI user based on the certificate */
status = makeKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength,
CRYPT_IKEYID_CERTID, keyID, keyIDlength );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_STR1 );
return( caGetIssuingUser( dbmsInfo, iCryptHandle,
certID, certIDlength,
KEYSET_ERRINFO ) );
}
/* This is just a standard read from a non-certificate table rather
than the certificate table so we call the get-first certificate
function directly rather than going via the indirect certificate-
import code. Since it's a direct call we need to provide a dummy
return variable for the state information that's normally handled
by the indirect-import code */
return( getFirstItemFunction( keysetInfoPtr, iCryptHandle, &dummy,
itemType, keyIDtype, keyID,
keyIDlength, KEYMGMT_FLAG_NONE ) );
}
/* If we're doing a check only, just check whether the item is present
without fetching any data */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
{
BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
char sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];
char encodedKeyID[ ENCODED_DBXKEYID_SIZE + 8 ];
const char *keyName = getKeyName( keyIDtype );
const char *selectString = getSelectString( itemType );
int encodedKeyIDlength;
REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REVOCATIONINFO );
REQUIRES( keyIDlength == KEYID_SIZE );
REQUIRES( keyIDtype == CRYPT_IKEYID_ISSUERID || \
keyIDtype == CRYPT_IKEYID_CERTID );
ENSURES( keyName != NULL && selectString != NULL );
/* Check whether this item is present. We don't care about the
result data, 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 */
status = makeKeyID( encodedKeyID, ENCODED_DBXKEYID_SIZE,
&encodedKeyIDlength, keyIDtype,
keyID, KEYID_SIZE );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_STR1 );
strlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );
strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, keyName );
strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, " = ?" );
initBoundData( boundDataPtr );
setBoundData( boundDataPtr, 0, encodedKeyID, encodedKeyIDlength );
return( dbmsQuery( sqlBuffer, NULL, 0, NULL, boundDataPtr,
getCachedQueryType( itemType, keyIDtype ),
DBMS_QUERY_CHECK ) );
}
/* Import the certificate by doing an indirect read, which fetches
either a single certificate or an entire chain if it's present */
return( iCryptImportCertIndirect( iCryptHandle, keysetInfoPtr->objectHandle,
keyIDtype, keyID, keyIDlength,
flags & KEYMGMT_MASK_CERTOPTIONS ) );
}
/* Add special data to the database. Technically this is a set-function but
because it initiates a query-fetch it's included with the get-functions */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int setSpecialItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
IN_ATTRIBUTE \
const CRYPT_ATTRIBUTE_TYPE dataType,
IN_BUFFER( dataLength ) const void *data,
IN_LENGTH_SHORT const int dataLength )
{
DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
char sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];
const KEYMGMT_ITEM_TYPE itemType = \
( dataType == CRYPT_KEYINFO_QUERY_REQUESTS ) ? \
KEYMGMT_ITEM_REQUEST : KEYMGMT_ITEM_PUBLICKEY;
const char *selectString = getSelectString( itemType );
int sqlLength, sqlQueryLength, status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( isReadPtr( data, dataLength ) );
ENSURES( dataType == CRYPT_KEYINFO_QUERY || \
dataType == CRYPT_KEYINFO_QUERY_REQUESTS );
ENSURES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_REQUEST );
ENSURES( selectString != NULL );
/* The kernel enforces a size range from 6...CRYPT_MAX_TEXTSIZE but we
perform an explicit check here against possible database-specific
values that may be more specific than the kernel's one-size-fits-all
values */
if( dataLength < 6 || dataLength > MAX_SQL_QUERY_SIZE - 64 )
{
retExtArg( CRYPT_ARGERROR_STR1,
( CRYPT_ARGERROR_STR1, KEYSET_ERRINFO,
"Invalid query length, should be from 6...%d "
"characters", MAX_SQL_QUERY_SIZE - 64 ) );
}
/* If we're cancelling an existing query, pass it on down */
if( dataLength == 6 && !strCompare( data, "cancel", dataLength ) )
{
return( dbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE,
DBMS_QUERY_CANCEL ) );
}
ENSURES( !keysetInfoPtr->isBusyFunction( keysetInfoPtr ) );
/* Rewrite the user-supplied portion of the query using the actual
column names and append it to the SELECT statement. This is a
special case free-format query where we can't use bound parameters
because the query data must be interpreted as SQL, unlike standard
queries where we definitely don't want it (mis-)interpreted as SQL.
dbmsFormatQuery() tries to sanitise the query as much as it can but
in general we rely on developers reading the warnings in the
documentation about the appropriate use of this capability */
strlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );
sqlLength = strlen( sqlBuffer );
status = dbmsFormatQuery( sqlBuffer + sqlLength,
( MAX_SQL_QUERY_SIZE - 1 ) - sqlLength,
&sqlQueryLength, data, dataLength );
if( cryptStatusError( status ) )
{
retExtArg( CRYPT_ARGERROR_STR1,
( CRYPT_ARGERROR_STR1, KEYSET_ERRINFO,
"Invalid query format" ) );
}
return( dbmsStaticQuery( sqlBuffer, DBMS_CACHEDQUERY_NONE,
DBMS_QUERY_START ) );
}
/****************************************************************************
* *
* Database Access Routines *
* *
****************************************************************************/
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initDBMSread( INOUT KEYSET_INFO *keysetInfoPtr )
{
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
keysetInfoPtr->getItemFunction = getItemFunction;
keysetInfoPtr->getFirstItemFunction = getFirstItemFunction;
keysetInfoPtr->getNextItemFunction = getNextItemFunction;
keysetInfoPtr->setSpecialItemFunction = setSpecialItemFunction;
return( CRYPT_OK );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -