文件安全和访问权限

由于文件是安全对象,因此对它们的访问由访问控制模型控制,该模型可控制对 Windows 中所有其他安全对象的访问。 有关此模型的详细说明,请参阅访问控制

调用 CreateFileCreateDirectoryCreateDirectoryEx 函数时,可以为文件或目录指定安全描述符。 如果为 lpSecurityAttributes 参数指定 NULL,则文件或目录将获取默认安全描述符。 文件或目录的默认安全描述符中的访问控制列表 (ACL) 是从其父目录继承的。 请注意,默认安全描述符仅在新建文件或目录时分配,而不会在重命名或移动文件或目录时分配。

若要检索文件或目录对象的安全描述符,请调用 GetNamedSecurityInfoGetSecurityInfo 函数。 若要更改文件或目录对象的安全描述符,请调用 SetNamedSecurityInfoSetSecurityInfo 函数

文件和目录的有效访问权限包括 DELETE、READ_CONTROL、WRITE_DAC、WRITE_OWNER 和 SYNCHRONIZE 标准访问权限 文件访问权限常量中的表格列出了特定于文件和目录的访问权限

尽管 SYNCHRONIZE 访问权限在标准访问权限列表中定义为在某个等待函数中指定文件句柄的权限,但在使用异步文件 I/O 操作时,应该等待正确配置的 OVERLAPPED 结构中包含的事件句柄,而不要使用具有 SYNCHRONIZE 访问权限的文件句柄进行同步

下面是文件和目录的常规访问权限

访问权限 说明
FILE_GENERIC_EXECUTE
FILE_EXECUTE
FILE_READ_ATTRIBUTES
STANDARD_RIGHTS_EXECUTE
SYNCHRONIZE
FILE_GENERIC_READ
FILE_READ_ATTRIBUTES
FILE_READ_DATA
FILE_READ_EA
STANDARD_RIGHTS_READ
SYNCHRONIZE
FILE_GENERIC_WRITE
FILE_APPEND_DATA
FILE_WRITE_ATTRIBUTES
FILE_WRITE_DATA
FILE_WRITE_EA
STANDARD_RIGHTS_WRITE
SYNCHRONIZE

 

Windows 将请求的访问权限和线程访问令牌中的信息与文件或目录对象的安全描述符中的信息进行比较。 如果比较不禁止授予所有请求的访问权限,则会将对象的句柄返回给线程并授予访问权限。 有关此过程的详细信息,请参阅线程与安全对象之间的交互

默认情况下,文件或目录访问权限的授权由与该文件或目录关联的安全描述符中的 ACL 严格控制。 具体而言,父目录的安全描述符不用于控制对任何子文件或目录的访问。 可以通过删除用户的 BYPASS_TRAVERSE_CHECKING 权限来强制实施 FILE_TRAVERSE 访问权限。 一般情况下不建议这样做,因为许多程序无法正确处理目录遍历错误。 对目录的 FILE_TRAVERSE 访问权限的主要用途是在需要与 Unix 系统实现互操作性时确保符合某些 IEEE 和 ISO POSIX 标准

Windows 安全模型为子目录提供了一种继承或阻止继承父目录安全描述符中一个或多个 ACE 的方式。 每个 ACE 包含的信息决定了它如何被继承,以及它是否对继承的目录对象产生影响。 例如,某些继承的 ACE 控制对继承目录对象的访问,这些 ACE 称为有效 ACE。 所有其他 ACE 称为仅继承的 ACE

Windows 安全模型还根据 ACE 继承规则强制将 ACE 自动继承到子对象。 这种自动继承以及每个 ACE 中的继承信息决定了安全限制如何在目录层次结构中向下传递。

请注意,不能使用拒绝访问的 ACE 来仅拒绝对文件的 GENERIC_READ 或 GENERIC_WRITE 访问权限。 这是因为,对于文件对象,GENERIC_READ 或 GENERIC_WRITE 的常规映射包括 SYNCHRONIZE 访问权限。 如果 ACE 拒绝受托人的 GENERIC_WRITE 访问权限,而受托人请求 GENERIC_READ 访问权限,则该请求将会失败,因为该请求隐式包含 ACE 隐式拒绝的 SYNCHRONIZE 访问权限,反之亦然。 不要使用拒绝访问的 ACE,而是使用允许访问的 ACE 来显式允许授予的访问权限。

管理对存储对象的访问的另一种方式是加密。 Windows 中文件系统加密的实现是加密文件系统 (EFS)。 EFS 只加密文件,而不加密目录。 加密的优势在于,它为媒体上应用的文件提供额外的保护,而不是通过文件系统和标准的 Windows 访问控制体系结构提供保护。 有关文件加密的详细信息,请参阅文件加密

在大多数情况下,读取和写入文件或目录对象安全设置的功能仅限于内核模式进程。 显然,你不希望任何用户进程能够更改专用文件或目录的所有权或访问限制。 但是,如果对文件或目录施加的访问限制不允许应用程序的用户模式进程读取该文件或目录,则备份应用程序将无法完成其文件备份作业。 备份应用程序必须能够替代文件和目录对象的安全设置才能确保完整备份。 同样,如果备份应用程序尝试在磁盘驻留副本上写入文件的备份副本,而你显式拒绝向备份应用程序进程授予写入权限,则还原操作无法完成。 在这种情况下,备份应用程序同样必须能够替代文件的访问控制设置。

SE_BACKUP_NAME 和 SE_RESTORE_NAME 访问权限是专门为备份应用程序提供此功能而创建的。 如果已在备份应用程序进程的访问令牌中授予并启用这些权限,则备份应用程序可以指定标准 READ_CONTROL 访问权限作为 dwDesiredAccess 参数的值,从而调用 CreateFile 来打开文件或目录进行备份。 但是,若要将调用进程标识为备份进程,对 CreateFile 的调用必须在 dwFlagsAndAttributes 参数中包含 FILE_FLAG_BACKUP_SEMANTICS 标志。 函数调用的完整语法如下:

HANDLE hFile = CreateFile( fileName,                   // lpFileName
                           READ_CONTROL,               // dwDesiredAccess
                           0,                          // dwShareMode
                           NULL,                       // lpSecurityAttributes
                           OPEN_EXISTING,              // dwCreationDisposition
                           FILE_FLAG_BACKUP_SEMANTICS, // dwFlagsAndAttributes
                           NULL );                     // hTemplateFile

这将允许备份应用程序进程打开文件并替代标准安全检查。 若要还原文件,备份应用程序将在打开要写入的文件时使用以下 CreateFile 调用语法

HANDLE hFile = CreateFile( fileName,                   // lpFileName
                           WRITE_OWNER | WRITE_DAC,    // dwDesiredAccess
                           0,                          // dwShareMode
                           NULL,                       // lpSecurityAttributes
                           CREATE_ALWAYS,              // dwCreationDisposition
                           FILE_FLAG_BACKUP_SEMANTICS, // dwFlagsAndAttributes
                           NULL );                     // hTemplateFile

在某些情况下,备份应用程序必须能够更改文件或目录的访问控制设置。 例如,当文件或目录的磁盘驻留副本的访问控制设置与备份副本不同时。 如果在备份文件或目录后更改了这些设置,或者文件或目录已损坏,就会发生这种情况。

在对 CreateFile 的调用中指定的 FILE_FLAG_BACKUP_SEMANTICS 标志授予备份应用程序进程读取文件或目录访问控制设置的权限。 有了此权限,备份应用程序进程就可以调用 GetKernelObjectSecuritySetKernelObjectSecurity 来读取和重置访问控制设置

如果备份应用程序必须有权访问系统级别的访问控制设置,则必须在传递给 CreateFile 的 dwDesiredAccess 参数值中指定 ACCESS_SYSTEM_SECURITY 标志

备份应用程序调用 BackupRead 来读取为还原操作指定的文件和目录,并调用 BackupWrite 来写入文件和目录

标准访问权限