Nt/2000 xp平台下的存储控制模型如何?
Nt/2000 xp平台下的存储控制模型如何?
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)