本系列講解了 Linux-PAM 的工作機(jī)制和配置方式,并利用幾個(gè) Linux-PAM 模塊做一些有趣的小實(shí)驗(yàn)。附錄中介紹了一些常用的 Linux-PAM 模塊。
本文的目標(biāo)讀者是期望了解 PAM 認(rèn)證機(jī)制的 Linux 用戶或者系統(tǒng)管理員。如果您是開發(fā)人員,希望編寫一個(gè)使用 PAM 認(rèn)證的應(yīng)用程序,或者是為 PAM 寫插件的開發(fā)人員,本文的內(nèi)容可能并不能滿足您的需求,請(qǐng)參閱《Linux-PAM應(yīng)用開發(fā)指南》(英文)和《Linux-PAM 模塊開發(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 的程序的名稱來命令。比如 /etc/pam.d/su,/etc/pam.d/login 等等。還有些配置文件比較通用,經(jīng)常被別的配置文件引用,也放在這個(gè)文件夾下,比如 /etc/pam.d/system-auth。這些文件的格式都保持一致:
工作類別 控制模式 模塊路徑 模塊參數(shù)
不難看出,文件夾形式的配置文件中只是沒有了服務(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ī)則。但也可以用 \\ 來放在行末,來連接該行和下一行。
例子的最后一行開頭有一個(gè)短橫線 -,意思是如果找不到這個(gè)模塊,導(dǎo)致無法被加載時(shí),這一事件不會(huì)被記錄在日志中。這個(gè)功能適用于那些認(rèn)證時(shí)非必需的、安裝時(shí)可能沒被安裝進(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)證流程棧。該列有兩種形式,一種是比較常見的“關(guān)鍵字”模式,另一種則是用方括號(hào)([])包含的“返回值=行為”模式。
“關(guān)鍵字”模式下,有以下幾種控制模式:
-
required:如果本條目沒有被滿足,那最終本次認(rèn)證一定失敗,但認(rèn)證過程不因此打斷。整個(gè)棧運(yùn)行完畢之后才會(huì)返回(已經(jīng)注定了的)“認(rèn)證失敗”信號(hào)。 -
requisite:如果本條目沒有被滿足,那本次認(rèn)證一定失敗,而且整個(gè)棧立即中止并返回錯(cuò)誤信號(hào)。 -
sufficient:如果本條目的條件被滿足,且本條目之前沒有任何required條目失敗,則立即返回“認(rèn)證成功”信號(hào);如果對(duì)本條目的驗(yàn)證失敗,不對(duì)結(jié)果造成影響。 -
optional:該條目?jī)H在整個(gè)棧中只有這一個(gè)條目時(shí)才有決定性作用,否則無論該條驗(yàn)證成功與否都和最終結(jié)果無關(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 代表其他所有沒有明確說明的返回值。返回值結(jié)果清單可以在 /usr/include/security/_pam_types.h 中找到,也可以查詢 pam(3) 獲取詳細(xì)描述。
流程棧中很可能有多個(gè)驗(yàn)證規(guī)則,每條驗(yàn)證的返回值可能不盡相同,那么到底哪一個(gè)驗(yàn)證規(guī)則能作為最終的結(jié)果呢?這就需要 actionN 的值來決定了。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)證無論結(jié)果怎樣都改變不了現(xiàn)狀了。 -
die:標(biāo)記die的返回值被命中時(shí),馬上退出棧并宣告失敗。整個(gè)返回值為這個(gè)die的返回值。 -
ok:在一個(gè)棧的運(yùn)行過程中,如果ok前面沒有返回值,或者前面的返回值為PAM_SUCCESS,那么這個(gè)標(biāo)記了ok的返回值將覆蓋前面的返回值。但如果前面執(zhí)行過的驗(yàn)證中有最終將導(dǎo)致失敗的返回值,那ok標(biāo)記的值將不會(huì)起作用。 -
done:在前面沒有bad值被命中的情況下,done值被命中之后將馬上被返回,并退出整個(gè)棧。 -
N(一個(gè)自然數(shù)):功效和ok類似,并且會(huì)跳過接下來的 N 個(gè)驗(yàn)證步驟。如果N = 0則和ok完全相同。 -
reset:清空之前生效的返回值,并且從下面的驗(yàn)證起重新開始。
我們?cè)谇拔闹幸呀?jīng)介紹了控制模式(contro)的“關(guān)鍵字”模式。實(shí)際上,“關(guān)鍵字”模式可以等效地用“返回值=行為”模式來表示。具體的對(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)([])包裹起來。