Hatena::Grouprubyist

Going My Ruby Way このページをアンテナに追加 RSSフィード

Ruby ロゴ (C) Ruby Association LLC

2011年09月06日(火)

SSHサーバを作る(その 19) ユーザ認証プロトコル

| 21:54 | SSHサーバを作る(その 19) ユーザ認証プロトコル - Going My Ruby Way を含むブックマーク はてなブックマーク - SSHサーバを作る(その 19) ユーザ認証プロトコル - Going My Ruby Way SSHサーバを作る(その 19) ユーザ認証プロトコル - Going My Ruby Way のブックマークコメント

gmrw-ssh2-server はパスワード認証 + shell セッションの実装までしました。

ssh クライアントでアクセスすると shell が動かせます。

  • Ubuntu Linux 11.04 / Ruby 1.9.2 or 1.8.7 / クライアント OpenSSH 5.8 で確認
  • パスワード認証できるユーザ/パスワードは固定(lib/gmrw/ssh2/server/config.rb に記述)
    • geust1/pass1 または guest2/pass2
  • 認証に成功しても、認可(ユーザ権限の取得)はされない
  • シェルは bash(ないしは環境変数 $SHELL の値)。ログインシェルではない。

では、今回はユーザ認証プロトコルのまとめです。

--------

ユーザ認証プロトコル

ユーザ認証プロトコルは、主に RFC4252 の範囲になります。

位置プロトコル提供する機能
最下層トランスポート層プロトコル*1気密性(暗号化)、完全性、サーバ認証、圧縮
中間層認証プロトコルクライアント認証(ユーザ認証)<==ここ
最上層コネクションプロトコル多重化チャネル

ユーザ認証プロトコルでは、ユーザに対する認証を行います。ユーザはサービスの認可を要求してきます。ユーザが認証された場合、要求したサービスが認可されます。

サービスは以下です*2

サービス名説明
ssh-connectionSSHプロトコルの最上層

認証にはいくつかの認証メソッドがあります。*3

認証メソッド名説明SSH仕様での要求レベル
publickey公開鍵認証REQUIRED
passwordパスワード認証OPTIONAL
hostbasedホストベース認証OPTIONAL
none*4認証なしNOT RECOMMENDED

ユーザ認証プロトコルで使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_REQUEST50C->S認証の要求
SSH_MSG_USERAUTH_FAILURE51S->C認証の要求に対する応答(失敗の場合)
SSH_MSG_USERAUTH_SUCCESS52S->C認証の要求に対する応答(成功の場合)
SSH_MSG_USERAUTH_BANNER53S->Cバナーの通知(非同期、随時)

認証メソッドが "publickey" の場合に使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_PK_OK60S->C認証の要求に対する応答(部分的な成功の場合)

認証メソッドが "password" の場合に使用されるメッセージです。

メッセージ番号方向説明
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ60S->C(期限切れなどの)パスワードの変更を促す

その他、RFC には、しきい値として

  • 認証失敗限度 20 回*5
  • 認証待ちタイムアウト限度 10分*6

SSH 仕様として提示されています。

認証メソッド "none" の場合

  <client>                         <server>
    |  <USERAUTH_REQUEST(50)>        |
    |------------------------------->|
    |                                |
    |        <USERAUTH_FAILURE(51)>  |
    |<-------------------------------|
    |                                |

認証メソッドが "none" の認証要求は失敗させるべきとされています。

クライアントはサーバの応答に含まれる「サーバが継続可能な認証メソッドのリスト」を得ることを期待して、この認証要求を送信します。

USERAUTH_REQUEST (C->S)
user_name
ユーザ名です
service_name
サービス名です
method_name
認証メソッド名です。この場合、"none"です
USERAUTH_FAILURE (S->C)
auths_can_continue
サーバが継続可能な認証メソッドのリストです(例:["password","publickey"])

認証メソッド "password" (パスワード変更なし)の場合

パスワード変更なしの認証要求の場合は以下のようになります。

  <client>                         <server>
    |  <USERAUTH_REQUEST(50)>        |
    |------------------------------->|
    |                                |
    |        <USERAUTH_SUCCESS(52)>  |
    |<-------------------------------|(※認証成功の場合)
    |                                | 
    |        <USERAUTH_FAILURE(51)>  |
    |<-------------------------------|(※認証失敗の場合)
    |                                |
    | <USERAUTH_PASSWD_CHANGEREQ(60)>|
    |<-------------------------------|(※期限切れなどパスワード変更を促す場合)
USERAUTH_REQUEST (C->S)
user_name
ユーザ名です
service_name
サービス名です
method_name
認証メソッド名です。この場合、"password"です
password
パスワードです
USERAUTH_SUCCESS (S->C)

パラメータはありません。

USERAUTH_FAILURE (S->C)
auths_can_continue
サーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
USERAUTH_PASSWD_CHANGEREQ (S->C)
prompt
クライアントに示すプロンプト文字列

認証メソッド "password" (パスワード変更あり)の場合

パスワード変更ありの認証要求の場合は以下のようになります。

  <client>                         <server>
    |  <USERAUTH_REQUEST(50)>        |
    |------------------------------->|
    |                                |
    |        <USERAUTH_SUCCESS(52)>  |
    |<-------------------------------|(※パスワード変更OK、認証OKの場合)
    |                                | 
    |        <USERAUTH_FAILURE(51)>  |
    |<-------------------------------|(※パスワード変更OK、認証NGの場合)
    |         [partial_success=true] |
    |                                |
    |        <USERAUTH_FAILURE(51)>  |
    |<-------------------------------|(※パスワード変更未サポート、
    |         [partial_success=false]|   または、旧パスワードNGの場合)
    |                                |
    | <USERAUTH_PASSWD_CHANGEREQ(60)>|
    |<-------------------------------|(※新パスワード受け入れ不可など
                                         パスワード変更を促す場合)
旧パスワード認証パスワード変更新パスワードパスワード認証応答
OKサポート適正有効SUCCESS
OKサポート適正無効FAILURE(partial=true)
---FAILURE(partial=false)
NG---FAILURE(partial=false)
OKサポート不適正有効CHANGEREQ*7
USERAUTH_REQUEST (C->S)
user_name
ユーザ名です
service_name
サービス名です
method_name
認証メソッド名です。この場合、"password"です
with_new_password
true です
old_password
旧パスワードです
new_password
新パスワードです
USERAUTH_SUCCESS (S->C)

パラメータはありません。

USERAUTH_FAILURE (S->C)
auths_can_continue
サーバが継続可能な認証メソッドのリストです(例:["password","publickey"])
partial_success
true または false。上の図、表のとおりです
USERAUTH_PASSWD_CHANGEREQ (S->C)
prompt
クライアントに示すプロンプト文字列

認証メソッド "publickey" の場合

今回は割愛(次回以降説明します)。

認証メソッド "hostbased" の場合

今回は割愛(次回以降説明するかも。。。)。

バナー

  <client>                         <server>
    |                                |
    |           <USERAUTH_BANNER(53)>|
    |<-------------------------------|(※認証プロトコル中随時、任意)

サーバはクライアントにバナーメッセージを送信できます。

通常、クライアントはバナーメッセージをユーザに表示します。

USERAUTH_BANNER (S->C)
message
バナーメッセージ

ユーザ認証プロトコルが終わったら

ユーザ認証プロトコルが終わったら、通常コネクションプロトコルに移行します。

----

今回のメモは以上です。

と、思いましたが Ruby の日記なのに Ruby のコードがひとつもないので、gmrw-ssh2-server のパスワード認証の該当部分を載っけます。

  property_ro :users, 'SSH2.config.users'

  def authenticate(message)
    user = message[:user_name]
    pass = message[:old_password]
    chpw = message[:with_new_password]

    ok = !chpw && (users[user] || {})[:password] == pass

    debug( "password auth : #{ok}" )

    ok ? welcome(message) : please_retry
  end

パスワード変更未サポート、期限切れ管理なし、です。

パスワードは lib/gmrw/ssh2/server/config.rb に書かれています。平文で。。。

*1OSI 7階層モデルでいうトランスポート層ではありません

*2SSH の仕様的にはローカルな拡張も可能です

*3:他のRFCでのその他の認証メソッドも定義されています。また、SSH の仕様的にはローカルな拡張も可能です

*4:通常 "none" は必ず失敗する疑似メソッドとして使用されます

*5:連続失敗回数のことと思います

*6:クライアントからの認証メッセージの送信間隔のことと思います

*7:USERAUTH_PASSWD_CHANGEREQ を送信した場合、クライアントはサーバがパスワード変更サポートあり、とみなします