Grokking Darwin ACLs

I have to admit, when I first heard that Apple was adding ACLs to the next version of OS X, I got a pretty nasty lump in my throat and ordered another pint of ale. I was first introduced to ACLs in DFS on AIX and I still have nightmares and flashbacks of files which can't be deleted by root and will forever remain on the disk until the next newfs. After reading through Apple's new File Services manual however, I've learned to stop fearing and start loving the ACL. Apple's implementation of ACLs on Darwin is actually very intuitive and makes a whole lot of sense.
Getting started
So - what's an ACL? An Access Control List is a set of rules that either allow or deny the privileges of performing various actions (read, write, execute, etc) to a user or group on a filesystem object such as a file or a directory. Like normal permissions, they can be inherited from parent to child and unlike normal permissions, they aren't limited to the old familiar User, Group, and Other ownership-based permissions. Filesystem objects in Tiger still retain User, Group, and Other UNIX permissions - ACLs either work with or against these permissions. Let's look at an example:
neo:/Users misha$ ls -le drwxrwxr-x + 2 misha misha 68 May 5 19:58 MyDirectory 0: user:weebl allow list,add_file 1: user:bob allow list,add_file
As you can see, the e flag for ls displays ACL information. ls in normal -la mode will show a plus sign next to the UNIX permissions for any files which have an ACL whether there are any ACL entries or not. Adding the e flag will show us the ACL entries directly following the filesystem object whose ACL they belong to. In this example, the directory "MyDirectory" is owned by the user misha and the group misha and they've both been granted rwx permissions. In addition to that, the users weebl and bob have been granted permission to add files to MyDirectory and to list its contents.
The Finder (God love it) was never a very good tool for modifying permissions on OS X and with ACLs, it's actually pretty unusable. UNIX admins will be glad to know that although you can use Workgroup Manager to change ACLs in Tiger Server, the chmod command has been updated as the weapon of choice in our war against the users. Along with the freshened ls command, adding, removing, and modifying ACLs is almost as easy as working with UNIX perms. The man page for chmod is a gold mine of information, complete with examples.
Before you go wild and starting chmoding everything in sight like I tried to after my first Tiger install, there are a couple of things to note. First off, Darwin ACLs only work with the HFS+ (extended) filesystem and secondly, a filesystem must be prepped with the fsaclctl command:
neo:/Users misha$ sudo fsaclctl -p /Volumes/panther Access control lists are not supported or currently disabled on /Volumes/panther. neo:/Users misha$ sudo fsaclctl -p /Volumes/panther -e neo:/Users misha$ sudo fsaclctl -p /Volumes/panther Access control lists are supported on /Volumes/panther.
Ed. Note: With fsaclctl you are more than welcome to use ACLs on OS X client, although I'm not sure of the usefullness of this on a client system. Also keep in mind that ACLs are extended attributes associated with the files themselves. So setting an ACL on Firewire drive means the ACLs will be there when you plug that drive into another system.
Whew. If you do happen to lock root out of a file, you can just turn off ACLs with fsaclctl, rm the file, and be back on your feet without a newfs - er diskutil reformat.
Adding entries to an ACLAn ACL entry has three components - the user or group that the rule pertains to, whether it's an "allow" or "deny" rule, and the permissions that the rule either grants or revokes. The first two components are self-explanatory, but there are a couple of caveats. First off, you cannot specify whether the entity the ACL entry pertains to is a user or a group. This means that you should be wary of having a user and a group with the same name. If you do have a user and a group with the same name, chmod picks the user as the entity. The second thing to be wary of is that access is determined by the first matching ACL entry in the list - by default the list is ordered user-deny, user-allow, group-deny, group-allow to avoid confusion, but the order can be modified with certain flags to chmod.
Ed. Note: Each entry in an ACL is called an Access Control Entity, or ACE. Each ACL contains a minimum of one ACE.
There are seventeen (ACK!) permissions which can be granted or revoked in an ACL entry. Workgroup Manager has a slightly different list which only contains thirteen. The chmod man page has detailed information about each permission. Here's a simple listing of them.
The following permissions are available for all filesystem objects:
- delete
- readattr
- writeattr
- readextattr
- writeextattr
- readsecurity
- writesecurity
- chown
The following permissions are available for directories:
- list
- search
- add_file
- add_subdirectory
- delete_child
The following permissions are available for files, links, devices, etc:
- read
- write
- append
- execute
In addition to the permissions, ACL inheritance is specified in the third part of the ACL entry by the following keywords:
- file_inherit
- directory_inherit
- limit_inherit
- only_inherit
The first two keywords are self-explanatory and probably what you want to use in most cases. limit_inherit only allows ACL entries to inherit to immediate subdirectories of the directory containing the ACL entry and only_inherit allows you to create entries that don't effect the directory whose ACL they belong to but do effect its children. It's worth noting that no inheritance is the default for an ACL entry.
That said, a simple ACL entry allowing bob to read files in a directory which will be inherited looks like this:
bob allow list,directory_inherit,file_inherit
The chmod command uses the +a flag to add an entry to an ACL. Here's an example of how to use this entry:
neo:~/MyDirectory misha$ mkdir Dir1 neo:~/MyDirectory misha$ chmod +a "bob allow list,directory_inherit,file_inherit" Dir1 neo:~/MyDirectory misha$ ls -lea total 0 drwxrwxr-x 3 misha misha 102 May 5 21:16 . drwxr-xr-x + 125 misha misha 4250 May 5 21:16 .. drwxrwxr-x + 2 misha misha 68 May 5 21:16 Dir1 0: user:bob allow list,file_inherit,directory_inherit neo:~/MyDirectory misha$ mkdir Dir1/Dir2 neo:~/MyDirectory misha$ ls -lea Dir1 total 0 drwxrwxr-x + 3 misha misha 102 May 5 21:16 . 0: user:bob allow list,file_inherit,directory_inherit drwxrwxr-x 3 misha misha 102 May 5 21:16 .. drwxrwxr-x + 2 misha misha 68 May 5 21:16 Dir2 0: user:bob inherited allow list,file_inherit,directory_inherit
To delete the ACL entry, simply use -a:
chmod -a "bob allow list,directory_inherit,file_inherit" Dir1
ACL entries can also be deleted by number:
chmod -a# 0 Dir1
When ACLs are inherited from directories to files, some funny things happen. ACL entries are translated a bit - for example, list becomes read. Consider:
neo:~/MyDirectory misha$ chmod +a "bob allow delete,chown,list,search,add_file,add_subdirectory,delete_child,file_inherit,directory_inherit" Dir1 neo:~/MyDirectory misha$ touch Dir1/File1 neo:~/MyDirectory misha$ ls -lea Dir1 total 0 drwxrwxr-x + 3 misha misha 102 May 5 21:25 . 0: user:bob allow list,add_file,search,delete,add_subdirectory,delete_child,chown,file_inherit,directory_inherit drwxrwxr-x 3 misha misha 102 May 5 21:16 .. -rw-rw-r-- + 1 misha misha 0 May 5 21:25 File1 0: user:bob inherited allow read,write,execute,delete,append,chown
This is expected behaviour. It's also worth noting that the output of ls -lea can be a bit misleading. Sometimes the ACLs show up, sometimes they don't. Witness:
neo:~ misha$ mkdir MyDirectory neo:~ misha$ chmod +a "bob allow list,directory_inherit" MyDirectory neo:~ misha$ mkdir MyDirectory/Dir1 neo:~ misha$ ls -lea MyDirectory total 0 drwxrwxr-x + 3 misha misha 102 May 5 21:35 . drwxr-xr-x 125 misha misha 4250 May 5 21:35 .. drwxrwxr-x 2 misha misha 68 May 5 21:35 Dir1
Hrm?
neo:~ misha$ ls -lea MyDirectory/Dir1 total 0 drwxrwxr-x + 2 misha misha 68 May 5 21:35 . 0: user:bob inherited allow list,directory_inherit drwxrwxr-x + 3 misha misha 102 May 5 21:35 .. 0: user:bob allow list,directory_inherit
Ah. Wierd.
ThoughtsWith seventeen different ACL permissions, UNIX permissions, users, groups, others, and of course "Locked files," things can get a little silly when you're trying to let The Boss read everyone else's files without letting him delete your filesystem by accident. That said, ACLs free the admin to create intelligent user/group mappings that reflect organizational structure, not file structure. Without ACLs, we're left adding members to groups they don't belong to just so that they'll have permission to view files that they need to fill their job function. With ACLs, weebl in sales doesn't become a member of the engineering group just so he can ready the next press release, weebl is simply given read access to the engineering group's directory, which they rightly own. This will allow for more intelligent directory service design and simplify system administration, not complicate it. And by extending existing UNIX commands instead of creating new ones, Apple has made it quite simple for us to jump on the bandwagon and utilize this feature set. Thanks!
