📄 cryptkey.c
字号:
REQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \
keyIDinfo.keyID != NULL && \
keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \
keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES( ( getnextcertInfo->auxInfo == NULL && \
getnextcertInfo->auxInfoLength == 0 ) || \
( getnextcertInfo->auxInfo != NULL && \
getnextcertInfo->auxInfoLength == sizeof( int ) ) );
/* Fetch the first certificate in a sequence from the keyset */
resetErrorInfo( keysetInfoPtr );
status = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer,
KEYID_SIZE, TRUE );
if( cryptStatusError( status ) )
return( status );
return( keysetInfoPtr->getFirstItemFunction( keysetInfoPtr,
&getnextcertInfo->cryptHandle,
getnextcertInfo->auxInfo, messageValue,
keyIDinfo.keyIDtype, keyIDinfo.keyID,
keyIDinfo.keyIDlength,
getnextcertInfo->flags ) );
}
if( message == MESSAGE_KEY_GETNEXTCERT )
{
MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
REQUIRES( getnextcertInfo->keyIDtype == CRYPT_KEYID_NONE && \
getnextcertInfo->keyID == NULL && \
getnextcertInfo->keyIDlength == 0 );
REQUIRES( ( getnextcertInfo->auxInfo == NULL && \
getnextcertInfo->auxInfoLength == 0 ) || \
( getnextcertInfo->auxInfo != NULL && \
getnextcertInfo->auxInfoLength == sizeof( int ) ) );
REQUIRES( getnextcertInfo->flags >= KEYMGMT_FLAG_NONE && \
getnextcertInfo->flags < KEYMGMT_FLAG_MAX && \
( getnextcertInfo->flags & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );
/* Fetch the next certificate in a sequence from the keyset */
return( keysetInfoPtr->getNextItemFunction( keysetInfoPtr,
&getnextcertInfo->cryptHandle,
getnextcertInfo->auxInfo,
getnextcertInfo->flags ) );
}
#ifdef USE_DBMS
if( message == MESSAGE_KEY_CERTMGMT )
{
MESSAGE_CERTMGMT_INFO *certMgmtInfo = \
( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;
REQUIRES( messageValue >= CRYPT_CERTACTION_CERT_CREATION && \
messageValue <= CRYPT_CERTACTION_LAST_USER );
/* Perform the certificate management operation */
resetErrorInfo( keysetInfoPtr );
status = initKeysetUpdate( keysetInfoPtr, NULL, NULL, 0, TRUE );
if( cryptStatusError( status ) )
return( status );
status = keysetInfoPtr->keysetDBMS->certMgmtFunction( keysetInfoPtr,
( certMgmtInfo->cryptCert != CRYPT_UNUSED ) ? \
&certMgmtInfo->cryptCert : NULL,
certMgmtInfo->caKey, certMgmtInfo->request,
messageValue );
if( cryptStatusOK( status ) )
{
/* The update succeeded, remember that the data in the keyset has
changed */
keysetInfoPtr->flags |= KEYSET_DIRTY;
}
return( status );
}
#endif /* USE_DBMS */
retIntError();
}
/* Open a keyset. This is a low-level function encapsulated by createKeyset()
and used to manage error exits */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 7 ) ) \
static int openKeyset( OUT_HANDLE_OPT CRYPT_KEYSET *iCryptKeyset,
IN_HANDLE const CRYPT_USER iCryptOwner,
IN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE keysetType,
IN_BUFFER( nameLength ) const char *name,
IN_LENGTH_SHORT_MIN( MIN_NAME_LENGTH ) const int nameLength,
IN_ENUM_OPT( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options,
OUT_PTR KEYSET_INFO **keysetInfoPtrPtr )
{
KEYSET_INFO *keysetInfoPtr;
STREAM stream;
CRYPT_KEYOPT_TYPE localOptions = options;
KEYSET_SUBTYPE keysetSubType = DUMMY_INIT;
OBJECT_SUBTYPE subType;
int storageSize, status;
assert( isWritePtr( iCryptKeyset, sizeof( CRYPT_KEYSET ) ) );
assert( isReadPtr( name, nameLength ) );
assert( isWritePtr( keysetInfoPtrPtr, sizeof( KEYSET_INFO * ) ) );
REQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
isHandleRangeValid( iCryptOwner ) );
REQUIRES( keysetType > CRYPT_KEYSET_NONE && \
keysetType < CRYPT_KEYSET_LAST );
REQUIRES( nameLength >= MIN_NAME_LENGTH && \
nameLength < MAX_ATTRIBUTE_SIZE );
REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );
/* Clear the return values */
*iCryptKeyset = CRYPT_ERROR;
*keysetInfoPtrPtr = NULL;
/* Perform general checks that can be done before we create the object */
if( ( keysetType == CRYPT_KEYSET_HTTP && \
options != CRYPT_KEYOPT_READONLY ) || \
( keysetType == CRYPT_KEYSET_LDAP && \
options == CRYPT_KEYOPT_CREATE ) )
{
/* We can't open an HTTP keyset for anything other than read-only
access, and we can't create an LDAP directory */
return( CRYPT_ERROR_PERMISSION );
}
if( keysetType == CRYPT_KEYSET_FILE && nameLength > MAX_PATH_LENGTH - 1 )
return( CRYPT_ARGERROR_STR1 );
/* Set up subtype-specific information */
switch( keysetType )
{
case CRYPT_KEYSET_FILE:
subType = SUBTYPE_KEYSET_FILE_PARTIAL;
storageSize = sizeof( FILE_INFO );
break;
case CRYPT_KEYSET_HTTP:
subType = SUBTYPE_KEYSET_HTTP;
storageSize = sizeof( HTTP_INFO );
break;
case CRYPT_KEYSET_LDAP:
subType = SUBTYPE_KEYSET_LDAP;
storageSize = sizeof( LDAP_INFO );
break;
case CRYPT_KEYSET_ODBC:
case CRYPT_KEYSET_DATABASE:
case CRYPT_KEYSET_PLUGIN:
subType = SUBTYPE_KEYSET_DBMS;
storageSize = sizeof( DBMS_INFO );
break;
case CRYPT_KEYSET_ODBC_STORE:
case CRYPT_KEYSET_DATABASE_STORE:
case CRYPT_KEYSET_PLUGIN_STORE:
subType = SUBTYPE_KEYSET_DBMS_STORE;
storageSize = sizeof( DBMS_INFO );
break;
default:
retIntError();
}
/* Handle compiler warnings of uninitialised variables, unfortunately
since it's non-scalar data we can't do this with the usual
DUMMY_INIT */
memset( &stream, 0, sizeof( STREAM ) );
/* If it's a flat-file keyset which is implemented on top of an I/O
stream make sure that we can open the stream before we try and
create the keyset object */
if( keysetType == CRYPT_KEYSET_FILE )
{
BOOLEAN isReadOnly;
status = openKeysetStream( &stream, name, nameLength, options,
&isReadOnly, &keysetSubType );
if( cryptStatusError( status ) )
return( status );
/* If we tried to open the file in read/write mode and it's
read-only, change the access mode to read-only */
if( isReadOnly )
localOptions = CRYPT_KEYOPT_READONLY;
/* If the keyset contains the full set of search keys and index
information needed to handle all keyset operations (e.g.
certificate chain building, query by key usage types) we mark it
as a full-function keyset with the same functionality as a DBMS
keyset rather than just a generic flat-file store */
if( keysetSubType == KEYSET_SUBTYPE_PKCS15 )
subType = SUBTYPE_KEYSET_FILE;
}
/* Create the keyset object */
status = krnlCreateObject( iCryptKeyset, ( void ** ) &keysetInfoPtr,
sizeof( KEYSET_INFO ) + storageSize,
OBJECT_TYPE_KEYSET, subType,
CREATEOBJECT_FLAG_NONE, iCryptOwner,
ACTION_PERM_NONE_ALL, keysetMessageFunction );
if( cryptStatusError( status ) )
{
if( keysetType == CRYPT_KEYSET_FILE )
sFileClose( &stream );
return( status );
}
*keysetInfoPtrPtr = keysetInfoPtr;
keysetInfoPtr->objectHandle = *iCryptKeyset;
keysetInfoPtr->ownerHandle = iCryptOwner;
keysetInfoPtr->options = localOptions;
switch( keysetType )
{
case CRYPT_KEYSET_FILE:
keysetInfoPtr->type = KEYSET_FILE;
keysetInfoPtr->keysetFile = ( FILE_INFO * ) keysetInfoPtr->storage;
break;
#ifdef USE_HTTP
case CRYPT_KEYSET_HTTP:
keysetInfoPtr->type = KEYSET_HTTP;
keysetInfoPtr->keysetHTTP = ( HTTP_INFO * ) keysetInfoPtr->storage;
break;
#endif /* USE_HTTP */
#ifdef USE_LDAP
case CRYPT_KEYSET_LDAP:
keysetInfoPtr->type = KEYSET_LDAP;
keysetInfoPtr->keysetLDAP = ( LDAP_INFO * ) keysetInfoPtr->storage;
break;
#endif /* USE_LDAP */
#ifdef USE_DBMS
default:
keysetInfoPtr->type = KEYSET_DBMS;
keysetInfoPtr->keysetDBMS = ( DBMS_INFO * ) keysetInfoPtr->storage;
break;
#endif /* USE_DBMS */
}
keysetInfoPtr->storageSize = storageSize;
/* If it's a flat-file keyset which is implemented on top of an I/O
stream, handle it specially */
if( keysetType == CRYPT_KEYSET_FILE )
{
status = completeKeysetFileOpen( keysetInfoPtr, keysetSubType,
&stream, name, nameLength );
if( cryptStatusError( status ) )
{
sFileClose( &keysetInfoPtr->keysetFile->stream );
if( options == CRYPT_KEYOPT_CREATE )
{
/* It's a newly-created file, make sure that we don't leave
it lying around on disk */
fileErase( keysetInfoPtr->keysetFile->fileName );
}
return( status );
}
return( CRYPT_OK );
}
/* Wait for any async keyset driver binding to complete. We do this as
late as possible to prevent file keyset reads that occur on startup
(for example to get configuration options) from stalling the startup
process */
if( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )
{
/* The kernel is shutting down, bail out */
assert( DEBUG_WARN );
return( CRYPT_ERROR_PERMISSION );
}
/* It's a specific type of keyset, set up the access information for it
and connect to it */
switch( keysetType )
{
case CRYPT_KEYSET_ODBC:
case CRYPT_KEYSET_DATABASE:
case CRYPT_KEYSET_PLUGIN:
case CRYPT_KEYSET_ODBC_STORE:
case CRYPT_KEYSET_DATABASE_STORE:
case CRYPT_KEYSET_PLUGIN_STORE:
status = setAccessMethodDBMS( keysetInfoPtr, keysetType );
break;
case CRYPT_KEYSET_HTTP:
status = setAccessMethodHTTP( keysetInfoPtr );
break;
case CRYPT_KEYSET_LDAP:
status = setAccessMethodLDAP( keysetInfoPtr );
break;
default:
retIntError();
}
if( cryptStatusError( status ) )
return( status );
ENSURES( keysetInfoPtr->initFunction != NULL && \
keysetInfoPtr->shutdownFunction != NULL && \
keysetInfoPtr->getItemFunction != NULL );
ENSURES( keysetType == CRYPT_KEYSET_HTTP || \
( keysetInfoPtr->setItemFunction != NULL && \
keysetInfoPtr->deleteItemFunction != NULL && \
keysetInfoPtr->isBusyFunction != NULL ) );
ENSURES( keysetType == CRYPT_KEYSET_HTTP || \
keysetType == CRYPT_KEYSET_LDAP || \
( keysetInfoPtr->getFirstItemFunction != NULL && \
keysetInfoPtr->getNextItemFunction != NULL ) );
#ifdef USE_LDAP
ENSURES( keysetType != CRYPT_KEYSET_LDAP || \
( keysetInfoPtr->getAttributeFunction != NULL && \
keysetInfoPtr->setAttributeFunction != NULL ) );
#endif /* USE_LDAP */
/* Initialise keyset access */
status = keysetInfoPtr->initFunction( keysetInfoPtr, name, nameLength,
keysetInfoPtr->options );
if( cryptStatusOK( status ) )
{
keysetInfoPtr->flags |= KEYSET_OPEN;
if( keysetInfoPtr->options == CRYPT_KEYOPT_CREATE )
keysetInfoPtr->flags |= KEYSET_EMPTY;
}
return( status );
}
/* Create a keyset object */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createKeyset( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue )
{
CRYPT_KEYSET iCryptKeyset;
KEYSET_INFO *keysetInfoPtr = NULL;
int initStatus, status;
assert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
REQUIRES( auxDataPtr == NULL && auxValue == 0 );
REQUIRES( createInfo->arg1 > CRYPT_KEYSET_NONE && \
createInfo->arg1 < CRYPT_KEYSET_LAST );
REQUIRES( createInfo->arg2 >= CRYPT_KEYOPT_NONE && \
createInfo->arg2 < CRYPT_KEYOPT_LAST );
REQUIRES( createInfo->strArgLen1 >= MIN_NAME_LENGTH && \
createInfo->strArgLen1 < MAX_ATTRIBUTE_SIZE );
/* Pass the call on to the lower-level open function */
initStatus = openKeyset( &iCryptKeyset, createInfo->cryptOwner,
createInfo->arg1, createInfo->strArg1,
createInfo->strArgLen1, createInfo->arg2,
&keysetInfoPtr );
if( cryptStatusError( initStatus ) )
{
/* If the create object failed, return immediately */
if( keysetInfoPtr == NULL )
return( initStatus );
/* The init failed, make sure that the object gets destroyed when we
notify the kernel that the setup process is complete */
krnlSendNotifier( iCryptKeyset, IMESSAGE_DESTROY );
}
/* We've finished setting up the object-type-specific info, tell the
kernel that the object is ready for use */
status = krnlSendMessage( iCryptKeyset, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
return( cryptStatusError( initStatus ) ? initStatus : status );
createInfo->cryptHandle = iCryptKeyset;
return( CRYPT_OK );
}
/* Generic management function for this class of object */
CHECK_RETVAL \
int keysetManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
const MANAGEMENT_ACTION_TYPE action )
{
static int initLevel = 0;
int status;
REQUIRES( action == MANAGEMENT_ACTION_INIT || \
action == MANAGEMENT_ACTION_SHUTDOWN );
switch( action )
{
case MANAGEMENT_ACTION_INIT:
status = dbxInitODBC();
if( cryptStatusOK( status ) )
{
initLevel++;
if( krnlIsExiting() )
{
/* The kernel is shutting down, exit */
return( CRYPT_ERROR_PERMISSION );
}
status = dbxInitLDAP();
}
if( cryptStatusOK( status ) )
initLevel++;
return( status );
case MANAGEMENT_ACTION_SHUTDOWN:
if( initLevel > 1 )
dbxEndLDAP();
if( initLevel > 0 )
dbxEndODBC();
initLevel = 0;
return( CRYPT_OK );
}
retIntError();
}
#endif /* USE_KEYSETS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -