📄 msg_acl.c
字号:
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 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 = \
( message & MESSAGE_FLAG_INTERNAL ) ? 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( RESOURCE_DATA ) : sizeof( int ) ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_NUM1 );
}
/* 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 )
{
if( !isWritePtr( ( void * ) messageDataPtr, sizeof( int ) ) )
return( CRYPT_ARGERROR_STR1 );
break;
}
/* Inner precondition: We're sending data to the object */
PRE( localMessage == MESSAGE_SETATTRIBUTE );
/* If it's a standard range check, make sure that the attribute
value is within the allowed range */
if( !isSpecialRange( attributeACL ) )
{
if( !checkNumericRange( *valuePtr, attributeACL->lowRange,
attributeACL->highRange ) )
return( CRYPT_ARGERROR_NUM1 );
break;
}
/* It's a special-case range check */
assert( isSpecialRange( attributeACL ) );
switch( getSpecialRangeType( attributeACL ) )
{
case RANGEVAL_ANY:
break;
case RANGEVAL_SELECTVALUE:
if( *valuePtr != CRYPT_UNUSED )
return( CRYPT_ARGERROR_NUM1 );
break;
case RANGEVAL_ALLOWEDVALUES:
if( !checkAttributeRangeSpecial( RANGEVAL_ALLOWEDVALUES,
getSpecialRangeInfo( attributeACL ),
*valuePtr ) )
return( CRYPT_ARGERROR_NUM1 );
break;
case RANGEVAL_SUBRANGES:
if( !checkAttributeRangeSpecial( RANGEVAL_SUBRANGES,
getSpecialRangeInfo( attributeACL ),
*valuePtr ) )
return( CRYPT_ARGERROR_NUM1 );
break;
default:
assert( NOTREACHED );
return( CRYPT_ARGERROR_NUM1 );
}
break;
}
case ATTRIBUTE_VALUE_OBJECT:
{
const OBJECT_ACL *objectACL = attributeACL->extendedInfo;
const int *valuePtr = messageDataPtr;
int objectParamHandle, objectParamSubType;
/* 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;
}
/* Inner precondition: We're sending data to the object */
PRE( localMessage == MESSAGE_SETATTRIBUTE );
/* Must contain a valid object handle */
if( !fullObjectCheck( *valuePtr, message ) || \
!isSameOwningObject( objectHandle, *valuePtr ) )
return( CRYPT_ARGERROR_NUM1 );
/* Object must be of the correct type */
if( objectACL->flags & ACL_FLAG_ROUTE_TO_CTX )
objectParamHandle = findTargetType( *valuePtr,
OBJECT_TYPE_CONTEXT );
else
if( objectACL->flags & ACL_FLAG_ROUTE_TO_CERT )
objectParamHandle = findTargetType( *valuePtr,
OBJECT_TYPE_CERTIFICATE );
else
objectParamHandle = *valuePtr;
if( cryptStatusError( objectParamHandle ) )
return( CRYPT_ARGERROR_NUM1 );
objectParamSubType = objectTable[ objectParamHandle ].subType;
if( !isValidSubtype( objectACL->subTypeA, objectParamSubType ) && \
!isValidSubtype( objectACL->subTypeB, objectParamSubType ) )
return( CRYPT_ARGERROR_NUM1 );
if( ( objectACL->flags & ACL_FLAG_STATE_MASK ) && \
!checkObjectState( objectACL->flags, objectParamHandle ) )
return( CRYPT_ARGERROR_NUM1 );
/* Postcondition: Object parameter is valid and accessible,
object is of the correct type and state */
POST( fullObjectCheck( *valuePtr, message ) && \
isSameOwningObject( objectHandle, *valuePtr ) );
POST( isValidSubtype( objectACL->subTypeA, objectParamSubType ) || \
isValidSubtype( objectACL->subTypeB, objectParamSubType ) );
POST( !( objectACL->flags & ACL_FLAG_STATE_MASK ) || \
checkObjectState( objectACL->flags, objectParamHandle ) );
break;
}
case ATTRIBUTE_VALUE_STRING:
case ATTRIBUTE_VALUE_WCSTRING:
{
const RESOURCE_DATA *msgData = messageDataPtr;
/* Inner precondition: If it's an internal message, it must be
a valid string value or a null value if we're obtaining a
length. Polled entropy data can be arbitrarily large so we
don't check its length */
PRE( isReadPtr( messageDataPtr, sizeof( RESOURCE_DATA ) ) );
PRE( !isInternalMessage || \
( ( localMessage == MESSAGE_GETATTRIBUTE_S && \
( ( msgData->data == NULL && msgData->length == 0 ) || \
( msgData->length >= 1 && \
isWritePtr( msgData->data, msgData->length ) ) ) ) || \
( localMessage == MESSAGE_SETATTRIBUTE_S && \
isReadPtr( msgData->data, msgData->length ) && \
( msgData->length < 16384 || \
messageValue == CRYPT_IATTRIBUTE_ENTROPY ) ) ) );
/* Must be a string value */
if( localMessage != MESSAGE_GETATTRIBUTE_S && \
localMessage != MESSAGE_SETATTRIBUTE_S )
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. We return a string arg error for both the buffer and
length, since the length isn't explicitly specified by an
external caller */
if( localMessage == MESSAGE_GETATTRIBUTE_S )
{
if( !( ( msgData->data == NULL && msgData->length == 0 ) || \
( msgData->length > 0 && \
isWritePtr( msgData->data, msgData->length ) ) ) )
return( CRYPT_ARGERROR_STR1 );
break;
}
/* Inner precondition: We're sending data to the object */
PRE( localMessage == MESSAGE_SETATTRIBUTE_S );
/* Make sure that the string length is within the allowed
range */
if( isSpecialRange( attributeACL ) )
{
if( !checkAttributeRangeSpecial( \
getSpecialRangeType( attributeACL ),
getSpecialRangeInfo( attributeACL ),
msgData->length ) )
return( CRYPT_ARGERROR_NUM1 );
}
else
if( attributeACL->valueType == ATTRIBUTE_VALUE_WCSTRING )
{
if( !checkAttributeRangeWidechar( msgData->data,
msgData->length,
attributeACL->lowRange,
attributeACL->highRange ) )
return( CRYPT_ARGERROR_NUM1 );
}
else
if( msgData->length < attributeACL->lowRange || \
msgData->length > attributeACL->highRange )
return( CRYPT_ARGERROR_NUM1 );
if( msgData->length > 0 && \
!isReadPtr( msgData->data, msgData->length ) )
return( CRYPT_ARGERROR_STR1 );
break;
}
case ATTRIBUTE_VALUE_TIME:
{
const RESOURCE_DATA *msgData = messageDataPtr;
/* Inner precondition: If it's an internal message, it must be
a string value corresponding to a time_t */
PRE( isReadPtr( messageDataPtr, sizeof( RESOURCE_DATA ) ) );
PRE( !isInternalMessage || \
( ( localMessage == MESSAGE_GETATTRIBUTE_S || \
localMessage == MESSAGE_SETATTRIBUTE_S ) && \
isReadPtr( msgData->data, msgData->length ) && \
msgData->length == sizeof( time_t ) ) );
/* Must be a string value */
if( localMessage != MESSAGE_GETATTRIBUTE_S && \
localMessage != MESSAGE_SETATTRIBUTE_S )
return( CRYPT_ARGERROR_VALUE );
/* If we're sending the data back to the caller, the only thing
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -