📄 msg_acl.c
字号:
}
else
{
ENSURES( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_OBJECT );
if( ( paramInfo( compareACL, 0 ).subTypeA & ~( SUBTYPE_CLASS_A | \
ST_CERT_ANY ) ) || \
paramInfo( compareACL, 0 ).subTypeB != ST_NONE )
retIntError();
}
}
ENSURES( i < FAILSAFE_ARRAYSIZE( compareACLTbl, COMPARE_ACL ) );
/* Perform a consistency check on the check ACL */
for( i = 0; checkACLTbl[ i ].checkType != MESSAGE_CHECK_NONE && \
i < FAILSAFE_ARRAYSIZE( checkACLTbl, CHECK_ACL ); i++ )
{
const CHECK_ACL *checkACL = &checkACLTbl[ i ];
int j;
ENSURES( checkACL->checkType > MESSAGE_CHECK_NONE && \
checkACL->checkType < MESSAGE_CHECK_LAST && \
checkACL->checkType == i + 1 );
ENSURES( checkACL->actionType == MESSAGE_NONE || \
( checkACL->actionType >= MESSAGE_CTX_ENCRYPT && \
checkACL->actionType <= MESSAGE_CRT_SIGCHECK ) );
if( ( checkACL->objectACL.subTypeA & \
~( SUBTYPE_CLASS_A | ST_CTX_ANY | ST_CERT_ANY | \
ST_KEYSET_ANY | ST_DEV_ANY ) ) || \
checkACL->objectACL.subTypeB != ST_NONE )
retIntError();
ENSURES( !( checkACL->objectACL.flags & ~ACL_FLAG_ANY_STATE ) )
if( checkACL->altACL == NULL )
continue;
for( j = 0; checkACL->altACL[ j ].object != OBJECT_TYPE_NONE && \
j < FAILSAFE_ITERATIONS_MED; j++ )
{
const CHECK_ALT_ACL *checkAltACL = &checkACL->altACL[ j ];
ENSURES( checkAltACL->object == OBJECT_TYPE_CONTEXT || \
checkAltACL->object == OBJECT_TYPE_CERTIFICATE );
ENSURES( checkAltACL->checkType > MESSAGE_CHECK_NONE && \
checkAltACL->checkType < MESSAGE_CHECK_LAST );
ENSURES( checkAltACL->depObject == OBJECT_TYPE_CONTEXT || \
checkAltACL->depObject == OBJECT_TYPE_CERTIFICATE );
if( ( checkAltACL->depObjectACL.subTypeA & \
~( SUBTYPE_CLASS_A | ST_CTX_ANY | ST_CERT_ANY ) ) || \
checkAltACL->depObjectACL.subTypeB != ST_NONE )
retIntError();
ENSURES( !( checkAltACL->depObjectACL.flags & ~ACL_FLAG_ANY_STATE ) )
ENSURES( checkAltACL->fdCheckType > MESSAGE_CHECK_NONE && \
checkAltACL->fdCheckType < MESSAGE_CHECK_LAST );
}
ENSURES( j < FAILSAFE_ITERATIONS_MED );
}
ENSURES( i < FAILSAFE_ARRAYSIZE( checkACLTbl, CHECK_ACL ) );
/* Perform a consistency check on the cert export pseudo-ACL */
for( i = 0; formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE && \
i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT );
i++ )
{
const ATTRIBUTE_ACL_ALT *formatACL = &formatPseudoACL[ i ];
ENSURES( formatACL->attribute > CRYPT_CERTTYPE_NONE && \
formatACL->attribute < CRYPT_CERTTYPE_LAST );
if( ( formatACL->subTypeA & ~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) || \
formatACL->subTypeB != ST_NONE )
retIntError();
if( formatACL->attribute < CRYPT_CERTFORMAT_LAST_EXTERNAL )
{
ENSURES( formatACL->access == ACCESS_Rxx_xxx );
}
else
{
ENSURES( formatACL->access == ACCESS_INT_Rxx_xxx || \
formatACL->access == ACCESS_INT_Rxx_Rxx );
}
ENSURES( formatACL->valueType == ATTRIBUTE_VALUE_STRING && \
formatACL->lowRange >= 16 && \
formatACL->lowRange < formatACL->highRange && \
formatACL->highRange <= 8192 && \
formatACL->extendedInfo == NULL );
}
ENSURES( i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ) );
/* Perform a consistency check on the create-object ACL */
for( i = 0; createObjectACL[ i ].type != OBJECT_TYPE_NONE && \
i < FAILSAFE_ARRAYSIZE( createObjectACL, CREATE_ACL );
i++ )
{
const CREATE_ACL *createACL = &createObjectACL[ i ];
ENSURES( isValidType( createACL->type ) );
ENSURES( paramInfo( createACL, 0 ).valueType == PARAM_VALUE_NUMERIC && \
paramInfo( createACL, 1 ).valueType == PARAM_VALUE_NUMERIC && \
( paramInfo( createACL, 2 ).valueType == PARAM_VALUE_STRING_NONE || \
paramInfo( createACL, 2 ).valueType == PARAM_VALUE_STRING ) && \
( paramInfo( createACL, 3 ).valueType == PARAM_VALUE_STRING_NONE || \
paramInfo( createACL, 3 ).valueType == PARAM_VALUE_STRING ) );
if( createACL->type == OBJECT_TYPE_CONTEXT )
{
ENSURES( paramInfo( createACL, 0 ).lowRange > CRYPT_ALGO_NONE && \
paramInfo( createACL, 0 ).highRange < CRYPT_ALGO_LAST );
}
else
{
/* Perform a composite check for a vaguely sensible value.
CRYPT_CERTTYPE_LAST is the highest possible value for all of
the non-context object types */
ENSURES( paramInfo( createACL, 0 ).lowRange > 0 && \
paramInfo( createACL, 0 ).highRange < CRYPT_CERTTYPE_LAST );
}
if( createACL->exceptions[ 0 ] == 0 && \
createACL->exceptions[ 1 ] != 0 )
retIntError();
if( ( createACL->exceptions[ 0 ] != 0 || \
createACL->exceptions[ 1 ] != 0 ) && \
createACL->exceptionACL == NULL )
retIntError();
}
ENSURES( i < FAILSAFE_ARRAYSIZE( createObjectACL, CREATE_ACL ) );
/* Perform a consistency check on the create-object-indirect ACL */
for( i = 0; createObjectIndirectACL[ i ].type != OBJECT_TYPE_NONE && \
i < FAILSAFE_ARRAYSIZE( createObjectIndirectACL, CREATE_ACL );
i++ )
{
const CREATE_ACL *createACL = &createObjectIndirectACL[ i ];
ENSURES( isValidType( createACL->type ) );
if( paramInfo( createACL, 0 ).valueType != PARAM_VALUE_NUMERIC || \
paramInfo( createACL, 1 ).valueType != PARAM_VALUE_NUMERIC || \
paramInfo( createACL, 2 ).valueType != PARAM_VALUE_STRING || \
( paramInfo( createACL, 3 ).valueType != PARAM_VALUE_STRING_NONE && \
paramInfo( createACL, 3 ).valueType != PARAM_VALUE_STRING ) )
retIntError();
ENSURES( paramInfo( createACL, 0 ).lowRange >= 0 && \
paramInfo( createACL, 0 ).highRange < CRYPT_CERTTYPE_LAST );
/* The low-range may be 0, which indicates that we're using
automatic format detection */
ENSURES( paramInfo( createACL, 2 ).lowRange >= 16 && \
paramInfo( createACL, 2 ).highRange < MAX_INTLENGTH );
if( createACL->exceptions[ 0 ] == 0 && \
createACL->exceptions[ 1 ] != 0 )
retIntError();
if( ( createACL->exceptions[ 0 ] != 0 || \
createACL->exceptions[ 1 ] != 0 ) && \
createACL->exceptionACL == NULL )
retIntError();
}
ENSURES( i < FAILSAFE_ARRAYSIZE( createObjectIndirectACL, CREATE_ACL ) );
/* Set up the reference to the kernel data block */
krnlData = krnlDataPtr;
return( CRYPT_OK );
}
void endMessageACL( void )
{
krnlData = NULL;
}
/****************************************************************************
* *
* Message Pre-dispatch Handlers *
* *
****************************************************************************/
/* If it's a destroy object message, adjust the reference counts of any
dependent objects and set the object's state to signalled. We do this
before we send the destroy message to the object in order that any
further attempts to access it will fail. This is handled anyway by the
message dispatcher, but setting the status to signalled now means that
it's rejected immediately rather than being enqueued and then dequeued
again once the destroy message has been processed */
int preDispatchSignalDependentObjects( const int objectHandle,
const MESSAGE_TYPE message, /* Unused */
const void *messageDataPtr, /* Unused */
const int messageValue, /* Unused */
const void *dummy )
{
OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
STDC_UNUSED int status;
/* Preconditions */
PRE( isValidObject( objectHandle ) && \
objectHandle >= NO_SYSTEM_OBJECTS );
PRE( isValidMessage( message & MESSAGE_MASK ) );
/* An inability to change the reference counts of the dependent objects
doesn't affect the object itself so we can't report it as an error,
however we can at least warn about it in debug mode */
if( isValidObject( objectInfoPtr->dependentDevice ) )
{
/* Velisurmaaja */
status = decRefCount( objectInfoPtr->dependentDevice, 0, NULL, TRUE );
assert( cryptStatusOK( status ) );
}
if( isValidObject( objectInfoPtr->dependentObject ) )
{
status = decRefCount( objectInfoPtr->dependentObject, 0, NULL, TRUE );
assert( cryptStatusOK( status ) );
}
objectInfoPtr->flags |= OBJECT_FLAG_SIGNALLED;
/* Postcondition: The object is now in the destroyed state as far as
other objects are concerned */
POST( isInvalidObjectState( objectHandle ) );
return( CRYPT_OK );
}
/* If it's an attribute get/set/delete, check the access conditions for the
object and the message parameters */
int preDispatchCheckAttributeAccess( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *auxInfo )
{
static const int FAR_BSS accessTypeTbl[ 5 ][ 2 ] = {
/* MESSAGE_GETATTRIBUTE */ /* MESSAGE_GETATTRIBUTE_S */
{ ACCESS_FLAG_R, ACCESS_FLAG_H_R }, { ACCESS_FLAG_R, ACCESS_FLAG_H_R },
/* MESSAGE_SETATTRIBUTE */ /* MESSAGE_SETATTRIBUTE_S */
{ ACCESS_FLAG_W, ACCESS_FLAG_H_W }, { ACCESS_FLAG_W, ACCESS_FLAG_H_W },
/* MESSAGE_DELETEATTRIBUTE */
{ ACCESS_FLAG_D, ACCESS_FLAG_H_D }
};
const ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;
const OBJECT_INFO *objectTable = krnlData->objectTable;
const OBJECT_INFO *objectInfo = &objectTable[ objectHandle ];
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
const int subType = objectInfo->subType;
int accessType = \
accessTypeTbl[ localMessage - MESSAGE_GETATTRIBUTE ]\
[ ( objectInfo->flags & OBJECT_FLAG_HIGH ) ? 1 : 0 ];
const BOOLEAN isInternalMessage = isInternalMessage( message ) ? \
TRUE : FALSE;
/* Preconditions */
PRE( isValidType( objectInfo->type ) );
PRE( isAttributeMessage( localMessage ) );
PRE( isAttribute( messageValue ) || isInternalAttribute( messageValue ) );
PRE( localMessage == MESSAGE_DELETEATTRIBUTE || messageDataPtr != NULL );
PRE( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) && \
attributeACL->attribute == messageValue );
/* If it's an internal message, use the internal access permssions */
if( isInternalMessage )
accessType = MK_ACCESS_INTERNAL( accessType );
/* Make sure that the attribute is valid for this object subtype */
if( !isValidSubtype( attributeACL->subTypeA, subType ) && \
!isValidSubtype( attributeACL->subTypeB, subType ) )
return( CRYPT_ARGERROR_VALUE );
/* Make sure that this type of access is valid for this attribute */
if( !( attributeACL->access & accessType ) )
{
/* If it's an internal-only attribute being accessed through an
external message, it isn't visible to the user so we return
an attribute value error */
if( !( attributeACL->access & ACCESS_MASK_EXTERNAL ) && \
!isInternalMessage )
return( CRYPT_ARGERROR_VALUE );
/* It is visible, return a standard permission error */
return( CRYPT_ERROR_PERMISSION );
}
/* Inner precondition: The attribute is valid for this subtype and is
externally visible or it's an internal message, and this type of
access is allowed */
PRE( isValidSubtype( attributeACL->subTypeA, subType ) || \
isValidSubtype( attributeACL->subTypeB, subType ) );
PRE( ( attributeACL->access & ACCESS_MASK_EXTERNAL ) || \
isInternalMessage );
PRE( attributeACL->access & accessType );
/* If it's a delete attribute message, there's no attribute data being
communicated so we can exit now */
if( localMessage == MESSAGE_DELETEATTRIBUTE )
{
assert( messageDataPtr == NULL );
return( CRYPT_OK );
}
/* Inner precondition: We're getting or setting the value of an attribute */
PRE( localMessage == MESSAGE_GETATTRIBUTE || \
localMessage == MESSAGE_GETATTRIBUTE_S || \
localMessage == MESSAGE_SETATTRIBUTE || \
localMessage == MESSAGE_SETATTRIBUTE_S );
/* Safety check for invalid pointers passed from an internal function */
if( attributeACL->valueType != ATTRIBUTE_VALUE_SPECIAL && \
!isReadPtr( messageDataPtr, \
( attributeACL->valueType == ATTRIBUTE_VALUE_STRING || \
attributeACL->valueType == ATTRIBUTE_VALUE_WCSTRING || \
attributeACL->valueType == ATTRIBUTE_VALUE_TIME ) ? \
sizeof( MESSAGE_DATA ) : sizeof( int ) ) )
retIntError();
/* Make sure that the attribute type matches the supplied value type.
We assert the preconditions for internal messages before the general
check to ensure that we throw an exception rather than just returning
an error code for internal programming errors */
switch( attributeACL->valueType )
{
case ATTRIBUTE_VALUE_BOOLEAN:
/* Inner precondition: If it's an internal message, it must be
a numeric value */
PRE( !isInternalMessage || \
localMessage == MESSAGE_GETATTRIBUTE || \
localMessage == MESSAGE_SETATTRIBUTE );
PRE( isReadPtr( messageDataPtr, sizeof( int ) ) );
/* Must be a numeric value */
if( localMessage != MESSAGE_GETATTRIBUTE && \
localMessage != MESSAGE_SETATTRIBUTE )
return( CRYPT_ARGERROR_VALUE );
/* If we're sending the data back to the caller, the only thing
that we can check is the presence of a writeable output
buffer */
if( localMessage == MESSAGE_GETATTRIBUTE )
{
if( !isWritePtr( ( void * ) messageDataPtr, sizeof( int ) ) )
return( CRYPT_ARGERROR_STR1 );
}
break;
case ATTRIBUTE_VALUE_NUMERIC:
{
const int *valuePtr = messageDataPtr;
/* Inner precondition: If it's an internal message, it must be
a numeric value */
PRE( !isInternalMessage || \
localMessage == MESSAGE_GETATTRIBUTE || \
localMessage == MESSAGE_SETATTRIBUTE );
PRE( isReadPtr( messageDataPtr, sizeof( int ) ) );
/* Must be a numeric value */
if( localMessage != MESSAGE_GETATTRIBUTE && \
localMessage != MESSAGE_SETATTRIBUTE )
return( CRYPT_ARGERROR_VALUE );
/* If we're sending the data back to the caller, the only thing
that we can check is the presence of a writeable output
buffer */
if( localMessage == MESSAGE_GETATTRIBUTE )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -