在普通权限中,用户对文件只有三种身份,就是属主、属组和其他人;每种用户身份拥有读(read)、写(write)和执行(execute)三种权限。但是在实际工作中,这三种身份实在是不够用,我们举个例子来看看。先看看示意图,如下图所示:
在CentOS 6.x系统中ACL权限默认是开启的,不需要手工开启。不过,如果你的操作系统不是CentOS 6.x,那该如何查看ACL权限是否开启了呢?可以这样查看:
[root@localhost ~]# mount
/dev/sda1 on /boot type ext4 (rw)
/dev/sda3 on / type ext4 (rw)
…省略部分输出…
#使用mount命令可以看到系统中已经挂载的分区,但是并没有看到ACL权限的设置
[root@localhost ~]# dumpe2fs -h /dev/sda3
#dumpe2fs是查询指定分区文件系统详细信息的命令
选项:
-h: 仅显示超级块中的信息,而不显示磁盘块组的详细信息
...省略部分输出...
Default mount options: user_xattr acl
...省略部分输出...
使用mount命令可以查看到系统中已经挂载的分区,而使用dumpe2fs命令可以查看到这个分区文件系统的详细信息。大家可以看到,我们的ACL权限是/dev/sda3分区的默认挂载选项,所以不需要手工挂载。不过我的Linux系统如果没有不过我的Linux系统如果没有默认挂载,则可以手工挂载吗?当然可以,执行如下命令:
[root@localhost ~]# mount -o remount, acl /
#重新挂载根分区,并加入ACL权限
使用mount命令重新挂载,并加入ACL权限。不过使用此命令是临时生效的。要想永久生效,需要修改/etc/fstab文件,命令如下:
[root@localhost ~]# vi /etc/fstab
UUID=c2ca6f57-b15c-43ea-bca0-f239083d8bd2 / ext4 defaults, acl 1 1
#加入ACL权限
[root@localhost ~]# mount -o remount /
#重新挂载文件系统或重启系统,使修改生效
我们知道了ACL权限的作用,也知道了如何开启ACL权限,接下来学习如何查看和设定ACL权限。命令如下:
[root@localhost ~]# getfacle 文件名
#查看ACL权限
[root@localhost ~]# setfacl 选项 文件名
#设定ACL权限
选项:
-m: 设定ACL权限。如果是给予用户ACL权限,则使用“u:用户名:权限”格式赋予;
如果是给予组ACL权限,则使用“g:组名:权限”格式赋予
-x: 删除指定的ACL权限
-b: 删除所有的ACL权限
-d: 设定默认ACL权限。只对目录生效,指目录中新建立的文件拥有此默认权限
-k: 删除默认ACL权限
-R: 递归设定ACL权限。指设定的ACL权限会对目录下的所有子文件生效
例子1:设定用户ACL权限
[root@localhost ~]# useradd zhangsan
[root@localhost ~]# useradd lisi
[root@localhost ~]# useradd st
[root@localhost ~]# groupadd tgroup
#添加需要试验的用户和用户组,省略设定密码的过程
[root@localhost ~]# mkdir /project
#建立需要分配权限的目录
[root@localhost ~]# chown root:tgroup /project/
#改变/project目录的属主和属组
[root@localhost ~]# chmod 770 /project/
#指定/project目录的权限
[root@localhost ~]# ll -d /project/
drwxrwx--- 2 root tgroup 4096 1月 19 04:21 /project/
#查看一下权限,已经符合要求了
#这时st学员来试听了,如何给她分配权限
[root@localhost ~]# setfacl -m u:st:rx /project/
#给用户st赋予r-x权限,使用“u:用户名:权限”格式
[root@localhost /]# cd /
[root@localhost /]# ll -d project/
drwxrwx---+ 3 root tgroup 4096 1月 19 05:20 project/
#使用ls –l查询时会发现,在权限位后面多了一个“+”,表示此目录拥有ACL权限
[root@localhost /]# getfacl project
#查看/project目录的ACL权限
# file: project ← 文件名
# owner: root ← 文件的属主
# group: tgroup ← 文件的属组
user::rwx ← 用户名栏是空的,说明是属主的权限
user:st:r-x ← 用户st的权限
group::rwx ← 组名栏是空的,说明是属组的权限
mask::rwx ← mask权限
other::--- ← 其他人的权限
我想给用户组赋予ACL权限可以吗?当然可以,命令如下:
例子2:设定用户组ACL权限
[root@localhost /]# groupadd tgroup2
#添加测试组
[root@localhost /]# setfacl -m g:tgroup2:rwx project/
#为组tgroup2分配ACL权限,使用“g:组名:权限”格式
[root@localhost /]# ll -d project/
drwxrwx---+ 2 root tgroup 4096 1月 19 04:21 project/
#属组并没有更改
[root@localhost /]# getfacl project/
# file: project/
# owner: root
# group: tgroup
user::rwx
user:st:r-x
group::rwx
group:tgroup2:rwx ← 用户组tgroup2拥有了rwx权限
mask::rwx
other::---
mask是用来指定最大有效权限的。mask的默认权限是rwx,如果我给st用户赋予了r-x的ACL权限,mj需要和mask的rwx权限“相与”才能得到st的真正权限,也就是r-x“相与”rwxtj出的值是r-x,所以st用户拥有r-x权限。如果把mask的权限改为r–,和st用户的权限相与,也就是r–“相与”r-x得出的值是r–,st用户的权限就会变为只读。大家可以这么理解:用户和用户组所设定的权限必须在mask权限设定的范围之内才能生效,mask权限就是最大有效权限。
不过我们一般不更改mask权限,只要给予mask最大权限rwx,那么任何权限和mask权限相与,得出的值都是权限本身。也就是说,我们通过给用户和用户组直接赋予权限,就可以生效,这样做更直观。
补充:逻辑与运算的运算符是“and”。可以理解为生活中所说的“并且”。也就是相与的两个值都为真,结果才为真;有一个值为假,与的结果就为假。比如A相与B,结果如下表所示:
修改最大有效权限的命令如下:
例子3:修改mask权限
[root@localhost /]# setfacl -m m:rx project/
#设定mask权限为r-x,使用“m:权限”格式
[root@localhost /]# getfacl project/
# file: project/
# owner: root
# group: tgroup
user::rwx
group::rwx #effective:r-x
mask::r-x
#mask权限变为r-x
other::---
例子5:默认ACL权限
[root@localhost /]# setfacl -m d:u:st:rx /project/
#使用“d:u:用户名:权限”格式设定默认ACL权限
[root@localhost project]# getfacl project/
# file: project/
# owner: root
# group: tgroup
user::rwx
user:st:r-x
group::rwx
group:tgroup2:rwx
mask::rwx
other::---
default:user::rwx ← 多出了default字段
default:user:st:r-x
default:group::rwx
default:mask::rwx
default:other::---
[root@localhost /]# cd project/
[root@localhost project]# touch bcd
[root@localhost project]# mkdir d2
#新建子文件和子目录
[root@localhost project]# ll
总用量 8
-rw-r--r-- 1 root root 0 1月 19 05:20 abc
-rw-rw----+ 1 root root 0 1月 19 05:33 bcd
drwxr-xr-x 2 root root 4096 1月 19 05:20 d1
drwxrwx---+ 2 root root 4096 1月 19 05:33 d2
#新建的bcd和d2已经继承了父目录的ACL权限
大家发现了吗?原先的abc和d1还是没有ACL权限,因为默认ACL权限是针对新建立的文件生效的。
例子6:递归ACL权限
[root@localhost project]# setfacl -m u:st:rx -R /project/
#-R 递归
[root@localhost project]# ll
总用量 8
-rw-r-xr--+ 1 root root 0 1月 19 05:20 abc
-rw-rwx---+ 1 root root 0 1月 19 05:33 bcd
drwxr-xr-x+ 2 root root 4096 1月 19 05:20 d1
drwxrwx---+ 2 root root 4096 1月 19 05:33 d2
#abc和d1也拥有了ACL权限
我们来看看怎么删除ACL权限,命令如下:
例子7:删除指定的ACL权限
[root@localhost /]# setfacl -x u:st /project/
#删除指定用户和用户组的ACL权限
[root@localhost /]# getfacl project/
# file: project/
# owner: root
# group: tgroup
user::rwx
group::rwx
group:tgroup2:rwx
mask::rwx
other::---
#st用户的权限已被删除
例子8:删除所有ACL权限
[root@localhost /]# setfacl -b project/
#会删除文件的所有ACL权限
[root@localhost /]# getfacl project/
# file: project/
# owner: root
# group: tgroup
user::rwx
group::rwx
other::---
#所有ACL权限已被删除
在Linux系统中我们已经学习过r(读)、w(写)、x(执行)这三种文件普通权限,但是我们在查询系统文件权限时会发现出现了一些其他权限字母,比如:
[root@localhost ~]# ll /usr/bin/passwd
-rwsr-xr-x 1 root root 25980 2月 222012 /usr/bin/passwd
大家发现了吗?在属主本来应该写x(执行)权限的位置出现了一个小写s,这是什么权限?我们把这种权限称作SetUID权限,也叫作SUID的特殊权限。这种权限有什么作用呢?我们知道,在Linux系统中,每个普通用户都可以更改自己的密码,这是合理的设置。问题是,普通用户的信息保存在/etc/passwd文件中,用户的密码实际保存在/etc/shadow文件中,也就是说,普通用户在更改自己的密码时修改了/etc/shadow文件中的加密密码,但是,看下面的代码:
[root@localhost ~]# ll /etc/passwd
-rw-r--r-- 1 root root 1728 1月 19 04:20 /etc/passwd
[root@localhost ~]# ll /etc/shadow
---------- 1 root root 1373 1月 19 04:21 /etc/shadow
/etc/passwd文件的权限是644,意味着只有超级用户root可以读/写,普通用户只有只读权限。/etc/shadow文件的权限是000,也就是没有任何权限。这意味着只有超级用户可以读取文件内容,并且可以强制修改文件内容;而普通用户没有任何针对/etc/shadow文件的权限。也就是说,普通用户对这两个文件其实都是没有写权限的,那为什么普通用户可以修改自己的权限呢?
其实,普通用户可以修改自己的密码的秘密不在于/etc/passwd和/etc/shadow这两个文件,而在于passwd命令。我们再来看看passwd命令的权限:
[root@localhost ~]# ll /usr/bin/passwd
-rwsr-xr-x. 1 root root 25980 2月 222012 /usr/bin/passwd
passwd命令拥有特殊权限SetUID,也就是在属主的权限位的执行权限上是s。可以这样来理解它:当一个具有执行权限的文件设置SetUID权限后,用户在执行这个文件时将以文件所有者的身份来执行。passwd命令拥有SetUID权限,所有者为root(Linux中的命令默认所有者都是root),也就是说,当普通用户使用passwd命令更改自己的密码的时候,实际上是在用passwd命令所有者root的身份在执行passwd命令,root当然可以将密码写入/etc/shadow文件,所以普通用户也可以修改/etc/shadow文件,命令执行完成后,该身份也随之消失。
SetUID的功能可以这样理解:
举个例子,有一个用户lamp,她可以修改自己的权限,因为passwd命令拥有SetUID权限;但是她不能查看/etc/shadow文件的内容,因为查看文件的命令(如cat)没有SetUID权限。命令如下:
[root@localhost ~]# su - lamp
[lamp@localhost ~]$ passwd
更改用户 lamp 的密码 。
为 lamp 更改 STRESS 密码。
(当前)UNIX 密码: ← 输入旧密码
新的 密码: ← 输入新密码
重新输入新的 密码:
passwd: 所有的身份验证令牌已经成功更新
#lamp可以修改自己的密码
[lamp@localhost ~]$ cat /etc/shadow
cat: /etc/shadow: 权限不够
#但是不能查看/etc/shadow文件的内容
我们画一张示意图来理解上述过程,如上图所示:
cat命令没有SetUID权限,所以就使用lamp用户身份去访问/etc/shadow文件,当然没有相应权限了。
如果把/usr/bin/passwd命令的SetUID权限取消,普通用户是不是就不能修改自己的密码了呢?试试吧:
[root@localhost ~]# chmod u-s /usr/bin/passwd
#属主取消SetUID权限
[root@localhost ~]# ll /usr/bin/passwd
-rwxr-xr-x. 1 root root 25980 2月 222012 /usr/bin/passwd
[root@localhost ~]# su - lamp
[lamp@localhost ~]$ passwd
更改用户 lamp 的密码 。
为 lamp 更改 STRESS 密码。
(当前)UNIX 密码: ← 看起来没有什么问题
新的 密码:
重新输入新的 密码:
passwd: 鉴定令牌操作错误 ← 但是最后密码没有生效
这个实验可以说明SetUID的作用了吧,不过记得一定要把/usr/bin/passwd命令的SetUID权限加回来。
那什么是SetGID呢?当s标志在属主的x位置时是SetUID,那么s标志在属组的x位置时是SetGID,简称为SGID。比如:
[root@localhost ~]# ll /usr/bin/locate
-rwx--s--x 1 root slocate 35612 8月 242010 /usr/bin/locate
和passwd命令类似,普通用户在执行locate命令的时候,会获取locate属组的组身份。locate命令是在系统中按照文件名查找符合条件的文件的,不过它不是直接搜索系统的,而是搜索/var/lib/mlocate/mlocate.db这个数据库的。
[root@localhost ~]# ll -d /tmp/
drwxrwxrwt 4 root root 4096 1月 20 06:17 /tmp/
[root@localhost ~]# useradd lamp
[root@localhost ~]# useradd lamp1
#建立测试用户lamp和lamp1,省略设置密码过程
[root@localhost ~]# su – lamp
#切换为lamp用户
[lamp@localhost ~]$ cd /tmp/
[lamp@localhost tmp]$ touch ftest
#建立测试文件
[lamp@localhost tmp]$ ll ftest
-rw-rw-r-- 1 lamp lamp 0 1月 20 06:36 ftest
[lamp@localhost tmp]$ su - lamp1
密码: ← 输入lamp1用户的密码
#切换成lamp1用户
[lamp1@localhost ~]$ cd /tmp/
[lamp1@localhost tmp]$ rm -rf ftest
rm: 无法删除"ftest": 不允许的操作
#虽然/tmp/目录的权限是777,但是拥有SBIT权限,所以lamp1用户不能删除其他用户建立的文件
说了这么多,到底该如何设置特殊权限呢?其实还是依赖chmod命令的,只不过文件的普通权限只有三个数字,例如,“755”代表属主拥有读、写、执行权限;属组拥有读、执行权限;其他人拥有读、执行权限。如果把特殊权限也考虑在内,那么权限就应该写成“4755”,其中“4”就是特殊权限SetUID了,“755”还是代表属主、属组和其他人的权限。这几个特殊权限这样来表示:
举个例子,我们手工赋予一下特殊权限:
[root@localhost ~]# touch ftest
[root@localhost ~]# chmod 4755 ftest
#赋予SetUID权限
[root@localhost ~]# ll ftest
-rwsr-xr-x 1 root root 0 1月 20 23:54 ftest
#查看一下,属主的x位变成了s
[root@localhost ~]# chmod 2755 ftest
#赋予SetGID权限
[root@localhost ~]# ll ftest
-rwxr-sr-x 1 root root 0 1月 20 23:54 ftest
#查看一下,属组的x位变成了s
[root@localhost ~]# mkdir dtest
[root@localhost ~]# chmod 1755 dtest/
#SBIT只对目录有效,所以建立测试目录,并赋予SBIT权限
[root@localhost ~]# ll -d dtest/
drwxr-xr-t 2 root root 4096 1月 20 23:56 dtest/
#查看一下,其他人的x位变成了s
我们可以把特殊权限设置为“7777”吗?命令执行是没有问题的,这样会把SetUID、SetGID、SBIT权限都赋予一个文件,命令如下:
[root@localhost ~]# chmod 7777 ftest
#一次赋予SetUID、SetGID和SBIT权限
[root@localhost ~]# ll ftest
-rwsrwsrwt 1 root root 0 1月 20 23:54 ftest
[root@localhost ~]# chmod 0755 ftest
#取消特殊权限
[root@localhost ~]# ll ftest
-rwxr-xr-x 1 root root 0 1月 20 23:54 ftest
我们讲过,在赋予权限的时候可以采用字母的方式,这对特殊权限来讲是同样适用的。比如我们可以通过“u+s”赋予SetUID权限,通过“g+s”赋予SetGID权限,通过“o+t”赋予SBIT权限。命令如下:
[root@localhost ~]# chmod u+s, g+s, o+t ftest
#设置特殊权限
[root@localhost ~]# ll ftest
-rwsr-sr-t 1 root root 0 1月 20 23:54 ftest
[root@localhost ~]# chmod u-s, g-s, o-t ftest
#取消特殊权限
[root@localhost ~]# ll ftest
-rwxr-xr-x 1 root root 0 1月 20 23:54 ftest
最后,还有一个大家要注意的问题,特殊权限只针对具有可执行权限的文件有效,不具有x权限的文件被赋予了SetUID和SetGID权限会被标记为S, SBIT权限会被标记为T,仔细想一下,如果没有可执行权限,则设置特殊权限无任何意义。命令如下:
[root@localhost ~]# chmod 7666 ftest
[root@localhost ~]# ll ftest
-rwSrwSrwT 1 root root 0 1月 20 23:54 ftest
大家也可以这样理解:S和T代表“空的”,没有任何意义。
chatrr只有root用户可以使用,用来修改文件系统的权限属性,建立凌驾于rwx基础权限之上的授权。命令格式如下:
[root@localhost ~]# chattr [+-=] [选项] 文件或目录名
选项:
+: 增加权限
-: 删除权限
=: 等于某权限
i: 如果对文件设置i属性,那么不允许对文件进行删除、改名,也不能添加和修改数据;
如果对目录设置i属性,那么只能修改目录下文件中的数据,但不允许建立和删除文件
a: 如果对文件设置a属性,那么只能在文件中增加数据,但是不能删除和修改数据;如果
对目录设置a属性,那么只允许在目录中建立和修改文件,但是不允许删除文件
e: Linux中的绝大多数文件都默认拥有e属性,表示该文件是使用ext文件系统进行
存储的,而且不能使用“chattr -e”命令取消e属性
sudo使用简单,管理员root使用visudo命令即可编辑其配置文件/etc/sudoers进行授权。命令如下:
[root@localhost ~]# visudo
…省略部分输出…
root ALL=(ALL) ALL
# %wheel ALL=(ALL) ALL ← 此行是注释的,没有生效
#这两行是系统为我们提供的模板,我们参照它写自己的就可以了
…省略部分输出…
解释一下文件的格式:
root ALL=(ALL) ALL
#用户名 被管理主机的地址=(可使用的身份) 授权命令(绝对路径)
# %wheel ALL=(ALL) ALL
#%组名 被管理主机的地址=(可使用的身份) 授权命令(绝对路径)
4个参数的具体含义如下:
例子1,授权用户lamp可以重启服务器,则由root用户添加如下行:
[root@localhost ~]# visudo
lamp ALL= /sbin/shutdown –r now
指定组名用百分号标记,如%admgroup,多个授权命令之间用逗号分隔。用户lamp可以使用sudo -l查看授权的命令列表。
[root@localhost ~]# su – lamp
#切换成lamp用户
[lamp@localhost ~]$ sudo -l
[sudo] password for lamp: ← 需要输入lamp用户的密码
User lamp may run the following commands on this host:
(root) /sbin/shutdown -r now
#可以看到lamp用户拥有了shutdown –r now的权限
提示输入密码为lamp普通用户的密码,是为了验证操作服务器的用户是不是lamp用户本人。lamp用户需要执行时,只需使用如下命令:
[lamp@localhost ~]$ sudo /sbin/shutdown -r now