贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

Windows2000 服务器端应用程序开发设计指南-存取控制(1)

发布: 2008-5-01 20:59 | 作者: Jeffrey Richter Jaso | 来源: 网络转载 | 查看: 270次

typedef struct _ACCESS_DENIED_ACE { 

ACE_HEADER Header;
ACCESS_MASK Mask;
DWORD SidStart;
}ACCESS_DENIED_ACE;
typedef struct _ACCESS_ALLOWED_ACE {
ACE_HEADER Header;
ACCESS_ MASK Mask;
DWORD SidStart;
}ACCESS_ALLOWED_ACE;
typedef struct _SYSTEM_AUDIT_ACE {
ACE_HEADER Header;
ACCESS_ MASK Mask;
DWORD SidStart;
}SYSTEM_AUDIT_ACE;

每个结构的定义是完全相同的,都包括允诺的Header成员,即目前熟悉的ACE_HEADER类型。

剩下的两个成员相当容易了解。第一个是遮罩,是一个指出存取权利被拒绝、允许或稽核的32位元遮罩。

接下来将立即讨论存取权利的重要细节,但是请记得对一个给定的对象类型,其存取权利被分为通用、标准及特殊权利,并被组合成个别的32位元值。这个32位元值是ACE的 遮罩 成员。有关存取遮罩格式,请看 图10-2 。

ACE结构的最后一个成员是SidStart,它指出ACE拒绝、允许或稽核存取这个对象的信任成员帐户的SID起点。这个成员需要稍作讨论。

请记得SID(在第九章讨论过)是个可变长度的二进制结构,它指出系统的信任成员帐户。因为每个ACE包含SID,ACE结构也是一个可变长度的结构。SidStart成员是一个包含在ACE中的SID起点的预留位置。SidStart值(及类型)是不恰当且不应该被存取的,因为它实际上是SID结构的第一对位元组。

您可能会发现以下的巨集指令对于从ACE结构取得SID是很有用的:

#define PSIDFromPACE(pACE)((PSID)(&((pACE)->SidStart)))

这个特殊的巨集指令取得指向任何ACE结构的指标-即对象或标准ACE-并且传回指向ACE的SID结构的指标。

标准ACE类型被分成叁种不同的结构,当您为ACL建立ACEs时,主要被用来作为逻辑的预留位置。然而,因为每个ACE结构是完全相同的,从DACL读取ACEs时,常见的情形是只编写使用其中一个ACE类型的程序代码,而不使用ACE_HEADER结构的AceType成员来维护ACE类型。以下的函数使用了此种技巧,并印出DACL中每个ACE的资讯:

void DumpACL( PACL pACL ){  

__try{
if (pACL == NULL){
_tprintf(TEXT("NULL DACL\n"));
__leave;
}
ACL_SIZE_INFORMATION aclSize = {0};
if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize),
AclSizeInformation))
__leave;
_tprintf(TEXT("ACL ACE count: %d\n"), aclSize.AceCount);
struct{
BYTE lACEType;
PTSTR pszTypeName;
}aceTypes[6] == {
{ACCESS_ALLOWED_ACE_TYPE, TEXT("ACCESS_ALLOWED_ACE_TYPE")},
{ACCESS_DENIED_ACE_TYPE, TEXT("ACCESS_DENIED_ACE_TYPE")},
{SYSTEM_AUDIT_ACE_TYPE,TEXT("SYSTEM_AUDIT_ACE_TYPE")},
{ACCESS_ALLOWED_OBJECT_ACE_TYPE,
TEXT("ACCESS_ALLOWED_OBJECT_ACE_TYPE")},
{ACCESS_DENIED_OBJECT_ACE_TYPE,
TEXT("ACCESS_DENIED_OBJECT_ACE_TYPE")},
{SYSTEM_AUDIT_OBJECT_ACE_TYPE,
TEXT("SYSTEM_AUDIT_OBJECT_ACE_TYPE")}};
struct{
ULONG lACEFlag;
PTSTR pszFlagName;
}aceFlags [7 ] =={
{INHERITED_ACE, TEXT("INHERITED_ACE")},
{CONTAINER_INHERIT_ACE, TEXT("CONTAINER_INHERIT_ACE")},
{OBJECT_INHERIT_ACE, TEXT("OBJECT_INHERIT_ACE")},
{INHERIT_ONLY_ACE, TEXT("INHERIT_ONLY_ACE")},
{NO_PROPAGATE_INHERIT_ACE, TEXT("NO_PROPAGATE_INHERIT_ACE")},
{FAILED_ACCESS_ACE_FLAG, TEXT("FAILED_ACCESS_ACE_FLAG")},
{SUCCESSFUL_ACCESS_ACE_FLAG,
TEXT("SUCCESSFUL_ACCESS_ACE_FLAG")}};
for (ULONG lIndex = 0; lIndex < aclSize.AceCount; lIndex++){
ACCESS_ALLOWED_ACE* pACE;
if (!GetAce(pACL, lIndex, (PVOID*)&pACE))
__leave;
_tprintf(TEXT("\nACE #%d\n"), lIndex);
ULONG lIndex2 = 6;
PTSTR pszString = TEXT("Unknown ACE Type");
while (lIndex2--){
if(pACE->Header.AceType == aceTypes [lIndex2 ].lACEType){
pszString = aceTypes[lIndex2].pszTypeName;
}
}
_tprintf(TEXT(" ACE Type =\n \t%s\n"), pszString);
_tprintf(TEXT(" ACE Flags = \n"));
lIndex2 = 7;
while (lIndex2--){
if ((pACE->Header.AceFlags &aceFlags [lIndex2 ].lACEFlag)
!=0)
_tprintf(TEXT(" \t%s\n"),
aceFlags[lIndex2].pszFlagName);
}
_tprintf(TEXT(" ACE Mask ((32->0)=\n \t "));
lIndex2 = (ULONG)1<<31;
while (lIndex2){
_tprintf(((pACE->Mask &lIndex2) != 0)?TEXT("1"):TEXT("0"));
lIndex2>>=1;
}
TCHAR szName[1024];
TCHAR szDom[1024];
PSID pSID = PSIDFromPACE(pACE);
SID_NAME_USE sidUse;
ULONG lLen1 = 1024, lLen2 = 1024;
if (!LookupAccountSid(NULL, pSID,
szName, &lLen1, szDom, &lLen2, &sidUse))
lstrcpy(szName, TEXT("Unknown"));
PTSTR pszSID;
if (!ConvertSidToStringSid(pSID, &pszSID))
__leave;
_tprintf(TEXT("\n ACE SID = \n \t%s (%s)\n"), pszSID, szName);
LocalFree(pszSID);
}
}__finally{}
}

ACEs的所有ACE类型倾印了ACCESS_ALLOWED_ACE结构,这个结构对任何标准ACE类型(尽管这个函数对对象ACEs将失去作用)都能作用,因为所有标准ACE结构都相同。

以下的程序片段可以与DumpACL函数一起被用来显示NTFS共享目录中的ACEs:

PSECURITY_DESCRIPTOR pSD;  

PACL pDACL;
ULONG lErr = GetNamedSecurityInfo(TEXT("C:\\Test\\Test"),
SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL,
&pDACL, NULL, &pSD);
if (lErr == ERROR_SUCCESS){
DumpACL(pDACL);
}

说明

DumpACL范例函数说明了如何读取DACL中的ACE资讯。您会在自己编写的程序代码中发现像这样有用的程序代码。您也会发现以DumpACL函数作为除错工具是很有帮助的,尤其是当您开始编写程序代码去修改安全对象的DACL时。在您作了修改的前后,使用它来倾印对象的DACL内容,以查看您的程序代码是否产生了所要求的结果。

这种技巧胜过使用浏览器的安全属性页检视安全性,因为系统的使用者介面不会逐字显示对象的ACE资讯。事实上,使用者介面不会显示没有事先在DACL中适当地安排ACEs顺序的DACL。


因为ACE结构的性质可让您发现它对定义一个表示每个ACE类型的Union很有帮助。于是就一个指向Union类型的指标来说,您可以处理从GetAce传回的ACEs。

以下的程序代码显示一个使用此类技巧的范例:

typedef union _ACE_UNION{ 

ACE_HEADER aceHeader;
ACCESS_ALLOWED_ACE aceAllowed;
ACCESS_DENIED_ACE aceDenied;
SYSTEM_AUDIT_ACE aceAudit;
}*PACE_UNION;
PACE_UNION pACE ;
GetAce(pDACL, 0, (PVOID*)&pACE);
switch (pACE->aceHeader.AceType){
.
.
.

 对象ACEs 除非您要编写保护及修改Active Directory对象安全性的程序代码,否则您不可能会在自己的应用程序中使用对象ACEs。然而,Active Directory是Windows 2000的一个重要元件,了解它保护对象安全的方法并没有害处。我们不会花太多时间在这个主题上,此处的说明只是为了避免混淆您对标准ACEs的认识。

就像标准ACES一样,对象ACEs有叁种结构:拒绝、允许及稽核信任成员存取权利。以下是对象ACEs的结构:

typedef struct _ACCESS_ALLOWED_OBJECT_ACE { 

ACE_HEADER Header;
ACCESS_ MASK Mask;
DWORD Flags;
GUID ObjectType;
GUID InheritedObjectType;
DWORD SidStart;
} ACCESS_ALLOWED_OBJECT_ACE, *PACCESS_ALLOWED_OBJECT_ACE;
typedef struct _ACCESS_DENIED_OBJECT_ACE {
ACE_HEADER Header;
ACCESS_MASK Mask;
DWORD Flags;
GUID ObjectType;
GUID InheritedObjectType;
DWORD SidStart;
} ACCESS_DENIED_OBJECT_ACE, *PACCESS_DENIED_OBJECT_ACE;
typedef struct _SYSTEM_AUDIT_OBJECT_ACE {
ACE_HEADER Header;
ACCESS_MASK Mask;
DWORD Flags;
GUID ObjectType;
GUID InheritedObjectType;
DWORD SidStart;
} SYSTEM_AUDIT_OBJECT_ACE, *PSYSTEM_AUDIT_OBJECT_ACE;

就像标准ACEs一样,除了附加的Flags、ObjectType及InheritedObjectType成员外,每个结构类型及结构的成员都相同。

注意不要把对象ACE结构的Flags成员与ACE_HEADER结构的AceFlags成员混淆了。Flags成员可以为0或是表10-12中任何值的组合。


说明

和Win32 SDK中类似的结构不同,表10-12中的标记不指出结构中是否有使用ObjectType及InheritedObjectType成员,而是指出这些成员是否真的存在于结构中!

没有固定成员清单的结构被称为 定形的(amorphous) 。每个对象ACE结构都是无定形的,在Win32 SDK中是非常罕见的结构。这显然是对象ACEs最难处理的一面。


 表10-12 对象ACE标记成员的值
叙述
ACE_OBJECT_TYPE_PRESENT 指出ObjectType成员存在于对象ACE结构中
ACE_INHERITED_OBJECT_TYPE_PRESENT 指出InheritedObjectType成员存在于对象ACE结构中

ObjectType及InheritedObjectType都是GUIDs。假如您不熟悉GUIDs,可以在《Platform SDK》文件或《Inside COM》(Dale Rogerson, Microsoft Press, 1997)找到这个主题的完整讨论。

就我们所需目标而言,您只需要懂得GUID是一个128位元的值,几乎无论什么东西都可以用它来作为唯一地识别。

幸运的是,Active Directory服务介面(Active Directory Service Interfaces, ADSI)为了在Active Directory对象上操作安全性而提供了使用介面,它负责从您的程序代码中移除处理对象ACEs。由于此原因,使得您需要编写在DACL中直接操作对象ACEs程序代码的机率非常小。有关这个主题的更多资讯,请参阅《Platform SDK》中对IADsSecurityDescriptor、IADsAccessControlList及IADsAccessControlEntry介面部份的讨论。


说明

在Active Directory外的安全对象ACLs中从未发现对象ACEs,对象ACEs使得ACL操作程序代码变得更复杂。由于这个原因,本章其馀的部分(及本章所有的程序代码)皆假定ACLs不包含对象ACEs。没有对象ACEs的ACLs减轻了我身为作者的工作,也简化让您了解复杂主题的工作。

 

评分:0

我来说两句

seccode