(注意:IMO问题主要是关于WinAPI和DACL而不是关于CNG,所以请继续阅读!)
我目前正在尝试修改Microsoft的加密提供程序开发工具包的示例CNG密钥存储提供程序,以便不将密钥存储在单个文件中。但是,我遇到了可以分配给私钥的安全描述符。
在Windows Server Management Console的“证书管理单元”中,可以管理证书的私钥,即可以更改密钥的所有者,DACL和SACL,从而导致NCryptSetProperty调用带有安全描述符作为参数。对于DACL,管理单元仅允许允许/拒绝"完全控制"或"读取",这导致在ACE的访问掩码中设置GENERIC_ALL或GENERIC_READ位。
据我所知,这些通用位需要映射到特定于应用程序的权限 - 否则AccessCheck将无法正常工作。但我真的需要手工做这个吗???
CreatePrivateObjectSecurity + SetPrivateObjectSecurity并不总是有效,因为CreatePrivateObjectSecurity对输入安全描述符中的所有者和组非常挑剔。此外,当应用映射时,通用位在访问掩码中被清除,这导致管理单元显示错误的设置(正如我所说,管理单元在显示当前权限时仅考虑GA和GR位)。
似乎我在这里遗漏了一些东西......
答案 0 :(得分:0)
在您PP_KEYSET_SEC_DESCR
的{{1}}实施中,您获得了SECURITY_DESCRIPTOR
的地址,您需要以某种方式将其应用于您的私钥存储。如果您的存储基于文件或注册表项(原则上是任何内核对象类型,但还可以在这里使用?),您需要使用文件或密钥HANDLE
调用CPSetProvParam
(必须具有WRITE_DAC
访问权限(如果您说存储多个文件用于存储单个密钥,则可能是多次)。在内核GENERIC中,对象的访问权限将自动转换为对象特定的权限。
如果您的存储实现不是直接基于某个内核对象,而是自定义 - 此时您需要自己将GENERIC访问(0xF0000000
掩码)转换为特定的访问权限(0x0000FFFF
掩码)
__________________编辑____________________
经过更多检查后,我发现提供商不仅必须将通用转换为SetKernelObjectSecurity
中的特定访问权限,还必须在CPSetProvParam
中将特定转换为通用,尽管这不直接指向文档。
CPGetProvParam
(在rsaenh.dll
中实现)大致如此:
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);
}
}
所以FILE_READ_DATA
已转换为GENERIC_READ
而FILE_WRITE_DATA
转换为GENERIC_ALL
(这正是算法) - 但您可以查看rsaenh.CheckAndChangeAccessMask
的代码(来自pdb符号)
rsaenh
首先通过MS_ENHANCED_PROV
(SE_FILE_OBJECT
)从文件中获取SD,然后将其转换为特定于通用访问权限。
这里是调用图和修改后的DACL(在右上角,修改后的ACCESS_MASK为红色)
GetNamedSecurityInfoW