2009-07-28/15:32
Dru Lavigne
01/10/2001
在第一部分里,我们已经考查了用adduser工具建立用户账号。在这个部分,我们将集中于建立用户账号时所修改的文件。
当超级用户建立一个用户账号时,会在口令数据库里添加对应于该用户的项目。实际上,你的FreeBSD系统需要更新四个口令数据库文件。让我们在仔细查看它们的格式之前先介绍一下这些文件。第一个文件称为/etc/passwd,它是个任何人都能读的ASCII文本文件:
file /etc/passwd
/etc/passwd: ASCII text
ls -l /etc/passwd
-rw-r--r-- 1 root wheel 1054 Dec 30 13:00 /etc/passwd
该文件的权限必须保持这种形式,否则很多FreeBSD工具就不能工作了。但是,在一个任何人都能读取的文件中保存口令会有安全风险的;为此,通常对应于口令的那一部分都用*来存储表示。
第二个文件是影子口令文件/etc/master.passwd。该文件包含用户口令的加密散列。我们会在将来的文章中详细讨论加密和散列;而现在,把散列想象为FreeBSD用于检测用户口令是否合法的值。
让我们来看一下该文件的类型及属性:
file /etc/master.passwd
/etc/master.passwd: ASCII text
ls -l /etc/master.passwd
-rw------- 1 root wheel 1226 Dec 30 13:00 /etc/master.passwd
影子口令文件仍然是ASCII明文文本,不过只有root可以读取了。
第三个和第四个口令文件是/etc/pwd.db和/etc/spwd.db。来看一下它们的文件类型:
file /etc/*pwd.db/etc/pwd.db: Berkeley DB Hash file (Version 2, Little
Endian, Bucket Size 4096, Bucket Shift 12, Directory Size 256, Segment Size 256,
Segment Shift 8, Overflow Point 3, Last Freed 2, Max Bucket 7, High Mask 0xf,
Low Mask 0x7, Fill Factor 32, Number of Keys 56)/etc/spwd.db: Berkeley DB
Hash file (Version 2, Little Endian, Bucket Size 4096, Bucket Shift 12,
Directory Size 256, Segment Size 256, Segment Shift 8, Overflow Point 3, Last
Freed 2, Max Bucket 7, High Mask 0xf, Low Mask 0x7, Fill Factor 32, Number of
Keys 56)
哦,它们干脆就不是ASCII文本文件了,所以就不要试图用cat、more或文本编辑器来打开它们了。这两个文件包含了与上面ASCII文本文件相同的信息,而用数据库的形式就提高了性能。这里的/etc/pwd.db是与/etc/passwd等价的数据库,它不包含任何散列。/etc/spwd.db的s表示shadow,所以它就是与etc/master.passwd等价的数据库,也不包含散列。
现在我们已经熟悉了这四文件的名称,来看一下它们包含的信息类型。以超级用户身份把/etc/master.passwd发送到屏幕上,结果看起来应该象这样:
su:
Password
more /etc/master.passwd
# $FreeBSD: src/etc/master.passwd,v 1.25 1999/09/13 17:09:07 peter Exp $
#
root:$1$hnH/w50a$tPdv5HZRsDP46FtsW8eXH/:0:0::0:0:Charlie &:/root:/bin/csh
toor:*:0:0::0:0:Bourne-again Superuser:/root:
daemon:*:1:1::0:0:Owner of many system processes:/root:/sbin/nologin
operator:*:2:5::0:0:System &:/:/sbin/nologin
bin:*:3:7::0:0:Binaries Commands and Source,,,:/:/sbin/nologin
tty:*:4:65533::0:0:Tty Sandbox:/:/sbin/nologin
kmem:*:5:65533::0:0:KMem Sandbox:/:/sbin/nologin
games:*:7:13::0:0:Games pseudo-user:/usr/games:/sbin/nologin
news:*:8:8::0:0:News Subsystem:/:/sbin/nologin
man:*:9:9::0:0:Mister Man Pages:/usr/share/man:/sbin/nologin
bind:*:53:53::0:0:Bind Sandbox:/:/sbin/nologin
uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
xten:*:67:67::0:0:X-10 daemon:/usr/local/xten:/sbin/nologin
pop:*:68:6::0:0:Post Office Owner:/nonexistent:/sbin/nologin
nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/sbin/nologin
genisis:$1$.3tvchjG$C6wtsUV9FcXF4wzBboisJ/:1001:0::0:0:User &:/home/genisis:/bin/csh
dlavigne:pZV8Ju.2sEqsY:1000:1000::0:0:Dru Lavigne:/home/dlavigne:/bin/tcsh
test::1002:1002::0:0:test:/home/test:/bin/tcsh
看起来是不是不太顺?当我们理解了它的格式以后就会容易多了。文件中每一行包含一个用户的记录,而每条记录由十个用冒号分隔的字段组成。这些字段是以下面的顺序排列的:
name:hash:uid:gid:class:change:expire:gecos:home_dir:shell
你会注意到我的FreeBSD系统有15个系统建立的系统账号;最后三个账号(genisis、dlavigne和test)是由超级用户建立的。
现在单独来看一下“dlavigne”这条记录:
dlavigne:pZV8Ju.2sEqsY:1000:1000::0:0:Dru Lavigne:/home/dlavigne:/bin/tcsh
第一个字段(dlavigne)是该用户用于登录到系统时所用的用户名。
第二个字段(pZV8Ju.2sEqsY)是加密散列;dlavigne很幸运,这并不是她在登录时键入的口令,也无法知道从该文件中读出的她的实际口令是什么。但是,注意“test”用户的第二个字段。因为那里个空白,就说明该用户没有使用口令,只要读一个该文件就知道了。再注意很多系统账号的第二个字段都是一个星号(*),这说明普通用户无法用账号进行登录。
第三个字段(1000)是用户的UID(user ID);这是FreeBSD用来区别不同用户的,所以它必须是唯一的。当我们用adduser工具,它提议从1000开始建立UID,所以我建立的所有用户都有大于1000的UID。注意用户“root”和“toor”的UID为0,这说明他们都是系统的超级用户。
第四个字段(1000)是用户的初始GID(group ID)。缺省情况下,当你在FreeBSD中建立一个用户时,会建立一个同名的组。
第五个字段(空白)是用户的类别。类别用于决定环境设定、会话记账和资源限制。我们会在将来讨论使用类别。这个字段缺省是空的。
第六个字段(0)表示口令的期限。这个字段缺省是零,表示用户无须更新他的口令。
第七个字段(0)表示用户账号的期限。如果用户账号过期,该用户将无法再登录了。这个字段缺省是零,表示账号永不过期。
第八个字段(Dru Lavigne)包含用户的“gecos”综合信息。这里可以包含用户的全名、办公地点、工作电话和家庭电话,中间只要用逗号分隔。术语“gecos”的来源很有趣。当Unix最初在Bell实验室开发时,主计算机运行的是General Electric Computer Operating System(gecos),使用该计算机的用户的地址信息都被存在口令文件的“gecos”字段中。
第九个字段(/home/dlavigne)是用户的主目录。它就是用户登录时所处的目录。
第十个字段(/bin/tcsh)是用户命令解释器shell的路径。
让我们快速地比较一下/etc/passwd和/etc/master.passwd文件。我不再需要超级用户身份来读这些文件了,所以我先退出超级用户账号:
exit
more /etc/passwd
# $FreeBSD: src/etc/master.passwd,v 1.25 1999/09/13 17:09:07 peter Exp $
#
root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/sbin/nologin
operator:*:2:5:System &:/:/sbin/nologin
bin:*:3:7:Binaries Commands and Source,,,:/:/sbin/nologin
tty:*:4:65533:Tty Sandbox:/:/sbin/nologin
kmem:*:5:65533:KMem Sandbox:/:/sbin/nologin
games:*:7:13:Games pseudo-user:/usr/games:/sbin/nologin
news:*:8:8:News Subsystem:/:/sbin/nologin
man:*:9:9:Mister Man Pages:/usr/share/man:/sbin/nologin
bind:*:53:53:Bind Sandbox:/:/sbin/nologin
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
xten:*:67:67:X-10 daemon:/usr/local/xten:/sbin/nologin
pop:*:68:6:Post Office Owner:/nonexistent:/sbin/nologin
nobody:*:65534:65534:Unprivileged user:/nonexistent:/sbin/nologin
genisis:*:1001:0:User &:/home/genisis:/bin/csh
dlavigne:*:1000:1000:Dru Lavigne:/home/dlavigne:/bin/tcsh
test:*:1002:1002:test:/home/test:/bin/tcsh
注意到它与影子口令文件很相似,只是所有的口令字段都用星号替换了用户的散列。同时,空白的和值为0的字段在此文件中都被省略了。
你还可能注意到当我们用ls -l命令以长格式列出这些口令文件时,只有root拥有这些文件的写权限。要注意有一点很重要,就是root不要用文本编辑器去直接打开这些文件进行编辑。当更改一个口令文件时,不能把对此文件的更改直接用在其它口令文件中。这应该是系统工具pwd_mkdb的工作。如果root需要更改一个口噙文件,他需要使用一个工具来把更改发送给pwd_mkdb。
用于此目的的工具之一就是vipw。命令vipw用环境变量EDITOR所定义的编辑器来打开整个口令文件,通常这个编辑器是vi,因此它会被称作“vipw”。如果出于某些原因而使你的编辑器不是vi,那你或许应该避免使用vipw工具或者把EDITOR改回vi。其它的编辑器会折行,这会摧毁象口令文件这样的系统文件,当然这是非常不好的。要使用这个工具,你应该熟练使用vi编辑器并了解十个字段所代表的含义和每个字段可接受的值。所以,只有超级用户才可以使用这个工具。
其它用于编辑口令文件的工具有chpass,它也称为chfn或chsh。任何用户都可以使用这些工具来更改口令文件中属于他们自己的值。我以用户“dlavigne”登录或运行chpass工具:
login: dlavigne
Password:
chpass
#Changing user database information for dlavigne.
Shell: /bin/tcsh
Full Name: Dru Lavigne
Office Location:
Office Phone:
Home Phone:
Other information:
~
/etc/pw.m32496: unmodified: line 1
注意到一个普通用户只限于更改他们自己的缺省shell和gecos综合信息字段。我加入了一个办公电话以查看发生什么情况。因为我在vi编辑器环境里,所以我用箭头键移到文件中适当的位置,按ESC键后再按一下a进入添加模式,然后键入电话号码123-4567。接着再按ESC,键入:wq保存更改并退出vi编辑器。然后屏幕上会显示如下信息:
chpass: updating the database...
chpass: done
接着如果我变成超级用户并寻找/etc/passwd文件中的相应项,会看到刚才的更改:
su:
Password:
more /etc/passwd
dlavigne:*:1000:1000:Dru Lavigne,,123-4567:/home/dlavigne:/bin/tcsh
注意在gecos综合字段中添加的两个逗号指出你正在读的值。它们总是这样的次序排列:
full_name,office_location,work_phone,home_phone
所以我知道123-4567是用户Dru Lavigne的工作电话。
现在,我以超级用户身份运行chpass。如果我给该命令一个用户名作为参数的话,我可以编辑属于该用户的项。来看一下超级可以为用户“dlavigne”作些什么:
chpass dlavigne
#Changing user database information for dlavigne.
Login: dlavigne
Password: pZV8Ju.2sEqsY
Uid [#]: 1000
Gid [# or name]: 1000
Change [month day year]:
Expire [month day year]:
Class:
Home directory: /home/dlavigne
Shell: /bin/tcsh
Full Name: Dru Lavigne
Office Location:
Office Phone: 123-4567
Home Phone:
Other information:
~
/etc/pw.B32584: unmodified: line 1
你应该能看懂该用户的所有十个字段了吧。超级用户账号可以用chpass带上用户名作参数来更改任何用户的记录。如果超级用户只键入:
chpass
他就可以更改root账号的记录了。chpass工具带有一些开关可使超级用户用于更改一个用户记录的特定字段;请看man 1 chpass的细节。
在所有口令数据库文件中安全更改用户口令的工具是passwd。我以“test”用户登录然后为该用户建一个口令:
login: test
注意到没有提示我输入口令,因为“test”当前只有一个空口令。我用passwd工具来更改一下:
passwd
Changing local password for test.
New password:
Retype new password:
passwd: updating the database...
passwd: done
通常,当用户更改他们的口令,系统会提示他们输入旧口令;这就避免了其他用户来更改口令了。让我们再次以“test”运行passwd工具:
passwd
Changing local password for test.
Old password:
New password:
Retype new password:
passwd: updating the database...
passwd: done
如果用户忘了他们的口令会如何?还没有彻底完蛋,因为超级用户可以为他们更改口令;当超级用户更改其它用户的口令时,系统就不会提示他输入该用户的旧口令了:
su:
Password:
passwd test
Changing local password for test.
New password:
Retype new password:
passwd: updating the database...
passwd: done
注意,超级用户要使用用户名作为passwd工具的一个参数;如果不带用户名,那更改的就是root账号的口令了。
我要介绍的最后一个更改口令文件的工具是rmuser。该工具用于删除用户账号和任何与该用户相关的东西;所以它只能由超级用户运行。让我们来删除“test”账号:
rmuser
Enter login name for user to remove: test
Matching password entry:
test:$1$P6kMmPWG$rZiu/HfaIPVwJC6hdOImc/:1002:1002::0:0:test:/home/test:/bin/tcsh
Is this the entry you wish to remove? y
Remove user's home directory (/home/test)? y
Killed process(es) belonging to test.
Updating password file, updating databases, done.
Updating group file: (removing group test -- personal group is empty) done.
Removing user's home directory (/home/test): done.
Removing user's incoming mail file /var/mail/test: done.
Removing files belonging to test from /tmp: done.
Removing files belonging to test from /var/tmp: done.
Removing files belonging to test from /var/tmp/vi.recover: done.
看,这是个很有效的工具;它不仅从口令文件中删除用户信息,还从删除用户的主目录、邮件文件和临时目录中属于该用户的任何文件。你还应该注意到,在我删除test用户前,他的口令字段已经不是空的了,看来passwd工具已经成功更新了口令数据库。