Nt/2000/xp平台下的存储控制模型(Access Control Model) (二)

类别:VC语言 点击:0 评论:0 推荐:

Nt/2000/xp平台下的存储控制模型(Access Control Model)

By 李智勇 2003-7-18 16:28

 

(二)

 

       在涉及其他之前,我们先来看一段可能会出问题的程序。

   if(ERROR_SUCCESS !=RegCreateKeyExW(HKEY_LOCAL_MACHINE,L"Software\\007h",0,NULL,

  REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hkey,NULL))

{return FALSE;}

 

  if(ERROR_SUCCESS !=RegSetValueEx(hkey,lpItem,0,REG_SZ,(LPBYTE)”90”,2))

{

RegCloseKey(hkey); return FALSE;

}

RegCloseKey(hkey);    

(程序1)

 

  这段程序很简单,就是打开注册表,并写值。在98或者管理员权限下基本上不会出现什么问题。但存在什么样的潜在问题呢?我们做这样的假设,这段代码运行在用户态的打印机驱动程序的某个DDI接口中,比如DrvEnablePDEV。这样当不同用户进行打印时这段代码都需要被调用。于是问题出现了,在其他用户权限下,有可能打开或者设置值失败。GetLastError()返回5(Access denied)。原因是当你建立相关子键"Software\\007h”时使用了NULL做为安全权限(lpSecurityAttributes)地参数。使用NULL意味着从父键直接继承DACL,而在这个DACL中一旦不包含对你所使用的帐户赋予权限的ACE,你对注册表的相关操作必然失败。(枚举"Software”的各个ACE的代码见后,但读懂ACE字符串有点难度,简单来说就是Built-in users只有对"Software”进行读的权利,所以Users组和Guest组的用户将无法写你所建立的子键”007h”,因为用上述方式建立的子键的DACL继承自"Software”)。为避免这种情况,建立注册表键时要明确制定安全权限。代码如下(from msdn 有更改):

这段代码建立一个管理员可以进行任何操作,任何用户都可以读写的子键,程序和相关结构的说明将在下节进行。

 

    SECURITY_ATTRIBUTES uSecurityAttributes;

      

    PSID pEveryoneSID = NULL, pAdminSID = NULL;

    PACL pACL = NULL;

    PSECURITY_DESCRIPTOR pSD = NULL;

    EXPLICIT_ACCESS ea[2];

 SID_IDENTIFIER_AUTHORITY SIDAuthWorld =  SECURITY_WORLD_SID_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY SIDAuthNT =         SECURITY_NT_AUTHORITY;

    SECURITY_ATTRIBUTES sa;

    LONG lRes;

    HKEY hkSub = NULL;

 

    // Create a well-known SID for the Everyone group.

    BOOL bResult=AllocateAndInitializeSid(&SIDAuthWorld,  1,

                     SECURITY_WORLD_RID,

                     0, 0, 0, 0, 0, 0, 0,

                     &pEveryoneSID);

                    

    // Initialize an EXPLICIT_ACCESS structure for an ACE.

    // The ACE will allow Everyone read access to the key.

    ZeroMemory(&ea, 2*sizeof(EXPLICIT_ACCESS));

    ea[0].grfAccessPermissions = KEY_READ|KEY_WRITE ;

    ea[0].grfAccessMode = SET_ACCESS;

    ea[0].grfInheritance= NO_INHERITANCE;

    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;

    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;

    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;

            

       AllocateAndInitializeSid(&SIDAuthNT, 2,

                     SECURITY_BUILTIN_DOMAIN_RID,

                     DOMAIN_ALIAS_RID_ADMINS,

                     0, 0, 0, 0, 0, 0,

                     &pAdminSID);

              // Initialize an EXPLICIT_ACCESS structure for an ACE.

                      // The ACE will allow the Administrators group full access to the key.

              ea[1].grfAccessPermissions = KEY_ALL_ACCESS;

              ea[1].grfAccessMode = SET_ACCESS;

              ea[1].grfInheritance= NO_INHERITANCE;

              ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;

              ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;

              ea[1].Trustee.ptstrName  = (LPTSTR) pAdminSID;

 

           // Create a new ACL that contains the new ACEs.

           dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);

          

               // Initialize a security descriptor. 

           pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,

                             SECURITY_DESCRIPTOR_MIN_LENGTH);

                            

        InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);

       

        SetSecurityDescriptorDacl(pSD,

            TRUE,     // bDaclPresent flag  

            pACL,

            FALSE);

           

            // Initialize a security attributes structure.

           sa.nLength = sizeof (SECURITY_ATTRIBUTES);

           sa.lpSecurityDescriptor = pSD;

           sa.bInheritHandle = FALSE;

              

if ((dwErr=RegCreateKeyExW(HKEY_LOCAL_MACHINE,L"Software\\800",0,NULL,

REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE,&sa,&hkey,NULL))!=ERROR_SUCCESS)

{ return ; }

else   if ((dwErr=RegSetValueEx(hkey,lpItem,0,REG_SZ,(LPBYTE)lpVer90,2))

!=ERROR_SUCCESS)

{ RegCloseKey(hkey);return; }

             

       RegCloseKey(hkey);

               if(pAdminSID)

              FreeSid(pAdminSID);

 

       if (pEveryoneSID)

        FreeSid(pEveryoneSID);

    if (pACL)

        LocalFree(pACL);

    if (pSD)

        LocalFree(pSD);

(程序2)

 

 

下面为读取当前注册表键安全信息并把它转为字符串的程序,转化后的字符串的解析,参见msdn.

       DWORD dwRes;

       PACL pOldDACL = NULL;

       PSECURITY_DESCRIPTOR pSD = NULL;

       PSID pprimarysid=NULL,pownersid=NULL;

       LPSTR pstring;

 

       HKEY hObject;

 

       if(ERROR_SUCCESS!=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\800",0,KEY_READ,&hObject))

                     return 0;

       // Get a pointer to the existing DACL.

      

       dwRes = GetSecurityInfo((HANDLE)hObject, SE_REGISTRY_KEY ,

              DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION

|OWNER_SECURITY_INFORMATION,

              &pownersid, &pprimarysid, &pOldDACL, NULL, &pSD);

 

       ConvertSecurityDescriptorToStringSecurityDescriptor(pSD,SDDL_REVISION_1,

              DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION

|OWNER_SECURITY_INFORMATION,

              &pstring,NULL);

 

 

    if(pSD != NULL)

        LocalFree((HLOCAL) pSD);

 

       if(pstring!=NULL)

              LocalFree((HLOCAL)pstring);

 

       RegCloseKey(hObject);

(程序 3)

 

本文地址:http://com.8s8s.com/it/it1587.htm