Linux 中的 PAM:如果遠端/外部身份驗證資料庫傳回否定回應,有什麼方法可以跳過本機身份驗證?

Linux 中的 PAM:如果遠端/外部身份驗證資料庫傳回否定回應,有什麼方法可以跳過本機身份驗證?

親愛的系統修補者們,

一位管理員朋友問了我以下問題:

在許多網路元素和伺服器上,他對 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_UNAVAILretval不是_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 設定檔語法實現相同的效果,而無需破解原始碼,那就太好了。

相關內容