歡迎您光臨本站 註冊首頁

Linux PAM 介紹

←手機掃碼閱讀     火星人 @ 2014-03-24 , reply:0

PAM入門介紹




PAM (Pluggable Authentication Modules )是由Sun提出的一種認證機制。它通過提供一些動態鏈接庫和一套統一的API,將系統提供的服務和該服務的認證方式分開,使得系統管理員可以靈活地根據需要給不同的服務配置不同的認證方式而無需更改服務程序,同時也便於向系統中添加新的認證手段。PAM最初是集成在Solaris中,目前已移植到其它系統中,如Linux、SunOS、HP-UX 9.0等。





一、PAM的結構

PAM的整個框架結構如下圖所示:






用 統-------PAM
-------服------- 核---------不同認證機制
戶 務------- 心
|
|
系統管理員--PAM配置文件



1.系統管理員通過PAM配置文件來制定認證策略,指定什麼服務該用什麼樣的認證方法;

2.應用程序開發者通過在服務程序中使用PAM API而實現對認證方法的調用;

3.PAM服務模塊開發者則利用PAM SPI來編寫認證模塊,將不同的認證機制加入到系統;

4.PAM核心庫(libpam)讀取配置文件,以此為根據將服務程序和相應認證方法聯繫起來;




二、PAM支持的四種管理界面:

1、認證管理(authentication management)
接受用戶名和密碼,進而對該用戶的密碼進行認證,並負責設置用戶的一些秘密信息。


2、帳戶管理(account management)
檢查帳戶是否被允許登錄系統,帳號是否已經過期,帳號的登錄是否有時間段的限制等等。


3、密碼管理(password management)
主要是用來修改用戶的密碼。


4、會話管理(session management)
主要是提供對會話的管理和記賬(accounting)。

三、PAM的文件:

/usr/lib/libpam.so.* PAM核心庫
/etc/pam.conf ,/etc/pam.d/* PAM配置文件
/usr/lib/security/pam_*.so 可動態載入的PAM service module



對於RedHat,其目錄不是/usr/lib,而是/lib。



四、PAM的配置:

PAM的配置是通過單個配置文件/etc/pam.conf,RedHat還支持另外一種配置方式,即通過配置目錄/etc/pam.d/,且這種的優先順序要高於單個配置文件的方式。


1、使用配置文件/etc/pam.conf

該文件是由如下的行所組成的:



service-name module-type control-flag module-path arguments


服務名(service-name):

比如telnet、login、ftp等,服務名字「OTHER」代表所有沒有在該文件中明確配置的其它服務。


模塊類型(module-type):

模塊類型有四種(auth、account、session、password)即對應PAM所支持的四種管理方式。同一個服務可以調用多個PAM模塊進行認證,這些模塊構成一個stack。


control-flag :

用來告訴PAM庫該如何處理與該服務相關的PAM模塊的成功或失敗情況。

它有四種可能的值:required,requisite,sufficient,optional。



·required :表示本模塊必須返回成功才能通過認證,但是如果該模塊返回失敗的話,失敗結果也不會立即通知用戶,而是要等到同一stack中的所有模塊全部執行完畢再將失敗結果返回給應用程序。可以認為是一個必要條件。



·requisite :該模塊必須返回成功才能通過認證,但是一旦該模塊返回失敗,將不再執行同一stack內的任何模塊,而是直接將控制權返回給應用程序。是一個必要條件。註:這種只有RedHat支持,Solaris不支持。



·sufficient :表明本模塊返回成功已經足以通過身份認證的要求,不必再執行同一stack內的其它模塊,但如果本模塊返回失敗的話可以忽略,可認為是一個充分條件。



·optional :表明本模塊是可選的,它的成功與否不會對身份認證起關鍵作用,其返回值一般被忽略。



module-path :

用來指明本模塊對應的程序文件的路徑名,一般採用絕對路徑,如果沒有給出絕對路徑,默認該文件在目錄/usr/lib/security下面。


arguments :

是用來傳遞給該模塊的參數。一般來說每個模塊的參數都不相同,可以由該模塊的開發者自己定義,但是也有以下幾個共同的參數:



·debug :該模塊應當用syslog( )將調試信息寫入到系統日誌文件中。

·no_warn :表明該模塊不應把警告信息發送給應用程序。

·use_first_pass :該模塊不能提示用戶輸入密碼,只能從前一個模塊得到輸入密碼。

·try_first_pass :該模塊首先用前一個模塊從用戶得到密碼,如果該密碼驗證不通過,再提示用戶輸入新的密碼。

·use_mapped_pass 該模塊不能提示用戶輸入密碼,而是使用映射過的密碼。

·expose_account 允許該模塊顯示用戶的帳號名等信息,一般只能在安全的環境下使用,因為泄漏用戶名會對安全造成一定程度的威脅。





2、使用配置目錄/etc/pam.d/(只適用於RedHat Linux)

該目錄下的每個文件的名字對應服務名,例如ftp服務對應文件/etc/pam.d/ftp。如果名為xxxx的服務所對應的配置文件 /etc/pam.d/xxxx不存在,則該服務將使用默認的配置文件/etc/pam.d/other。每個文件由如下格式的文本行所構成:


module-type control-flag module-path arguments


每個欄位的含義和/etc/pam.conf中的相同。



3、配置的例子

例一:用/etc/pam.conf配置默認的認證方式。

下面的例子將拒絕所有沒有在/etc/pam.conf中明確配置的服務。OTHER代表沒有明確配置的其它所有服務,pam_deny模塊的作用只是簡單地拒絕通過認證。


OTHER auth required /usr/lib/security/pam_deny.so
OTHER account required /usr/lib/security/pam_deny.so
OTHER password required /usr/lib/security/pam_deny.so
OTHER session required /usr/lib/security/pam_deny.so


例二:通過/etc/pam.d/rsh文件配置rsh服務的認證方式。

rsh服務認證用戶時,先使用/etc/hosts.equiv和.rhosts文件的認證方式,然後再根據/etc/nologin文件的存在與否來判斷是否允許該用戶使用rsh,最後使用password database來認證用戶。

auth required /lib/security/pam_rhosts_auth.so
auth required /lib/security/pam_nologin.so
account required /lib/security/pam_pwdb.so
session required /lib/security/pam_pwdb.so


例三:通過/etc/pam.conf配置ftpd的認證方式。

下面是ftpd服務利用PAM模塊進行用戶認證的三個步驟。

首先用pam_ftp模塊檢查當前用戶是否為匿名用戶,如果是匿名用戶,則sufficient控制標誌表明無需再進行後面的認證步驟,直接通過認證;否則繼續使用pam_unix_auth模塊來進行標準的unix認證,即用 /etc/passwd和/etc/shadow進行認證;

通過了pam_unix_auth模塊的認證之後,還要繼續用pam_listfile模塊來檢查該用戶是否出現在文件/etc/ftpusers中,如果是則該用戶被deny掉。


ftpd auth sufficient pam_ftp.so
ftpd auth required pam_unix_auth.so use_first_pass
ftpd auth required pam_listfile.so onerr=succeed item=user sense=deny file=/etc/ftpusers


五、密碼映射(password-mapping)

密碼映射允許用戶在不同的認證機制下使用不同的密碼,其中有一個主密碼(primary password),其它密碼為次密碼(secondary passwords,可能有多個)。主密碼用來對次密碼進行加密。在主密碼認證通過後,認證模塊利用主密碼將加密過的次密碼(也稱為mapped password)解密,並對次密碼進行認證。
註:如果使用了一次性密碼的機制,就不使用密碼映射。

所有服務模塊必須支持如下4個映射選項(在第四部分已經簡單解釋過):

1、use_first_pass
這個選項指示本模塊不能提示用戶輸入密碼,而是使用已有的密碼,即從第一個向用戶提示輸入密碼的模塊那裡取得密碼,並對該密碼進行認證。

2、try_first_pass
這個選項指示本模塊首先嘗試使用已有的密碼,即從第一個向用戶提示輸入密碼的模塊那裡取得密碼,並對該密碼進行認證。如果密碼認證失敗,則再提示用戶輸入密碼。

3、use_mapped_pass
這個選項指示本模塊不能向用戶提示輸入密碼,而應使用映射過的密碼,即利用主密碼將加密過的次密碼解密出來並進行認證。

4、try_mapped_pass
這個選項指示本模塊首先嘗試使用映射過的密碼,即利用主密碼將加密過的次密碼解密出來並進行認證。如果密碼認證失敗,則再提示用戶輸入密碼。

密碼映射的例子:

下面是/etc/pam.conf中關於login服務的配置。

這裡login共有3種認證機制:Kerberos、UNIX和RSA認證,兩個 required控制標誌表明用戶必須通過Kerberos認證和UNIX認證才能使用login服務,optional選項則說明RSA認證是可選的。首先用戶輸入主密碼進行Kerberos認證;use_mapped_pass選項指示UNIX認證模塊利用主密碼將用於UNIX認證的次密碼解密出來並對該次密碼進行認證;try_first_pass選項指示RSA認證模塊先使用第一個模塊(即Kerberos模塊)的密碼作為進行認證的密碼,當對該密碼認證失敗時才提示用戶輸入用於RSA認證的次密碼。


login auth required pam_kerb_auth.so debug
login auth required pam_unix_auth.so use_mapped_pass
login auth optional pam_rsa_auth.so try_first_pass



六、PAM API

1、框架API:
任何一個支持PAM的服務程序在進行認證時必須以pam_start( )開始進行初始化,最後以pam_end( )結束以便進行清理工作。

2、認證管理API:
pam_authenticate( )對用戶名/密碼進行認證。
pam_setcred( )用來修改用戶的秘密信息。

3、帳戶管理API:
pam_acct_mgmt( )檢查帳戶本身是否有許可權登錄系統、帳戶是否過期、帳戶是否有登錄時間限制等。

4、密碼管理API:
pam_chauthtok( )修改用戶的密碼。

5、會話管理API:
一個會話以pam_open_session( )開始,最後以pam_close_session( )結束。

6、其它:
pam_get_item( )、pam_set_item( )用來讀寫PAM事務(transaction)的狀態信息。
pam_get_data( )、pam_set_data( )用來取得和設置PAM模塊及會話的相關信息。
pam_putenv( )、pam_getenv( )、pam_getenvlist( )用來讀寫環境變數。
pam_strerror( )返回相關的錯誤信息。


例子程序(摘自Sun的白皮書):

下面的例子使用PAM API寫了一個簡單的login服務程序(註:這不是個完整的程序,所以省略了對pam_close_session的調用)。

#include

/* 回調函數 */
static int login_conv(int num_msg, struct pam_message **msg, struct pam_response **response, void *appdata_ptr);


struct pam_conv pam_conv = {login_conv, NULL};



/* 進行認證的PAM句柄 */
pam_handle_t *pamh;

void main(int argc, char *argv[], char **renvp){


/* 初始化,並提供一個回調函數 */
if ((pam_start("login", user_name, &pam_conv, &pamh)) != PAM_SUCCESS) login_exit(1);

/* 設置一些參數 */
pam_set_item(pamh, PAM_TTY, ttyn);
pam_set_item(pamh, PAM_RHOST, remote_host);

while (!authenticated && retry < MAX_RETRIES){



/* 密碼認證管理,檢查用戶輸入的密碼是否正確 */
status = pam_authenticate(pamh, 0);



authenticated = (status == PAM_SUCCESS);
}

if (status != PAM_SUCCESS){



/* 顯示錯誤原因 */
fprintf(stderr,"error: %s\n", pam_strerror(pamh, status));

login_exit(1);
}

/* 通過了密碼認證之後再調用帳戶管理API,檢查用戶帳號是否已經過期 */
if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS){
if (status == PAM_AUTHTOK_EXPIRED){



/* 過期則要求用戶更改密碼 */
status = pam_chauthtok(pamh, 0);
if (status != PAM_SUCCESS) login_exit(1);
}
}

/* 通過帳戶管理檢查之後則打開會話 */
if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)
login_exit(status);

/* 設置用戶組 */
setgid(pwd->pw_gid);

/*
* Initialize the supplementary group access list before
* pam_setcred because PAM modules might add groups
* during the pam_setcred call
*/
initgroups(user_name, pwd->pw_gid);

status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
if (status != PAM_SUCCESS) login_exit(status);

/* 設置真實的用戶ID(或者有效的用戶ID)*/
setuid(pwd->pw_uid);


/* PAM事務的結束 */
pam_end(pamh, PAM_SUCCESS);

}

/* 出錯則清理現場並退出 */
static void login_exit(int exit_code)
{
if (pamh) pam_end(pamh, PAM_ABORT);
exit(exit_code);
}


/* 這個回調函數被PAM認證模塊調用以便顯示錯誤信息或者或者用來取得用戶輸入,採用圖形界面的服務程序則應使用圖形界面來取得用戶輸入或顯示提示信息*/


int login_conv(int num_msg, struct pam_message **msg, struct pam_response **response, void *appdata_ptr){
while (num_msg--){
switch (m->msg_style)
{
case PAM_PROMPT_ECHO_OFF:
r->resp = strdup(getpass(m->msg));
break;
case PAM_PROMPT_ECHO_ON:
(void) fputs(m->msg, stdout);
r->resp = malloc(PAM_MAX_RESP_SIZE);
fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
/* add code here to remove \n from fputs */
break;
case PAM_ERROR_MSG:
(void) fputs(m->msg, stderr);
break;
case PAM_TEXT_INFO:
(void) fputs(m->msg, stdout);
break;
default:
log_error();
break;
}
}
return (PAM_SUCCESS);
}


七、PAM SPI

當服務程序(ftpd、telnetd等)調用PAM API函數pam_xxx( )時,由PAM 框架(libpam)根據該服務在/etc/pam.conf文件中的配置調用指定的PAM模塊中對應的SPI函數pam_sm_xxx( )。如下:




系統服務程序 PAM Framework PAM Service Module

ftpd pam_unix
telnetd PAM API PAM SPI pam_rhosts
. ------------------> libpam ---------------> .
. pam_xxx() pam_sm_xxx() .




API函數的名字為pam_xxx( ),對應的SPI函數的名字為pam_sm_xxx( ),即每個服務模塊需要引出相應的函數以供libpam調用。為方便對照,再列一下。


API 對應的 SPI
---------------------------------------------------------------------
帳號管理 pam_acct_mgmt( ) pam_sm_acct_mgmt( )
認證管理 pam_authenticate( ) pam_ sm_authenticate( )
密碼管理 pam_chauthtok( ) pam_ sm_chauthtok( )
會話管理 pam_open_session( ) pam_ sm_open_session( )
會話管理 pam_close_session( ) pam_ sm_close_session( )
認證管理 pam_setcred( ) pam_ sm_setcred( )

八、常用的PAM服務模塊

下面是Linux提供的PAM模塊列表(只是其中一部分):

模塊文件 模塊功能描述 相關配置文件
-------------- -------------------------- -----------------------
pam_access 提供logdaemon風格登錄控制 /etc/security/access.conf
pam_chroot 提供類似chroot命令的功能
pam_cracklib 對密碼的強度進行一定的檢查 庫文件libcrack和字典文件
/usr/lib/cracklib_dict

pam_deny 總是無條件地使認證失敗
pam_env 設置取消環境變數 /etc/security/pam_env.conf
pam_filter 對輸入輸出流進行過濾 filters
pam_ftp.so 對匿名ftp用戶進行認證
pam_group 當用戶在指定的終端上請求指定的 /etc/security/group.conf
服務時賦予該用戶相應的組許可權

pam_issue 在提示用戶輸入用戶名之前顯示 /etc/issue
/etc/issue文件的內容

pam_krb4 對用戶密碼進行Kerberos認證相應的Kerberos庫文件
pam_lastlog 在用戶登錄成功后顯示關於 /var/log/lastlog
用戶上次登錄的信息,並維護
/var/log/lastlog文件。

pam_limits 限制用戶會話所能使用的系統資源 /etc/security/limits.conf
pam_listfile 根據指定的某個文件決定是否 例如/etc/ftpusers
允許或禁止提供服務

pam_mail 檢查用戶的郵箱中是否有新郵件 /var/spool/mail/xxxx
pam_mkhomedir 為用戶建立主目錄 /etc/skel/
pam_motd 顯示/etc/motd文件的內容 /etc/motd
pam_nologin 根據/etc/nologin文件的存在與否 /etc/nologin
來決定用戶認證是否成功

pam_permit 總是無條件地使認證成功
pam_pwdb 作為pam_unix_xxxx模塊的一個替代。/etc/pwdb.conf
使用Password Database通用介面
進行認證。

pam_radius 提供遠程身份驗證撥入用戶服務(RADIUS)的認證
pam_rhosts_auth 利用文件~/.rhosts和/etc/hosts.equiv和~/.rhosts
/etc/hosts.equiv對用戶進行認證。

pam_rootok 檢查用戶是否為超級用戶,如果
是超級用戶則無條件地通過認證。

pam_securetty 提供標準的Unix securetty檢查 /etc/securetty

pam_time 提供基於時間的控制,比如限制 /etc/security/time.conf
用戶只能在某個時間段內才能登錄

pam_unix 提供標準的Unix認證 /etc/passwd和/etc/shadow
pam_userdb 利用Berkeley DB資料庫來檢查用戶/密碼

pam_warn 利用syslog( )記錄一條告警信息
pam_wheel 只允許wheel組的用戶有超級用戶的存取許可權


參考資料:

1、DCE/OSF-RFC 86.0
2、Linux-PAM documentation & source code
3、Sun Solaris PAM documentation
--
This function returns if fchg is busy with a program change.

[火星人 ] Linux PAM 介紹已經有653次圍觀

http://coctec.com/docs/linux/show-post-142044.html