📄 msg_acl.c
字号:
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,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const ATTRIBUTE_ACL *formatACL;
int i;
/* Precondition */
PRE( isValidObject( objectHandle ) );
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++ );
if( formatPseudoACL[ i ].attribute == CRYPT_CERTFORMAT_NONE )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
formatACL = ( ATTRIBUTE_ACL * ) &formatPseudoACL[ i ];
/* The easiest way to handle this check is to use an ACL, treating the
format type as a pseudo-attribute type */
POST( formatACL->attribute == messageValue );
return( preDispatchCheckAttributeAccess( objectHandle,
( message & MESSAGE_FLAG_INTERNAL ) ? \
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,
const void *dummy )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
const RESOURCE_DATA *msgData = messageDataPtr;
/* Precondition */
PRE( isValidObject( objectHandle ) );
PRE( isReadPtr( messageDataPtr, sizeof( RESOURCE_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, set its owner to the owner of the object
that it's being created through */
int preDispatchSetObjectOwner( const int objectHandle,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
const OBJECT_INFO *objectTable = krnlData->objectTable;
MESSAGE_CREATEOBJECT_INFO *createInfo = \
( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr;
/* Precondition */
PRE( fullObjectCheck( objectHandle, message ) && \
objectTable[ objectHandle ].type == OBJECT_TYPE_DEVICE );
PRE( messageDataPtr != NULL );
PRE( isValidType( messageValue ) );
PRE( createInfo->cryptOwner == CRYPT_ERROR );
/* Set the new object's owner to the owner of the object that it's being
created through. If it's being created through the system device
object (which has no owner), we set the owner to the default user
object */
if( objectHandle == SYSTEM_OBJECT_HANDLE )
createInfo->cryptOwner = DEFAULTUSER_OBJECT_HANDLE;
else
{
const int ownerObject = objectTable[ objectHandle ].owner;
/* Inner precondition: The owner is a valid user object */
PRE( isValidObject( ownerObject ) && \
objectTable[ ownerObject ].type == OBJECT_TYPE_USER );
createInfo->cryptOwner = ownerObject;
}
/* Postcondition: The new object's owner will be the user object it's
being created through or the default user if it's being done via the
system object */
POST( ( objectHandle == SYSTEM_OBJECT_HANDLE && \
createInfo->cryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
( objectHandle != SYSTEM_OBJECT_HANDLE && \
createInfo->cryptOwner == objectTable[ objectHandle ].owner ) );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Message Post-Dispatch Handlers *
* *
****************************************************************************/
/* If we're fetching or creating an object, it won't be visible to an
outside caller. If it's an external message, we have to make the object
externally visible before we return it */
int postDispatchMakeObjectExternal( const int dummy,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *auxInfo )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
const BOOLEAN isInternalMessage = \
( message & MESSAGE_FLAG_INTERNAL ) ? TRUE : FALSE;
CRYPT_HANDLE objectHandle;
int status;
/* Preconditions */
PRE( localMessage == MESSAGE_GETATTRIBUTE || \
localMessage == MESSAGE_DEV_CREATEOBJECT || \
localMessage == MESSAGE_DEV_CREATEOBJECT_INDIRECT || \
localMessage == MESSAGE_KEY_GETKEY || \
localMessage == MESSAGE_KEY_GETNEXTCERT || \
localMessage == MESSAGE_KEY_CERTMGMT );
PRE( messageDataPtr != NULL );
/* If it's an internal message, there are no problems with object
visibility. In addition most messages are internal, so performing
this check before anything else quickly weeds out the majority of
cases */
if( isInternalMessage )
return( CRYPT_OK );
switch( localMessage )
{
case MESSAGE_GETATTRIBUTE:
{
const ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;
/* Inner precondition: Since it's an external message, we must
be reading a standard attribute */
PRE( isAttribute( messageValue ) );
PRE( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) || \
attributeACL->attribute == messageValue );
/* If it's not an object attribute read, we're done */
if( attributeACL->valueType == ATTRIBUTE_VALUE_SPECIAL )
{
attributeACL = getSpecialRangeInfo( attributeACL );
POST( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );
}
if( attributeACL->valueType != ATTRIBUTE_VALUE_OBJECT )
return( CRYPT_OK );
/* Inner precondition: We're reading an object attribute and
sending the response to an external caller */
PRE( attributeACL->valueType == ATTRIBUTE_VALUE_OBJECT );
PRE( isValidObject( *( ( int * ) messageDataPtr ) ) );
PRE( !isInternalMessage );
objectHandle = *( ( int * ) messageDataPtr );
break;
}
case MESSAGE_DEV_CREATEOBJECT:
case MESSAGE_DEV_CREATEOBJECT_INDIRECT:
{
MESSAGE_CREATEOBJECT_INFO *createInfo = \
( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr;
PRE( isReadPtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
objectHandle = createInfo->cryptHandle;
break;
}
case MESSAGE_KEY_GETKEY:
case MESSAGE_KEY_GETNEXTCERT:
{
MESSAGE_KEYMGMT_INFO *getkeyInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
PRE( isReadPtr( getkeyInfo, sizeof( MESSAGE_KEYMGMT_INFO ) ) );
objectHandle = getkeyInfo->cryptHandle;
break;
}
case MESSAGE_KEY_CERTMGMT:
{
MESSAGE_CERTMGMT_INFO *certMgmtInfo = \
( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;
PRE( isReadPtr( certMgmtInfo, sizeof( MESSAGE_CERTMGMT_INFO ) ) );
/* If it's not a cert management action that can return an
object, there's no object to make visible */
if( messageValue != CRYPT_CERTACTION_ISSUE_CERT && \
messageValue != CRYPT_CERTACTION_CERT_CREATION && \
messageValue != CRYPT_CERTACTION_ISSUE_CRL )
return( CRYPT_OK );
/* If the caller has indicated that they're not interested in the
newly-created object, it won't be present so we can't make it
externally visible */
if( certMgmtInfo->cryptCert == CRYPT_UNUSED )
return( CRYPT_OK );
/* Inner precondition: It's an action that can return an object,
and there's an object present */
PRE( messageValue == CRYPT_CERTACTION_ISSUE_CERT || \
messageValue == CRYPT_CERTACTION_CERT_CREATION || \
messageValue == CRYPT_CERTACTION_ISSUE_CRL );
PRE( certMgmtInfo->cryptCert != CRYPT_UNUSED );
objectHandle = certMgmtInfo->cryptCert;
break;
}
default:
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
/* Postcondition: We've got a valid internal object to make externally
visible */
POST( isValidObject( objectHandle ) && \
isInternalObject( objectHandle ) );
/* Make the object externally visible. In theory we should make this
attribute read-only, but it's currently still needed in init.c (the
kernel self-test, which checks for internal vs. external
accessibility), keyex.c (to make PGP imported contexts visible),
sign.c (to make CMS signing attributes externally visible), and
cryptapi.c when creating objects (to make them externally visible)
and destroying objects (to make the appear destroyed if a dec-
refcount leaves it still active) */
status = krnlSendMessage( objectHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_INTERNAL );
if( cryptStatusError( status ) )
return( status );
/* Postcondition: The object is now externally visible */
POST( isValidObject( objectHandle ) && \
!isInternalObject( objectHandle ) );
return( CRYPT_OK );
}
/* If there's a dependent object with a given relationship to the controlling
object, forward the message. In practice the only dependencies are those
of PKC contexts paired with certs, for which a message sent to one (e.g. a
check message such as "is this suitable for signing?") needs to be
forwarded to the other */
int postDispatchForwardToDependentObject( const int objectHandle,
const MESSAGE_TYPE message,
const void *dummy1,
const int messageValue,
const void *dummy2 )
{
const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
const int dependentObject = objectInfoPtr->dependentObject;
const OBJECT_TYPE objectType = objectInfoPtr->type;
const OBJECT_TYPE dependentType = isValidObject( dependentObject ) ? \
krnlData->objectTable[ dependentObject ].type : CRYPT_ERROR;
const CHECK_ALT_ACL *checkAltACL;
MESSAGE_CHECK_TYPE localMessageValue = messageValue;
int status;
TEMP_VAR( const MESSAGE_TYPE localMessage = message & MESSAGE_MASK );
/* Precondition: It's an appropriate message type being forwarded to a
dependent object */
PRE( isValidObject( objectHandle ) );
PRE( localMessage == MESSAGE_CHECK );
PRE( messageValue > MESSAGE_CHECK_NONE && \
messageValue < MESSAGE_CHECK_LAST );
PRE( isValidObject( dependentObject ) || dependentObject == CRYPT_ERROR );
/* Find the ACL information for the message type */
status = findCheckACL( messageValue, objectInfoPtr->type, NU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -