精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
It is possible to have a class member that has type PSECURITY_DESCRIPTOR to secure access to your object. If you want to make your security descriptor writable, you'll have to add special logic to your property functions. In particular when updating, you are expected to merge the new security descriptor into the current security descriptor.
You can use your own logic to manage the security descriptors (it will be easier to manage in SDDL form). Or you can make use of a special API, CreatePrivateObjectSecurity(), to do it for you. First, you must decide which methods of your class you want to restrict (you can restrict up to 16 methods per security descriptor). These methods must include generic actions specified in the GENERIC_MAPPING structure (even if you don't support them—just provide empty methods in this case).
The class given in the Platform SDK sample defines the actions in fig. 26 as part of its private object. Not only should the class map its own methods to these actions, it should map a GENERIC_MAPPING structure onto this structure (without this GENERIC_MAPPING structure, the AccessCheck() function will not work).
可能有一个类成员,其类型PSECURITY_DESCRIPTOR可以保护对您的对象的访问。如果要使安全描述符可写,则必须在属性函数中添加特殊的逻辑。特别是在更新时,您应该将新的安全描述符合并到当前的安全描述符中。
您可以使用自己的逻辑来管理安全描述符(以SDDL形式进行管理将更加容易)。或者,您可以使用特殊的APICreatePrivateObjectSecurity()来为您完成此任务。首先,必须确定要限制类的哪些方法(每个安全描述符最多可以限制16个方法)。这些方法必须包括GENERIC_MAPPING结构中指定的通用操作(即使您不支持它们,在这种情况下也请提供空方法)。
Platform SDK示例中提供的类定义了图5中的动作。26作为其私有对象的一部分。该类不仅应将其自身的方法映射到这些动作,还应将一个GENERIC_MAPPING结构映射到该结构(没有该GENERIC_MAPPING结构,该AccessCheck()函数将无法工作)。
ACCESS_READ// ==1 <-- GENERIC_MAPPING::GenericRead ACCESS_MODIFY// ==2 <-- GENERIC_MAPPING::GenericWrite ACCESS_DELETE // ==4 ACCESS_ALL// ==7 <-- GENERIC_MAPPING::GenericAll
Figure 26: An example of the set of actions performable by a custom class.
In the constructor for your class, make a call to CreatePrivateObjectSecurity() and store the returned security descriptor in one of your class members. You have now associated the security descriptor to your class. Should you need to update the security descriptor (e.g. during a configuration change), make a call to SetPrivateObjectSecurity(). This function will merge the old security descriptor with your own security descriptor.
When you are about to perform an action (i.e. one of your methods are called), you should now make a call to AccessCheckAndAuditAlarm(). You make a call here because if there are any audit entries in the security descriptor, you'll want an audit event to be fired. AccessCheckAndAuditAlarm() requires you to supply information for the audit event log. Once the call has been made, make a call to ObjectCloseAuditAlarm().
在您的类的构造函数中,调用CreatePrivateObjectSecurity()并将返回的安全描述符存储在您的一个类成员中。现在,您已将安全描述符与您的类相关联。如果您需要更新的安全描述符(如结构变更时),请调用SetPrivateObjectSecurity()。此函数将旧的安全描述符与您自己的安全描述符合并。
当你即将要执行的操作(即一个被调用的方法,),你现在应该做一个AccessCheckAndAuditAlarm()调用。您在这里打电话是因为,如果安全描述符中有任何审核条目,您将希望触发审核事件。AccessCheckAndAuditAlarm()要求您提供审核事件日志的信息。调用完成后,再调用ObjectCloseAuditAlarm()。
If your class bears a parent-child relationship model (like a folder), you'll want to support inheritance in your security descriptors. In this case, you'd use the Ex variants of the *PrivateSecurity functions. These functions bear two extra parameters: a GUID (in case your class multiple inherits), and the AutoInheritFlags. The AutoInheritFlags control how inheritance is applied from the parent object, and can also reduce the overhead of enabling privileges.
When you have finished using the class, call DestroyPrivateObjectSecurity() in the destructor to release the resources. ATL provides no special classes to handle privately secure objects. Therefore, just call the private security APIs directly. And for method 1, privately secure objects are only viable for classes (which is not available in C).
如果您的类具有父子关系模型(如文件夹),则需要在安全描述符中支持继承。在这种情况下,您将使用*PrivateSecurity函数的Ex变体。这些功能承担两个额外的参数:一个GUID(如果你的类继承多个),和AutoInheritFlags。该AutoInheritFlags如何继承从父对象施加,并且也可以减少使特权的开销控制。
当您使用类后,调用DestroyPrivateObjectSecurity()析构函数中释放资源。ATL没有提供特殊类来处理私有安全对象。因此,只需直接调用私有安全性API。对于方法1,私有安全对象仅适用于类(在C中不可用)。
class SecureClass { private: PSECURITY_DESCRIPTOR ppSD; double len; CAccessToken ProcToken; bool CheckClassAccess(DWORD RightsToCheck) const; /* This helper is where we do the access check */ public: enum Rights { /* The set of rights */ ReadLen = 1, WriteLen = 2, SetClassSecurity = 4, CopyClass = 8 }; ~SecureClass(); SecureClass(int FullRights, const CHandle &ThreadHandle); SecureClass(const SecureClass &OldClass); /* Copy constructor needs CopyClass access */ double get_len(void) const ; /* You must have ReadLen rights to access this property */ void set_len(double Newlen) ; /* You must have WriteLen rights to write this property */ void set_SecDesc(SECURITY_INFORMATION psi, PSECURITY_DESCRIPTOR pNewSD); /** You need SetClassSecurity rights to access * this method **/ };
Figure 27: The outline of a class that secures access through security descriptors.
That's a lot of information just to build a security descriptor (especially if you worked using method 1)! Most of the time you just want to retrieve and edit the security descriptor for an object. I've summarized the required steps, so you won't have to remember all of the above:仅用于构建安全描述符的信息很多(特别是如果您使用方法1进行工作)!大多数时候,您只想检索和编辑对象的安全描述符。我已经总结了所需的步骤,因此您不必记住以上所有内容:
If you need to enable any privileges, do that first.
In this part you were shown how to obtain a SID, print it, convert it into a TRUSTEE, and convert it to a user name. You extracted information from your access token, such as who you are, which groups you are a member of, the list of restricted groups, the list of privileges and their state. You enabled and disabled a privilege, and created a restricted token to run a low privilege application.
Next, you obtained a security descriptor from a file, converted it to absolute form, then extracted the five parts of the security descriptor. You converted the security descriptor to SDDL form, and printed its contents. For the DACL, you were shown how to create and edit an Access Control List, and print out its contents. You then edited a security descriptor, applied inheritance rules to it, and finally secured an object with it (predefined and custom objects).
在这一部分中,向您展示了如何获取SID,打印,将其转换为TRUSTEE以及如何将其转换为用户名。您从访问令牌中提取了信息,例如您是谁,您属于哪个组,受限组列表,特权列表及其状态。您启用和禁用特权,并创建了受限制的令牌来运行低特权应用程序。
接下来,从文件中获取安全描述符,将其转换为绝对格式,然后提取安全描述符的五个部分。您已将安全描述符转换为SDDL格式,并打印了其内容。对于DACL,向您展示了如何创建和编辑访问控制列表以及如何打印其内容。然后,您编辑了安全描述符,对其应用了继承规则,最后使用它保护了一个对象(预定义和自定义对象)。
You were shown how to do all of this in NT3.x-style, 2000-style, and ATL style. This all culminates in the AccessCheck() function, which checks if you are allowed access to a certain resource.
I have left out domain issues and multiple inherited objects since they are out of scope for this series. To learn about these, I recommend checking out the Windows resource kits. The demo project contains all the code for this part, written in methods 1, 2 and 3. Currently the samples are not designed to be reusable, but given sufficient interest, I may change that (I'm saving the real functionality for part 4). In order to compile method 2, you need the boost::regex library and the WMI SDK installed and enabled. To compile method 3, you need the ATL libraries.
向您展示了如何以NT3.x样式,2000样式和ATL样式完成所有这些操作。这一切最终在该AccessCheck()函数中达到顶峰,该函数检查是否允许您访问特定资源。
我没有涉及域问题和多个继承的对象,因为它们超出了本系列的范围。要了解这些信息,建议您查看Windows资源工具包。该演示项目包含用方法1、2和3编写的该部分的所有代码。当前,这些示例并不是为了可重用而设计的,但是由于有足够的兴趣,我可能会做出更改(我将保留第4部分的实际功能))。为了编译方法2,您需要boost::regex安装并启用该库和WMI SDK。要编译方法3,您需要ATL库。
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州市文化路47号院1号楼4层(47-1楼位于文化路和红专路十字路口东北角,郑州大学工学院招待所南边,工学院科技报告厅西边。)