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工具已經成功更新了口令數據庫。