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

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

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

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

第一个挑战-即维持弹性-是最难克服的。大多数的存取控制需求,可以使用Windows存取控制直接实作。然而,随着弹性而产生的复杂性,以及移除复杂性时就会移除了某些开发人员所期待的特色。

看起来第二个挑战似乎比较可能达成,但是这个实例还未被证明。Microsoft实作了一组「高阶」安全性的函数,并且已加入Win32 API中。这些函数彻底地简化了某些安全性程序设计的观点,以及某些具有历史性的错误及固有的缺点。以下举出一个范例:

DWORD GetEffectiveRightsFromAcl( 

PACL pACL,
PTRUSTEE pTrustee,
PACCESS_MASK pAccessRights);

GetEffectiveRightsFromAcl函数为了搜寻ACL及传回DACL指出允许之存取权利到信任成员的存取遮罩而准备。听起来非常方便!这样的函数可以潜在中将我们的需求移到加入ACEs之前,先在DACL中搜寻ACEs。然而,GetEffective RightsFromAcl试图做太多的事,如些一来,会产生做出来的成果几乎不能使用的情形。

GetEffectiveRightsFromAcl函数指出允许存取权是以一致的允许存取ACEs之组合为基础,然后再减去一致的拒绝存取ACEs的组合。这意味着GetEffective RightsFromAcl可以传回一组存取权利,它会指出ACL没有授予想要的存取权给信任成员部份,在我离开时仍旧不知道如何处理这个问题。没有授予存取权是因为缺少允许存取ACEs,或是因为存在拒绝存取ACEs呢?我厌恶增加允许存取ACE的方法,只想找出无效拒绝存取ACE使我仍然没有存取权的原因。

GetEffectiveRightsFromAcl不只会搜寻符合您提供的信任成员ACEs,也搜寻信任成员所属之群组帐户的任何ACEs。但是这个函数并没有包括内建的群组,例如Everyone及受认证的使用者。假如它需要寻找群组的ACEs,而信任您程序代码的群组成员并没有列举权利时,此动作会失败。最后,没有方法可以限制搜寻程序只找出明确指派给信任成员的存取权。

GetEffectiveRightsFromAcl是为了使您的程序代码能够查出信任成员对象上的存取检查是否成功或失败而准备。然而,存取检查需要一个权杖而非信任成员SID。权杖包含权限;权杖也可以被调整或限制(请参阅 第十一章 )。在检查存取时,GetEffectiveRightsFromAcl不会把权限带到帐户里。存取检查能够执行成功是以对象所有权为基础,但是GetEffectiveRightsFromAcl并不了解对象所有权。这些方法使得GetEffectiveRightsFromAcl的使用有限。

更有帮助的函数SetEntriesInAcl及GetExplicitEntriesFromAcl是为了帮助您在卸下为ACEs及ACLs分配的内存责任的同时,也可以直接处理ACL而准备。这些函数的目的很重要,但是这个函数具有历史性的错误及效能上的争议。某些问题已经被清除了,不过如果您选择在专案中使用这些函数,彻底测试其程序代码是很重要的。

应该与SetEntriesInAcl一起使用的BuildExplicitAccessWithName函数不会传回任何值,它会潜在地把错误方案(当使用低阶函数呼叫LookupAccountName时,可以撷取)委托给SetEntriesInAcl函数。由于SetEntriesInAcl没有回报失败项目的方法,因此您会因为无法从失败案例中恢复而离开。

您可以有其他的选择。Active Template Library(ATL)的开发人员设计了一个称为CSecurityDescriptor的C++ 类别,定义在标头档AtlCom.h中。CSecurityDescriptor之额外的好处是提供全部的类别原始码。尽管此类别提供了大量的功能,但本身也有陷阱。例如,此函数会以一向不遵守Windows 2000提出的ACE顺序的方式增加ACEs,虽然它们遵守Windows NT 4.0的方针。此外,从核心对象撷取安全性的AttachObject函数则用GetKernelObjectSecurity代替GetSecurityInfo,它是与Windows 2000一起使用所建议的函数。

如前所述,CSecurityDescriptor类别最好的东西即是拥有原始码。假如它朝您需要的方向去运作,那会很好!如果没有的话,您便可以选择修改类别。而且若您找到任何错误,可以选择使用您拥有与Windows之低阶存取控制相关的知识来修改它们。

安全的私有对象
 

我已经提过好几次,您可以经由使用Windows存取控制来保护软件建立的私有对象。这个特色真的很强大,尤其是它可能对服务开发人员有用。到目前为止您已经学习的DACL建立技巧,适用于保护私人对象和系统对象,所以在您自己的对象上实作存取控制所需学习的部份并不多。

这个工作牵涉到需要保护的对象在您的软件及系统间共用的情形。您的软件必须执行以下的工作,以实作对象的私有安全性:

  • 您的软件必须为您的对象定义特定的权利(使用存取遮罩的低16位元)。
     
  • 您的软件必须决定哪个标准权利与您的对象有关。
     
  • 您的软件必须决定通用权利对应到哪个标准及特定权利。
     
  • 您的软件必须把安全描述项(系统建立的)与对象联系在一起。
     
  • 您的软件必须将适合您对象的安全描述项与对象储存到永续性储存体中。
     
  • 您的软件在安全对象上执行安全性活动前,必须先执行存取检查。
     

系统提供了以下的特色:

  • 为您的对象建立及删除安全描述项的函数。
     
  • 取得及设定这些安全描述项之特殊部分函数。
     
  • 在某方面来说,一个执行存取检查的函数会与Windows之其他安全对象一致。
     

在我们开始讨论特定函数前,必须阐明以下两点:

  • 私人对象安全性应该能被不同安全性环境中执行服务之客户端服务软件使用。
     
  • 私人对象安全性要求您的软件使用权杖指出客户端之安全性环境。请记得权杖包含了一个信任帐户的SID与它的群组SIDs、权限及预设DACL(第十一章将会更详细讨论权杖的内容)。
     

建立一个私下被保护的对象时,您应该建立对象的安全描述项。可呼叫CreatePrivateObjectSecurity函数实作:

BOOL CreatePrivateObjectSecurity( 

PSECURITY_DESCRIPTOR psdParentDescriptor,
PSECURITY_DESCRIPTOR psdCreatorDescriptor,
PSECURITY_DESCRIPTOR *ppsdNewDescriptor,
BOOL fIsDirectoryObject,
HANDLE hToken,
PGENERIC_MAPPING gmGenericMapping);

CreatePrivateObjectSecurity函数有一个非必要的父安全描述项与建立者描述项,这两个参数都可以为NULL。假如两者都没有提供的话,CreatePrivateObjectSecurity函数会透过所提供之权杖中找到的预设DACL而建立一个安全描述项。在预设DACL中找到的通用权利,可使用从被传递之GENERIC_MAPPING结构中找到的资讯,并将它们对应到对象的特定及标准权利。CreatePrivateObjectSecurity函数经由指派它的位址给PSECURITY_DESCRIPTOR变数,以传回新的安全描述项,您所传递的位址为ppsdNewDescriptor参数值。这是一个新的安全描述项,现在您应该把它与您的私有安全对象联系在一起。当您需要释放此函数所分配的内存时,应该传递指向想要释放之安全描述项的变数位址给DestroyPrivateObjectSecurity。

BOOL DestroyPrivateObjectSecurity( 

PSECURITY_DESCRIPTOR *ppsd ObjectDescriptor );

被您初始化及传递给CreatePrivateObjectSecurity的GENERIC_MAPPING结构定义如下:

typedef struct _GENERIC_MAPPING { 

ACCESS_MASK GenericRead;
ACCESS_MASK GenericWrite;
ACCESS_MASK GenericExecute;
ACCESS_MASK GenericAll;
}GENERIC_MAPPING;

您可经由将每个成员设定到每个通用权利之适当的标准及特定权利组合,以填写这个简单的结构。从权杖的预设DACL建立DACL时,系统会使用这个资讯。


说明

您不应直接修改从CreatePrivateObjectSecurity传回的安全描述项。尽管系统提供从此描述项要求特定安全性资讯的函数,您的软件应该把这个传回的指标视为黑箱,犹如安全描述项被储存在系统内存一般。


当客户端试图对软件中的安全对象作用时,首先客户端必须接受存取检查。为此,您应传递执行安全工作所需的权利、安全描述项及客户端的权杖到AccessCheck函数中。

BOOL AccessCheck( 

PSECURITY_DESCRIPTOR pSecurityDescriptor,
HANDLE hClientToken,
DWORD dwDesiredAccess,
PGENERIC_MAPPING gmGenericMapping,
PPRIVILEGE_SET pPrivilegeSet,
PDWORD pdwPrivilegeSetLength,
PDWORD pdwGrantedAccess,
PBOOL pfAccessStatus);

您也必须包含此对象的GENERIC_MAPPING结构位址以及PRIVILEGE_SET结构阵列的位址。系统使用PRIVILEGE_SET结构来描述用来授予存取的权限。系统以几个实例来授予使用权限的存取权,而您应该提供够大的缓冲器以接收数个回传的权限。PRIVILEGE_SET结构定义如下:

typedef struct _PRIVILEGE_SET { 

DWORD PrivilegeCount;
DWORD Control;
LUID_AND_ATTRIBUTES Privilege [ANYSIZE_ARRAY];
}PRIVILEGE_SET;

ANYSIZE_ARRAY值被定义为1,而您应该建立一个够大的缓冲器以接收有关的权限。一旦收到权限缓冲器要求的大小后,您可以呼叫AccessCheck,然后再配置一个够大的缓冲器。


说明

当您的客户端要求对象的WRITE_OWNER、READ_CONTROL、WRITE_DAC或ACCESS_SYSTEM_SECURITY的存取时,该权限可以被用来授予存取。假如这些权利没有明确地指派给您客户端的信任成员帐户,系统会为覆盖对象安全性的权限检查客户端的权杖。这种权限的一个例子为SE_TAKE_OWNERSHIP_NAME,它可让客户端设定系统中任何对象的拥有权。


您的客户端被授予的存取遮罩会经由pdwGrantedAccess参数传回,而经由pfAccessStatus参数传回的Boolean值会指出AccessCheck函数是否成功。

在实作私有对象之安全性时,AccessCheck函数是其中心,假如您的软件是安全的,而它一定会在对象执行安全工作前呼叫AccessCheck,则当您软件的客户端被允许存取时,Windows会处理剩下的细节部份。


说明

您也可以使用AccessCheckAndAuditAlarm函数建立稽核事件及私有安全对象。稽核的内容将在本章稍后讨论。


到此为止,您已经知道如何建立及删除私有安全性的方法,您也知道如何及应在何时呼叫AccessCheck函数。所以私有对象主题唯一剩下的部分即是如何修改安全描述项的元件。为了修改私人对象的安全性,首先应该取得您要调整的安全描述项元件。这通常是DACL,它可以是对象的拥有者或SACL。可使用GetPrivateObjectSecurity实作。

BOOL GetPrivateObjectSecurity( 

PSECURITY_DESCRIPTOR psdObjectDescriptor,
SECURITY_INFORMATION secInfo,
PSECURITY_DESCRIPTOR psdResultantDescriptor,
DWORD dwDescriptorLength,
PDWORD pdwReturnLength);

GetPrivateObjectSecurity函数取得一个指向私有安全对象的安全描述项指标,并传回所要求的安全描述项。您可以使用熟悉的secInfo参数以指出您想撷取对象安全描述项的哪个部分。

您必须提供一个够大的缓冲器来包含持有要求资讯的安全描述项。一旦得到要求的缓冲器大小时,便可以呼叫GetPrivateObjectSecurity函数,并且再一次撷取资讯。

在您拥有对象的安全描述项后,必须修改它,然后再使用SetPrivateObjectSecurity函数重新设定修改过的安全描述项给私有对象。

BOOL SetPrivateObjectSecurity{ 

SECURITY_INFORMATION secInfo,
PSECURITY_DESCRIPTOR psdModificationDescriptor,
PSECURITY_DESCRIPTOR *ppsdObjectsSecurityDescriptor,
PGENERIC_MAPPING gmGenericMapping,
HANDLE hClientToken);

secInfo参数指出「修改安全描述项」中的哪些资讯已被设定到对象的私有安全描述项中。您可以传递PSECURITY_DESCRIPTOR变数的位址,它包含一个指向对象私有安全描述项的指标。SetPrivateObjectSecurity函数会释放安全描述项,并以新的安全描述项取代它,其位址从提供的指标变数中传回。您也必须传递hClientToken参数,以使系统可以确认对象拥有者的设定,及其通用的对应结构。

安全描述项的修改通常会使用以下这些步骤执行:

  1. 撷取对象的安全描述项。
  2. 建立及初始新的安全描述项(本章稍早曾示范)。
  3. 从原始的安全描述项复制安全性资讯到新的安全描述项。
  4. 修改新的安全描述项(使用遍及本章所叙述的技巧)。
  5. 把新的安全描述项放回私人对象。

为了取得安全描述项的个别元件,您应该使用以下的函数:即GetSecurityDescriptorOwner、GetSecurityDescriptorDacl、GetSecurityDescriptorSacl及GetSecurityDescriptorGroup。为了设定新安全描述项的内部元件,您可以使用SetSecurityDescriptorOwner、SetSecurityDescriptorDacl、SetSecurity DescriptorSacl、SetSecurityDescriptorGroup来设定。

这些函数都很相似,所以我准备展示及讨论最常见与复杂GetSecurityDescriptorDacl及SetSecurityDescriptorDacl函数。

64/6<123456>
 

评分:0

我来说两句

seccode