正確處理Linux里的密碼
在Linux里,有很多API函數(shù)是用來(lái)處理密碼的,但是這只能解決一半的問(wèn)題。你不得不使用好的密碼處理辦法。例如,只有在絕對(duì)必要的時(shí)候才使用純文本密碼這種(安全)策略。
暴露純文本(密碼內(nèi)容)的唯一機(jī)會(huì)是在進(jìn)行身份驗(yàn)證時(shí)詢問(wèn)用戶密碼的時(shí)候。有一些可用的API函數(shù)能夠減少這種風(fēng)險(xiǎn),包括加密,這應(yīng)該在獲得用戶密碼之后立即進(jìn)行。
密碼處理的第一條原則是,絕對(duì)不要將純文本的密碼寫(xiě)到磁盤(pán)上——即使是你會(huì)立即刪掉的臨時(shí)文件。一旦數(shù)據(jù)到了磁盤(pán)上,你在使用之后就很難保證數(shù)據(jù)沒(méi)有丟失。
雖然這個(gè)原則看起來(lái)似乎很簡(jiǎn)單,但是你必須要記住:Linux使用的是虛擬內(nèi)存。如果你加載了交換分區(qū),內(nèi)存(里的內(nèi)容)會(huì)在任何時(shí)候被寫(xiě)到磁盤(pán)上。為了防止密碼緩沖區(qū)被寫(xiě)到交換分區(qū)上,你可以使用mlock API調(diào)用:
const intsz = 25;
char *buf = malloc(sz);
mlock(buf, sz);
memset(buf, 0, sz);
為了確保緩沖區(qū)真的被鎖定了,你必須至少向每個(gè)內(nèi)存頁(yè)寫(xiě)入一個(gè)值。
另一個(gè)重要的原則是,決不要將輸入的密碼反饋到終端上。你可以編寫(xiě)自己的函數(shù)或者使用getpass函數(shù),它像下面這樣工作:
const char prompt[] = "Password: ";
char *pword = NULL;
pword = getpass(prompt);
有時(shí)候你無(wú)法使用getpass。在這樣的情況下,你將需要編寫(xiě)自己的getpass函數(shù)。下面就是一個(gè)例子:
#include <termios.h>
#include <stdio.h>
ssize_t
my_getpass (char **lineptr, size_t *n, FILE *stream)
{
structtermios old, new;
intnread;
/* Turn echoing off and fail if we can't. */
if (tcgetattr (fileno (stream), &old) != 0)
return -1;
new = old;
new.c_lflag &= ~ECHO;
if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0)
return -1;
/* Read the password. */
nread = getline (lineptr, n, stream);
/* Restore terminal. */
(void) tcsetattr (fileno (stream), TCSAFLUSH, &old);
return nread;
}
return nread;
}
很顯然,傳遞到函數(shù)里的緩沖區(qū)應(yīng)該首先被鎖定。
可插拔驗(yàn)證模塊(PAM)
PAM是一個(gè)模塊化的系統(tǒng),它將驗(yàn)證、密碼管理、會(huì)話管理,以及帳號(hào)管理抽象出來(lái)。它授權(quán)被編寫(xiě)用來(lái)同PAM一起工作的應(yīng)用程序來(lái)使用各種模塊,并允許這些模塊被卸載或者被別的模塊替換,而不需要重新編寫(xiě)應(yīng)用程序。


