Mapping of access mask in DACL for CNG keys

扶醉桌前 提交于 2019-12-12 03:29:18

问题


(Note: IMO the question is mainly about WinAPI and DACL and not about CNG, so please read on!)

I'm currently trying to modify the sample CNG key storage provider of Microsoft's Cryptographic Provider Development Kit in such a way that it does not store the keys in single files. However, I'm in trouble with the security descriptors that can be assigned to the private keys.

In the Certificates Snap-in of the Windows Server Management Console, private keys of certificates can be managed, i.e. the owner, DACL and SACL of a key can be changed, which results in a NCryptSetProperty call with a security descriptor as parameter. For the DACL, the snap-in only allows to allow/deny "full control" or "read", which results in the GENERIC_ALL or GENERIC_READ bit to be set in the access mask of the ACE.

As I have learnt, these generic bits need to be mapped to application specific rights - otherwise AccessCheck will not work. But do I really need to do this by hand???

CreatePrivateObjectSecurity+SetPrivateObjectSecurity does not always work since CreatePrivateObjectSecurity is very picky about the owner and group in the input security descriptor. Moreover, when the mapping is applied, the generic bits are cleared in the access mask, which results in the snap-in showing wrong settings (as I said, the snap-in only considers the GA and GR bits when displaying current permissions).

Seems I'm missing some pieces here...


回答1:


in your CPSetProvParam implementation for PP_KEYSET_SEC_DESCR you got address of a SECURITY_DESCRIPTOR, which you need somehow apply to your private key storage. if your storage based on file(s) or registry key(s) ( in principle any kernel object type, but what more can be used here ?) you need call SetKernelObjectSecurity with file or key HANDLE (which must have WRITE_DAC access) (may be multiple time if you say have multiple files for store single key). in kernel GENERIC access to object will be auto converted to object specific rights.

if your implementation of storage not direct based on some kernel object, but custom - you need yourself at this point convert GENERIC access (0xF0000000 mask) to specific access rights (0x0000FFFF mask)

__________________ EDIT ____________________

after more check i found that provider must not only convert generic to specific access in CPSetProvParam but also convert specific to generic in CPGetProvParam despite this not directly point in documentation.

this is how MS_ENHANCED_PROV (implemented in rsaenh.dll) approximately do this:

void CheckAndChangeAccessMask(PSECURITY_DESCRIPTOR SecurityDescriptor)
{
    BOOL bDaclPresent, bDaclDefaulted;
    PACL Dacl;
    ACL_SIZE_INFORMATION asi;

    if (
        GetSecurityDescriptorDacl(SecurityDescriptor, &bDaclPresent, &Dacl, &bDaclDefaulted) 
        &&
        bDaclPresent
        &&
        Dacl
        &&
        GetAclInformation(Dacl, &asi, sizeof(asi), AclSizeInformation)
        &&
        asi.AceCount
        )
    {

        union{
            PVOID pAce;
            PACE_HEADER pah;
            PACCESS_ALLOWED_ACE paa;
        };

        do 
        {
            if (GetAce(Dacl, --asi.AceCount, &pAce))
            {
                switch (pah->AceType)
                {
                case ACCESS_ALLOWED_ACE_TYPE:
                case ACCESS_DENIED_ACE_TYPE:
                    ACCESS_MASK Mask = paa->Mask, Gen_Mask = 0;

                    if (Mask & FILE_READ_DATA)
                    {
                        Gen_Mask |= GENERIC_READ;
                    }

                    if (Mask & FILE_WRITE_DATA)
                    {
                        Gen_Mask |= GENERIC_ALL;
                    }

                    paa->Mask = Gen_Mask;
                    break;
                }
            }
        } while (asi.AceCount);
    }
}

so FILE_READ_DATA converted to GENERIC_READ and FILE_WRITE_DATA to GENERIC_ALL (this is exactly algorithm) - however you can look yourself code of rsaenh.CheckAndChangeAccessMask (name from pdb symbols)

rsaenh first get SD from file by GetNamedSecurityInfoW (SE_FILE_OBJECT) and then convert it specific to generic access. here the call graph and modified DACL (in the top-right, modified ACCESS_MASK in red color)



来源:https://stackoverflow.com/questions/40984950/mapping-of-access-mask-in-dacl-for-cng-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!