任务单 #46471

SSH 認証ダイアログが閉じるまで、認証バナーが VTWindow に表示されない

开放日期: 2023-01-07 08:55 最后更新: 2023-05-01 00:07

报告人:
属主:
(无)
类型:
状态:
开启
组件:
里程碑:
(无)
优先:
5 - Medium
严重性:
5 - Medium
处理结果:
文件:
Vote
Score: 0
No votes
0.0% (0/0)
0.0% (0/0)

Details

認証バナーを VTWindow に表示する設定になっていると、受け取った SSH_MSG_USERAUTH_BANNER は認証ダイアログを閉じるまで描画されません。

RFC は認証前に表示されることを想定しているように思います。

RFC 4252 5.4 Banner Message

In some jurisdictions, sending a warning message before authentication may be relevant for getting legal protection.

Many UNIX machines, for example, normally display text from /etc/issue, use TCP wrappers, or similar software to display a banner before issuing a login prompt.

もしかしたら #40995 はこれと関連があるかも?

任务单历史 (3/12 Histories)

2023-01-07 08:55 Updated by: nmaya
  • New Ticket "SSH 認証ダイアログが閉じるまで、認証バナーが VTWindow に表示されない" created
2023-01-07 17:29 Updated by: doda
评论

記憶に頼って書いてます。

認証処理は以下の順番でパケットが送られます。

  1. C: SSH_MSG_SERVICE_REQUEST
  2. S: SSH_MSG_SERVICE_ACCEPT
  3. S: SSH_MSG_USERAUTH_BANNER (Optional)
  4. C SSH_MSG_USERAUTH_REQUEST
  5. S: SSH_MSG_USERAUTH_SUCCESS/FAILURE
  6. -以下略-

ttsshでは、認証方式が決まってSSH_MSG_USERAUTH_REQUESTを送る際の前処理としてSSH_MSG_SERVICE_REQUESTを送る(ただし送信済みの場合はスキップする)という実装だったと思います。

なので認証ダイアログが開いた段階ではSSH_MSG_SERVICE_REQUESTが送られていない為サーバーは認証処理がまだ開始していないと認識しているので、SSH_MSG_USERAUTH_BANNERもまだ送られてきていないとういう状態だったはずです。

ただ、CheckAuthListFIrst=1ならば一度SSH_MSG_USERAUTH_REQUESTを送信するので、状況が変わるかも。 CheckAuthListFIrst=1でも起きるならば、他にも原因があるかもしれません。

2023-01-08 01:24 Updated by: nmaya
  • Details Updated
评论

ブレークポイントを設定しながらログを取って確認しました。

CheckAuthListFirst=0 だと認証前に表示されているので、正確ではありませんでした。CheckAuthListFirst=1 だと遅れて表示されているように見えます。

CheckAuthListFirst=0 だと、このように動いているようです。これは期待通りです。

認証ダイアログが開く
ユーザ名を入力する
パスワードを入力する
認証ダイアログのOKボタンを押す
認証ダイアログが消える
C: SSH_MSG_SERVICE_REQUEST
S: SSH_MSG_SERVICE_ACCEPT
C SSH_MSG_USERAUTH_REQUEST("none")
S: SSH_MSG_USERAUTH_BANNER
バナーが表示される
S: SSH_MSG_USERAUTH_FAILURE ("none" は必ず FAILURE になる)
C: SSH_MSG_USERAUTH_REQUEST (本当の認証)
S: SSH_MSG_USERAUTH_SUCCESS

CheckAuthListFirst=1 だと、このように動いているようです。

認証ダイアログが開く
ユーザ名を入力して、フォーカスアウトする
C: SSH_MSG_SERVICE_REQUEST
S: SSH_MSG_SERVICE_ACCEPT
C SSH_MSG_USERAUTH_REQUEST("none")
S: SSH_MSG_USERAUTH_BANNER ... ログされているので、ここで受信はしている
バナーが表示されない ... このあたりからおかしい
handle_SSH2_userauth_failure() に来ない ... S: SSH_MSG_USERAUTH_FAILURE ("none" は必ず FAILURE になる) が送られてきているはずだが...

-> 認証ダイアログのOKボタンを押す
   何も起こらない ... ログインできない ticket #40995
-> 認証ダイアログのDisconnectボタンを押す
   C: SSH_MSG_DISCONNECT
   バナーが表示される ... 「ここまでバナーが表示されない」ということでこの ticket を切った
   S: SSH_MSG_USERAUTH_FAILURE

CheckAuthListFirst=1 のときの期待する動き

認証ダイアログが開く
ユーザ名を入力して、フォーカスアウトする
C: SSH_MSG_SERVICE_REQUEST
S: SSH_MSG_SERVICE_ACCEPT
C SSH_MSG_USERAUTH_REQUEST("none")
S: SSH_MSG_USERAUTH_BANNER
バナーが表示される
S: SSH_MSG_USERAUTH_FAILURE ("none" は必ず FAILURE になる)

パスワードを入力する
認証ダイアログのOKボタンを押す
C: SSH_MSG_USERAUTH_REQUEST (本当の認証)
S: SSH_MSG_USERAUTH_SUCCESS
2023-01-08 15:21 Updated by: nmaya
评论

# wireshark と KeyKey.log を使ってパケットの中身まで見たかったのですが、手元でうまくいきません(ログファイルを指定しても復号されない)。

しかし、やりとりとパケットサイズを見た感じでは、以下のことが起こっているようです。

CheckAuthListFirst=1 で、認証ダイアログを出したまま(ユーザ名のフォーカスアウトで)送った SSH_MSG_USERAUTH_REQUEST の返事(SSH_MSG_USERAUTH_FAILURE)が返ってきません。

C: SSH_MSG_SERVICE_REQUEST
S: SSH_MSG_SERVICE_ACCEPT
C: SSH_MSG_USERAUTH_REQUEST("none")
S: SSH_MSG_USERAUTH_BANNER
S: SSH_MSG_USERAUTH_FAILURE ("none" は必ず FAILURE になる) <- これが来ていない
  • 問題1
    • サーバから SSH_MSG_USERAUTH_FAILURE が返ってこない(ような変な送り方をしている?)
  • 問題2?
    • DISCONNECT に対する FAILURE が返ってくると。バナーが VTWinodw に表示されている様子
    • 「SUCCESS/FAILURE が返ってくるまでバナーが VTWinodw に表示されない」という問題?
(Edited, 2023-01-10 23:06 Updated by: nmaya)
2023-01-10 23:10 Updated by: nmaya
2023-01-23 22:58 Updated by: nmaya
评论

サーバから SSH_MSG_USERAUTH_FAILURE が返ってこない(ような変な送り方をしている?)

SSH のパケットを見ると SSH_MSG_USERAUTH_FAILURE が返ってきていました。

ですので、サーバは同じレスポンスを返しているのに、TTSSH 側が受信する動きに違いがあります。

CheckAuthListFIrst が 0 でも 1 でも SSH_MSG_USERAUTH_REQUEST("none") は送られます。認証ダイアログが生きた状態かどうか?の違いかもしれません。

2023-02-07 23:57 Updated by: nmaya
评论

SSH_MSG_USERAUTH_BANNER の message が長くて PKT_recv() に渡されているバッファの長さを超えた場合、続きを読む必要があります。

続きを読むために PostMessage() を呼んでいるようですが、続きが読み込まれず処理が止まっています。

この現象は、CheckAuthListFIrst が 1 のとき(SSH 認証ダイアログが表示されているとき)のみ発生します。

問題が起きているTCPパケット(SSH_MSG_USERAUTH_BANNER と SSH_MSG_USERAUTH_FAILURE が同じ TCP パケットに乗っている。これで1パケット)

  • SSH Packet 1 (1200 byte)
    • SSH packet length 4 byte (1164)
    • Padding length 1 byte (13)
    • Payload
      • Message Type 1 byte SSH_MSG_USERAUTH_BANNER
      • string message
        • string length 4 byte (0x475 = 1141)
        • string data 1141 byte
      • string language tag
        • string length 4 byte (0)
    • Padding 13 byte
    • MAC 32 byte
  • SSH Packet 2 (64 byte)
    • SSH packet length 4 bytes (28)
    • Padding length 1 byte (12)
    • Payload
      • Message Type 1 byte SSH_MSG_USERAUTH_FAILURE
      • string list
        • string len 4 byte
        • string data 9 byte ("publickey")
      • bool 1 byte
    • Padding 12 byte
    • MAC 32 byte

処理の流れ @ PKT_recv()

  • パケットが読み込まれる
    • pvar->pkt_state.buf にデータが入る
  • SSH2_handle_packet(), その先の handle_SSH2_userauth_banner() が呼ばれ、pvar->ssh_state.payload_datastart, pvar->ssh_state.payload_datalen がセットされる
  • while の先頭に来て、pvar->pkt_state.buf から 1024 バイトが buf にコピーされる(message の途中まで)
    • この段階で VTWindow への描画指示が行われているようだが、認証ダイアログが消えるまでは描画が行われない模様 ※2
  • データの長さが 1024 より大きいので buflen が 0 になる
    • while を抜ける
  • SSH_is_any_payload(pvar) が TRUE なので、pvar->NotificationWindow に PostMessage() する
    • ここでふたたび PKT_recv() に来て SSH_MSG_USERAUTH_BANNER の残りを読み取り、続けて SSH_MSG_USERAUTH_FAILURE が処理される。のが正しい動きだと思われるが、CheckAuthListFIrst が 1 だとそうはならない。※1
    • CheckAuthListFIrst が 0 だとふたたび PKT_recv() に来ている

まとめ

前のコメントに書いたように

  • ※1 #40995 SSH_MSG_USERAUTH_FAILURE が処理されずに先に進まない
  • ※2 #46471 (このチケット)SSH認証ダイアログがあるうちは VTWindow への描画が反映されない

の二つの問題がありそう。

2023-04-24 23:23 Updated by: zmatsuo
评论

問題※2についてですが、Tera Term の仕様と言えそうです。

Tera TermはWindowsのメッセージをすべて処理したのち、 アイドル処理として受信バッファのデータを処理します。

例えば、SSH認証ダイアログが出ている間、 DialogBoxIndirectParamW()に入ったまま返って来ないので アイドル処理ができなくなり、受信バッファのデータが処理されません。

たとえば、出力が少し遅延するコマンドを入力して、

sleep 5 && ls
出力される前に、ダイアログ(例えば、設定-端末など)を表示していると、 vtwinには出力されず、ダイアログを閉じたところで出力されます。

SSH_MSG_USERAUTH_BANNER受信処理内で、描画まで行うなどで 対処できるかもしれませんが特別処理となりそうです。

アイドル処理をスレッドに置き換えたいなと思いますが 取り掛かるのは先になりそうですね。

(Edited, 2023-04-24 23:26 Updated by: zmatsuo)
2023-04-26 19:58 Updated by: nmaya
评论

確認ありがとうございます。すぐに修正するのは難しそうですね。

取り得る選択肢:

  • 今のまま「認証後」に表示される、でよいとする
  • 今のままで RFC の「認証前」「ログインプロンプトの前」に従おうとする。AuthBanner のデフォルトを 2 か 3 にして回避する

いずれにしろ「5.0 で根本的な解決はしない」という認識に修正します。

2023-04-27 01:34 Updated by: zmatsuo
评论

試しにメッセージを使ってアイドル処理を動作させてみました。 とりあえず手もとではうまく動作しているようです。

SetTimer() を使うとVTWindowのウィンドウプロシージャーにメッセージ(WM_TIMER)を配送できるようです。

ttxssh/ssh.c の SetTimer()を入れる箇所、ディレイ時間など見ていただけないでしょうか。

idleブランチ(r10690)に入れました。

SetTimer() で動作していますが、PostMessage()を使ったメッセージのほうが良いかもしれません。

2023-04-29 00:08 Updated by: zmatsuo
  • 状态 Update from 开启 to 关闭
评论

comment の※1を対策できないか調べてみました。

次のことを行い再現する状態にしました

  • SSH_MSG_USERAUTH_BANNER の message を長くする(3500byteぐらいにしてみました)
  • TeraTermの設定 CheckAuthListFIrst = 1

Windows の ssh(C:/Windows/System32/OpenSSH/ssh.exeです)とcygwinのsshでBANNERが正しく表示されるのを確認しました。

TeraTerm 上では SSH認証ダイアログでOKを押しても先に進まなくなりました。

idleブランチ(r10690)の修正に加えて、受信データを処理させるよう次のようにしてみました。

--- a/ttssh2/ttxssh/pkt.c
+++ b/ttssh2/ttxssh/pkt.c
@@ -337,7 +337,9 @@ int PKT_recv(PTInstVar pvar, char *buf, int buflen)
 	}

 	if (SSH_is_any_payload(pvar)) {
 		PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY, pvar->socket, MAKELPARAM(FD_READ, 0));
+		SetTimer(pvar->cv->HWin, IdKickIdleTimer, 300, 0);
 	}

 	return amount_in_buf;
すると、処理が進んでログインできるようになりました。

でもBANNERが途中で途切れた状態になりました。

サーバーからのデータは処理できたけど受信バッファに入れずにいるような印象です。

もう少しttxsshに詳しくならないと解決できなさそうです。

2023-05-01 00:07 Updated by: zmatsuo
  • 状态 Update from 关闭 to 开启
评论

誤ってクローズしていました。オープンに戻します。

Attachment File List

No attachments

编辑

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » 登录名