在 PAM 會話中對使用者進行外部驗證/在 PAM 會話中對 PAM 會話進行身份驗證

在 PAM 會話中對使用者進行外部驗證/在 PAM 會話中對 PAM 會話進行身份驗證

有沒有辦法在自訂 PAM 會話中正確驗證使用者身分?

我目前正在編寫自己的 PAM 身份驗證模組,該模組允許用戶透過外部令牌登入。必須先生成此令牌,然後使用者才能使用我的模組登入。因此,當不存在令牌時,我想回退到預設的 PAM 身份驗證,並在使用者通過身份驗證後立即繼續我的程式碼。

這有可能嗎?在偽代碼中,我的模組如下所示:

pam_sm_authenticate() {
  if (first_login) {
    code_copied_from_pam_unix_to_authenticate_user();
    // do something else here?
  } else {
    custom_auth();
  }
}

作為快速修復,我將 Linux 的 pam_unix 模組中的程式碼複製到我自己的模組中,並且它可以工作。然而,這並不是很令人滿意,因為它需要大量額外的庫,並且只有在 pam_unix 不改變的情況下才有效。我更願意在我的會話中開啟另一個 PAM 會話,但尚未使其正常運作。

答案1

不要讓您的程式碼執行所有邏輯:首先使用 PAM 及其配置來確保您的模組在最佳條件下運作(即不需要複製pam_unix程式碼)。

首先,讓我為您的模組建議另一個偽代碼:

pam_sm_authenticate() {
    if (first_login) return PAM_CRED_INSUFFICIENT;
    else custom_auth();
}

在這裡,我認為首次登入是憑證不足的情況。我告訴 PAM 該模組失敗了,因為它沒有完全驗證用戶身份所需的一切。現在,假設您的模組被稱為my_module,可能的配置是:

auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1]      pam_unix.so
auth sufficient                  my_module.so
auth requisite                   pam_deny.so

詳細資訊如下:

  • 首先,請求經過my_module。這裡有幾種可能性:

    1. 首次登入:您的模組返回PAM_CRED_INSUFFICIENT。這個案例是捕捉透過 PAM(通過cred_insufficient),在這種情況下,它被配置為將鏈標記為成功 ( ok),但繼續前進
    2. 這不是第一次登錄,您完成了custom_auth()並且成功了(它返回了PAM_SUCCESS)。在這種情況下,我們結束鏈 ( done) :授予存取權限
    3. 這不是第一次登錄,並且custom_auth()沒有得到很好的結果(PAM_AUTH_ERR或其他類型的內部錯誤)。在這種情況下,請跳過接下來的 2 行 ( default=2)。該鏈直接進入pam_deny,但總是失敗:拒絕訪問
  • 在第一個場景中,鏈條繼續到pam_unix。這裡有兩種可能性:

    1. UNIX 身份驗證成功。這標誌著該鏈成功 ( ok) 且繼續下一個模組
    2. UNIX 身份驗證失敗。跳過下一個模組 ( default=1),鏈以 結束pam_deny拒絕訪問
  • 如果到了第三行,就表示第一次my_module結束了,成功了。您的模組再次被呼叫 ( ) 作為。又是兩種可能:PAM_CRED_INSUFFICIENTpam_unix// do something else here?sufficient

    1. 這次,您的模組成功了:授予存取權限
    2. 該模組再次失敗,但除了憑證不足之外還有另一個原因:拒絕訪問

您可能還想執行自訂程式碼UNIX 驗證後,即使失敗了。為此,請將第二行更改為:

auth [success=ok default=bad]    pam_unix.so

my_module無論如何,這都會使該鏈再經歷一次,但該鏈將被標記為失敗的。即使您的模組最終在這裡成功,該鏈也會失敗。

您可能還想讓您的模組知道我們在鏈中調用了它多少次:區分第一次調用my_module和第二次調用。這可以透過參數輕鬆完成:

auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1]      pam_unix.so
auth sufficient                  my_module.so second_time
auth requisite                   pam_deny.so

在這裡,第二次呼叫pam_sm_authenticate將傳遞一個參數(通過argvargc),這應該對您有幫助定位運行時鏈中的模組。當然,你的firstLogin條件應該足以做出這樣的區分。

相關內容