📄 msg_acl.c
字号:
const void *rangeInfo,
const int value )
{
/* Precondition: The range checking information is valid */
PRE( rangeType > RANGEVAL_NONE && rangeType < RANGEVAL_LAST );
PRE( rangeInfo != NULL );
/* RANGEVAL_ALLOWEDVALUES contains an int [] of permitted values,
terminated by CRYPT_ERROR */
if( rangeType == RANGEVAL_ALLOWEDVALUES )
{
const int *allowedValuesInfo = rangeInfo;
int i;
for( i = 0; allowedValuesInfo[ i ] != CRYPT_ERROR; i++ )
{
INV( i < 5 );
if( value == allowedValuesInfo[ i ] )
return( TRUE );
}
return( FALSE );
}
/* RANGEVAL_SUBRANGES contains a SUBRANGE [] of allowed subranges,
terminated by { CRYPT_ERROR, CRYPT_ERROR } */
if( rangeType == RANGEVAL_SUBRANGES )
{
const RANGE_SUBRANGE_TYPE *allowedValuesInfo = rangeInfo;
int i;
for( i = 0; allowedValuesInfo[ i ].lowRange != CRYPT_ERROR; i++ )
{
INV( i < 5 );
if( checkNumericRange( value, allowedValuesInfo[ i ].lowRange,
allowedValuesInfo[ i ].highRange ) )
return( TRUE );
}
return( FALSE );
}
assert( NOTREACHED );
return( FALSE ); /* Get rid of compiler warning */
}
/* Check whether a string value falls within the given limits, with special
handling for widechar strings. This sort of thing really shouldn't be
in the kernel, but not having it here makes correct string length range
checking difficult */
static BOOLEAN checkAttributeRangeWidechar( const void *value,
const int valueLength,
const int minLength,
const int maxLength )
{
#ifdef USE_WIDECHARS
const wchar_t *wcString = value;
/* If it's not a multiple of wchar_t in size or smaller than a
wchar_t, it can't be a widechar string */
if( ( valueLength % WCSIZE ) || ( valueLength < WCSIZE ) )
return( ( valueLength < minLength || valueLength > maxLength ) ? \
FALSE : TRUE );
/* If wchar_t is > 16 bits and the bits above 16 are all zero, it's
definitely a widechar string */
#if INT_MAX > 0xFFFFL
if( WCSIZE > 2 && *wcString < 0xFFFF )
return( ( valueLength < ( minLength * WCSIZE ) || \
valueLength > ( maxLength * WCSIZE ) ) ? \
FALSE : TRUE );
#endif /* > 16-bit machines */
/* Now it gets tricky. The only thing that we can still safely check
for is something that's been bloated out into widechars from ASCII */
if( ( valueLength > WCSIZE * 2 ) && \
( wcString[ 0 ] < 0xFF && wcString[ 1 ] < 0xFF ) )
return( ( valueLength < ( minLength * WCSIZE ) || \
valueLength > ( maxLength * WCSIZE ) ) ? \
FALSE : TRUE );
#endif /* USE_WIDECHARS */
/* It's not a widechar string or we can't handle these, perform a
straight range check */
return( ( valueLength < minLength || valueLength > maxLength ) ? \
FALSE : TRUE );
}
/* Check whether a given action is permitted for an object */
static int checkActionPermitted( const OBJECT_INFO *objectInfoPtr,
const MESSAGE_TYPE message )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
int requiredLevel, actualLevel;
/* Determine the required level for access. Like protection rings, the
lower the value, the higher the privilege level. Level 3 is all-access,
level 2 is internal-access only, level 1 is no access, and level 0 is
not-available (e.g. encryption for hash contexts) */
requiredLevel = objectInfoPtr->actionFlags & \
MK_ACTION_PERM( localMessage, ACTION_PERM_MASK );
/* Make sure that the action is enabled at the required level */
if( message & MESSAGE_FLAG_INTERNAL )
/* It's an internal message, the minimal permissions will do */
actualLevel = MK_ACTION_PERM( localMessage, ACTION_PERM_NONE_EXTERNAL );
else
/* It's an external message, we need full permissions for access */
actualLevel = MK_ACTION_PERM( localMessage, ACTION_PERM_ALL );
if( requiredLevel < actualLevel )
{
/* The required level is less than the actual level (e.g. level 2
access attempted from level 3), return more detailed information
about the problem */
return( ( ( requiredLevel >> ACTION_PERM_SHIFT( localMessage ) ) == ACTION_PERM_NOTAVAIL ) ? \
CRYPT_ERROR_NOTAVAIL : CRYPT_ERROR_PERMISSION );
}
return( CRYPT_OK );
}
/* Find the appropriate check ACL for a given message type */
static int findCheckACL( const int messageValue,
const OBJECT_TYPE objectType,
const CHECK_ACL **checkACLptr,
const CHECK_ALT_ACL **checkAltACLptr )
{
const CHECK_ACL *checkACL;
const CHECK_ALT_ACL *checkAltACL;
/* Precondition: It's a valid check message type */
PRE( messageValue > MESSAGE_CHECK_NONE && \
messageValue < MESSAGE_CHECK_LAST );
/* Clear return values */
if( checkACLptr != NULL )
*checkACLptr = NULL;
if( checkAltACLptr != NULL )
*checkAltACLptr = NULL;
/* Find the appropriate ACL(s) for a given check type */
if( messageValue > MESSAGE_CHECK_NONE && \
messageValue < MESSAGE_CHECK_LAST )
checkACL = &checkACLTbl[ messageValue - 1 ];
if( checkACL == NULL )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* Inner precondition: We have the correct ACL */
PRE( checkACL->checkType == messageValue );
/* If there's a sub-ACL present, find the correct ACL for this object
type */
if( ( checkAltACL = checkACL->altACL ) != NULL )
{
int i;
for( i = 0; checkAltACL[ i ].object != CRYPT_OBJECT_NONE && \
checkAltACL[ i ].object != objectType; i++ );
if( checkAltACL[ i ].object == CRYPT_OBJECT_NONE )
return( CRYPT_ARGERROR_OBJECT );
checkAltACL = &checkAltACL[ i ];
if( checkAltACL->checkType > MESSAGE_CHECK_NONE && \
checkAltACL->checkType < MESSAGE_CHECK_LAST )
checkACL = &checkACLTbl[ checkAltACL->checkType - 1 ];
if( checkACL == NULL )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
}
/* Postcondition: There's a valid ACL present */
POST( isReadPtr( checkACL, sizeof( CHECK_ACL ) ) );
POST( checkACL->altACL == NULL || \
isReadPtr( checkAltACL, sizeof( CHECK_ALT_ACL ) ) );
if( checkACLptr != NULL )
*checkACLptr = checkACL;
if( checkAltACLptr != NULL )
*checkAltACLptr = checkAltACL;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
int initMessageACL( KERNEL_DATA *krnlDataPtr )
{
int i;
/* Perform a consistency check on the compare ACL */
for( i = 0; compareACLTbl[ i ].compareType != MESSAGE_COMPARE_NONE; i++ )
{
const COMPARE_ACL *compareACL = &compareACLTbl[ i ];
if( compareACL->compareType <= MESSAGE_COMPARE_NONE || \
compareACL->compareType >= MESSAGE_COMPARE_LAST || \
compareACL->compareType != i + 1 )
return( CRYPT_ERROR_FAILED );
if( ( compareACL->objectACL.subTypeA & ~( SUBTYPE_CLASS_A | \
ST_CTX_ANY | ST_CERT_ANY ) ) || \
compareACL->objectACL.subTypeB != ST_NONE )
return( CRYPT_ERROR_FAILED );
if( ( compareACL->objectACL.flags != 0 ) && \
( compareACL->objectACL.flags != ACL_FLAG_HIGH_STATE ) )
return( CRYPT_ERROR_FAILED );
if( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_STRING )
{
if( paramInfo( compareACL, 0 ).lowRange < 2 || \
paramInfo( compareACL, 0 ).lowRange > \
paramInfo( compareACL, 0 ).highRange || \
paramInfo( compareACL, 0 ).highRange > MAX_ATTRIBUTE_SIZE )
return( CRYPT_ERROR_FAILED );
}
else
{
if( paramInfo( compareACL, 0 ).valueType != PARAM_VALUE_OBJECT )
return( CRYPT_ERROR_FAILED );
if( ( paramInfo( compareACL, 0 ).subTypeA & ~( SUBTYPE_CLASS_A | \
ST_CERT_ANY ) ) || \
paramInfo( compareACL, 0 ).subTypeB != ST_NONE )
return( CRYPT_ERROR_FAILED );
}
}
/* Perform a consistency check on the check ACL */
for( i = 0; checkACLTbl[ i ].checkType != MESSAGE_CHECK_NONE; i++ )
{
const CHECK_ACL *checkACL = &checkACLTbl[ i ];
int j;
if( checkACL->checkType <= MESSAGE_CHECK_NONE || \
checkACL->checkType >= MESSAGE_CHECK_LAST || \
checkACL->checkType != i + 1 )
return( CRYPT_ERROR_FAILED );
if( checkACL->actionType != MESSAGE_NONE && \
( checkACL->actionType < MESSAGE_CTX_ENCRYPT || \
checkACL->actionType > MESSAGE_CRT_SIGCHECK ) )
return( CRYPT_ERROR_FAILED );
if( ( checkACL->objectACL.subTypeA & \
~( SUBTYPE_CLASS_A | ST_CTX_ANY | ST_CERT_ANY | \
ST_KEYSET_ANY | ST_DEV_ANY ) ) || \
checkACL->objectACL.subTypeB != ST_NONE )
return( CRYPT_ERROR_FAILED );
if( checkACL->objectACL.flags & ~ACL_FLAG_ANY_STATE )
return( CRYPT_ERROR_FAILED );
if( checkACL->altACL == NULL )
continue;
for( j = 0; checkACL->altACL[ j ].object != OBJECT_TYPE_NONE; j++ )
{
const CHECK_ALT_ACL *checkAltACL = &checkACL->altACL[ j ];
if( checkAltACL->object != OBJECT_TYPE_CONTEXT && \
checkAltACL->object != OBJECT_TYPE_CERTIFICATE )
return( CRYPT_ERROR_FAILED );
if( checkAltACL->checkType <= MESSAGE_CHECK_NONE || \
checkAltACL->checkType >= MESSAGE_CHECK_LAST )
return( CRYPT_ERROR_FAILED );
if( checkAltACL->depObject != OBJECT_TYPE_CONTEXT && \
checkAltACL->depObject != OBJECT_TYPE_CERTIFICATE )
return( CRYPT_ERROR_FAILED );
if( ( checkAltACL->depObjectACL.subTypeA & \
~( SUBTYPE_CLASS_A | ST_CTX_ANY | ST_CERT_ANY ) ) || \
checkAltACL->depObjectACL.subTypeB != ST_NONE )
return( CRYPT_ERROR_FAILED );
if( checkAltACL->depObjectACL.flags & ~ACL_FLAG_ANY_STATE )
return( CRYPT_ERROR_FAILED );
if( checkAltACL->fdCheckType <= MESSAGE_CHECK_NONE || \
checkAltACL->fdCheckType >= MESSAGE_CHECK_LAST )
return( CRYPT_ERROR_FAILED );
}
}
/* Perform a consistency check on the cert export pseudo-ACL */
for( i = 0; formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE; i++ )
{
const ATTRIBUTE_ACL_ALT *formatACL = &formatPseudoACL[ i ];
if( formatACL->attribute <= CRYPT_CERTTYPE_NONE || \
formatACL->attribute >= CRYPT_CERTTYPE_LAST )
return( CRYPT_ERROR_FAILED );
if( ( formatACL->subTypeA & ~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) || \
formatACL->subTypeB != ST_NONE )
return( CRYPT_ERROR_FAILED );
if( formatACL->attribute < CRYPT_CERTFORMAT_LAST_EXTERNAL )
{
if( formatACL->access != ACCESS_Rxx_xxx )
return( CRYPT_ERROR_FAILED );
}
else
{
if( formatACL->access != ACCESS_INT_Rxx_xxx && \
formatACL->access != ACCESS_INT_Rxx_Rxx )
return( CRYPT_ERROR_FAILED );
}
if( formatACL->valueType != ATTRIBUTE_VALUE_STRING || \
formatACL->lowRange < 16 || \
formatACL->lowRange >= formatACL->highRange || \
formatACL->highRange > 8192 || \
formatACL->extendedInfo != NULL )
return( CRYPT_ERROR_FAILED );
}
/* 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,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
/* Precondition */
PRE( isValidObject( objectHandle ) && \
objectHandle >= NO_SYSTEM_OBJECTS );
if( isValidObject( objectInfoPtr->dependentDevice ) )
/* Velisurmaaja */
decRefCount( objectInfoPtr->dependentDevice, 0, NULL, TRUE );
if( isValidObject( objectInfoPtr->dependentObject ) )
decRefCount( objectInfoPtr->dependentObject, 0, NULL, TRUE );
objectInfoPtr->flags |= OBJECT_FLAG_SIGNALLED;
/* Postcondition: The object is now in the destroyed state as far as
other objects are concerned */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -