rascal-pendular, bear-den, and no entry

前へ | 目次 | 索引 | 次へ

Appendix H: PuTTY 認証プラグインプロトコル

この付録は PuTTY と認証ヘルパプラグインの間のローカル IPC で使用されるプロトコルの仕様を記載している。

もしすでに認証プラグインがあり、PuTTY がそれを使用するよう設定したい場合は、section 4.24.3 の手順を参照のこと。この付録は新しい認証プラグインを書く人のためのものである。

H.1 要件

プロトコルの仕様は以下の要件に基づく。

keyboard-interactive 認証の自動化。 そもそもの動機として、一般的な SSH ユーザ認証方式の “keyboard-interactive” ([RFC4256] で定義) が様々な種類のチャレンジ・レスポンスやワンタイムパスワード形式の認証に使われ得ることがある。そしてそのいくつもで、必要な応答が HTTPS トランザクションのような補助的なネットワーク接続によって取得される。もしユーザがウェブブラウザから SSH クライアントへ手動でタイプして写したりコピー&ペーストしたりする必要がなく、代わりにこの作業を自動化できれば便利である。

プロンプトをユーザに渡せる。 一方でいくつかのユーザ認証方式は部分的にしか自動化できない。サーバのプロンプトのいくつかは人間による入力が必要かもしれない。また、認証を自動化するプラグインは SSH サーバによって提供されない独自の質問をする必要があるかもしれない。 (例えば、“実際の応答をハッシュによって生成するためのマスター鍵を入力してください”のような。) そのため、サーバの質問を受け取ってから、自身の質問をユーザにできる必要がある。その質問はサーバと同じかもしれないし、そうでないかもしれない。

ユーザ名を自動入力できる。 認証方式は SSH ログインで使用するユーザ名を見つける仕組みと一緒になっていることがある。そのためプラグインはクライアントがユーザ名を送信するよりも前に開始する必要がある。

他の種の SSH ユーザ認証への将来的な拡張。 このプロトコルのそもそもの動機は keyboard-interactive 特有である。しかし他にも SSH 認証方式は存在するため、将来的には自動化の恩恵を受けるかもしれない。それらが何かやどのように自動化するかは今ここでは予想しないが、後で必要になった時にそれらを差し込む余地は空けておく必要がある。

最小限の情報損失。 Keyboard-interactive プロンプトと応答は SSH プロトコル自体の通信と可能な限り近い形式でプラグインとやり取りする必要がある。そのため、プロトコルのデータ形式とマーシャリングは SSH に似ている。 (代わりに、例えば SSH バイナリパケットを別のよく知られた JSON のような形式に変換すると、エッジケースとして文字エンコーディングの問題を発生させ得るだろう。)

半二重通信。 入出力ストリームの一つを読みつつ同時に別のものを書き込もうとすると、ソフトウェアは非常に複雑化する。 selectWaitForMultipleObjects などを含む体系化されたイベントループが必要になり、そこから最初に起こったイベントに対してハンドラを呼び出す。そのような複雑さをこの種のアプリケーションに追加する必要はない。大量のデータの塊を転送する訳でも、関係のない処理を多重化する訳でもないからである。そのため、プラグイン製作者にとって物事を簡単にするために、次にどちらの側がメッセージを送信するはずかを常に 100% 明確にするという基本原則を設けた。それによって、プラグインをプロトコルに沿って逐次進行するコードとして書くことができ、単純な読み書きの関数呼び出しで一つ一つのメッセージを受信送信できる。

成功/失敗の連絡, プラグイン側でキャッシュを容易にするため。 プラグインは次回のために最近使われたデータをキャッシュしたいかもしれない。しかしそれは、そのデータを使った認証が実際に成功した場合のみである。そのためクライアントは判る限りは結果をプラグインに知らせる必要がある。 (しかしこれは最善の努力 (ベストエフォート) としてのみである。明らかにプラグインは回答に依存することはできない。なぜなら IPC プロトコルは必ず、他方が制御できない事由でクラッシュしたり停止したりする可能性を抱えているからである。)

H.2 転送と設定

プラグインはクライアントプラットフォーム上の実行プログラムである。

SSH クライアントは、プラグインを特定の接続で使うように手動で設定する。設定はコマンドラインの形式をとり、プラグインである実行プログラムの場所と、プラグイン固有のコマンドライン引数を任意で取る。

クライアントはプラグインをサブプロセスとして起動し、標準入出力として 8-bit クリーンなパイプの組を渡す。このパイプを使い、クライアントとプラグインは次に説明するプロトコルで通信する。

H.3 データ形式とマーシャリング

プロトコルは SSH 自体の低レベルなデータ形式を取り入れている。特に以下のエンコーディングは [RFC4251] の 第 5 節による:

byte (バイト)
整数の 0 以上 0xFF 以下, 1 バイトのバイナリデータとして転送する。
boolean (真偽値)
“true” または “false”, それぞれ 1 または 0 の byte として転送する。
uint32 (符号なし 32 bit 整数)
整数 0 以上 0xFFFFFFFF 以下, 4 バイトのバイナリデータとして、バイトオーダーはビッグエンディアン (“ネットワーク”) で転送する。
string (文字列)
byte のシーケンス, 前置データとして uint32 のバイトシーケンスの長さ。長さには長さフィールド自体は含まない。例えば、空文字列は 4 つのゼロ byte (uint32 エンコーディングの 0)。文字列 "AB" は 6 つの byte 0,0,0,2,'A','B'。

SSH 自体と異なり、プロトコルとクライアントの間は暗号化されない。ローカルのプロセス間パイプは OS カーネルによって保護されているとみなされるためである。そのためこのバイナリパケットプロトコルは SSH のものより非常に単純で、SFTP や OpenSSH エージェントプロトコルに似ている。

双方向の通信で送られ SSH クライアントとプラグインが交換するデータは message (メッセージ) のシーケンスで成り立っている。 message は string でエンコードされる。 string の内容はメッセージの種類を表す byte で始まり、その種類によって残りの形式は決まる。

H.4 プロトコルのバージョン管理

プロトコル自体はバージョン付けされる。接続が確立すると、クライアントは対応している最大のバージョンを示し、プラグインは使用されるバージョン (クライアントの値を超えない) を選んで応答する。

バージョン番号を含めることで、後からプロトコルに互換性のない変更が可能になる。

バージョン番号はこの仕様のリリースバージョンを表すが、奇数の番号はリリースまでのドラフトや開発版のバージョンを表す。奇数バージョンで折衝したクライアントとプラグインは相互に通信できると保証されない。その組み合わせをテストする開発者が互換性があると保証する責任がある。

このドキュメントではプロトコルバージョン 2 を記述する。これは最初にリリースされるバージョンである。 (対応するドラフトはバージョン 1 である。)

H.5 イベントの概要とシーケンス

SSH のユーザ認証フェイズの一番最初に、クライアントは設定されたプラグインサブプロセスを起動する。 PuTTY は即座に PLUGIN_INIT メッセージを送り、プラグインに SSH の接続先に関しての初期の情報を通知する。

プラグインは PLUGIN_INIT_RESPONSE で応答する。任意で SSH クライアントに使用するユーザ名を通知できる。

クライアントは SSH サーバと通常の方法で認証を開始する。プラグインから提供されたユーザ名を (あるならば) 使い、もしくは代わりに通常の方針で (プラグインに依らずに) 手に入る名前を使う。

クライアントは通常の方針に従って試みる認証方式を選ぶ。もし選んだ方式がこのプロトコルが対応していなければ、クライアントはプラグインに問い合わせずに独自にその方式を実行する。

しかし、もしクライアントとサーバがこのプロトコルが対応する方式を試みると決めたら、クライアントは PLUGIN_PROTOCOL を送信し、使用される認証方式を SSH プロトコル ID で記述する。プラグインはその認証方式を補助する場合、PLUGIN_PROTOCOL_ACCEPT を応答し、そうでない場合は PLUGIN_PROTOCOL_REJECT で応答する。

プラグインが PLUGIN_PROTOCOL_REJECT を送信した場合、クライアントはプラグインが存在しない時のように続行する。後で別の認証方式が (この認証方式が失敗したか、サーバが複数の方式を要求したために) 決まった場合、クライアントは更に PLUGIN_PROTOCOL を送り再試行してもよい。

プラグインが PLUGIN_PROTOCOL_ACCEPT を送信した場合、プロトコルでその認証方式特有の部分が開始する。これは PLUGIN_AUTH_SUCCESS または PLUGIN_AUTH_FAILURE で終了する。その後、クライアントは更に PLUGIN_PROTOCOL を送信してもよい。

現在、唯一の対応している方式は “keyboard-interactive” ([RFC4256]) である。クライアントがこれをサーバに通知した後、後続のプロトコルは次の通り:

サーバが SSH_MSG_USERAUTH_INFO_REQUEST メッセージを送りユーザから認証の応答を要求する度に、SSH クライアントはそのメッセージを PLUGIN_KI_SERVER_REQUEST に変換し、プラグインに渡す。

この時点で、プラグインは任意で PLUGIN_KI_USER_REQUEST を応答し、実際にユーザに提示されるプロンプトを含められる。クライアントはユーザに REQUEST メッセージにある質問の返答を要求してから、対応する PLUGIN_KI_USER_RESPONSE を応答する。プラグインはこのやり取りを複数回繰り返せる。

プラグインがサーバの認証プロンプトに応答するためのすべての情報を手に入れたら、PLUGIN_KI_SERVER_RESPONSE をクライアントに送信する。それは SSH_MSG_USERAUTH_INFO_RESPONSE に変換され、サーバに送られる。

その後、[RFC4256] の通り、サーバは認証を受け入れるか、拒否するか、別の SSH_MSG_USERAUTH_INFO_REQUEST を送信するか自由にできる。それぞれの SSH_MSG_USERAUTH_INFO_REQUEST が上記と同じように処理される。

サーバが keyboard-interactive 認証を SSH_MSG_USERAUTH_SUCCESS または SSH_MSG_USERAUTH_FAILURE で終了した場合、クライアントはプラグインに PLUGIN_AUTH_SUCCESS または PLUGIN_AUTH_FAILURE を送信して通知する。 PLUGIN_AUTH_SUCCESSその特定の認証方式が成功した時に送信され、SSH サーバがその後更に認証するかどうかに関わらない: 特に、SSH_MSG_USERAUTH_FAILURE の “partial success” フラグ付き ([RFC4252] 5.1 節参照) は PLUGIN_AUTH_SUCCESS に変換される。

プラグインの標準入力は、いかなる理由でもクライアントがプラグインのサービスを必要としなくなった時に閉じる。これは認証が完了したから (全体的に成功したり失敗したり) か、ユーザが認証途中でセッションを中断したからか、クライアントがクラッシュしたからかもしれない。

H.6 メッセージフォーマット

このセクションではプロトコルのそれぞれのメッセージフォーマットについて記述する。

section H.3 の記述の通り、それぞれのメッセージはどれも二つのフィールドで始まる:

長さフィールドはそれ自体の長さを含まないが、種類コードの長さは含む。

以下のサブセクションで、種類コードの後の、残りのメッセージのフォーマットについてそれぞれ記載する。

種類コード自体はこのように定義される:

#define PLUGIN_INIT                   1
#define PLUGIN_INIT_RESPONSE          2
#define PLUGIN_PROTOCOL               3
#define PLUGIN_PROTOCOL_ACCEPT        4
#define PLUGIN_PROTOCOL_REJECT        5
#define PLUGIN_AUTH_SUCCESS           6
#define PLUGIN_AUTH_FAILURE           7
#define PLUGIN_INIT_FAILURE           8

#define PLUGIN_KI_SERVER_REQUEST     20
#define PLUGIN_KI_SERVER_RESPONSE    21
#define PLUGIN_KI_USER_REQUEST       22
#define PLUGIN_KI_USER_RESPONSE      23

もしこのプロトコルが更なる認証方式を補助できるよう拡張されるなら、それらのメッセージの種類もまた 20 から始まり、keyboard-interactive のコードと重複する。

H.6.1 PLUGIN_INIT

方向: クライアントからプラグインへ

いつ: 接続開始時に最初のメッセージとして送信される

次に何が起こるか: プラグインは PLUGIN_INIT_RESPONSEPLUGIN_INIT_FAILURE を送信する

種類コードの後のメッセージの内容:

H.6.2 PLUGIN_INIT_RESPONSE

方向: プラグインからクライアントへ

いつ: PLUGIN_INIT への応答

次に何が起こるか: クライアントは PLUGIN_PROTOCOL を送信するか、おそらくセッションを切断する (プラグインが補助できる認証方式を合意できなかった場合)。

種類コードの後のメッセージの内容:

H.6.3 PLUGIN_INIT_FAILURE

方向: プラグインからクライアントへ

いつ: PLUGIN_INIT への応答

次に何が起こるか: セッションが終了する

種類コードの後のメッセージの内容:

H.6.4 PLUGIN_PROTOCOL

方向: クライアントからプラグインへ

いつ: PLUGIN_INIT_RESPONSE の後、または、前回の PLUGIN_AUTH_SUCCESS 認証フェイズが PLUGIN_AUTH_SUCCESSPLUGIN_AUTH_FAILURE で終了した後に送信される。

次に何が起こるか: プラグインは PLUGIN_PROTOCOL_ACCEPTPLUGIN_PROTOCOL_REJECT を送信する

種類コードの後のメッセージの内容:

H.6.5 PLUGIN_PROTOCOL_REJECT

方向: プラグインからクライアントへ

いつ: PLUGIN_PROTOCOL の後に送信する

次に何が起こるか: クライアントは更に PLUGIN_PROTOCOL を送信するか、セッションを終了する

種類コードの後のメッセージの内容:

H.6.6 PLUGIN_PROTOCOL_ACCEPT

方向: プラグインからクライアントへ

いつ: PLUGIN_PROTOCOL の後に送信する

次に何が起こるか: 合意した認証プロトコルに依存する。 Keyboard-interactive の場合、クライアントは PLUGIN_KI_SERVER_REQUESTPLUGIN_AUTH_SUCCESSPLUGIN_AUTH_FAILURE を送信する。他の方式は指定されない。

種類コードの後のメッセージの内容: なし

H.6.7 PLUGIN_KI_SERVER_REQUEST

方向: クライアントからプラグインへ

いつ: PLUGIN_PROTOCOL の後に送信する。もしくは PLUGIN_KI_SERVER_RESPONSE の後、サーバが SSH_MSG_USERAUTH_INFO_REQUEST を送信した場合

次に何が起こるか: プラグインは PLUGIN_KI_USER_REQUESTPLUGIN_KI_SERVER_RESPONSE を送信する

種類コードの後のメッセージの内容: サーバによって送信されたばかりの SSH_MSG_USERAUTH_INFO_REQUEST の正確な内容。詳細は [RFC4256] の第 3.2 節を参照。概要は:

H.6.8 PLUGIN_KI_SERVER_RESPONSE

方向: プラグインからクライアントへ

いつ: PLUGIN_KI_SERVER_REQUEST への応答。おそらく一つ以上の PLUGIN_KI_USER_REQUESTPLUGIN_KI_USER_RESPONSE の組が介在した後

次に何が起こるか: クライアントは更に PLUGIN_KI_SERVER_REQUEST を送信すか。 PLUGIN_AUTH_SUCCESSPLUGIN_AUTH_FAILURE を送信する。

種類コードの後のメッセージの内容: クライアントがサーバに送り返すべき SSH_MSG_USERAUTH_INFO_RESPONSE の正確な内容。詳細は [RFC4256] の第 3.4 節を参照。概要は:

H.6.9 PLUGIN_KI_USER_REQUEST

方向: プラグインからクライアントへ

いつ: PLUGIN_KI_SERVER_REQUEST への応答。プラグインがユーザにプロンプトを提示しないとサーバの認証プロンプトに応答できない場合。

次に何が起こるか: クライアントは PLUGIN_KI_USER_RESPONSE を送信する

種類コードの後のメッセージの内容: PLUGIN_KI_SERVER_REQUEST と全く同じ (section H.6.7 参照)。

H.6.10 PLUGIN_KI_USER_RESPONSE

方向: クライアントからプラグインへ

いつ: PLUGIN_KI_USER_REQUEST への応答

次に何が起こるか: プラグインは PLUGIN_KI_SERVER_RESPONSE を送信するか、別の PLUGIN_KI_USER_REQUEST を送信する

種類コードの後のメッセージの内容: PLUGIN_KI_SERVER_RESPONSE と全く同じ (section H.6.8 参照)。

H.6.11 PLUGIN_AUTH_SUCCESS

方向: クライアントからプラグインへ

いつ: PLUGIN_KI_SERVER_RESPONSE の後に送信する。もしくは (稀な場合に) PLUGIN_PROTOCOL_ACCEPT の後。

次に何が起こるか: クライアントは別の PLUGIN_PROTOCOL を送信するか、セッションを停止する

種類コードの後のメッセージの内容: なし

H.6.12 PLUGIN_AUTH_FAILURE

方向: クライアントからプラグインへ

いつ: PLUGIN_KI_SERVER_RESPONSE の後に送信する。もしくは (稀な場合に) PLUGIN_PROTOCOL_ACCEPT の後。

次に何が起こるか: クライアントは別の PLUGIN_PROTOCOL を送信するか、セッションを停止する

種類コードの後のメッセージの内容: なし

H.7 参考文献

[RFC4251] RFC 4251, “The Secure Shell (SSH) Protocol Architecture”.

[RFC4252] RFC 4252, “The Secure Shell (SSH) Authentication Protocol”.

[RFC4256] RFC 4256, “Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)” (プロトコル中の ID である “keyboard-interactive” としてよく知られる).


このマニュアルや PuTTY のツールに意見がある場合は、 Feedback page を参照してください。

翻訳についてはフィードバックから送信できます。

©1997-2025 Simon Tatham ©2015-2025 SATO Kentaro

[PuTTY custom build 0.83.ranvis-doc]