PAM について考える。pam_ssh.so とか。
以下の文書は様々なセキュリティリスクについてアセスメントしてないんで参考程度にとどめておいてください。
PAM の auth の流れ
ステート図については⇒【http://corvus.kek.jp/~manabe/pcf/pam.htm】を参照。
書式についてはいっぱいころがっているので省略。で,コントロールフラグについて。
コントロールフラグは PAM モジュールが「成功」「失敗」のステータスを返した時にどのような処理を行なうかを指定します。基本は required, requisite, sufficient, optional の四種類です。
http://memo.blogdns.net/pamandnss.html
- required (必要条件)
- そのモジュールから成功のステータスが返る事を要求します。required となっているモジュールが失敗のステータスを返すと他のモジュールの処理の結果にかかわらずログインに失敗します。ただし、処理は打ち切られる事なく次のモジュールに進みます。
- requisite (必須条件)
- required と似ていますが、requisite となっているモジュールが失敗するとその時点でそのモジュールタイプの処理は打ち切られます。
- sufficient (充分条件)
- sufficient となっているモジュールが成功のステータスを返すと、既に required のモジュールのどれかが失敗していない限り、そのモジュールタイプの処理は成功と見なされ、以降のモジュールは処理されません。
- optional (オプション)
- optional とされているモジュールは通常はそのステータスを無視されます。しかし、他のモジュールが全て「無視」のステータスを返した場合、optional のモジュールのステータスが使われます。
なるほど。厳密な挙動については等価な[...]オプションを考えるとわかりやすいかも。
Each of the four keywords: required; requisite; sufficient; and optional, have an equivalent expression in terms of the [...] syntax.
They are as follows:
http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/sag-configuration-file.html
- required:
- [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
- requisite:
- [success=ok new_authtok_reqd=ok ignore=ignore default=die]
- sufficient:
- [success=done new_authtok_reqd=done default=ignore]
- optional:
- [success=ok new_authtok_reqd=ok default=ignore]
実例をもとに
RedHat 系のデフォルトな /etc/pam.d/system-auth(-ac) の auth 部分は
#%PAM-1.0 auth required pam_env.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so ... snip ...
となってます。
- (pam_env.so で system-wide な環境変数を設定する?;今回の話としては無視してかまわないです)
- pam_unix.so でローカル認証(/etc/passwd)を行う。
- 成功したら,認証成功でおしまい(sufficient)。
- ローカル認証に失敗した場合,pam_succeed_if.so により,
- uid < 500 の場合,ログを残さず(quiet)認証失敗でおしまい(requisite)
- uid >= 500 の場合,pam_deny.so により(常に)認証失敗でログを残しつつおしまい
たぶんこういうことなのではないかなぁ。
gdm ログイン時に同時に ssh-add したい (1)
って pam_ssh.so を使うだけの話なのですが。
pam_ssh.so は auth と session について使えます。
という仕組みになってます。なので,pam_unix の代わりに pam_ssh をログイン認証に使ってみます。
/etc/pam.d/gdm の auth 部は
auth required pam_env.so auth include system-auth
のようになってます。つまり system-auth の内容に準ずるわけですが,system-auth(-ac) の内容は変わりうるので,コピペしてそれを改変してみます。
まずはコピペ。
auth required pam_env.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so
pam_env.so は被るので削除しました。
で,pam_unix.so の代わりに pam_ssh.so を使うのでそのまま置き換えます。あと,session 部分にも pam_ssh.so を利用するよう書きます。
#%PAM-1.0 auth required pam_env.so auth sufficient pam_ssh.so try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so ... snip ... session optional pam_keyinit.so force revoke session include system-auth session required pam_loginuid.so session optional pam_console.so session optional pam_ssh.so
これで gdm で再ログインすると,パスワードを聞かれる際に passphrase を入れろ,といわれますんで鍵のパスフレーズを入力してログイン。ps すると ssh-agent が常駐しているのがわかります。で,外部ホストに ssh かけるとパスフレーズ入力なしでログインできます。便利便利。
これでローカルパスワードを削除するというのも運用ポリシーとしておもしろいかもしれません。
gdm ログイン時に同時に ssh-add したい (2)
これだと key pair を作っていないユーザがログインできないので
というポリシーを考えてみます。
というものズバリが FedoraNews にころがってました(⇒http://fedoranews.org/cms/node/1461。んが,微妙に書いている内容が間違っている気がします。まだしも古い内容(http://fedoranews.org/mediawiki/index.php/Logging_into_KDE_with_your_SSH_passphrase)のほうが正確かも(設定が古いですが)。
先ほどと同じように system-auth(-ac) の auth 部分を /etc/pam.d/gdm にコピーして
#%PAM-1.0 auth required pam_env.so auth sufficient pam_ssh.so try_first_pass auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so ... snip ... session optional pam_keyinit.so force revoke session include system-auth session required pam_loginuid.so session optional pam_console.so session optional pam_ssh.so
このように pam_unix.so より前に pam_ssh.so をもってきます。
両方とも sufficient になっているので,まず pam_ssh.so で認証してから,だめだったら pam_unix.so で認証,になってくれる,はずです。ためしていないです。
gdm ログイン時に同時に ssh-add したい (3)
次に以下のようなポリシーの場合を考えてみます。
なんてひどいポリシー!。実際問題これも (2) でいいと思うんですが,実は一番最初に取り組んだのがこの課題で,なかなか頭をつかったので,せっかくなので書いてみます。
問題は,sufficient なコントロールフラグだと,成功するとそこで処理が終わってしまうんですね。だから単純に
auth sufficient pam_unix.so nullok try_first_pass auth optional pam_ssh.so try_first_pass
とすると,pam_unix.so が認証に成功した時点で pam_ssh.so に移らず ssh-add されません。
なので,あれこれ考えた結果が,以下のようなものです。
auth required pam_unix.so nullok try_first_pass auth optional pam_ssh.so try_first_pass auth sufficient pam_permit.so auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so
pam_unix.so のコントロールフラグを required にすることで,後続のモジュールにも制御がわたされるようにします。で,pam_permit.so というのは常に認証成功するモジュールなのですが,sufficient というコントロールフラグは,以前の required なモジュールで成功となっている場合のみ評価されるので,pam_unix.so が成功した場合は認証成功で認証打ち切り,pam_unix.so が失敗した場合は無視されて後続の pam_deny.so 等にうつる,という挙動になります。
pam_permit.so はめっちゃ注意して使えよ,と man にも書いてあるのであまりいい解とはいえないのですが,他の方法がおもいつきませんでした。