映射

2016-12-05 66 views
0

(注:IMO的問題主要是關於WinAPI的和DACL,而不是關於CNG,所以請繼續閱讀!)映射

我目前正試圖修改的樣品CNG密鑰微軟的加密提供程序開發工具包的存儲提供商以這種方式,它不會而不是將密鑰存儲在單個文件中。但是,我遇到了可以分配給私鑰的安全描述符。

在Windows Server Management Console的證書管理單元中,可以管理證書的私鑰,即密鑰的所有者,DACL和SACL可以更改,從而導致NCryptSetProperty調用的安全描述符爲參數。對於DACL,管理單元僅允許/拒絕「完全控制」或「讀取」,這會導致GENERIC_ALL或GENERIC_READ位置於ACE的訪問掩碼中。

據我所知,這些通用位需要映射到特定於應用程序的權限 - 否則AccessCheck將無法工作。但是我真的需要手工做這個嗎?

CreatePrivateObjectSecurity + SetPrivateObjectSecurity並不總是有效,因爲CreatePrivateObjectSecurity對輸入安全描述符中的所有者和組非常挑剔。而且,當應用映射時,通用位在訪問掩碼中被清除,導致管理單元顯示錯誤的設置(正如我所說的,管理單元在顯示當前權限時僅考慮GA和GR位)。

看來我錯過了一些作品在這裏...

回答

0

CPSetProvParam實施PP_KEYSET_SEC_DESCR你有SECURITY_DESCRIPTOR的地址,你需要以某種方式應用到你的私人密鑰存儲。如果您的存儲基於文件或註冊表項(原則上是任何內核對象類型,但此處還可以使用什麼內容?),則需要使用文件或密鑰HANDLE(必須具有WRITE_DAC訪問權限)調用SetKernelObjectSecurity(可能如果你說有多個文件存儲單鍵)。在內核中對對象的GENERIC訪問將被自動轉換爲對象特定的權限。

如果存儲的實現不是直接根據某些內核對象,但自定義 - 你需要自己在這一點上轉換通用接入(0xF0000000面膜)以特定的訪問權限(0x0000FFFF面罩)

__________________編輯____________________

經過更多檢查後,我發現供應商不僅必須將CPSetProvParam中的通用轉換爲特定訪問,還要將其轉換爲CPGetProvParam中的特定通用,儘管這並不直接指向文檔。

這是MS_ENHANCED_PROV(在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_READFILE_WRITE_DATAGENERIC_ALL(這正是算法) - 但是你可以看看自己的rsaenh.CheckAndChangeAccessMask代碼(名稱來自pdb符號)

rsaenh首先通過GetNamedSecurityInfoWSE_FILE_OBJECT)從文件中獲得SD,然後將其轉換爲通用配音SS。 這裏調用圖及修改DACL(在右上角的紅色,修改ACCESS_MASK) enter image description here

+0

正如我上面寫的:我不把所接收的安全描述符文件或任何其他內核對象,但需要在內部存儲它。實際上,我嘗試將所有關鍵數據(公鑰和私鑰以及屬性!)存儲在數據庫中。因此,只有* PrivateObjectSecurity函數是可能的 - 但不起作用(s.a.)。 – dannyM

+0

僅將GENERIC權限映射到特定權限**也是不正確的,因爲當CPGetProvParam/NCryptGetPropertyFn應該返回SD時,我需要再次將其轉換回來。原因是Windows Server Management Console **只識別GENERIC權限。似乎這裏有一些缺失的功能... – dannyM

+0

@dannyM - 對不起,我錯了 - 編輯自我答案。 CP確實需要在'CPGetProvParam'中轉換爲通用掩碼 - 我在編輯的答案中描述了這一點 – RbMm