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。ここでは 2 つの可能性があります。

    1. UNIX認証が成功しました。これにより、チェーンは成功(ok)とマークされ、次のモジュールに進む
    2. UNIX 認証に失敗しました。次のモジュールはスキップされ ( default=1)、チェーンは で終了しますpam_denyアクセスが拒否されました
  • 3 行目に到達した場合、 が最初my_moduleに終了し、 が成功したことを意味します。モジュールはとして再度 ( )呼び出されます。ここでも 2 つの可能性があります。PAM_CRED_INSUFFICIENTpam_unix// do something else here?sufficient

    1. 今回は、モジュールは成功しました:アクセスを許可
    2. モジュールは再度失敗しますが、資格情報の不足とは別の理由です。アクセスが拒否されました

カスタムコードを実行することもできますUNIX認証後失敗した場合でも、実行を継続します。そのためには、2 行目を次のように変更します。

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

これにより、チェーンはmy_module必ずもう一度実行されますが、チェーンは次のようにマークされます。失敗したモジュールがここで成功したとしても、チェーンは失敗します。

モジュールにチェーン内で何回呼び出されたかを認識させ、最初の呼び出しとmy_module2 番目の呼び出しを区別することもできます。これは引数を使用して簡単に行うことができます。

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

ここで、2回目の呼び出しでは引数(およびを介して)pam_sm_authenticateが渡され、argvargc見つける実行時にチェーン内のモジュール。もちろん、firstLoginこのような区別を行うには条件で十分です。

関連情報