![]() |
|
| Daemon News Ezine | BSD News | BSD Mall | BSD Support Forum | BSD Advocacy | BSD Updates |
Working With ACLs in FreeBSD 5.xGrzegorz Czapliñski <gregory@prioris.mini.pw.edu.pl>In this article I will describe how to create and configure unique access permissions on files and directories using Access Control Lists (ACLs). ACLs provide an extended set of permissions for a file or directory. These permissions can be used in addition to the conventional UNIX permissions for files and directories. Standard UNIX file permissions provide read, write and execute access to three user classes:
ACLs are used to provide greater data access control for each file or directory. They enable you to define permissions for specific users and groups. Every ACL has the following syntax: [ACL tag]:[ACL qualifier]:[Access permissions] ACL tag is a scope of the file permissions to the owner, group, others, specific users, specific groups or ACL's mask. The ACL qualifier field describes the user or group associated with the ACL entry. It might be UID or user's name, GID or group's name, or empty. Access permissions are the effective permissions for [ACL tag] and are specified as:
Entry types:
ACLs are part of UFS2 filesystem shipped with FreeBSD 5.0-RELEASE as an option or FreeBSD 5.1-RELEASE as the default filesystem during the installation. To check which filesystem you have on your system type: # dumpfs /tmp | head -1 magic 19540119 (UFS2) time Fri Aug 15 19:23:30 2003 You must have ACL support compiled into the kernel too. Add: options UFS_ACL #Support for access control lists to your kernel config compile and install a new kernel according to the instructions in the June 2003 Answerman column. To enable ACLs on a partition, after newfs(1)'ing it issue the commands: # tunefs -a enable /dev/da1s1e # mount /dev/da1s1e /mountpoint # mount | grep acl /dev/da1s1e on /mountpoint (ufs, local, soft-updates, acls) This indicates that soft-updates and acls are enabled on the /dev/da1s1e partition mounted under /mountpoint. The other way to check if ACLs are enabled is to use tunefs(1) command: # tunefs -p /dev/da1s1e tunefs: ACLs: (-a) enabled tunefs: MAC multilabel: (-l) disabled tunefs: soft updates: (-n) enabled tunefs: maximum blocks per file in a cylinder group: (-e) 2048 tunefs: average file size: (-f) 16384 tunefs: average number of files in a directory: (-s) 64 tunefs: minimum percentage of free space: (-m) 8% tunefs: optimization preference: (-o) time tunefs: volume label: (-L) Before I show some examples please read the manpages for setfacl(1) and getfacl(1). The commands and their output below are separated by one empty line for clarity. On my test system I have a user calld acl and he belongs to wheel group. When you see touch(1) command in an example, that means I recreated a file after it was removed. Modifying ACLsCreate an empty file: % umask 027 % touch file.txt % ls -l file.txt -rw-r----- 1 acl wheel 0 Aug 5 22:35 file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- group::r-- other::--- The file.txt is a normal file without any ACL permissions set yet. Add an ACL permissions: % setfacl -m u::rw,g::r,u:gregory:rw file.txt (! Change "gregory" to some other username.) % ls -l file.txt -rw-rw----+ 1 acl wheel 0 Aug 5 22:41 file.txt The little "+" at the end of access rights column indicates that the file has ACL set. % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::r-- mask::rw- other::--- This command shows that owner has read/write access, group has read access, and user gregory has read/write access. I have to point now that the mask indicates the maximum permissions for user gregory. If the command was (set the mask - "m::r"): % setfacl -m u::rw,g::r,u:gregory:rw,m::r file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- # effective: r-- group::r-- mask::r-- other::--- user gregory would have read/write access, but the mask would downgrade the effective access rights to read only. There is an "-M" switch that is used to set and modify the ACL entries. The information about actual ACLs are kept in a file (in this example acls.txt). % touch file.txt Create acls.txt file which looks like: % cat acls.txt u:bin:rwx % setfacl -M acls.txt file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:bin:rwx group::r-- mask::rwx other::--- In the last example ACL entry for user bin was specified in a file acls.txt. Recalculating an ACL maskThe ACLs look as above (the last getfacl(1) command), issue a command: % setfacl -m u::rw,g::r,u:bin:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:bin:rw- user:gregory:rw- group::r-- mask::rw- other::--- Now, users gregory and bin have read/write access, and the mask has been "group" ACL entries in the resulting ACL. If the last command was: % setfacl -n -m u::rw,g::r,u:bin:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:bin:rw- # effective: r-- user:gregory:rw- # effective: r-- group::r-- mask::r-- other::--- the mask would not get recalculated (switch -n). Effective rights for users gregory and bin would be read only. Deleting an ACLTo delete an ACL entry for user bin do: % setfacl -n -x u:bin:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- # effective: r-- group::r-- mask::r-- other::--- The entry for user bin was deleted. If you want the mask not to get recalculated, remember to use the "-n" switch. If you didn't use it, the mask would be read/write now, effectively changing permissions for user gregory to read/write. To remove permanently ACL from a file issue: % setfacl -bn file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- group::r-- other::--- % ls -l file.txt -rw-r----- 1 acl wheel 0 Aug 5 23:08 file.txt Compare the above with that: % setfacl -b file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- group::r-- mask::r-- other::--- In the next example, setfacl(1) command is able to change permissions for all user classes - owner, group, others. % umask 027 % touch file.txt % ls -l file.txt -rw-r----- 1 acl wheel 0 Aug 5 23:13 file.txt % setfacl -m u::rw,g::r,o::r,u:gregory:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::r-- mask::rw- other::r-- alphax% ls -l file.txt -rw-rw-r--+ 1 acl wheel 0 Aug 5 23:12 file.txt More interesting example: % touch file.txt % ls -l total 0 -rw-r----- 1 acl wheel 0 Aug 5 23:24 file.txt % chmod 660 file.txt % ls -l total 0 -rw-rw---- 1 acl wheel 0 Aug 5 23:24 file.txt % setfacl -m u::rw,g::r,o::r,u:gregory:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::r-- mask::rw- other::r-- % ls -l total 2 -rw-rw-r--+ 1 acl wheel 0 Aug 5 23:25 file.txt % chmod 644 file.txt % ls -l total 2 -rw-r--r--+ 1 acl wheel 0 Aug 5 23:25 file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- # effective: r-- group::r-- mask::r-- other::r-- The last setfacl(1) command set the access rights as follows: user::rw- user:gregory:rw- group::r-- mask::rw- other::r-- Then I changed explicitly access rights with chmod(1) command: % chmod 644 file.txt and the access rights reapeared as: user::rw- user:gregory:rw- # effective: r-- group::r-- mask::r-- other::r-- Note, the mask is closely associated with group access rights. Changing Unix access rights with chmod(1), you also change the mask value. Consider this scenario: % touch file.txt % setfacl -m u::rw,g::rw,o::r,u:gregory:rw file.txt % ls -l file.txt -rw-rw-r--+ 1 acl wheel 0 Aug 6 20:19 file.txt % setfacl -m m::r file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- # effective: r-- group::rw- # effective: r-- mask::r-- other::r-- % ls -l file.txt -rw-r--r--+ 1 acl wheel 0 Aug 6 20:20 file.txt Changing the mask value, does change group access rights. If you see a file with a magic "+" at the end of access rights column, check it with getfacl(1). Copying ACL entries% touch file.txt % setfacl -m u::rw,g::r,u:gregory:rw file.txt % getfacl file.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::rw- mask::rw- other::r-- % getfacl file.txt | setfacl -b -n -M - file1.txt % getfacl file.txt file1.txt #file:file.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::rw- mask::rw- other::r-- #file:file1.txt #owner:1009 #group:0 user::rw- user:gregory:rw- group::rw- mask::rw- other::r-- Creating default ACLsDefault ACL entries provide a way to propagate ACL information automatically to files and directories. New files and directories inherit ACL information from their parent directory if that parent has an ACL that contains default entries. You can set default ACL entries only on directories. Example: % umask 027 % mkdir dir % ls -l total 2 drwxr-x--- 2 acl wheel 512 Aug 6 11:50 dir % getfacl dir #file:dir #owner:1009 #group:0 user::rwx group::r-x other::--- Before you set any default ACL entries for users or groups, you must set default ACL entries for owner, group, other, and ACL mask. Consider this: % setfacl -m u::rwx,m::rwx,g::rx,o::rx dir % getfacl dir #file:dir #owner:1009 #group:0 user::rwx group::r-x mask::rwx other::r-x % setfacl -dm u:gregory:rwx,m::rwx dir setfacl: acl_set_file() failed for dir: Invalid argument The correct order is: % setfacl -dm u::rwx,m::rwx,g::rx,o::rx dir 1. Set default ALC entries for directory owner, group, others and the mask. % getfacl -d dir #file:dir #owner:1009 #group:0 user::rwx group::r-x mask::rwx other::r-x To view default ACLs issue getfacl(1) with the "-d" switch. % setfacl -dm u:gregory:rwx,m::rwx dir 2. Set default ALC entry for user gregory. To see the effect of default ACLs on subdirectories issue the following commands: % mkdir dir/subdir % getfacl -d dir #file:dir #owner:1009 #group:0 user::rwx user:gregory:rwx group::r-x mask::rwx other::r-x % getfacl -d dir/subdir #file:dir/subdir #owner:1009 #group:0 user::rwx user:gregory:rwx group::r-x mask::rwx other::r-x The subdir directory successfully inherited default ACL entries from its parent. Suppose, you want to set default ACL entries for additional user bin: % setfacl -dm u:bin:rwx,m::rwx dir % getfacl -d dir #file:dir #owner:1009 #group:0 user::rwx user:bin:rwx user:gregory:rwx group::r-x mask::rwx other::r-x % getfacl -d dir/subdir #file:dir/subdir #owner:1009 #group:0 user::rwx user:gregory:rwx group::r-x mask::rwx other::r-x That new default ACL entries for addtional user bin are not visible on dir/subdir as the directory was created before the ACL entry for bin was set. To see the effect of default ACLs on files, create a file beneath the dir directory: % touch dir/file.txt % ls -l dir/file.txt -rw-r-----+ 1 acl wheel 0 Aug 6 12:14 dir/file.txt % getfacl dir/file.txt #file:dir/file.txt #owner:1009 #group:0 user::rw- user:bin:rwx # effective: r-- user:gregory:rwx # effective: r-- group::r-x # effective: r-- mask::r-- other::--- The setfacl(1) manual states: "Currently only directories may have default ACL's. Deleting default ACLsTo delete default ACLs on directories, use setfacl(1) with the "-k" switch: % setfacl -k dir % getfacl -d dir #file:dir #owner:1009 #group:0 % getfacl dir #file:dir #owner:1009 #group:0 user::rwx group::r-x other::--- To delete a default ACL entry for user bin do: % mkdir dir % setfacl -dm u::rwx,m::rwx,g::rx,o::rx dir % setfacl -dm u:gregory:rwx,u:bin:rwx,m::rwx dir % getfacl -d dir #file:dir #owner:1009 #group:0 user::rwx user:bin:rwx user:gregory:rwx group::r-x mask::rwx other::r-x Create acls.txt file which looks like: % cat acls.txt u:bin:rwx % setfacl -dX acls.txt dir alphax% getfacl -d dir #file:dir #owner:1009 #group:0 user::rwx user:gregory:rwx group::r-x mask::rwx other::r-x or simply type: % setfacl -d -x u:bin:rwx dir Things to remembersetfacl(1) always recalculates the ACL mask to allow maximum effective permissions for every ACL entry, unless the "-n" switch is used. If you use the chmod(1) command to change the file group owner permissions on a file with ACL entries, both the file group owner permissions and the ACL mask are changed to the new permissions. Be aware that the new ACL mask permissions may change the effective permissions for additional users and groups who have ACL entries on the file. ACLs are developed on FreeBSD-5.X line. Things may change rapidly from time to time. If you use any of FreeBSD-5.X follow freebsd-current mailing list. On the August 3rd, Robert Watson sent a message saying that he has modified the semantics of the application of the default ACL in combination with the umask. Becaue of the developement process you may notice differences in output, therefore I hope my article will give you good insight on ACLs. ACLs are a good way to improve filesystem security on your server. They are flexible and as a new option shipped with the UFS2 filesystem make FreeBSD a more powerful system than ever. Special thanks go to Jason McIntyre, Joe Warner and other proofreaders. |