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

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

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

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

修改DACL
 

建立安全对象牵涉到与需要实作服务一样多的存取控制。您可以实作许多服务,而从来不用修改现存对象的安全性,这是令人惊异的。当然,某些程序必须处理已经拥有应用安全性的现存对象。在此种情况下,您的软件必须能够读取及修改对象的DACL。以下是您可以采取的步骤:

  1. 撷取您要修改之对象的DACL。
  2. 假如您正在移除ACEs,在DACL中搜寻这些ACEs并加以删除。
  3. 收集您将加入ACEs的信任成员SIDs。
  4. 建立您将加入的ACEs。
  5. 在DACL中搜寻是否有与您将加入相同的ACEs。若有任何一个存在,将它们从您加入的ACEs群组中移除。
  6. 计算新DACL的大小。
  7. 分配内存及初始化新的DACL。
  8. 复制旧的DACL到新的DACL。
  9. 在新的DACL中将新的ACEs插入适当的位置。
  10. 指派DACL回对象。

如您所见,读取及修改对象DACL的程序并没有那么简单,然而我应告诉您,我已经提供了最糟情况的方案。通常您并非真的移除ACEs,所以可以忽略步骤二的动作。而一般的情形下,您只增加了一个个别的ACE;假如该ACE已经存在DACL中,那么您可以中止整个程序,并简化步骤五的动作。


说明

在ACLs中搜寻已经存在的ACEs是很重要的,虽然完全一样的ACEs并不会影响对象的 安全性 。其原因是ACEs占用了系统中的内存,而某些系统对象(例如,window站台)会出乎意料的持有少数ACEs。每次执行就增加ACE,没有检查工作之必要性的任何软件,最后将耗尽系统的资源。


现在让我告诉您处理读取及修改DACL之工作必须使用的工具。让我们从一个简单的函数开始(您已经知道如何读取DACL中的资讯,这些技巧将在此处开始产生作用)。

BOOL DeleteAce(
PACL pACL,
DWORD dwACEIndex);

DeleteAce函数会从DACL中移除一个ACE,您必须传递ACL及您要移除的ACE索引值给它。


说明

如果您对这个对象所做的唯一修改只是移除ACEs,那么您不用为新的DACL分配内存。您可以简单地移除经由GetSecurityInfo传回之DACL中的ACEs,然后再放置修改过的DACL回对象。


处理程序的下一个步骤即是要求您拥有便于使用的ACE,因为您将使用到AddAce函数,它会要求一个已建立的ACE;再者,因为您可能会在ACL中搜寻已存在的ACE,此时有个ACE结构可对照DACL之ACEs是方便的。

可惜系统不提供让您使用简便方法建立ACEs的函数。建立ACEs的工作是复杂的,因为每个ACE皆包括了一个SID结构,而SID结构的长度是可变的。最好使用您的SID长度及ACE结构长度分配一个缓冲器给ACE,并复制SID到ACE中,然后设定其ACE栏位。以下的函数显示了实行的方法:

PACE_UNION AllocateACE(ULONG bACEType, ULONG bACEFlags,
ULONG lAccessMask,PSID pSID ){
PACE_UNION pReturnACE = NULL;
PBYTE pbBuffer = NULL;
try{
// 取得ACE中SID的偏移量
ULONG lSIDOffset = (ULONG)(&((ACCESS_ALLOWED_ACE*)0)->SidStart);
// 取得没有SID的ACE大小
ULONG lACEStructSize = sizeof(ACCESS_ALLOWED_ACE)-
sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart);
// 取得SID的长度
ULONG lSIDSize = GetLengthSid(pSID);
// 分配一个缓冲器给ACE
pbBuffer = (PBYTE)LocalAlloc(LPTR, lACEStructSize + lSIDSize);
if (pbBuffer == NULL)
goto leave;
// 复制SID到ACE
if(!CopySid(lSIDSize, (PSID)(pbBuffer+lSIDOffset), pSID)){
goto leave;
}
pReturnACE = (PACE_UNION) pbBuffer;
pReturnACE->aceHeader.AceSize = (USHORT)(lACEStructSize + lSIDSize);
pReturnACE->aceHeader.AceType = (BYTE)bACEType;
pReturnACE->aceHeader.AceFlags = (BYTE)bACEFlags;
pReturnACE->aceAllowed.Mask = lAccessMask;
leave:;
}catch(...){}
// 在错误实例中释放缓冲器
if (pbBuffer != (PBYTE)pReturnACE){
LocalFree(pbBuffer);
}
return (pReturnACE);
}

当在使用AllocateAce时,您只须在执行完成时传递回传的ACE给LocalFree。


说明

AllocateAce会传回一个PACE_UNION指标,它是本章先前定义的类型,我选择使用此技巧并以一般的方式表示ACEs。选择特定ACE类型之其中一个也是常见的方法,例如ACCESS_ ALLOWED_ACE,可使用在您的ACE之一般操作上。两种方法都行得通;然而,在本章的一些范例函数中,所使用的是PACE_UNION。


现在您已经建立了ACE,接下来您必须在对象现存的DACL中搜寻符合的ACEs。您可以经由使用本章先前谈论的ACL读取技巧来实作。在我编写执行此工作程序代码时使用了两个函数:一个用来对照ACEs,另一个则是在ACL中搜寻符合的ACE。

BOOL IsEqualACE(PACE_UNION pACE1,PACE_UNION pACE2 ){
BOOL fReturn =FALSE;
try{{
if(pACE1->aceHeader.AceType !=pACE2->aceHeader.AceType)
goto leave;
//取得ACE中SID的偏移量
ULONG lSIDOffset =(ULONG)(&((ACCESS_ALLOWED_ACE*)0)->SidStart);
//取得没有SID的ACE大小
ULONG lACEStructSize =sizeof(ACCESS_ALLOWED_ACE)-
sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart);
PBYTE pbACE1 =(PBYTE)pACE1;
PBYTE pbACE2 =(PBYTE)pACE2;
fReturn =TRUE;
while(lACEStructSize--)
fReturn =(fReturn &&((pbACE1 [lACEStructSize ] ===
pbACE2 [lACEStructSize ])));
/检查SIDs
fReturn =fReturn &&EqualSid((PSID)(pbACE1+lSIDOffset),
(PSID)(pbACE2+lSIDOffset));
}leave:;
}catch(...){
}
return (fReturn);
}

以下是第二个函数的内容:

int FindACEInACL(PACL pACL, PACE_UNION pACE ){
int nACEIndex =-1;
try{{
ACL_SIZE_INFORMATION aclSize;
if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize),
AclSizeInformation)){
goto leave;
}
while (aclSize.AceCount--){
PACE_UNION pACETemp;
if(!GetAce(pACL, aclSize.AceCount, (PVOID *)&pACETemp))
goto leave;
if(IsEqualACE(pACETemp, pACE)){
nACEIndex = (int)aclSize.AceCount;
break;
}
}
}leave:;
}catch(...){
}
return (nACEIndex);
}

FindACEInACL函数会传回DACL中符合的ACE索引值,如果没有找到,则传回 -1值。您应该使用此函数或类似的函数,以找出您打算加到对象DACL的ACEs是否已经存在DACL中(FindACEInACL函数对于寻找您想要使用DeleteAce删除的ACEs也是很有帮助的)。

现在您已经知道哪些ACEs必须加入DACL及已建立的ACEs,现在是计算新DACL大小的时候了。您可以使用在本章前面出现过的CalculateACLSize函数。它可让您使用现存的ACL、SIDs阵列及ACEs阵列来计算ACL大小。您可以传递NULL给这些参数。在我们的范例中,您有可能会传递一个现存的ACL及ACEs阵列,以在加入ACEs后用来计算新ACL的大小。

在您分配内存给新的ACL后,应使用InitializeAcl(本章前面讨论过)来初始化新的ACL。接下来您必须从旧的ACL复制ACEs到新的ACL。

TAG: Windows2000 应用程序 开发 服务器端 设计指南 存取

61/6123456>
 

评分:0

我来说两句

seccode