【问题标题】:Get generic folder permissions (like GENERIC_ALL) using Java's AclFileAttributeView使用 Java 的 AclFileAttributeView 获取通用文件夹权限(如 GENERIC_ALL)
【发布时间】:2014-09-29 13:16:35
【问题描述】:

我使用 Java7 中的 AclFileAttributeView 来读取 Windows 目录的文件夹权限。问题是我无法获得完整的概述,因为 AclFileAttributeView 不返回通用权限,如 GENERIC_ALL、GENERIC_WRITE、GENERIC_READ 和 GENERIC_EXECUTE(访问掩码中的四个高位)。事实上,当涉及到通用权限时,它给了我关于同一成员的其​​他 AclEntries 的错误信息。举个例子吧:

当我使用 AccessChk 之类的工具列出系统帐户的 c:\windows 的 AclEntries 时,我得到以下信息:

[2] ACCESS_ALLOWED_ACE_TYPE: NT AUTHORITY\SYSTEM
  FILE_ADD_FILE
  FILE_ADD_SUBDIRECTORY
  FILE_LIST_DIRECTORY
  FILE_READ_ATTRIBUTES
  FILE_READ_EA
  FILE_TRAVERSE
  FILE_WRITE_ATTRIBUTES
  FILE_WRITE_EA
  DELETE
  SYNCHRONIZE
  READ_CONTROL
[3] ACCESS_ALLOWED_ACE_TYPE: NT AUTHORITY\SYSTEM
    [OBJECT_INHERIT_ACE]
    [CONTAINER_INHERIT_ACE]
    [INHERIT_ONLY_ACE]
  GENERIC_ALL

如您所见,第一个 AclEntry 仅适用于文件夹本身,并且具有特殊权限 WRITE_ACL 和 WRITE_OWNER。 第二个 AclEntry 仅适用于子文件夹和文件,并包含通用权限 GENERIC_ALL。这正是我在 Windows 资源管理器的“安全”选项卡中看到的。系统帐户的两条记录,一条仅适用于文件夹(具有部分权限),一条适用于具有完全控制权的子文件夹/文件。

现在我使用以下代码运行我的 java 程序:

AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
System.out.println(view.getAcl());

这为我的系统帐户提供了以下结果:

  • NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
  • 新台币 AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW

第一个AclEntry只适用于文件夹本身,包含了所有的特殊权限,包括WRITE_ACL和WRITE_OWNER,这是不正确的!第二个 AclEntry 没有显示任何权限,因为它上面有 GENERIC_ALL!

我不确定这是哪里出错了,JRE 似乎只是解码了操作系统给出的 ACE 位掩码 (sun.nio.fs.WindowsSecurityDescriptor.decode)。

有人遇到过同样的问题吗?我会尝试一些其他的 JRE,也许会有所作为。

【问题讨论】:

  • 关于 WRITE_ACL 的外观,Java 可能会插入它,因为对象的所有权隐含地为您提供了此权限。 WRITE_OWNER 也可能如此,我不确定。不知道为什么第二个 ACL 为空 - 除非该函数的目的是为您提供有关 该特定对象 的访问权限的信息,因此排除仅继承访问权限?
  • 也许 JVM 的本机 C++ 部分正在执行一些额外的逻辑,但据我所知,它使用本机方法 WindowsNativeDispatcher.GetAce 来检索位掩码,然后调用 WindowsSecurityDescriptor.decode 其中这些位被转换为标志和权限。我认为这是导致问题的原因,此方法中未使用四个高位(用于通用权限)。所以我很害怕这只是在 JVM 中丢失,它应该(至少)将通用权限转换为特殊权限。也许有人知道读取 NTFS 权限的库?

标签: java windows permissions directory acl


【解决方案1】:

我也遇到了同样的问题。事实证明the spec for AclFileAttributeView states 它被设计为与RFC 3530: Network File System (NFS) version 4 Protocol 兼容。在 RFC 3530 中,不支持 GENERIC_* 值。我还查看了运行 JVM 的 JDK 代码源(来自 OpenJDK project,从 here 下载)。虽然在我看来,有一种方法可以通过从适当的 RFC 3530 标志到 GENERIC_* 的映射来使 JVM 兼容,但维护者显然没有。这就是您的空条目的原因 NT AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW

更糟糕的是,JVM 不支持来自 Windows 安全描述符的 SE_DACL_PROTECTED 和 SE_SACL_PROTECTED 标志(通过元标志 (UN)PROTECTED_(S/D)ACL_SECURITY_INFORMATION 设置,如 cmets here 所示。如果您使用AccessChk 工具,它实际上向您显示 有效 ACE 列表,而不是 AclFileAttributeView 和其他 Windows 工具所做的 实际 ACE 列表(查看 @987654326 @.) 这就是 ACE 数量不同的原因。在我的情况下,我有 9 个 ACE,但 AccessChk 显示了 5 个。在这 9 个中,有 4 个在 SID(用户或组)值上真正重复,其中第一个 ACE对于给定的 SID 具有权限,而给定 SID 的第二个 ACE 没有权限,而只是设置或未设置 SE_DACL_PROTECTED。

我不完全确定您想用这些 ACL 做什么,但我可能会根据您的意图为您提供解决方案。我继续对JNA project 进行了更改,以开始允许人们以更直接的方式修改 Windows 安全描述符。你可以看到我的合并拉取请求here。我不知道他们多久将版本发布到 Maven 公共存储库,因此您可能必须直接下载并编译源代码才能获得这些更改。有关如何获取对象的 SD,请参阅 GetNamedSecurityInfo。然后,您可以使用 AdvApi32Util 中的帮助 API 来操作 SECURITY_DESCRIPTOR 对象。请参阅public static SECURITY_DESCRIPTOR_RELATIVE getFileSecurityDescriptor(File file, boolean getSACL) 了解将 SD 转换为自相关格式的方法,然后该对象允许您遍历 ACL 中的 ACE。

【讨论】:

  • 我已经编译了最新的源代码,getFileSecurityDescriptor 运行良好。我之前使用过 JRE 的 setAcl 方法来修改 ACL,但是该方法依赖于旧的 setFileSecurity API 方法并且不会将更改传播到子文件夹和文件。我将从 JNA 项目中尝试您的 setFileSecurityDescriptor(因为它依赖于 setnamedsecurityinfo)。如果有一个从 SECURITY_DESCRIPTOR_RELATIVE 结构中添加或删除 ACE 的辅助方法也会很好......有什么计划吗?
  • 目前没有。问题是事情基本上是一个连续的字节数组,成员只是指向该数组的指针。就地操作会很棘手。最好使用新的构造函数在对象的副本上执行此操作,该构造函数采用所有者、组、dacl、sacl 并利用更多较低级别的 api,例如 SetEntriesInAcl。我确实有 ACL 操作的计划,但可能需要 3-4 个月。
【解决方案2】:

我最终使用反射来获取 ACE 的访问掩码(使用 sun.nio.fs.WindowsNativeDispatcher.GetAce)。使用访问掩码,我检查四个高位以确定通用权限。

它还允许我获得 INHERITED_ACE 位,这在 JRE 规范中不可用。我得到了“原始”ACL 信息,它比 Windows 安全选项卡要多得多。例如,我的 c:\ 驱动器为 BUILT-IN\Administrators 提供了两个 ACE,一个具有 GENERIC_ALL 权限并传播到子文件夹和文件(不是容器本身),另一个具有应用的特殊权限,根本没有标志(仅适用于当前容器)。这就是 Windows 使用这些通用权限的方式。这同样适用于子文件夹,如 Program Files 目录,传播通用权限,每个子容器都有一个单独的 ACE,用于仅适用于容器本身的实际特殊权限。

关于AccessChck工具,你确定使用-l参数吗?这提供了更多信息和“原始”ACL 信息。

我已经使用 JNA 项目从服务器检索本地组。感谢您提供有关 AdvApi32Util 的提示!我会仔细看看的。您对 JRE 中的 setACL 方法的体验如何?

我使用所有这些来发布一个工具,该工具将来自 LDAP 的组成员身份与在目录和文件中找到的 ACL 信息相结合。所有这些信息都保存在本地数据库(或外部)中,可用于创建概览。此概述提供了许多过滤器选项并显示特定用户或一组用户(包括嵌套组成员身份)的权限信息。因为所有内容都保存在数据库中,所以它可以在几秒钟内为您提供概览,而不是每次都扫描整个网络。您还可以跟踪权限,它显示权限来自哪里,来自哪个组成员或来自哪个文件夹等。它将包含修改单个 ACE 的功能,但重点是查看权限。

该工具已准备好进行测试;)如果您有兴趣,请告诉我...该工具不是免费的,因为我花了很多时间来编写,但如果您有需要请告诉我'重新感兴趣。我可以给你一个执照。请参阅以下链接以获得快速印象。别介意这个网站,它仍然提到了该工具的旧版本。

Scan screenshot
Overview screenshot

Permission Analyzer 64bit
Permission Analyzer 32bit
Permission Analyzer 64bit with embedded JRE
Permission Analyzer 32bit with embedded JRE

【讨论】:

    猜你喜欢
    • 2014-05-04
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 2019-09-13
    • 2014-01-05
    • 2018-07-29
    • 2021-09-05
    相关资源
    最近更新 更多