記憶に頼って書いてます。
認証処理は以下の順番でパケットが送られます。
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でも起きるならば、他にも原因があるかもしれません。
ブレークポイントを設定しながらログを取って確認しました。
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
# 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 になる) <- これが来ていない
サーバから SSH_MSG_USERAUTH_FAILURE が返ってこない(ような変な送り方をしている?)
SSH のパケットを見ると SSH_MSG_USERAUTH_FAILURE が返ってきていました。
ですので、サーバは同じレスポンスを返しているのに、TTSSH 側が受信する動きに違いがあります。
CheckAuthListFIrst が 0 でも 1 でも SSH_MSG_USERAUTH_REQUEST("none") は送られます。認証ダイアログが生きた状態かどうか?の違いかもしれません。
SSH_MSG_USERAUTH_BANNER の message が長くて PKT_recv() に渡されているバッファの長さを超えた場合、続きを読む必要があります。
続きを読むために PostMessage() を呼んでいるようですが、続きが読み込まれず処理が止まっています。
この現象は、CheckAuthListFIrst が 1 のとき(SSH 認証ダイアログが表示されているとき)のみ発生します。
前のコメントに書いたように
の二つの問題がありそう。
問題※2についてですが、Tera Term の仕様と言えそうです。
Tera TermはWindowsのメッセージをすべて処理したのち、 アイドル処理として受信バッファのデータを処理します。
例えば、SSH認証ダイアログが出ている間、 DialogBoxIndirectParamW()に入ったまま返って来ないので アイドル処理ができなくなり、受信バッファのデータが処理されません。
たとえば、出力が少し遅延するコマンドを入力して、
sleep 5 && ls出力される前に、ダイアログ(例えば、設定-端末など)を表示していると、 vtwinには出力されず、ダイアログを閉じたところで出力されます。
SSH_MSG_USERAUTH_BANNER受信処理内で、描画まで行うなどで 対処できるかもしれませんが特別処理となりそうです。
アイドル処理をスレッドに置き換えたいなと思いますが 取り掛かるのは先になりそうですね。
確認ありがとうございます。すぐに修正するのは難しそうですね。
取り得る選択肢:
いずれにしろ「5.0 で根本的な解決はしない」という認識に修正します。
試しにメッセージを使ってアイドル処理を動作させてみました。 とりあえず手もとではうまく動作しているようです。
SetTimer() を使うとVTWindowのウィンドウプロシージャーにメッセージ(WM_TIMER)を配送できるようです。
ttxssh/ssh.c の SetTimer()を入れる箇所、ディレイ時間など見ていただけないでしょうか。
idleブランチ(r10690)に入れました。
SetTimer() で動作していますが、PostMessage()を使ったメッセージのほうが良いかもしれません。
comment の※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に詳しくならないと解決できなさそうです。
認証バナーを VTWindow に表示する設定になっていると、受け取った SSH_MSG_USERAUTH_BANNER は認証ダイアログを閉じるまで描画されません。
RFC は認証前に表示されることを想定しているように思います。
もしかしたら #40995 はこれと関連があるかも?