分类: 系统运维
2012-03-29 12:24:15
UNIX系统的密码文件,被POSIX.1称为用户数据库,包含了下表所示的域。这些域包含在定义于
/etc/passwd文件的域 | ||||||
描述 | 结构体passwd的成员 | POSIX.1 | FreeBSD 5.2.1 | Linux 2.4.22 | Mac OS X 10.3 | Solaris 9 |
用户名 | char *pw_name | * | * | * | * | * |
加密密码 | char *pw_passwd | * | * | * | * | |
数值化用户ID | uid_t pw_uid | * | * | * | * | * |
数值化组ID | gid_t pw_gid | * | * | * | * | * |
注解域 | char *pw_gecos | * | * | * | * | |
初始工作目录 | char *pw_dir | * | * | * | * | * |
初始外壳(用户程序) | char *pw_shell | * | * | * | * | * |
用户访问类 | char *pw_class | * | * | |||
下次修改密码的时间 | time_t pw_change | * | * | |||
帐户到时时间 | time_t pw_expire | * | * |
注意POSIX.1只指定了passwd结构里十个域里的五个。多数平台支持至少七个域。基于BSD的平台支持所有的域。
历史上,密码文件存储在/etc/passwd里,并且是个ASCII文件。每行包含着上表描述的域,以冒号分隔。例如,Linux上的/etc/passwd文件的四行可能是:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
rwhod:x:119:65534::/var/spool/rwho:/bin/null
注意关于这些项的以下几点:
1、通常有一个名为root的项。这个项有个值为0的用户ID(超级用户)。
2、加密密码域包含单个字符,作为占位符。早期UNIX系统版本使用该域存储加密密码。因为在一个对所有人可读的文件里存储加密密码是一个安全漏洞,所以加密密码被存储在其它地方。我们将在下节讨论密码时更深入地讨论这个问题。
3、密码文件项的一些域可以为空。如果加密密码域为空,它通常表示这个用户没有密码。(这不被提倡。)项rwhod有一个空白域:注解域。一个空注解域没有效果。
4、shell域包含了可执行程序的路径,它作为用户的登录shell。一个空的shell域的默认值通常为/bin/sh。虽然这样,注意,项
rwhod有一个/dev/null的登录shell。显然,这是一个设备,而且不能执行,所以它这里的使用是阻止任何人作为用户rwhod登录我们的系
统。许多服务都为后台进程(第13章)有独立的用户ID,来帮助实现这个服务。
5、/dev/null有几个替代品,都可以阻止特定用户登录一个系统。常见的有/bin/false,它简单地退出并返回一个不成功(非0)的状
态;shell视这个状态为false。另一个常见的是/bin/true,它做的只是返回一个成功(0)状态。一些系统提供nologin命令,它打印
一个可定制的错误信息,并返回一个非0状态并退出。
6、nobody用户名可以用来登录一个系统,但它的用户ID(65534)和组ID(65534)没有提供任何权限。这个用户ID和组ID能访问的文件只有对所有人可读可写的文件。(它假设没有任何属于用户ID65534和组ID65534的文件,这也应该是这样。)
7、一些提供finger命令的系统在注解域支持额外的信息。这些域的由冒号分隔:用户名、办公地点、办公电话以及家庭电话。此外,在注释域里的一个与号(ampersand,&)被一个(转换的)用户名通过一些工具代替。例如,我们可能有:
someone:x:988:1004:Mr. Someone, Shang hai NanJing Rd., 021-12345678, 021-87654321:/home/here:/bin/null
通过finger命令来打印someone的信息:
$ finger -p someone
Login: someone Name: Mr. Someone
Directory: /home/here Shell: /bin/null
Office: Shang hai NanJing Rd. Office Phone: 021-12345678
Home Phone: 021-87654321
Never logged in.
No mail.
即使你的系统不支持finger命令,这些域仍然可以在注释域中,只是这些域只是简单一个注解,而不被系统工具解释。
一些系统提供了vipw命令,允许管理员修改密码文件。vipw命令把改变序列化到密码文件,并保证额外的文件与做过的改变一致。这在通过GUI提供相似功能的系统上也很普遍。
POSIX.1只定义了两个函数来从密码文件中得到项。这些函数允许我们通过用户名或用户ID查找一个项。
getpwuid函数被ls程序使用,来把包含在一个i-node里的用户ID数值映射到一个用户登录名。getpwnam函数被login函数使用,当我们输入我们的登录名的时候。
两个函数都返回一个指向passwd结构体的指针,并填满它。这个结构体通常是这个函数的一个静态变量,所以它的内容在每次我们调用这些函数的时候会被覆写。
这两个POSIX.1函数在我们要查找登录名或用户ID时都很好,但一些程序想遍历整个密码文件。有以下三个函数可以用:
这三个函数不是基本POSIX.1的一部分,而是定义在SUS的XSI扩展里。如此,所有UNIX系统都需要支持它们。
我们调用getpwent函数来返回密码文件的下个项。和那两个POSIX.1函数一样,getpwent返回一个由它填满的结构体的指针。这个结构体通 常在我们每次调用这个函数的时候被覆写。如果这是第一次调用这个函数,它会打开任何它使用的文件。当我们使用这个函数时没有隐含的顺序:这些项可以是任何 顺序,因为一些系统使用文件/etc/passwd的哈希版本。
函数setpwent回退任何它使用的文件,而endpwent关闭这些文件。当使用getpwent时,我们必须总是保证在完成后调用endpwent
来关闭它们。尽管getpwent足够智能,知道它何时必须打开它的文件(我们每一次调用它的时候),但它从不知道我们什么时候完成。
下面的代码是getpwnam的一个实现: