一、介绍
作为对linux_fans提出建议的回应,本文主要描述在用户空间,和process credentials相关的内容,具体包括:
- /etc/passwd文件
- /etc/shadow文件
- /etc/group文件
- 从系统登录过程看如何使用这些文件
二、/etc/passwd文件
系统中的每一个用户都会有一个登录帐号,在系统登录的时候,用户要输入登录帐号和密码,通过系统认证之后,该用户就可以使用该计算机相关资源了。对应每一个帐号,/etc/passwd文件中都有一行来对应,一个简单的例子如下:
唐伯虎:x:9527:1004:华府的低等下人:/home/tangbohu:/bin/bash
每一行有7个域组成,“:”是分隔符,如下:
- login name
- optional encrypted password
- numerical user ID
- numerical group ID
- user name or comment field
- user home directory
- optional user command interpreter
对于一个系统用户而言,登录帐号(login name或者说是user name)是标识自己的一个字符串,在系统中是唯一的。numerical user ID是一个非负数字,和user name一样也是标识用户的(计算机系统处理数字会容易一些)。举一个简单的例子:“唐伯虎”就是一个user name,而9527(user ID)就是“唐伯虎”在华府(系统)中的终身代号。从系统用户的角度看,user ID就是确认一个用户的身份,但是对于进程,其user ID包括real user ID,effective user ID,save set-user-ID和file system user ID。
User ID可以是不唯一的。也就是说,可以有多个user name对应同样的User ID。这个特性允许不同的用户(不同的pass word)拥有同样的权限。系统中,有的时候会使用User ID作为索引,搜索user name。例如ls可以列出一个文件输出哪一个登录用户。这时候,ls进程可以从文件inod中获取其uid的信息,但是用户层面当然需要显示友好界面,于是使用uid作为index在/etc/passwd文件中检索,发现第一个符合的登录用户名就显示出来。
optional encrypted password域之所以有一个optional,因为这个域可以包含加密后的password,也可以不包含。当密码不包含在passwd文件中的时候有多种种情况,一种是大家常见的情况,该域是一个x字符,表示具体的password在/etc/shadow文件中。当该域的内容是“!”或者“!!”,表示password无效,不能用该用户登录。如果该域的内容是“*”,表示该用户被disable。如果该域的内容为空,说明该用户不需要密码,可以直接登录进入。
其他的域比较简单,可以参考man page的描述。
二、/etc/shadow文件
我们来看看shadow和passwd文件的属性:
$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1650 Mar 11 16:05 /etc/shadow
$ ls -l /etc/passwd
-rw-r--r-- 1 root root 1499 Mar 11 16:04 /etc/passwd
最开始的时候,密码信息也是保存在passwd文件中,但是由于passwd文件对于所有用户都是可读的(例如你可以在shell界面输入whoami命令,这个命令就需要访问这个文件并把进程的User ID作为索引在passwd文件中检索user name)。如果加密后的用户密码也保存在passwd中的话,所有用户都可以看到加密后的用户密码,可以采用各种手段进行攻击,从而引入安全问题。基于安全的考量,目前分成了两个文件,并且shadow对其他用户是不可读的。
shadow文件的全称是passwd shadow文件。对应每一个帐号,/etc/shadow文件中都有一行来对应,每一行有9个域组成,“:”是分隔符,如下:
1、login name
2、encrypted password
3、date of last password change
4、minimum password age
5、maximum password age
6、password warning period
7、password inactivity period
8、account expiration date
9、reserved field
对各个域的解释非常简单,这里就不再详细描述了。
三、/etc/group文件
为了方便权限的管理,GNU/Linux操作系统使用了group这样的概念,一个用户可以属于一个或者多个group,我们可以用下面的例子来理解:假设一个公司有30人,共用一个系统。这30个人被分成了3个部门:硬件部,软件部和管理部。一般而言,硬件team的文件只允许硬件team的人访问,因此对于一个文件的权限可以针对group设定,这样,可以屏蔽属于其他部门人员的访问。公司一般又会以具体的项目来组织(也就是传说中的矩阵管理),一个项目组会包括来自各个部门的人,这样一个人也有可能属于多个group。
在GNU/linux操作系统中,系统内定义的所有group的信息保存在/etc/group文件中,对应每一个group,/etc/group文件中都有一行来对应,一个简单的例子如下:
华府低等下人:x:1004:唐伯虎,石榴姐,路人甲
每一行有9个域组成,“:”是分隔符,如下:
1、 group name
2、 encrypted passwd
3、 group ID
4、 user list
类似user name和user ID,group name是人类可懂度较高的字符并且在系统内是唯一的,group ID是机器比较喜欢的数字。从系统用户的角度看,group ID就是确认用户组(包括若干用户)的身份,但是对于进程,其group ID包括real group ID,effective group ID,save set-group-ID和file system group ID。
组密码目前已经不太常用了。很久以前,unix不支持一个用户属于多个组,一个用户在一个特定的时间内只能属于一个group。不过用户可以通过newgrp命令登录到另外一个group,这时候就需要密码验证了。几个简单的例子如下:张三属于系统软件组,又属于AAA项目,那么张三应该自由的访问AAA项目以及系统软件组的文档。登录后张三属于系统软件组,但是想要访问AAA项目文档的时候必然遇到权限问题,这时候就需要调用newgrp以便可以顺利访问AAA项目文档。这样的特性一定会被使用者唾弃,因此从4.2 BSD开始,各种unix(包括linux)都支持了一个用户属于多个组的特性。
用户列表包含了属于该group的所有user。
四、从系统登录过程看如何使用这些文件
用户登录过程是这样的:系统的启动是在init进程控制下进行的,在启动的最后,init会创建getty进程(fork then exec),在若干个terminal上输出提示符并等待用户输入其用户名。每一个使用GNU/Linux的人都很熟悉这个界面。在完成用户名输入后,getty进程会加载login elf文件(exec)。Login进程会收集用户输入的password并加密。加密结果和/etc/shadow文件中login user name对应的encrypted password做比对,如果一样,那么用户认证就OK了,login做了很多事情,但是和本文相关的包括:
1、 检索/etc/group文件,获得该user name所属的group ID list,并设定该进程的supplementary group ID list。
2、 设定该进程的user ID。由于login具备root用户的权限,因此有权限进行该操作。这个操作是一个标志性的操作,此操作之前是root用户,拥有无上的权限,调用该操作之后,绚烂归于平淡,变成一个普通用户(当然,用户如果用root用户登录,其权限不变)
3、 根据/etc/passwd中的设定加载该用户对应的shell可执行文件(exec)
用户登录完成之后,在该shell启动的任何进程都属于该user。
参考链接 |
process credentials相关的用户空间文件 |