📄 msg_acl.c
字号:
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( isValidMessage( message & MESSAGE_MASK ) );
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 = isInternalMessage( message ) ? \
TRUE : FALSE;
/* 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, /* Unused */
const int messageValue, /* Unused */
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, /* Unused */
const int messageValue, /* Unused */
const void *dummy )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
/* Precondition: It's a valid access */
PRE( isValidObject( objectHandle ) );
PRE( isValidMessage( localMessage ) );
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, /* Unused */
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( isValidMessage( message & MESSAGE_MASK ) );
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, /* Unused */
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( fullObjectCheck( objectHandle, message ) );
PRE( isReadPtr( messageACL, sizeof( MESSAGE_ACL ) ) && \
messageACL->type == ( message & MESSAGE_MASK ) );
if( isInHighState( objectHandle ) )
return( CRYPT_ERROR_PERMISSION );
/* 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 is in the low state so a state change message
is valid and the object parameter is valid, accessible, and of the
correct type */
POST( !isInHighState( objectHandle ) );
POST( fullObjectCheck( messageValue, message ) && \
isSameOwningObject( objectHandle, messageValue ) );
POST( isValidSubtype( objectACL->subTypeA, subType ) || \
isValidSubtype( objectACL->subTypeB, subType ) );
return( CRYPT_OK );
}
/* We're exporting a certificate, make sure that the format is valid for
this cert type */
int preDispatchCheckExportAccess( const int objectHandle,
const MESSAGE_TYPE message, /* Unused */
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const ATTRIBUTE_ACL *formatACL;
int i;
/* Precondition */
PRE( isValidObject( objectHandle ) );
PRE( isValidMessage( message & MESSAGE_MASK ) );
PRE( messageDataPtr != NULL );
PRE( messageValue > CRYPT_CERTFORMAT_NONE && \
messageValue < CRYPT_CERTFORMAT_LAST );
/* Make sure that the export format is valid */
if( messageValue <= CRYPT_CERTFORMAT_NONE || \
messageValue >= CRYPT_CERTFORMAT_LAST )
return( CRYPT_ARGERROR_VALUE );
/* Find the appropriate ACL for this export type */
for( i = 0; formatPseudoACL[ i ].attribute != messageValue &&
formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE && \
i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT );
i++ );
ENSURES( i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ) );
ENSURES( formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE );
/* The easiest way to handle this check is to use an ACL, treating the
format type as a pseudo-attribute type */
formatACL = ( ATTRIBUTE_ACL * ) &formatPseudoACL[ i ];
POST( formatACL->attribute == messageValue );
return( preDispatchCheckAttributeAccess( objectHandle,
isInternalMessage( message ) ? \
IMESSAGE_GETATTRIBUTE_S : MESSAGE_GETATTRIBUTE_S,
messageDataPtr, messageValue, formatACL ) );
}
/* It's data being pushed or popped, make sure that it's a valid data
quantity */
int preDispatchCheckData( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue, /* Unused */
const void *dummy )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
const MESSAGE_DATA *msgData = messageDataPtr;
/* Precondition */
PRE( isValidObject( objectHandle ) );
PRE( isValidMessage( localMessage ) );
PRE( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );
PRE( messageValue == 0 );
/* Make sure that it's either a flush (buffer = NULL, length = 0)
or valid data */
if( msgData->data == NULL )
{
if( localMessage != MESSAGE_ENV_PUSHDATA )
return( CRYPT_ARGERROR_STR1 );
if( msgData->length != 0 )
return( CRYPT_ARGERROR_NUM1 );
}
else
{
if( msgData->length <= 0 )
return( CRYPT_ARGERROR_NUM1 );
if( !isReadPtr( msgData->data, msgData->length ) )
return( CRYPT_ARGERROR_STR1 );
}
/* Postcondition: It's a flush or it's valid data */
POST( ( localMessage == MESSAGE_ENV_PUSHDATA && \
msgData->data == NULL && msgData->length == 0 ) || \
( msgData->data != NULL && msgData->length > 0 ) );
return( CRYPT_OK );
}
/* We're creating a new object, make sure that the create parameters are
valid and set the new object's owner to the owner of the object that it's
being created through */
int preDispatchCheckCreate( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const OBJECT_INFO *objectTable = krnlData->objectTable;
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
cons
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -