📄 cryptcfg.c
字号:
void endOptions( OPTION_INFO *optionList )
{
int i;
/* Walk through the config table clearing and freeing each option */
for( i = 1; fixedOptionInfo[ i ].option != CRYPT_ATTRIBUTE_NONE; i++ )
{
const FIXED_OPTION_INFO *fixedOptionInfoPtr = &fixedOptionInfo[ i ];
OPTION_INFO *optionInfoPtr = &optionList[ i ];
if( fixedOptionInfoPtr->type == OPTION_STRING )
{
/* If the string value that's currently set isn't the default
setting, clear and free it */
if( optionInfoPtr->strValue != fixedOptionInfoPtr->strDefault )
{
zeroise( optionInfoPtr->strValue,
strlen( optionInfoPtr->strValue ) );
clFree( "endOptions", optionInfoPtr->strValue );
}
}
}
/* Clear and free the config table */
memset( optionList, 0, OPTION_INFO_SIZE );
clFree( "endOptions", optionList );
}
/****************************************************************************
* *
* Read and Write the Config Options *
* *
****************************************************************************/
/* Read any user-defined configuration options. Since the config file is an
untrusted source, we set the values in it via external messages rather than
manipulating the config info directly, which means that everything read is
subject to the usual ACL checks */
static int readTrustedCerts( const CRYPT_KEYSET iCryptKeyset,
void *trustInfoPtr )
{
RESOURCE_DATA msgData;
BYTE buffer[ CRYPT_MAX_PKCSIZE + 1536 ];
int status;
/* Read each trusted cert from the keyset */
setMessageData( &msgData, buffer, CRYPT_MAX_PKCSIZE + 1536 );
status = krnlSendMessage( iCryptKeyset, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_TRUSTEDCERT );
while( cryptStatusOK( status ) )
{
/* Add the cert data as a trusted cert item and look for the next
one */
addTrustEntry( trustInfoPtr, CRYPT_UNUSED, msgData.data,
msgData.length );
setMessageData( &msgData, buffer, CRYPT_MAX_PKCSIZE + 1536 );
status = krnlSendMessage( iCryptKeyset, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );
}
return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );
}
int readConfig( const CRYPT_USER iCryptUser, const char *fileName,
void *trustInfoPtr )
{
CRYPT_KEYSET iCryptKeyset;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
STREAM stream;
DYNBUF configDB;
char configFilePath[ MAX_PATH_LENGTH + 128 ]; /* Protection for Windows */
int status;
/* Try and open the config file. If we can't open it, it means the that
file doesn't exist, which isn't an error */
fileBuildCryptlibPath( configFilePath, fileName, FALSE );
setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );
createInfo.arg2 = CRYPT_KEYOPT_READONLY;
createInfo.strArg1 = configFilePath;
createInfo.strArgLen1 = strlen( configFilePath );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_KEYSET );
if( cryptStatusError( status ) )
return( CRYPT_OK ); /* No config data present */
iCryptKeyset = createInfo.cryptHandle;
/* Get the config info from the keyset */
status = dynCreate( &configDB, iCryptKeyset,
CRYPT_IATTRIBUTE_CONFIGDATA );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* No config options present, there may still be trusted certs */
status = readTrustedCerts( iCryptKeyset, trustInfoPtr );
krnlSendNotifier( iCryptKeyset, IMESSAGE_DECREFCOUNT );
return( status );
}
if( cryptStatusOK( status ) )
status = readTrustedCerts( iCryptKeyset, trustInfoPtr );
krnlSendNotifier( iCryptKeyset, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
{
dynDestroy( &configDB );
return( status );
}
/* Read each config option */
sMemConnect( &stream, dynData( configDB ), dynLength( configDB ) );
while( cryptStatusOK( status ) && \
stell( &stream ) < dynLength( configDB ) )
{
CRYPT_ATTRIBUTE_TYPE attributeType;
long option;
int value, tag, i;
/* Read the wrapper and option index and map it to the actual option.
If we find an unknown index or one that shouldn't be writeable to
persistent storage, we skip it and continue. This is done to
handle new options that may have been added after this version of
cryptlib was built (for unknown indices) and because the stored
config options are an untrusted source so we have to check for
attempts to feed in bogus values (for non-writeable options) */
readSequence( &stream, NULL );
status = readShortInteger( &stream, &option );
if( cryptStatusError( status ) )
continue;
for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
if( fixedOptionInfo[ i ].index == option )
break;
if( fixedOptionInfo[ i ].option > LAST_STORED_OPTION || \
fixedOptionInfo[ i ].index == CRYPT_UNUSED )
{
readUniversal( &stream );
continue;
}
attributeType = fixedOptionInfo[ i ].option;
/* Read the option value and set the option. We don't treat a failure
to set the option as a problem since the user probably doesn't want
the entire system to fail because of a bad config option, and in any
case we'll fall back to a safe default value */
tag = peekTag( &stream );
if( tag == BER_BOOLEAN || tag == BER_INTEGER )
{
/* It's a numeric value, read the appropriate type and try and set
the option */
if( tag == BER_BOOLEAN )
status = readBoolean( &stream, &value );
else
{
long integer;
status = readShortInteger( &stream, &integer );
value = ( int ) integer;
}
if( cryptStatusOK( status ) )
krnlSendMessage( iCryptUser, IMESSAGE_SETATTRIBUTE, &value,
attributeType );
}
else
{
int length;
/* It's a string value, set the option straight from the encoded
data */
status = readGenericHole( &stream, &length, BER_STRING_UTF8 );
if( cryptStatusError( status ) )
continue;
setMessageData( &msgData, sMemBufPtr( &stream ), length );
krnlSendMessage( iCryptUser, IMESSAGE_SETATTRIBUTE_S, &msgData,
attributeType );
status = sSkip( &stream, length );
}
}
sMemDisconnect( &stream );
/* Clean up */
dynDestroy( &configDB );
return( status );
}
/* Write any user-defined configuration options. This is performed in two
phases, a first phase that encodes the config data and a second phase
that writes the data to disk. The reason for the split is that the
second phase doesn't require the use of the user object data any more
and can be a somewhat lengthy process due to disk accesses and other bits
and pieces. Because of this the caller is expected to unlock the user
object between the two phases to ensure that the second phase doesn't
stall all other operations that require it */
int encodeConfigData( OPTION_INFO *optionList, const char *fileName,
void *trustInfoPtr, void **data, int *length )
{
STREAM stream;
const BOOLEAN trustedCertsPresent = \
( enumTrustedCerts( trustInfoPtr, CRYPT_UNUSED,
CRYPT_UNUSED ) != CRYPT_ERROR ) ? \
TRUE : FALSE;
int i;
/* Clear the return values */
*data = NULL;
*length = 0;
/* If neither the config options nor any cert trust settings have
changed, there's nothing to do */
for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
if( optionList[ i ].dirty )
break;
if( fixedOptionInfo[ i ].option >= LAST_STORED_OPTION && \
!trustedCertsPresent )
return( CRYPT_OK );
/* Make a first pass through the config options to determine the total
encoded length of the ones that don't match the default setting. We
can't just check the isDirty flag because if a value is reset to its
default setting the encoded size will be zero even though the isDirty
flag is set */
for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
{
const FIXED_OPTION_INFO *fixedOptionInfoPtr = &fixedOptionInfo[ i ];
const OPTION_INFO *optionInfoPtr = &optionList[ i ];
/* If it's an option that can't be written to disk, skip it */
if( fixedOptionInfoPtr->index == CRYPT_UNUSED )
continue;
if( fixedOptionInfoPtr->type == OPTION_STRING )
{
/* If the string value is the same as the default, there's
nothing to do */
if( optionInfoPtr->strValue == NULL || \
optionInfoPtr->strValue == fixedOptionInfoPtr->strDefault )
continue;
*length += ( int ) sizeofObject( \
sizeofShortInteger( fixedOptionInfoPtr->index ) + \
sizeofObject( strlen( optionInfoPtr->strValue ) ) );
}
else
{
/* If the integer/boolean value that's currently set isn't the
default setting, update it */
if( optionInfoPtr->intValue == fixedOptionInfoPtr->intDefault )
continue;
*length += ( int ) sizeofObject( \
sizeofShortInteger( fixedOptionInfoPtr->index ) + \
( fixedOptionInfoPtr->type == OPTION_NUMERIC ? \
sizeofShortInteger( optionInfoPtr->intValue ) : \
sizeofBoolean() ) );
}
}
/* If we've gone back to all default values from having non-default ones
stored, we either have to write only trusted certs or nothing at all */
if( *length <= 0 )
{
char configFilePath[ MAX_PATH_LENGTH + 128 ]; /* Protection for Windows */
/* There's no data to write, if there are trusted certs present
notify the caller */
if( trustedCertsPresent )
return( OK_SPECIAL );
/* There's nothing to write, delete the config file */
fileBuildCryptlibPath( configFilePath, fileName, FALSE );
fileErase( configFilePath );
return( CRYPT_OK );
}
assert( *length > 0 );
/* Allocate a buffer to hold the encoded values */
if( ( *data = clAlloc( "encodeConfigData", *length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
/* Write the config options */
sMemOpen( &stream, *data, *length );
for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
{
const FIXED_OPTION_INFO *fixedOptionInfoPtr = &fixedOptionInfo[ i ];
const OPTION_INFO *optionInfoPtr = &optionList[ i ];
/* If it's an option that can't be written to disk, skip it */
if( fixedOptionInfoPtr->index == CRYPT_UNUSED )
continue;
if( fixedOptionInfoPtr->type == OPTION_STRING )
{
if( optionInfoPtr->strValue == NULL || \
optionInfoPtr->strValue == fixedOptionInfoPtr->strDefault )
continue;
writeSequence( &stream,
sizeofShortInteger( fixedOptionInfoPtr->index ) + \
sizeofObject( strlen( optionInfoPtr->strValue ) ) );
writeShortInteger( &stream, fixedOptionInfoPtr->index,
DEFAULT_TAG );
writeCharacterString( &stream, optionInfoPtr->strValue,
strlen( optionInfoPtr->strValue ),
BER_STRING_UTF8 );
continue;
}
if( optionInfoPtr->intValue == fixedOptionInfoPtr->intDefault )
continue;
if( fixedOptionInfoPtr->type == OPTION_NUMERIC )
{
writeSequence( &stream,
sizeofShortInteger( fixedOptionInfoPtr->index ) + \
sizeofShortInteger( optionInfoPtr->intValue ) );
writeShortInteger( &stream, fixedOptionInfoPtr->index,
DEFAULT_TAG );
writeShortInteger( &stream, optionInfoPtr->intValue,
DEFAULT_TAG );
}
else
{
writeSequence( &stream,
sizeofShortInteger( fixedOptionInfoPtr->index ) + \
sizeofBoolean() );
writeShortInteger( &stream, fixedOptionInfoPtr->index,
DEFAULT_TAG );
writeBoolean( &stream, optionInfoPtr->intValue, DEFAULT_TAG );
}
}
assert( sGetStatus( &stream ) == CRYPT_OK );
sMemDisconnect( &stream );
/* We've written the config data to the memory buffer, let the caller
know that they can unlock it and commit it to permanent storage */
return( OK_SPECIAL );
}
int commitConfigData( const CRYPT_USER cryptUser, const char *fileName,
const void *data, const int length )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
char configFilePath[ MAX_PATH_LENGTH + 128 ]; /* Protection for Windows */
int status;
/* Build the path to the config file and try and create it */
fileBuildCryptlibPath( configFilePath, fileName, TRUE );
setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );
createInfo.arg2 = CRYPT_KEYOPT_CREATE;
createInfo.strArg1 = configFilePath;
createInfo.strArgLen1 = strlen( configFilePath );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_KEYSET );
if( cryptStatusError( status ) )
/* Map the lower-level keyset-specific error into a more meaningful
generic error */
return( CRYPT_ERROR_OPEN );
/* Send the config data (if there is any) and any trusted certs to the
keyset */
if( length > 0 )
{
setMessageData( &msgData, ( void * ) data, length );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_CONFIGDATA );
}
if( cryptStatusOK( status ) )
status = krnlSendMessage( cryptUser, IMESSAGE_SETATTRIBUTE,
&createInfo.cryptHandle,
CRYPT_IATTRUBUTE_CERTKEYSET );
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
{
fileErase( configFilePath );
return( CRYPT_ERROR_WRITE );
}
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -