📄 msg_acl.c
字号:
/****************************************************************************
* *
* Message ACLs Handlers *
* Copyright Peter Gutmann 1997-2005 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "acl.h"
#include "kernel.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "acl.h"
#include "kernel.h"
#else
#include "crypt.h"
#include "kernel/acl.h"
#include "kernel/kernel.h"
#endif /* Compiler-specific includes */
/* A pointer to the kernel data block */
static KERNEL_DATA *krnlData = NULL;
/****************************************************************************
* *
* Message ACLs *
* *
****************************************************************************/
/* Compare ACL for compare messages */
static const FAR_BSS COMPARE_ACL compareACLTbl[] = {
/* Hash/MAC value */
{ MESSAGE_COMPARE_HASH,
MK_CMPACL_S( ST_CTX_HASH | ST_CTX_MAC,
16, CRYPT_MAX_HASHSIZE ) },
/* PKC keyID */
{ MESSAGE_COMPARE_KEYID,
MK_CMPACL_S( ST_CTX_PKC,
2, 128 ) },
/* PGP keyID */
{ MESSAGE_COMPARE_KEYID_PGP,
MK_CMPACL_S( ST_CTX_PKC,
PGP_KEYID_SIZE, PGP_KEYID_SIZE ) },
/* OpenPGP keyID */
{ MESSAGE_COMPARE_KEYID_OPENPGP,
MK_CMPACL_S( ST_CTX_PKC,
PGP_KEYID_SIZE, PGP_KEYID_SIZE ) },
/* X.509 subject DN */
{ MESSAGE_COMPARE_SUBJECT,
MK_CMPACL_S( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN,
2, MAX_ATTRIBUTE_SIZE ) },
/* PKCS #7 issuerAndSerialNumber */
{ MESSAGE_COMPARE_ISSUERANDSERIALNUMBER,
MK_CMPACL_S( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN,
2, MAX_ATTRIBUTE_SIZE ) },
/* Cert SHA-1 fingerprint */
{ MESSAGE_COMPARE_FINGERPRINT,
MK_CMPACL_S( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN,
20, 20 ) },
/* Certificate object */
{ MESSAGE_COMPARE_CERTOBJ,
MK_CMPACL_O( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN,
ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ) },
/* End-of-ACL marker */
{ MESSAGE_COMPARE_NONE,
MK_CMPACL_END() }
};
/* Check ACL for check messages */
#define PUBKEY_CERT_OBJECT ( ST_CERT_CERT | ST_CERT_ATTRCERT | \
ST_CERT_CERTCHAIN | ST_CERT_CERTREQ | \
ST_CERT_REQ_CERT )
#define PUBKEY_KEYSET_OBJECT ( ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | \
ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | \
ST_KEYSET_HTTP | ST_KEYSET_LDAP | \
ST_DEV_FORT | ST_DEV_P11 | ST_DEV_CAPI )
#define PRIVKEY_KEYSET_OBJECT ( ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | \
ST_DEV_FORT | ST_DEV_P11 | ST_DEV_CAPI )
static const FAR_BSS CHECK_ALT_ACL checkCAACLTbl[] = {
/* The CA capability is spread across certs (the CA flag)
and contexts (the signing capability), which requires a two-phase
check. First we check the primary object, and then we check the
secondary one. Since the primary object has a dependent object but
the secondary one doesn't, we have to change the check type that we
perform on the secondary to reflect this. The checking performed is
therefore:
Type Target Object Action Dep.Obj. Fded chk
---- ------ ------ ------ ------- --------
Privkey + CA cert Context PKC SIGN Cert CACERT
Cert + pubkey Cert Cert SIGCHECK PKC SIGCHECK
In theory we'd need to perform some sort of generic sign-or-sigcheck
check for the case where the cert is the primary object, but since the
cert + context combination can only occur for public-key contexts it's
safe to check for a SIGCHECK capability. Similarly, when the context
is the primary object it's always a private key, so we can check for a
SIGN capability */
{ OBJECT_TYPE_CONTEXT, MESSAGE_CHECK_PKC_SIGN,
MK_CHKACL_ALT( OBJECT_TYPE_CERTIFICATE, ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN,
MESSAGE_CHECK_CACERT ) },
{ OBJECT_TYPE_CERTIFICATE, MESSAGE_CHECK_PKC_SIGCHECK,
MK_CHKACL_ALT( OBJECT_TYPE_CONTEXT, ST_CTX_PKC,
MESSAGE_CHECK_PKC_SIGCHECK ) },
/* End-of-ACL marker */
{ OBJECT_TYPE_NONE,
MK_CHKACL_ALT_END() }
};
static const FAR_BSS CHECK_ACL checkACLTbl[] = {
/* PKC actions. These get somewhat complex to check because the primary
message target may be a context or cert object with an associated
public key, so we have to allow both object types */
{ MESSAGE_CHECK_PKC, /* Public or private key context */
MK_CHKACL( MESSAGE_NONE,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_PRIVATE, /* Private key context */
MK_CHKACL( MESSAGE_NONE,
ST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN ) },
{ MESSAGE_CHECK_PKC_ENCRYPT, /* Public encryption context */
MK_CHKACL( MESSAGE_CTX_ENCRYPT,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_DECRYPT, /* Private decryption context */
MK_CHKACL( MESSAGE_CTX_DECRYPT,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_SIGCHECK, /* Public signature check context */
MK_CHKACL( MESSAGE_CTX_SIGCHECK,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_SIGN, /* Private signature context */
MK_CHKACL( MESSAGE_CTX_SIGN,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_KA_EXPORT, /* Key agreement - export context */
MK_CHKACL( MESSAGE_NONE,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
{ MESSAGE_CHECK_PKC_KA_IMPORT, /* Key agreement - import context */
MK_CHKACL( MESSAGE_NONE,
ST_CTX_PKC | PUBKEY_CERT_OBJECT ) },
/* Conventional encryption/hash/MAC actions */
{ MESSAGE_CHECK_CRYPT, /* Conventional encryption capability */
MK_CHKACL( MESSAGE_CTX_ENCRYPT,
ST_CTX_CONV ) },
{ MESSAGE_CHECK_HASH, /* Hash capability */
MK_CHKACL( MESSAGE_CTX_HASH,
ST_CTX_HASH ) },
{ MESSAGE_CHECK_MAC, /* MAC capability */
MK_CHKACL( MESSAGE_CTX_HASH,
ST_CTX_MAC ) },
/* Checks that an object is ready to be initialised to perform this
operation */
{ MESSAGE_CHECK_CRYPT_READY, /* Ready for init for conv.encr.*/
MK_CHKACL_EX( MESSAGE_CTX_ENCRYPT,
ST_CTX_CONV, ACL_FLAG_LOW_STATE ) },
{ MESSAGE_CHECK_MAC_READY, /* Ready for init for MAC */
MK_CHKACL_EX( MESSAGE_CTX_HASH,
ST_CTX_MAC, ACL_FLAG_LOW_STATE ) },
{ MESSAGE_CHECK_KEYGEN_READY, /* Ready for init key generation */
MK_CHKACL_EX( MESSAGE_CTX_GENKEY,
ST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ACL_FLAG_LOW_STATE ) },
/* Checks on purely passive container objects that constrain action
objects (for example a cert being attached to a context) for which
the state isn't important in this instance. Usually we check to make
sure that the cert is in the high state, but when a cert is being
created/imported it may not be in the high state yet at the time the
check is being carried out.
In addition to certs the message can be sent to a keyset to check
whether it contains keys capable of performing the required action */
{ MESSAGE_CHECK_PKC_ENCRYPT_AVAIL, /* Encryption available */
MK_CHKACL_EX( MESSAGE_CTX_ENCRYPT,
PUBKEY_CERT_OBJECT | PUBKEY_KEYSET_OBJECT,
ACL_FLAG_ANY_STATE ) },
{ MESSAGE_CHECK_PKC_DECRYPT_AVAIL, /* Decryption available */
MK_CHKACL_EX( MESSAGE_CTX_DECRYPT,
PUBKEY_CERT_OBJECT | PRIVKEY_KEYSET_OBJECT,
ACL_FLAG_ANY_STATE ) },
{ MESSAGE_CHECK_PKC_SIGCHECK_AVAIL, /* Signature check available */
MK_CHKACL_EX( MESSAGE_CTX_SIGCHECK,
PUBKEY_CERT_OBJECT | PUBKEY_KEYSET_OBJECT,
ACL_FLAG_ANY_STATE ) },
{ MESSAGE_CHECK_PKC_SIGN_AVAIL, /* Signature available */
MK_CHKACL_EX( MESSAGE_CTX_SIGN,
PUBKEY_CERT_OBJECT | PRIVKEY_KEYSET_OBJECT,
ACL_FLAG_ANY_STATE ) },
{ MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL,/* Key agreement - export available */
MK_CHKACL_EX( MESSAGE_NONE,
PUBKEY_CERT_OBJECT, ACL_FLAG_ANY_STATE ) },
{ MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL,/* Key agreement - import available */
MK_CHKACL_EX( MESSAGE_NONE,
PUBKEY_CERT_OBJECT, ACL_FLAG_ANY_STATE ) },
/* Misc.actions. The CA capability is spread across certs (the CA flag)
and contexts (the signing capability), which requires a two-phase
check specified in a sub-ACL. The CA-cert check is never applied
directly, but is the second part of the two-phase check performed for
the CA capability */
{ MESSAGE_CHECK_CA, /* Cert signing capability */
MK_CHKACL_EXT( MESSAGE_NONE, ST_NONE, checkCAACLTbl ) },
{ MESSAGE_CHECK_CACERT, /* CA cert, part two of CHECK_CA */
MK_CHKACL( MESSAGE_CHECK_NONE,
ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ) },
/* End-of-ACL marker */
{ MESSAGE_CHECK_NONE,
MK_CHKACL_END() }
};
/* When we export a cert the easiest way to handle the export check is via
a pseudo-ACL that's checked via the standard attribute ACL-checking
function. The following ACL handles cert exports */
static const FAR_BSS ATTRIBUTE_ACL_ALT formatPseudoACL[] = {
/* Encoded cert data */
MKACL_S_ALT(
CRYPT_CERTFORMAT_CERTIFICATE,
ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \
ST_CERT_OCSP_RESP, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* Encoded cert.chain */
MKACL_S_ALT(
CRYPT_CERTFORMAT_CERTCHAIN,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* Base64-encoded certificate */
MKACL_S_ALT(
CRYPT_CERTFORMAT_TEXT_CERTIFICATE,
ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* Base64-encoded cert.chain */
MKACL_S_ALT(
CRYPT_CERTFORMAT_TEXT_CERTCHAIN,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* XML-encoded certificate */
MKACL_S_ALT(
CRYPT_CERTFORMAT_XML_CERTIFICATE,
ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* XML-encoded cert.chain */
MKACL_S_ALT(
CRYPT_CERTFORMAT_XML_CERTCHAIN,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* SET OF cert in chain */
MKACL_S_ALT(
CRYPT_ICERTFORMAT_CERTSET,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_INT_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),
/* SEQUENCE OF cert in chain */
MKACL_S_ALT(
CRYPT_ICERTFORMAT_CERTSEQUENCE,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_INT_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),
/* SSL certificate chain */
MKACL_S_ALT(
CRYPT_ICERTFORMAT_SSL_CERTCHAIN,
ST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ACCESS_INT_Rxx_xxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),
/* Encoded non-signed object data. We allow this attribute to be read
for objects in the high as well as the low state even though in
theory it's only present for low (non-signed) objects because the
object can be in the high state if it was imported from its external
encoded form */
MKACL_S_ALT(
CRYPT_ICERTFORMAT_DATA,
ST_CERT_CMSATTR | ST_CERT_REQ_REV | ST_CERT_RTCS_REQ | \
ST_CERT_RTCS_RESP | ST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP | \
ST_CERT_PKIUSER, ST_NONE, ACCESS_INT_Rxx_Rxx,
ROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),
/* End-of-ACL marker */
MKACL_S_ALT(
CRYPT_CERTFORMAT_NONE, ST_NONE, ST_NONE, ACCESS_xxx_xxx,
ROUTE( OBJECT_TYPE_NONE ), RANGE( 0, 0 ) ),
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Check whether a numeric value falls within a range */
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 ) );
/* 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 */
static BOOLEAN checkAttributeRangeSpecial( const RANGEVAL_TYPE rangeType,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -