本系列講解了 Linux-PAM 的工作機(jī)制和配置方式帽揪,并利用幾個(gè) Linux-PAM 模塊做一些有趣的小實(shí)驗(yàn)。附錄中介紹了一些常用的 Linux-PAM 模塊辅斟。
本文的目標(biāo)讀者是期望了解 PAM 認(rèn)證機(jī)制的 Linux 用戶或者系統(tǒng)管理員转晰。如果您是開(kāi)發(fā)人員,希望編寫一個(gè)使用 PAM 認(rèn)證的應(yīng)用程序士飒,或者是為 PAM 寫插件的開(kāi)發(fā)人員查邢,本文的內(nèi)容可能并不能滿足您的需求,請(qǐng)參閱《Linux-PAM應(yīng)用開(kāi)發(fā)指南》(英文)和《Linux-PAM 模塊開(kāi)發(fā)指南》(英文)酵幕。
目錄
Linux-PAM 的配置文件(本文)
Linux-PAM 模塊一覽(未完成)
參考文獻(xiàn)(未完成)
2. Linux-PAM 的配置文件綜述
PAM 的各個(gè)模塊一般存放在 /lib/security/
或 /lib64/security/
中扰藕,以動(dòng)態(tài)庫(kù)文件的形式存在(可參閱 dlopen(3)
),文件名格式一般為 pam_*.so
芳撒。PAM 的配置文件可以是 /etc/pam.conf
這一個(gè)文件邓深,也可以是 /etc/pam.d/
文件夾內(nèi)的多個(gè)文件。如果 /etc/pam.d/
這個(gè)文件夾存在笔刹,Linux-PAM 將自動(dòng)忽略 /etc/pam.conf
芥备。
/etc/pam.conf
類型的格式如下:
服務(wù)名稱 工作類別 控制模式 模塊路徑 模塊參數(shù)
/etc/pam.d/
類型的配置文件通常以每一個(gè)使用 PAM 的程序的名稱來(lái)命令。比如 /etc/pam.d/su
舌菜,/etc/pam.d/login
等等萌壳。還有些配置文件比較通用,經(jīng)常被別的配置文件引用,也放在這個(gè)文件夾下讶凉,比如 /etc/pam.d/system-auth
染乌。這些文件的格式都保持一致:
工作類別 控制模式 模塊路徑 模塊參數(shù)
不難看出山孔,文件夾形式的配置文件中只是沒(méi)有了服務(wù)名稱這一列:服務(wù)名稱已經(jīng)是文件名了懂讯。
由于很難在時(shí)下的發(fā)行版本中找到使用 /etc/pam.conf
這一獨(dú)立文件作為 PAM 配置的例子,此處僅就 /etc/pam.d/
格式舉例台颠。在筆者安裝的 CentOS(x64) 7.2.1511 中褐望,/etc/pam.d/login
的內(nèi)容如下:
#%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth substack system-auth
auth include postlogin
account required pam_nologin.so
account include system-auth
password include system-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
session optional pam_console.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include system-auth
session include postlogin
-session optional pam_ck_connector.so
#
表示注釋。
每一行代表一條規(guī)則串前。但也可以用 \\
來(lái)放在行末瘫里,來(lái)連接該行和下一行。
例子的最后一行開(kāi)頭有一個(gè)短橫線 -
荡碾,意思是如果找不到這個(gè)模塊谨读,導(dǎo)致無(wú)法被加載時(shí),這一事件不會(huì)被記錄在日志中坛吁。這個(gè)功能適用于那些認(rèn)證時(shí)非必需的劳殖、安裝時(shí)可能沒(méi)被安裝進(jìn)系統(tǒng)的模塊。
工作類別(type)拨脉、流程棧(stack)和控制模式(control)
我們?cè)赱第一篇]({% post_url 2016-03-30-pam-tutorial-1-intro %})中接觸了 Linux-PAM 的四種工作類別(type)哆姻。在上面的例子中,工作類別作為第一列出現(xiàn)玫膀。
講到這里矛缨,我們有必要聊一聊 PAM 的流程棧(stack)概念:它是認(rèn)證時(shí)執(zhí)行步驟和規(guī)則的堆疊。在某個(gè)服務(wù)的配置文件中帖旨,它體現(xiàn)在了配置文件中的自上而下的執(zhí)行順序中箕昭。棧是可以被引用的,即在一個(gè)棧(或者流程)中嵌入另一個(gè)棧解阅。我們之后和它會(huì)有更多的接觸落竹。
第二列為控制模式(control),用于定義各個(gè)認(rèn)證模塊在給出各種結(jié)果時(shí) PAM 的行為瓮钥,或者調(diào)用在別的配置文件中定義的認(rèn)證流程棧筋量。該列有兩種形式,一種是比較常見(jiàn)的“關(guān)鍵字”模式碉熄,另一種則是用方括號(hào)([]
)包含的“返回值=行為”模式桨武。
“關(guān)鍵字”模式下,有以下幾種控制模式:
-
required
:如果本條目沒(méi)有被滿足锈津,那最終本次認(rèn)證一定失敗呀酸,但認(rèn)證過(guò)程不因此打斷。整個(gè)棧運(yùn)行完畢之后才會(huì)返回(已經(jīng)注定了的)“認(rèn)證失敗”信號(hào)琼梆。 -
requisite
:如果本條目沒(méi)有被滿足性誉,那本次認(rèn)證一定失敗窿吩,而且整個(gè)棧立即中止并返回錯(cuò)誤信號(hào)。 -
sufficient
:如果本條目的條件被滿足错览,且本條目之前沒(méi)有任何required
條目失敗纫雁,則立即返回“認(rèn)證成功”信號(hào);如果對(duì)本條目的驗(yàn)證失敗倾哺,不對(duì)結(jié)果造成影響轧邪。 -
optional
:該條目?jī)H在整個(gè)棧中只有這一個(gè)條目時(shí)才有決定性作用,否則無(wú)論該條驗(yàn)證成功與否都和最終結(jié)果無(wú)關(guān)羞海。 -
include
:將其他配置文件中的流程棧包含在當(dāng)前的位置忌愚,就好像將其他配置文件中的內(nèi)容復(fù)制粘貼到這里一樣。 -
substack
:運(yùn)行其他配置文件中的流程却邓,并將整個(gè)運(yùn)行結(jié)果作為該行的結(jié)果進(jìn)行輸出硕糊。該模式和include
的不同點(diǎn)在于認(rèn)證結(jié)果的作用域:如果某個(gè)流程棧include
了一個(gè)帶requisite
的棧,這個(gè)requisite
失敗將直接導(dǎo)致認(rèn)證失敗腊徙,同時(shí)退出棧简十;而某個(gè)流程棧substack
了同樣的棧時(shí),requisite
的失敗只會(huì)導(dǎo)致這個(gè)子棧返回失敗信號(hào)昧穿,母棧并不會(huì)在此退出勺远。
“返回值=行為”模式則更為復(fù)雜,其格式如下:
[value1=action1 value2=action2 ...]
其中时鸵,valueN
的值是各個(gè)認(rèn)證模塊執(zhí)行之后的返回值胶逢。有 success
、user_unknown
饰潜、new_authtok_reqd
初坠、default
等等數(shù)十種。其中彭雾,default
代表其他所有沒(méi)有明確說(shuō)明的返回值碟刺。返回值結(jié)果清單可以在 /usr/include/security/_pam_types.h
中找到,也可以查詢 pam(3)
獲取詳細(xì)描述薯酝。
流程棧中很可能有多個(gè)驗(yàn)證規(guī)則半沽,每條驗(yàn)證的返回值可能不盡相同,那么到底哪一個(gè)驗(yàn)證規(guī)則能作為最終的結(jié)果呢吴菠?這就需要 actionN
的值來(lái)決定了者填。actionN
的值有以下幾種:
-
ignore
:在一個(gè)棧中有多個(gè)認(rèn)證條目的情況下,如果標(biāo)記ignore
的返回值被命中做葵,那么這條返回值不會(huì)對(duì)最終的認(rèn)證結(jié)果產(chǎn)生影響占哟。 -
bad
:標(biāo)記bad
的返回值被命中時(shí),最終的認(rèn)證結(jié)果注定會(huì)失敗。此外榨乎,如果這條bad
的返回值是整個(gè)棧的第一個(gè)失敗項(xiàng)怎燥,那么整個(gè)棧的返回值一定是這個(gè)返回值,后面的認(rèn)證無(wú)論結(jié)果怎樣都改變不了現(xiàn)狀了蜜暑。 -
die
:標(biāo)記die
的返回值被命中時(shí)铐姚,馬上退出棧并宣告失敗。整個(gè)返回值為這個(gè)die
的返回值史煎。 -
ok
:在一個(gè)棧的運(yùn)行過(guò)程中谦屑,如果ok
前面沒(méi)有返回值驳糯,或者前面的返回值為PAM_SUCCESS
篇梭,那么這個(gè)標(biāo)記了ok
的返回值將覆蓋前面的返回值。但如果前面執(zhí)行過(guò)的驗(yàn)證中有最終將導(dǎo)致失敗的返回值酝枢,那ok
標(biāo)記的值將不會(huì)起作用恬偷。 -
done
:在前面沒(méi)有bad
值被命中的情況下,done
值被命中之后將馬上被返回帘睦,并退出整個(gè)棧袍患。 -
N
(一個(gè)自然數(shù)):功效和ok
類似,并且會(huì)跳過(guò)接下來(lái)的 N 個(gè)驗(yàn)證步驟竣付。如果N = 0
則和ok
完全相同诡延。 -
reset
:清空之前生效的返回值,并且從下面的驗(yàn)證起重新開(kāi)始古胆。
我們?cè)谇拔闹幸呀?jīng)介紹了控制模式(contro)的“關(guān)鍵字”模式肆良。實(shí)際上,“關(guān)鍵字”模式可以等效地用“返回值=行為”模式來(lái)表示逸绎。具體的對(duì)應(yīng)如下:
-
required
:
[success=ok new_authtok_reqd=ok ignore=ignore default=bad]
-
requisite
:
[success=ok new_authtok_reqd=ok ignore=ignore default=die]
-
sufficient
:
[success=done new_authtok_reqd=done default=ignore]
-
optional
:
[success=ok new_authtok_reqd=ok default=ignore]
模塊路徑和模塊參數(shù)
正如前文所述惹恃,模塊一般保存在 /lib/security
或 /lib64/security
中(取決于操作系統(tǒng)位數(shù))。Linux-PAM 配置文件中的模塊位置可以是相對(duì)于上述文件夾的相對(duì)路徑棺牧,也可以是文件的全路徑巫糙。
模塊參數(shù)用空格與模塊路徑相隔。該參數(shù)將只和特定模塊相關(guān)颊乘,因此某個(gè)模塊的文檔中一定包含其參數(shù)的信息参淹。如果需要在單個(gè)參數(shù)中使用空格,可以將整個(gè)參數(shù)用方括號(hào)([]
)包裹起來(lái)乏悄。