**安全描述符**（英語：）是安全信息的数据结构，用于可安全（securable）的Windows对象，这些对象可以被唯一名称辨识。安全描述符可用于任何命名对象，包括文件、文件夹、共享、注册表键、进程、线程、命名管道、服务、工作对象以及其他资源。

简介
--

安全描述符包含自主决定的存取控制串列（DACL），里面包含有访问控制项（ACE），因此可以允许或拒绝特定用户或用户组的访问。它们还包含一个系统访问控制列表（SACL）以控制对象访问请求的日志（logging）。ACE可以显式应用于对象，或者从父对象继承。ACE的顺序在ACL中很重要，拒绝访问的ACE应该比允许访问的ACE更早出现。安全描述符还包含对象所有者。

强制完整性控制就是通过新类型的ACE在安全描述符上实现。

应用
--

文件和文件夹的权限可以使用各种工具编辑，这包括Windows Explorer、WMI，以及命令行工具如Cacls、XCacls、ICacls（英语：）、SubInACL，免费的Win32控制台FILEACL，自由实用工具SetACL（英语：），以及其他实用工具。要编辑一个安全描述符，用户需要有该对象的WRITE\_DAC访问权限，该权限通常默认授予管理员和该对象的所有者。

数据结构
----

```
typedef struct \_SECURITY\_DESCRIPTOR {
 UCHAR Revision;
 UCHAR Sbz1;
 SECURITY\_DESCRIPTOR\_CONTROL Control; //其自身的一些控制位
 PSID Owner; //Owner安全标识符(Security identifiers) 相当于UUID，标识用户、用户群、计算机帐户
 PSID Group; //Group安全标识符(Security identifiers) 相当于UUID
 PACL Sacl; //（System Access Control List），其指出了在该对象上的一组存取方式（如，读、写、运行等）的存取控制权限细节的列表。
 PACL Dacl; //（Discretionary Access Control List），其指出了允许和拒绝某用户或用户组的存取控制列表。 如果一个对象没有DACL，那么就是说这个对象是任何人都可以拥有完全的访问权限。 
} SECURITY\_DESCRIPTOR, \*PISECURITY\_DESCRIPTOR;

typedef struct \_ACL {
 BYTE AclRevision;
 BYTE Sbz1;
 WORD AclSize;
 WORD AceCount;
 WORD Sbz2;
} ACL, \*PACL;

```

取得对象上的安全设置，或修改对象上的安全设置的Windows API。如：GetNamedSecurityInfo, SetNamedSecurityInfo，GetSecurityInfo, SetSecurityInfo。

底层安全描述符函数：

* 对于文件、目录、邮槽、命名管道，可以使用其专用函数GetFileSecurity和SetFileSecurity函数来取得或设置文件对象的SD，以设置其访问权限。
* 对于进程、线程、访问token（英语：）、文件映射对象、信号量、事件、互斥锁、可等待定时器，使用 GetKernelObjectSecurity与SetKernelObjectSecurity函数
* 对于Window Station与桌面，使用GetUserObjectSecurity与SetUserObjectSecurity函数
* 对于注册表键，使用RegGetKeySecurity与RegSetKeySecurity函数
* 对于Windows服务对象，使用QueryServiceObjectSecurity and SetServiceObjectSecurity函数
* 对于打印机对象，使用GetPrinter and SetPrinter函数的PRINTER\_INFO\_2结构参数。
* 对于网络共享，使用NetShareGetInfo and NetShareSetInfo 的网络502级别。
* 对于进程创建的私有对象，使用CreatePrivateObjectSecurity, DestroyPrivateObjectSecurity, GetPrivateObjectSecurity and SetPrivateObjectSecurity函数

例子
--

```
#include <windows.h>

void main(void)
{
 SECURITY\_ATTRIBUTES sa; //和文件有关的安全结构
 SECURITY\_DESCRIPTOR sd; //声明一个SD

 BYTE aclBuffer[1024];
 PACL pacl = (PACL)&aclBuffer; //声明一个ACL，长度是1024

 BYTE sidBuffer[100];
 PSID psid = (PSID)&sidBuffer; //声明一个SID，长度是100

 DWORD sidBufferSize = 100;
 char domainBuffer[80];
 DWORD domainBufferSize = 80;
 SID\_NAME\_USE snu;
 HANDLE file;

 //初始化一个SD
 InitializeSecurityDescriptor(&sd, SECURITY\_DESCRIPTOR\_REVISION);

 //初始化一个ACL
 InitializeAcl(pacl, 1024, ACL\_REVISION);

 //查找一个用户hchen，并取该用户的SID
 LookupAccountName(0, "uidp1078", psid,&sidBufferSize, domainBuffer,&domainBufferSize, &snu);

 //设置该用户的Access-Allowed的ACE，其权限为"所有权限"
 AddAccessAllowedAce(pacl, ACL\_REVISION, GENERIC\_ALL, psid);

 //把ACL设置到SD中
 SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE);

 //把SD放到文件安全结构SA中
 sa.nLength = sizeof(SECURITY\_ATTRIBUTES);
 sa.bInheritHandle = FALSE;
 sa.lpSecurityDescriptor = &sd;

 //创建文件
 file = CreateFile("d:\\testfile",0, 0, &sa, CREATE\_NEW, FILE\_ATTRIBUTE\_NORMAL, 0);

 CloseHandle(file);
}

```

参见
--

* 信息技术安全审计（英语：）
* 授权（英语：）
* 计算机安全
* 信息安全
* 令牌 (Windows NT架构)（英语：）
* Windows SID
* SDDL（英语：）

参考资料
----

1. ↑ . Microsoft. 2008-04-24  [2008-07-16]. （原始内容存档于2017-12-22）.
2. ↑ . Microsoft.  [2008-07-16]. （原始内容存档于2008-05-05）.
3. ↑ . Microsoft. 2008-04-24  [2008-07-16]. （原始内容存档于2017-10-08）.
4. ↑   （页面存档备份，存于） What is the Windows Integrity Mechanism?
5. ↑ .  [2016-06-23]. （原始内容存档于2010-09-08）.
6. ↑ .  [2016-06-23]. （原始内容存档于2012-08-29）.
7. ↑ . Microsoft. 2004-03-23  [2008-07-25]. （原始内容存档于2008-04-16）.
8. ↑ . Microsoft. 2008-04-24  [2008-07-23]. （原始内容存档于2017-12-22）.

外部链接
----

* CACLS command description on SS64.com （页面存档备份，存于）
* SetACL SourceForge page （页面存档备份，存于）