📄 msg_acl.c
字号:
MKACP_S_NONE() } },
/* Certificate object */
{ OBJECT_TYPE_CERTIFICATE,
{ MKACP_N( CRYPT_CERTTYPE_NONE + 1, CRYPT_CERTTYPE_LAST - 1 ),
MKACP_N( 0, 0 ),
MKACP_S_NONE(),
MKACP_S_NONE() } },
/* Device object */
{ OBJECT_TYPE_DEVICE,
{ MKACP_N( CRYPT_DEVICE_NONE + 1, CRYPT_DEVICE_LAST - 1 ),
MKACP_N( 0, 0 ),
MKACP_S_NONE(), /* See exception list */
MKACP_S_NONE() },
/* Exceptions: PKCS #11 and CryptoAPI devices have the device name as
the first string parameter */
{ CRYPT_DEVICE_PKCS11, CRYPT_DEVICE_CRYPTOAPI }, &deviceSpecialACL },
/* Session object */
{ OBJECT_TYPE_SESSION,
{ MKACP_N( CRYPT_SESSION_NONE + 1, CRYPT_SESSION_LAST - 1 ),
MKACP_N( 0, 0 ),
MKACP_S_NONE(),
MKACP_S_NONE() } },
/* User object */
{ OBJECT_TYPE_USER,
{ MKACP_N( CRYPT_USER_NONE + 1, CRYPT_USER_LAST - 1 ),
MKACP_N( 0, 0 ),
MKACP_S( MIN_NAME_LENGTH,
CRYPT_MAX_TEXTSIZE ), /* User name */
MKACP_S( MIN_NAME_LENGTH,
CRYPT_MAX_TEXTSIZE ) } }, /* User password */
{ OBJECT_TYPE_NONE, { { 0 } } },
{ OBJECT_TYPE_NONE, { { 0 } } }
};
/* Create-object-indirect ACLs */
static const CREATE_ACL FAR_BSS certSpecialACL = {
OBJECT_TYPE_CERTIFICATE,
/* PKCS #7/CMS certificate collections must include a identifier for
the leaf certificate in the collection, to allow the cert-import
code to pick and assemble the required certs into a chain */
{ MKACP_N( CRYPT_ICERTTYPE_CMS_CERTSET,
CRYPT_ICERTTYPE_CMS_CERTSET ),/* Cert.type hint */
MKACP_N( CRYPT_IKEYID_KEYID,
CRYPT_IKEYID_ISSUERANDSERIALNUMBER ),/* Key ID type */
MKACP_S( 16, MAX_INTLENGTH - 1 ), /* Cert.object data */
MKACP_S( 3, MAX_INTLENGTH - 1 ) } /* Key ID */
};
static const CREATE_ACL FAR_BSS createObjectIndirectACL[] = {
/* Certificate object instantiated from encoded data */
{ OBJECT_TYPE_CERTIFICATE,
{ MKACP_N( CRYPT_CERTTYPE_NONE,
CRYPT_CERTTYPE_LAST - 1 ), /* Cert.type hint (may be _NONE) */
MKACP_N( 0, 0 ), /* See exception list */
MKACP_S( 16, MAX_INTLENGTH - 1 ), /* Cert.object data */
MKACP_S_NONE() }, /* See exception list */
/* Exception: CMS certificate-set objects have a key ID type as the
second integer argument and a key ID as the second string
argument */
{ CRYPT_ICERTTYPE_CMS_CERTSET }, &certSpecialACL },
{ OBJECT_TYPE_NONE, { { 0 } } },
{ OBJECT_TYPE_NONE, { { 0 } } }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Check whether a numeric value falls within a range */
CHECK_RETVAL \
static BOOLEAN checkNumericRange( const int value, const int lowRange,
const int highRange )
{
/* Precondition: The range values are either both negative or both
positive. This is needed for the range comparison to work */
PRE( ( lowRange < 0 && highRange < 0 ) || \
( lowRange >= 0 && highRange >= 0 && lowRange <= highRange ) );
/* Check whether the value is within the allowed range. Since some
values can be negative (e.g. cursor movement codes) we have to
reverse the range check for negative values */
if( lowRange >= 0 )
{
/* Positive, it's a standard comparison */
if( value >= lowRange && value <= highRange )
return( TRUE );
}
else
{
PRE( highRange <= lowRange );
/* Negative, reverse the comparison */
if( value >= highRange && value <= lowRange )
return( TRUE );
}
return( FALSE );
}
/* Check whether a numeric value falls within a special-case range type */
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static BOOLEAN checkAttributeRangeSpecial( const RANGEVAL_TYPE rangeType,
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 < FAILSAFE_ITERATIONS_SMALL; i++ )
{
INV( i < 5 );
if( value == allowedValuesInfo[ i ] )
return( TRUE );
}
ENSURES( i < FAILSAFE_ITERATIONS_SMALL );
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 < FAILSAFE_ITERATIONS_SMALL; i++ )
{
INV( i < 5 );
if( checkNumericRange( value, allowedValuesInfo[ i ].lowRange,
allowedValuesInfo[ i ].highRange ) )
return( TRUE );
}
ENSURES( i < FAILSAFE_ITERATIONS_SMALL );
return( FALSE );
}
retIntError_Boolean();
}
/* 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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static BOOLEAN checkAttributeRangeWidechar( const void *value,
const int valueLength,
const int minLength,
const int maxLength )
{
#ifdef USE_WIDECHARS
const wchar_t *wcString = value;
#endif /* USE_WIDECHARS */
PRE( isReadPtr( value, valueLength ) );
PRE( minLength >= 0 && maxLength >= 0 && minLength <= maxLength );
#ifdef USE_WIDECHARS
/* 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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int checkActionPermitted( const OBJECT_INFO *objectInfoPtr,
const MESSAGE_TYPE message )
{
const MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
int requiredLevel, actualLevel;
PRE( isReadPtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );
PRE( isValidMessage( localMessage ) );
/* 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( isInternalMessage( message ) )
{
/* 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 */
CHECK_RETVAL \
static int findCheckACL( const int messageValue,
const OBJECT_TYPE objectType,
OUT_OPT_PTR const CHECK_ACL **checkACLptr,
OUT_OPT_PTR const CHECK_ALT_ACL **checkAltACLptr )
{
const CHECK_ACL *checkACL = NULL;
const CHECK_ALT_ACL *checkAltACL;
/* Precondition: It's a valid check message type */
PRE( messageValue > MESSAGE_CHECK_NONE && \
messageValue < MESSAGE_CHECK_LAST );
PRE( checkACLptr == NULL || \
isReadPtr( checkACLptr, sizeof( CHECK_ACL * ) ) );
PRE( checkAltACLptr == NULL || \
isReadPtr( checkAltACLptr, sizeof( CHECK_ALT_ACL * ) ) );
/* 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 ];
ENSURES( checkACL != NULL );
/* 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 < FAILSAFE_ITERATIONS_MED; i++ );
ENSURES( i < FAILSAFE_ITERATIONS_MED );
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 ];
ENSURES( checkACL != NULL );
}
/* 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;
PRE( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
/* Perform a consistency check on the compare ACL */
for( i = 0; compareACLTbl[ i ].compareType != MESSAGE_COMPARE_NONE && \
i < FAILSAFE_ARRAYSIZE( compareACLTbl, COMPARE_ACL ); i++ )
{
const COMPARE_ACL *compareACL = &compareACLTbl[ i ];
ENSURES( compareACL->compareType > MESSAGE_COMPARE_NONE && \
compareACL->compareType < MESSAGE_COMPARE_LAST && \
compareACL->compareType == i + 1 );
if( ( compareACL->objectACL.subTypeA & ~( SUBTYPE_CLASS_A | \
ST_CTX_ANY | ST_CERT_ANY ) ) || \
compareACL->objectACL.subTypeB != ST_NONE )
retIntError();
ENSURES( ( compareACL->objectACL.flags == 0 ) || \
( compareACL->objectACL.flags == ACL_FLAG_HIGH_STATE ) );
if( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_STRING )
{
ENSURES( paramInfo( compareACL, 0 ).lowRange >= 2 && \
paramInfo( compareACL, 0 ).lowRange <= \
paramInfo( compareACL, 0 ).highRange && \
paramInfo( compareACL, 0 ).highRange <= MAX_ATTRIBUTE_SIZE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -