📄 msg_acl.c
字号:
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;
}
/* If we're sending the data back to the caller, we can't check
it yet */
if( localMessage == MESSAGE_GETATTRIBUTE_S )
break;
/* Inner precondition: We're sending data to the object */
PRE( localMessage == MESSAGE_SETATTRIBUTE_S );
/* Must contain a time_t in a sensible range */
if( !isReadPtr( msgData->data, sizeof( time_t ) ) || \
*( ( time_t * ) msgData->data ) < MIN_TIME_VALUE )
return( CRYPT_ARGERROR_STR1 );
if( msgData->length != sizeof( time_t ) )
return( CRYPT_ARGERROR_NUM1 );
break;
}
case ATTRIBUTE_VALUE_SPECIAL:
/* It's an ACL with an object-subtype-specific sub-ACL, find the
precise ACL for this object subtype */
for( attributeACL = getSpecialRangeInfo( attributeACL ); \
attributeACL->valueType != ATTRIBUTE_VALUE_NONE; \
attributeACL++ )
if( isValidSubtype( attributeACL->subTypeA, subType ) || \
isValidSubtype( attributeACL->subTypeB, subType ) )
break;
if( attributeACL->valueType == ATTRIBUTE_VALUE_NONE )
{
assert( NOTREACHED );
return( CRYPT_ERROR_PERMISSION );
}
/* Recursively check the message against the sub-ACL */
return( preDispatchCheckAttributeAccess( objectHandle, message,
messageDataPtr, messageValue, attributeACL ) );
default:
assert( NOTREACHED );
return( CRYPT_ERROR_PERMISSION );
}
return( CRYPT_OK );
}
/* It's a compare message, make sure that the parameters are OK */
int preDispatchCheckCompareParam( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const OBJECT_INFO *objectTable = krnlData->objectTable;
const OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
const COMPARE_ACL *compareACL = NULL;
/* Precondition: It's a valid compare message type */
PRE( fullObjectCheck( objectHandle, message ) );
PRE( messageValue > MESSAGE_COMPARE_NONE && \
messageValue < MESSAGE_COMPARE_LAST );
/* Find the appropriate ACL for this compare type */
if( messageValue > MESSAGE_COMPARE_NONE && \
messageValue < MESSAGE_COMPARE_LAST )
compareACL = &compareACLTbl[ messageValue - 1 ];
if( compareACL == NULL )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* Inner precondition: We have the correct ACL, and the full object
check has been performed by the kernel */
PRE( compareACL->compareType == messageValue );
/* Check the message target. The full object check has already been
performed by the message dispatcher so all we need to check is the
compare-specific subtype. We throw an exception if we find an
invalid parameter, both because this is an internal message and this
situation shouldn't occur, and because an error return from a compare
message is perfectly valid (it denotes a non-match) so parameter
errors won't otherwise be caught by the caller */
if( !( isValidSubtype( compareACL->objectACL.subTypeA, \
objectInfoPtr->subType ) ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_OBJECT );
}
if( ( compareACL->objectACL.flags & ACL_FLAG_STATE_MASK ) && \
!checkObjectState( compareACL->objectACL.flags, objectHandle ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_OBJECT );
}
/* Check the message parameters. We throw an exception if we find an
invalid parameter for the reason given above */
if( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_OBJECT )
{
const CRYPT_HANDLE iCryptHandle = *( ( CRYPT_HANDLE * ) messageDataPtr );
PRE( fullObjectCheck( iCryptHandle, message ) && \
isSameOwningObject( objectHandle, iCryptHandle ) );
PRE( checkParamObject( paramInfo( compareACL, 0 ), iCryptHandle ) );
}
else
{
const RESOURCE_DATA *msgData = messageDataPtr;
PRE( checkParamString( paramInfo( compareACL, 0 ),
msgData->data, msgData->length ) );
}
/* Postconditions: The compare parameters are valid, either an object
handle or a string value at least as big as a minimal-length DN */
POST( ( messageValue == MESSAGE_COMPARE_CERTOBJ && \
isValidHandle( *( ( CRYPT_HANDLE * ) messageDataPtr ) ) ) || \
( messageValue != MESSAGE_COMPARE_CERTOBJ && \
isReadPtr( messageDataPtr, sizeof( RESOURCE_DATA ) ) && \
( ( RESOURCE_DATA * ) messageDataPtr )->length >= 2 && \
isReadPtr( ( ( RESOURCE_DATA * ) messageDataPtr )->data, \
( ( RESOURCE_DATA * ) messageDataPtr )->length ) ) );
return( CRYPT_OK );
}
/* It's a check message, make sure that the parameters are OK */
int preDispatchCheckCheckParam( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const OBJECT_INFO *objectTable = krnlData->objectTable;
const OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
const CHECK_ACL *checkACL = NULL;
int status;
/* Precondition: It's a valid check message type */
PRE( fullObjectCheck( objectHandle, message ) );
PRE( messageValue > MESSAGE_CHECK_NONE && \
messageValue < MESSAGE_CHECK_LAST );
/* Find the ACL information for the message type */
status = findCheckACL( messageValue, objectInfoPtr->type,
&checkACL, NULL );
if( cryptStatusError( status ) )
return( status );
/* Check the message target. The full object check has already been
performed by the message dispatcher so all we need to check is the
compare-specific subtype */
if( !( isValidSubtype( checkACL->objectACL.subTypeA, \
objectInfoPtr->subType ) ) )
return( CRYPT_ARGERROR_OBJECT );
if( ( checkACL->objectACL.flags & ACL_FLAG_STATE_MASK ) && \
!checkObjectState( checkACL->objectACL.flags, objectHandle ) )
/* The object is in the wrong state, meaning that it's inited when
it shouldn't be or not inited when it should be, return a more
specific error message */
return( isInHighState( objectHandle ) ? \
CRYPT_ERROR_INITED : CRYPT_ERROR_NOTINITED );
/* Make sure that the object's usage count is still valid. The usage
count is a type of meta-capability that overrides all other
capabilities in that an object with an expired usage count isn't
valid for anything no matter what the available capabilities are */
if( objectInfoPtr->usageCount != CRYPT_UNUSED && \
objectInfoPtr->usageCount <= 0 )
return( CRYPT_ARGERROR_OBJECT );
/* If this is a context and there's an action associated with this
check, make sure that the requested action is permitted for this
object */
if( objectInfoPtr->type == OBJECT_TYPE_CONTEXT && \
checkACL->actionType != MESSAGE_NONE )
{
const BOOLEAN isInternalMessage = \
( message & MESSAGE_FLAG_INTERNAL ) ? TRUE : FALSE;
int status;
/* Check that the action is permitted. We convert the return status
to a CRYPT_ERROR_NOTAVAIL, which makes more sense than a generic
object error */
status = checkActionPermitted( objectInfoPtr,
isInternalMessage ? \
MKINTERNAL( checkACL->actionType ) : \
checkACL->actionType );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_NOTAVAIL );
}
/* Postconditions: The object being checked is valid */
POST( fullObjectCheck( objectHandle, message ) && \
( isValidSubtype( checkACL->objectACL.subTypeA, \
objectInfoPtr->subType ) ) );
return( CRYPT_OK );
}
/* It's a context action message, check the access conditions for the object */
int preDispatchCheckActionAccess( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
int status;
/* Precondition: It's a valid access */
PRE( isValidObject( objectHandle ) );
PRE( isActionMessage( localMessage ) );
/* If the object is in the low state, it can't be used for any action */
if( !isInHighState( objectHandle ) )
return( CRYPT_ERROR_NOTINITED );
/* If the object is in the high state, it can't receive another message
of the kind that causes the state change */
if( localMessage == MESSAGE_CTX_GENKEY )
return( CRYPT_ERROR_INITED );
/* If there's a usage count set for the object and it's gone to zero, it
can't be used any more */
if( objectInfoPtr->usageCount != CRYPT_UNUSED && \
objectInfoPtr->usageCount <= 0 )
return( CRYPT_ERROR_PERMISSION );
/* Inner precondition: Object is in the high state and can process the
action message */
PRE( isInHighState( objectHandle ) );
POST( objectInfoPtr->usageCount == CRYPT_UNUSED || \
objectInfoPtr->usageCount > 0 );
/* Check that the requested action is permitted for this object */
status = checkActionPermitted( objectInfoPtr, message );
if( cryptStatusError( status ) )
return( status );
/* Postcondition */
POST( localMessage != MESSAGE_CTX_GENKEY );
POST( isInHighState( objectHandle ) );
POST( objectInfoPtr->usageCount == CRYPT_UNUSED || \
objectInfoPtr->usageCount > 0 );
POST( cryptStatusOK( checkActionPermitted( objectInfoPtr, message ) ) );
return( CRYPT_OK );
}
/* If it's a state change trigger message, make sure that the object isn't
already in the high state */
int preDispatchCheckState( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue, const void *dummy )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
/* Precondition: It's a valid access */
PRE( isValidObject( objectHandle ) );
if( isInHighState( objectHandle ) )
return( CRYPT_ERROR_PERMISSION );
/* If it's a keygen message, perform a secondary check to ensure that key
generation is permitted for this object */
if( localMessage == MESSAGE_CTX_GENKEY )
{
int status;
/* Check that the requested action is permitted for this object */
status = checkActionPermitted( &krnlData->objectTable[ objectHandle ],
message );
if( cryptStatusError( status ) )
return( status );
}
/* Postcondition: Object is in the low state so a state change message
is valid */
POST( !isInHighState( objectHandle ) );
return( CRYPT_OK );
}
/* Check the access conditions for a message containing an optional handle
as the message parameter */
int preDispatchCheckParamHandleOpt( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *auxInfo )
{
const MESSAGE_ACL *messageACL = ( MESSAGE_ACL * ) auxInfo;
const OBJECT_ACL *objectACL = &messageACL->objectACL;
const OBJECT_INFO *objectTable = krnlData->objectTable;
int subType;
/* Preconditions: The access is valid and we've been supplied a valid
check ACL */
PRE( isValidObject( objectHandle ) );
PRE( isReadPtr( messageACL, sizeof( MESSAGE_ACL ) ) && \
messageACL->type == ( message & MESSAGE_MASK ) );
/* If the object parameter is CRYPT_UNUSED (for example for a self-signed
cert), we're OK */
if( messageValue == CRYPT_UNUSED )
return( CRYPT_OK );
/* Make sure that the object parameter is valid and accessible */
if( !fullObjectCheck( messageValue, message ) || \
!isSameOwningObject( objectHandle, messageValue ) )
return( CRYPT_ARGERROR_VALUE );
/* Make sure that the object parameter subtype is correct */
subType = objectTable[ messageValue ].subType;
if( !isValidSubtype( objectACL->subTypeA, subType ) && \
!isValidSubtype( objectACL->subTypeB, subType ) )
return( CRYPT_ARGERROR_VALUE );
/* Postcondition: Object parameter is valid, accessible, and of the
correct type */
POST( fullObjectCheck( messageValue, message ) && \
isSameOwningObject( objectHandle, messageValue ) );
POST( isValidSubtype( objectACL->subTypeA, subType ) || \
isValidSubtype( objectACL->subTypeB, subType ) );
return( CRYPT_OK );
}
/* Perform a combined check of the object and the handle */
int preDispatchCheckStateParamHandle( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *auxInfo )
{
const MESSAGE_ACL *messageACL = ( MESSAGE_ACL * ) auxInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -