Hatena::Grouprubyist

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

Ruby ロゴ (C) Ruby Association LLC

2011年09月18日(日)

SSHサーバを作る(その24) コネクションプロトコル(3)

| 11:44 | SSHサーバを作る(その24) コネクションプロトコル(3) - Going My Ruby Way を含むブックマーク はてなブックマーク - SSHサーバを作る(その24) コネクションプロトコル(3) - Going My Ruby Way SSHサーバを作る(その24) コネクションプロトコル(3) - Going My Ruby Way のブックマークコメント

チャネルリクエストのタイプ

  <client>                         <server>
    |  <CHANNEL_REQUEST(98)>         |
    |------------------------------->|リクエスト
    |................................|............................           
    |                                |※REQUEST の want_reply が true の場合
    |                                |
    |          <CHANNEL_SUCCESS(99)> |
    |<-------------------------------| (※成功の場合)
    |                                |
    |         <CHANNEL_FAILURE(100)> |
    |<-------------------------------| (※失敗の場合)
    |                                |

CHANNEL_REQUEST のパラメータはリクエストタイプごとに特有です。

recipient channel
受信側チャネル番号(通常、サーバ側チャネル番号)
request type
リクエストタイプ
want_reply
応答の要/不要フラグ
以降のパラメータ
request type ごとに特有

リクエストタイプ "pty-req" (Client -> Server)

リクエストタイプ "pty-req" は後続の shell などで使用する疑似端末の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "ptr-req"
want reply応答の要/不要フラグ
TERM environment variable value環境変数 TERM の値 (e.g., vt100)
terminal width (characters) 端末の幅(文字数) (e.g., 80)。ピクセル数の指定より優先
terminal height (rows)端末の高さ(行数) (e.g., 24)。ピクセル数の指定より優先
terminal width (pixels)端末の幅(ピクセル数) (e.g., 640)
terminal height (pixels)端末の高さ(ピクセル数) (e.g., 480)
encoded terminal modes(符号化された)ターミナルモード

ターミナルモードは以下のようなストリームです。

 [opcode + argument ], [opcode + argument], [opcode + argument] ... 
  • opcode は byte 型です
  • opcode 0 はストリームの終了を表します
  • opcode 1 〜 159 は uint32 型の argument を持ちます
  • それ以外の opcode は未定義です

opcode は RFC 4254 で定義(欠番あり)されています。(以下、一部抜粋)

          opcode  mnemonic       description
          ------  --------       -----------
          0     TTY_OP_END  Indicates end of options.
          1     VINTR       Interrupt character; 255 if none.  Similarly
                             for the other characters.  Not all of these
                             characters are supported on all systems.
          2     VQUIT       The quit character (sends SIGQUIT signal on
                             POSIX systems).
          3     VERASE      Erase the character to left of the cursor.
          4     VKILL       Kill the current input line.

                     (以下、略)

リクエストタイプ "env" (Client -> Server)

リクエストタイプ "env" は環境変数の設定の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "env"
want reply応答の要/不要フラグ
variable name環境変数の名前 (e.g., LANG)
variable value環境変数の値 (e.g., ja_JP.UTF-8)

リクエストタイプ "shell" (Client -> Server)

リクエストタイプ "shell" はプログラム(ユーザのデフォルトシェル)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "shell"
want reply応答の要/不要フラグ

リクエストタイプ "exec" (Client -> Server)

リクエストタイプ "exec" はプログラム(任意のコマンド)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "exec"
want reply応答の要/不要フラグ
command起動を要求するコマンド (e.g, hostname)

リクエストタイプ "subsystem" (Client -> Server)

リクエストタイプ "subsystem" はプログラム(サブシステム)の起動の要求です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "subsystem"
want reply応答の要/不要フラグ
subsystemサブシステムの名前(e.g., sftp)

リクエストタイプ "exit-status" (Server -> Client)

リクエストタイプ "exit-status" は終了ステータスの返却です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "exit-status"
want reply応答の要/不要フラグ。この場合 false
exit_status終了ステータス(e.g., 0)

リクエストタイプ "exit-signal" (Server -> Client)

リクエストタイプ "exit-signal" はシグナルによる終了の通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "exit-signal"
want reply応答の要/不要フラグ。この場合 false
signal nameシグナル名 (下記)
core dumpedコアダンプしたか否かのフラグ
error messageエラーメッセージ
language tag error message の言語タグ(RFC3066参照)

シグナル名は以下のように RFC で定義されています*1

            ABRT
            ALRM
            FPE
            HUP
            ILL
            INT
            KILL
            PIPE
            QUIT
            SEGV
            TERM
            USR1
            USR2

ちなみに、Ubuntu Linux でのシグナルの一覧です。(kill -l)

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

リクエストタイプ "signal" (Client -> Server)

リクエストタイプ "signal" はシグナルの通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "signal"
want reply応答の要/不要フラグ。この場合 false
signal nameシグナル名 (上記)

リクエストタイプ "window-change" (Client -> Server)

リクエストタイプ "window-change" は端末のサイズ変更の通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、サーバ側チャネル番号)
request typeリクエストタイプ。この場合 "window-change"
want reply応答の要/不要フラグ。この場合 false
terminal width (characters) 端末の幅(文字数) (e.g., 80)。ピクセル数の指定より優先
terminal height (rows)端末の高さ(行数) (e.g., 24)。ピクセル数の指定より優先
terminal width (pixels)端末の幅(ピクセル数) (e.g., 640)
terminal height (pixels)端末の高さ(ピクセル数) (e.g., 480)

リクエストタイプ "xon-xoff" (Server -> Client)

リクエストタイプ "xon-xoff" はフロー制御の可否通知です。

CHANNEL_REQUEST フィールド説明
recipient channel受信側チャネル番号(通常、クライアント側チャネル番号)
request typeリクエストタイプ。この場合 "xon-off"
want reply応答の要/不要フラグ。この場合 false
client can doフロー制御をクライアントが行えるかの可否

リクエストタイプ "x11-req"

説明を割愛します。(詳細は RFC4254 を参照)

----

gmrw-ssh2-server ではリクエストタイプ "shell" を扱います。

起動するシェルは環境変数 SHELL の値か "bash" です。

他のリクエストタイプのほとんどは未対応です。

以下は、gmrw-ssh2-server のリクエスト受け付けに関するコードです。

    def_initialize :service
    property :program, :null
    property :term, '{}'
    property :env,  '{}'

    property_ro :requests, '{
      "env"     => :env_request_received,
      "pty-req" => :pty_req_request_received,
      "exec"    => :exec_request_received,
      "shell"   => :exec_request_received,
    }'

    def request(message)
      request = requests[message[:request_type]] || :not_support
      send(request, message) {|*a| message[:want_reply] && reply(*a) }
    end

    def not_support(*)
      yield( :channel_failure )
    end

    def env_request_received(message)
      env[message[:env_var_name]] = message[:env_var_value]
      yield( :channel_success )
    end

    def pty_req_request_received(message)
      env['TERM']   = message[:term_env_var]
      term[:cols]   = message[:term_cols]
      term[:rows]   = message[:term_rows]
      term[:width]  = message[:term_width]
      term[:height] = message[:term_height]
      term[:modes]  = message[:term_modes]
      yield( :channel_success )
    end

    def exec_request_received(message)
      program(Program.new(self)).start(message[:command])
      yield( :channel_success )
    end

*1SSH 仕様として拡張も認められています