Search code examples
javawindowspermissionsdirectoryacl

Get generic folder permissions (like GENERIC_ALL) using Java's AclFileAttributeView


I use the AclFileAttributeView from Java7 to read the folder permissions of a Windows directory. The problem is that I'm not able to get a complete overview because the AclFileAttributeView doesn't return generic permissions like GENERIC_ALL, GENERIC_WRITE, GENERIC_READ and GENERIC_EXECUTE (the four high-order bits in the access mask). In fact, when it comes to generic permissions it gives me wrong information about other AclEntries for the same member. Let me give an example:

When I use a tool like AccessChk to list the AclEntries of c:\windows for the System account I get the following:

[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

As you can see the first AclEntry only applies to the folder itself and has not the special permissions WRITE_ACL and WRITE_OWNER. The second AclEntry applies only to subfolders and files and contains the generic permission GENERIC_ALL. This is exactly how I see it in the Security tab of Windows Explorer. Two records for the System account, one applies only to the folder (with a subset of permissions) and one applies to subfolders/files with Full control.

Now I run my java program using the following code:

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

This gives my the following results for the System account:

  • 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
  • NT AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW

The first AclEntry applies only to the folder itself and contains all the special permissions, including WRITE_ACL and WRITE_OWNER, which is not correct! The second AclEntry doesn't show any permissions, because it has GENERIC_ALL on it!

I'm not sure where this goes wrong, it seems the JRE just decodes the ACE bitmask given by the OS (sun.nio.fs.WindowsSecurityDescriptor.decode).

Has anyone experienced these same issues? I will try some other JRE's, perhaps that makes a difference.


Solution

  • I too ran into this same issue. As it turns out the spec for AclFileAttributeView states it is designed to be compatible with RFC 3530: Network File System (NFS) version 4 Protocol. In RFC 3530, there is no support for GENERIC_* values. I also looked at the JDK code source (From OpenJDK project downloaded from here) which runs the JVM. While it seems to me that there would be a way to make the JVM compatible by mapping from the appropriate RFC 3530 flags to and from GENERIC_*, the maintainers clearly have not. This is the reason for your empty entry NT AUTHORITY\SYSTEM:FILE_INHERIT/DIRECTORY_INHERIT/INHERIT_ONLY:ALLOW

    Worse yet, the JVM does NOT support the SE_DACL_PROTECTED and SE_SACL_PROTECTED flags from Windows Security descriptors (which are set via the meta flags (UN)PROTECTED_(S/D)ACL_SECURITY_INFORMATION as indicated in comments here. If you use the tool AccessChk, it actually shows you the effective ACE list not the actual ACE list, which AclFileAttributeView and other Windows tools do (look at FileTest.) This is the reason why the number of ACEs are different. In my case, I had 9 ACEs but AccessChk showed 5. 4 out of those 9 where really duplicates on the SID (the user or group) value where the 1st ACE for a given SID had permissions and the 2nd ACE for a given SID had NO permissions, but just the SE_DACL_PROTECTED set or not set.

    I'm not entirely sure what it is you wanted to DO with these ACLs, but I may have a solution for you depending upon your intent. I went ahead and made changes to the JNA project to start allowing one to modify Windows Security Descriptors in a more direct way. You can see my merged pull request here. I don't know how often they publish versions to the Maven public repo, so you may have to download and compile the source directly to get those changes. See the GetNamedSecurityInfo for how to get the SD of an object. Then, you can use the help APIs in AdvApi32Util to maninuplate the SECURITY_DESCRIPTOR objects. See public static SECURITY_DESCRIPTOR_RELATIVE getFileSecurityDescriptor(File file, boolean getSACL) for a way to get the SD into self relative format and then that object allows you to walk the ACEs in the ACL.