親愛的系統修補者們,
一位管理員朋友問了我以下問題:
在許多網路元素和伺服器上,他對 TACACS+ 伺服器使用遠端身份驗證。在某些此類專有裝置上,如果遠端方法傳回「驗證伺服器不可用」(無法存取、逾時),則驗證僅詢問本機驗證資料庫。如果遠端認證伺服器是可用,並返回否定回應,有問題的框從表面上看,並且不會嘗試針對本地用戶資料庫進行身份驗證。
現在......在基於 Linux 的機器上,他希望實現相同的行為。而他似乎無法做到。 Linux 作業系統首先嘗試遠端身份驗證,但在得到明確的否定回應(伺服器回應「身份驗證失敗,這些不是有效憑證」)後,它會繼續嘗試本機資料庫。
我了解到遠端 TACACS+ 身份驗證是由一個名為 pam_tacplus 的 PAM 模組安排的。總體而言,在閱讀有關 PAM 的內容後,我似乎明白 pam_tacplus 並不是罪魁禍首。相反,觀察到的行為正是 PAM 整體的工作方式。如果是這種情況,直接的解決方案可能必須涉及向 PAM 程式碼庫添加一個可配置的全域選項,也許還需要添加特定的 PAM 設定檔關鍵字/語法,以按照所需的方向修改行為。
歡迎有關此主題的任何進一步說明:-)
答案1
……基於進一步的閱讀,讓我提出一個答案。顯然,熱烈歡迎任何補充或更正。
首先我發現這已經很老了PAM 簡介。這些年來可能並沒有失去任何敏銳的智慧。
如果我看一下底層,auth 模組回傳值是記錄在官方 linux-pam 文件中。
在清單中,我可以看到一個有前途的 retval ,名為 PAM_AUTHINFO_UNAVAIL 。
實際上定義在libpam/include/security/_pam_types.h。
#define PAM_SUCCESS 0
#define PAM_AUTHINFO_UNAVAIL 9
#define _PAM_RETURN_VALUES 32
中的 PAM_AUTHINFO_UNAVAIL 定義似乎有衝突libpam/include/security/_pam_compat.h
# define PAM_AUTHINFO_UNAVAIL 12
——也許可以安全地忽略。
原始檔libpam/pam_dispatch.c 包含一個名為 _pam_dispatch_aux() 的關鍵函數它實際上遍歷已註冊的身份驗證模組的堆疊,並對它們的返回值進行操作。而且,事實證明它並沒有直接基於“retval”做太多事情,可能包含PAM_AUTHINFO_UNAVAIL
.它確實直接回應 的某些特定「內部特殊用途」值retval
,但對 沒有特殊處理PAM_AUTHINFO_UNAVAIL
。retval
不是_pam_dispatch_aux()
其本身的返回值:相反,retval
它只是在 for(;;) 循環內聲明的局部變量,該變量遍歷已註冊的身份驗證模組的堆疊,其中塊本地retval
收集特定模組的返回值。 stackwalking 循環實際上會根據其他變數做出重要決策:其中一個是派生的,稱為action
,另一個是impression
由模組透過引用「傳回」的結構成員。那麼也許它畢竟可能受到模組自己的程式碼的影響?
事實上,它action
是取自“動作查找表”,
索引為的retval
——啊哈!
action = h->actions[cached_retval];
操作表是由模組定義的嗎?但是,如果 _PAM_ACTION_* 巨集是#define於libpam/pam_private.h?
原來 actions[] 表是以通用方式初始化_pam_parse_conf_file()
透過呼叫in的函數libpam/pam_handlers.c
,該函數執行直接字串比較(匹配)諸如
required
, requisite
, optional
,之類的關鍵字sufficient
。
並且,整個表目前有 32 個位置(請參閱上面引用的巨集定義)批發初始化在解析特定模組的配置條目之前,將其變更為 _PAM_ACTION_UNDEF。然後,個體「強度關鍵字」將個體重新映射retval
到特定的期望動作。
所以:似乎很明顯可以從中獲得靈感:
} else if (!strcasecmp("required", tok)) {
D(("*PAM_F_REQUIRED*"));
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
_pam_set_default_control(actions, _PAM_ACTION_BAD);
} else if (!strcasecmp("sufficient", tok)) {
D(("*PAM_F_SUFFICIENT*"));
actions[PAM_SUCCESS] = _PAM_ACTION_DONE;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE;
_pam_set_default_control(actions, _PAM_ACTION_IGNORE);
}
並添加類似的東西
} else if (!strcasecmp("reqd_if_avail", tok)) {
D(("*PAM_F_REQD_IF_AVAIL*"));
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
actions[PAM_AUTHINFO_UNAVAIL] = _PAM_ACTION_IGNORE; // !!!!!!!!!!
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK; // ?
actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
_pam_set_default_control(actions, _PAM_ACTION_BAD); // !!!
}
而且,顯然 pam_tacplus幫助我們走上這條道路。
如果可以透過現有的 PAM 設定檔語法實現相同的效果,而無需破解原始碼,那就太好了。