[ttssh2-commit] [10073] ホスト鍵確認ダイアログ表示中にSSH_MSG_EXT_INFOが扱え無い問題を修正した。

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2022年 7月 18日 (月) 00:40:50 JST


Revision: 10073
          https://osdn.net/projects/ttssh2/scm/svn/commits/10073
Author:   doda
Date:     2022-07-18 00:40:49 +0900 (Mon, 18 Jul 2022)
Log Message:
-----------
ホスト鍵確認ダイアログ表示中にSSH_MSG_EXT_INFOが扱え無い問題を修正した。

問題:
  ホスト鍵がssh_known_hostsに登録されていないサーバへの接続時、サーバ側が
  ユーザ認証でrsa-sha2-256/512に対応していると、ホスト鍵の確認ダイアログ
  表示中に「現在のステージでは想定外のSSH2 メッセージです」というエラーを
  表示して接続を切断してしまう。

原因:
  ホスト鍵確認ダイアログ表示中に送られて来た SSH_MSG_EXT_INFO が扱え無い為。

  ホスト鍵確認ダイアログを表示した時は、KEXの処理を中断するようになっていた。
  その状態で SSH_MSG_NEWKEYS を受信した場合は、SSH_MSG_NEWKEYS の処理も
  保留していた。
  それにより、KEXの処理が中断する事で通信暗号用の鍵/IVが設定されず、また
  SSH_MSG_NEWKEYS の処理も保留している為、受信方向の暗号化(復号)が開始
  されない状態となっていた。
  そこに暗号化された SSH_MSG_EXT_INFO を受信した為、復号せずにそのまま読み
  不明なパケットとして扱っていた。

対処:
  ホスト鍵確認ダイアログを表示しても、KEXの処理を中断せず暗号鍵/IVの設定を
  行い、またSSH_MSG_NEWKEYS受信時に即復号処理を開始するようにした。
  SSH_MSG_NEWKEYSの送信はホスト鍵の確認後に行うようにする事で、ホスト鍵確認
  ダイアログ表示中にユーザ認証を開始しないようにした。

Modified Paths:
--------------
    trunk/ttssh2/ttxssh/crypt.c
    trunk/ttssh2/ttxssh/hosts.c
    trunk/ttssh2/ttxssh/ssh.c
    trunk/ttssh2/ttxssh/ssh.h
    trunk/ttssh2/ttxssh/ttxssh.h

-------------- next part --------------
Modified: trunk/ttssh2/ttxssh/crypt.c
===================================================================
--- trunk/ttssh2/ttxssh/crypt.c	2022-07-17 15:40:39 UTC (rev 10072)
+++ trunk/ttssh2/ttxssh/crypt.c	2022-07-17 15:40:49 UTC (rev 10073)
@@ -795,28 +795,11 @@
 
 BOOL CRYPT_choose_ciphers(PTInstVar pvar)
 {
-	if (SSHv1(pvar)) {
-		pvar->crypt_state.sender_cipher = choose_cipher(pvar,
-		                                                pvar->crypt_state.
-		                                                supported_sender_ciphers);
-		pvar->crypt_state.receiver_cipher =
-			choose_cipher(pvar, pvar->crypt_state.supported_receiver_ciphers);
+	pvar->crypt_state.sender_cipher =
+		choose_cipher(pvar, pvar->crypt_state.supported_sender_ciphers);
+	pvar->crypt_state.receiver_cipher =
+		choose_cipher(pvar, pvar->crypt_state.supported_receiver_ciphers);
 
-	} else { // SSH2(yutaka)
-		if (pvar->ciphers[MODE_OUT] == NULL) {
-			pvar->crypt_state.sender_cipher = SSH_CIPHER_NONE;
-		}
-		else {
-			pvar->crypt_state.sender_cipher = get_cipher_id(pvar->ciphers[MODE_OUT]);
-		}
-		if (pvar->ciphers[MODE_IN] == NULL) {
-			pvar->crypt_state.receiver_cipher = SSH_CIPHER_NONE;
-		}
-		else {
-			pvar->crypt_state.receiver_cipher = get_cipher_id(pvar->ciphers[MODE_IN]);
-		}
-	}
-
 	if (pvar->crypt_state.sender_cipher == SSH_CIPHER_NONE
 		|| pvar->crypt_state.receiver_cipher == SSH_CIPHER_NONE) {
 		UTIL_get_lang_msg("MSG_CIPHER_NONE_ERROR", pvar,
@@ -1089,6 +1072,7 @@
 			// SSH2
 			cipher = pvar->ciphers[MODE_OUT];
 			if (cipher) {
+				pvar->crypt_state.sender_cipher = get_cipher_id(pvar->ciphers[MODE_OUT]);
 				enc = &pvar->ssh2_keys[MODE_OUT].enc;
 				cipher_init_SSH2(&pvar->cc[MODE_OUT], cipher,
 				                 enc->key, enc->key_len,
@@ -1098,6 +1082,7 @@
 				pvar->crypt_state.encrypt = crypt_SSH2_encrypt;
 			}
 			else {
+				pvar->crypt_state.sender_cipher = SSH_CIPHER_NONE;
 				isOK = FALSE;
 			}
 		}
@@ -1133,6 +1118,7 @@
 			// SSH2
 			cipher = pvar->ciphers[MODE_IN];
 			if (cipher) {
+				pvar->crypt_state.receiver_cipher = get_cipher_id(pvar->ciphers[MODE_IN]);
 				enc = &pvar->ssh2_keys[MODE_IN].enc;
 				cipher_init_SSH2(&pvar->cc[MODE_IN], cipher,
 				                 enc->key, enc->key_len,
@@ -1142,6 +1128,7 @@
 				pvar->crypt_state.decrypt = crypt_SSH2_decrypt;
 			}
 			else {
+				pvar->crypt_state.receiver_cipher = SSH_CIPHER_NONE;
 				isOK = FALSE;
 			}
 		}

Modified: trunk/ttssh2/ttxssh/hosts.c
===================================================================
--- trunk/ttssh2/ttxssh/hosts.c	2022-07-17 15:40:39 UTC (rev 10072)
+++ trunk/ttssh2/ttxssh/hosts.c	2022-07-17 15:40:49 UTC (rev 10073)
@@ -70,10 +70,6 @@
 static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 
-BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar);
-void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar);
-
-
 static wchar_t **parse_multi_path(wchar_t *buf)
 {
 	int i;
@@ -1867,7 +1863,7 @@
 			 * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̂\xBD\x82߂Ɉꎞ\x92\xE2\x8E~\x82\xB5\x82Ă\xA2\x82\xBD
 			 * SSH\x83T\x81[\x83o\x82Ƃ̃l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x8DĊJ\x82\xB3\x82\xB9\x82\xE9\x81B
 			 */
-			HOSTS_resume_session_after_known_hosts(pvar);
+			SSH_notify_host_OK(pvar);
 
 			pvar->hosts_state.hosts_dialog = NULL;
 
@@ -1876,11 +1872,6 @@
 
 		case IDCANCEL:			/* kill the connection */
 canceled:
-			/*
-			 * known_hosts\x82\xF0\x83L\x83\x83\x83\x93\x83Z\x83\x8B\x82\xB7\x82邽\x82߁A\x8DĊJ\x97p\x82̃\x8A\x83\\x81[\x83X\x82\xF0\x94j\x8A\xFC\x82\xB5\x82Ă\xA8\x82\xAD\x81B
-			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			notify_closed_connection(pvar, "authentication cancelled");
 			EndDialog(dlg, 0);
@@ -1891,8 +1882,6 @@
 			 * known_hosts\x92\x86\x82ɃT\x81[\x83o\x91\xA4\x82\xA9\x82\xE7\x83l\x83b\x83g\x83\x8F\x81[\x83N\x90ؒf\x82\xB3\x82ꂽ\x8Fꍇ\x81A
 			 * \x83_\x83C\x83A\x83\x8D\x83O\x82݂̂\xF0\x95‚\xB6\x82\xE9\x81B
 			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			EndDialog(dlg, 0);
 			return TRUE;
@@ -2022,7 +2011,7 @@
 			 * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̂\xBD\x82߂Ɉꎞ\x92\xE2\x8E~\x82\xB5\x82Ă\xA2\x82\xBD
 			 * SSH\x83T\x81[\x83o\x82Ƃ̃l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x8DĊJ\x82\xB3\x82\xB9\x82\xE9\x81B
 			 */
-			HOSTS_resume_session_after_known_hosts(pvar);
+			SSH_notify_host_OK(pvar);
 
 			pvar->hosts_state.hosts_dialog = NULL;
 
@@ -2031,11 +2020,6 @@
 
 		case IDCANCEL:			/* kill the connection */
 canceled:
-			/*
-			 * known_hosts\x82\xF0\x83L\x83\x83\x83\x93\x83Z\x83\x8B\x82\xB7\x82邽\x82߁A\x8DĊJ\x97p\x82̃\x8A\x83\\x81[\x83X\x82\xF0\x94j\x8A\xFC\x82\xB5\x82Ă\xA8\x82\xAD\x81B
-			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			notify_closed_connection(pvar, "authentication cancelled");
 			EndDialog(dlg, 0);
@@ -2046,8 +2030,6 @@
 			 * known_hosts\x92\x86\x82ɃT\x81[\x83o\x91\xA4\x82\xA9\x82\xE7\x83l\x83b\x83g\x83\x8F\x81[\x83N\x90ؒf\x82\xB3\x82ꂽ\x8Fꍇ\x81A
 			 * \x83_\x83C\x83A\x83\x8D\x83O\x82݂̂\xF0\x95‚\xB6\x82\xE9\x81B
 			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			EndDialog(dlg, 0);
 			return TRUE;
@@ -2178,7 +2160,7 @@
 			 * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̂\xBD\x82߂Ɉꎞ\x92\xE2\x8E~\x82\xB5\x82Ă\xA2\x82\xBD
 			 * SSH\x83T\x81[\x83o\x82Ƃ̃l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x8DĊJ\x82\xB3\x82\xB9\x82\xE9\x81B
 			 */
-			HOSTS_resume_session_after_known_hosts(pvar);
+			SSH_notify_host_OK(pvar);
 
 			pvar->hosts_state.hosts_dialog = NULL;
 
@@ -2187,11 +2169,6 @@
 
 		case IDCANCEL:			/* kill the connection */
 canceled:
-			/*
-			 * known_hosts\x82\xF0\x83L\x83\x83\x83\x93\x83Z\x83\x8B\x82\xB7\x82邽\x82߁A\x8DĊJ\x97p\x82̃\x8A\x83\\x81[\x83X\x82\xF0\x94j\x8A\xFC\x82\xB5\x82Ă\xA8\x82\xAD\x81B
-			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			notify_closed_connection(pvar, "authentication cancelled");
 			EndDialog(dlg, 0);
@@ -2202,8 +2179,6 @@
 			 * known_hosts\x92\x86\x82ɃT\x81[\x83o\x91\xA4\x82\xA9\x82\xE7\x83l\x83b\x83g\x83\x8F\x81[\x83N\x90ؒf\x82\xB3\x82ꂽ\x8Fꍇ\x81A
 			 * \x83_\x83C\x83A\x83\x8D\x83O\x82݂̂\xF0\x95‚\xB6\x82\xE9\x81B
 			 */
-			HOSTS_cancel_session_after_known_hosts(pvar);
-
 			pvar->hosts_state.hosts_dialog = NULL;
 			EndDialog(dlg, 0);
 			return TRUE;
@@ -2416,48 +2391,6 @@
 	return FALSE;
 }
 
-/*
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82Ń\x86\x81[\x83U\x8F\xB3\x94F\x8C\xE3\x81ASSH\x83T\x81[\x83o\x82Ƃ̃l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x8DĊJ\x82\xB7\x82\xE9\x81B
- */
-BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar)
-{
-	enum ssh_kex_known_hosts type;
-	int ret = FALSE;
-
-	type = pvar->contents_after_known_hosts.kex_type;
-	if (type == SSH1_PUBLIC_KEY_KNOWN_HOSTS) {
-		ret = handle_server_public_key_after_known_hosts(pvar);
-
-	} else if (type == SSH2_DH_KEX_REPLY_KNOWN_HOSTS) {
-		ret = handle_SSH2_dh_kex_reply_after_known_hosts(pvar);
-
-	} else if (type == SSH2_DH_GEX_REPLY_KNOWN_HOSTS) {
-		ret = handle_SSH2_dh_gex_reply_after_known_hosts(pvar);
-
-	} else if (type == SSH2_ECDH_KEX_REPLY_KNOWN_HOSTS) {
-		ret = handle_SSH2_ecdh_kex_reply_after_known_hosts(pvar);
-
-	}
-
-	return (ret);
-}
-
-/*
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xCCSSH\x82\xB2\x82Ƃ̃L\x83\x83\x83\x93\x83Z\x83\x8B\x8F\x88\x97\x9D
- */
-void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar)
-{
-	enum ssh_kex_known_hosts type;
-
-	type = pvar->contents_after_known_hosts.kex_type;
-	if (type != NONE_KNOWN_HOSTS) {
-		handle_SSH2_canel_reply_after_known_hosts(pvar);
-	}
-
-	return;
-}
-
-
 void HOSTS_notify_disconnecting(PTInstVar pvar)
 {
 	if (pvar->hosts_state.hosts_dialog != NULL) {

Modified: trunk/ttssh2/ttxssh/ssh.c
===================================================================
--- trunk/ttssh2/ttxssh/ssh.c	2022-07-17 15:40:39 UTC (rev 10072)
+++ trunk/ttssh2/ttxssh/ssh.c	2022-07-17 15:40:49 UTC (rev 10073)
@@ -143,7 +143,9 @@
 static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen);
 static void ssh2_scp_free_packetlist(Channel_t *c);
 static void get_window_pixel_size(PTInstVar pvar, int *x, int *y);
-static BOOL store_contents_for_known_hosts(PTInstVar pvar, enum ssh_kex_known_hosts kex_type, UINT_PTR offset);
+static void do_SSH2_dispatch_setup_for_transfer(PTInstVar pvar);
+static void ssh2_prep_userauth(PTInstVar pvar);
+static void ssh2_send_newkeys(PTInstVar pvar);
 
 // \x83}\x83N\x83\x8D
 #define remained_payload(pvar) ((pvar)->ssh_state.payload + payload_current_offset(pvar))
@@ -1771,10 +1773,6 @@
 	                                   supported_types))
 		return FALSE;
 
-	// \x8C㔼\x8F\x88\x97\x9D\x97p\x82̃f\x81[\x83^\x82\xF0\x91ޔ\xF0\x82\xB5\x82Ă\xA8\x82\xAD
-	if (store_contents_for_known_hosts(pvar, SSH1_PUBLIC_KEY_KNOWN_HOSTS, 0) == FALSE)
-		return FALSE;
-
 	/* this must be the LAST THING in this function, since it can cause
 	   host_is_OK to be called. */
 	hostkey.type = KEY_RSA1;
@@ -1784,15 +1782,11 @@
 
 	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, &hostkey);
 	if (ret == TRUE) {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82͕s\x97v\x82Ȃ̂ŁA
-		 * \x91\xB1\x82\xAB\x82̏\x88\x97\x9D\x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B
-		 */
-		ret = handle_server_public_key_after_known_hosts(pvar);
+		// known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82͕s\x97v\x82Ȃ̂ŁA\x91\xB1\x82\xAB\x82̏\x88\x97\x9D\x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B
+		SSH_notify_host_OK(pvar);
 
 	} else {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA
-		 * \x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
-		 */
+		// known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA\x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
 
 	}
 
@@ -1799,13 +1793,6 @@
 	return FALSE;
 }
 
-BOOL handle_server_public_key_after_known_hosts(PTInstVar pvar)
-{
-	SSH_notify_host_OK(pvar);
-
-	return TRUE;
-}
-
 /*
 The ID must have already been found to start with "SSH-". It must
 be null-terminated.
@@ -2936,8 +2923,7 @@
 	pvar->shell_id = SSH_CHANNEL_INVALID;
 	pvar->session_nego_status = 0;
 	pvar->settings.ssh_protocol_version = 2;  // SSH2(default)
-	pvar->rekeying = 0;
-	pvar->key_done = 0;
+	pvar->kex_status = 0;
 	pvar->ssh2_autologin = 0;  // autologin disabled(default)
 	pvar->ask4passwd = 0; // disabled(default) (2006.9.18 maya)
 	pvar->userauth_retry_count = 0;
@@ -3001,15 +2987,31 @@
 	}
 }
 
+void ssh2_finish_encryption_setup(PTInstVar pvar)
+{
+	notify_established_secure_connection(pvar);
+	pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
+}
+
 void SSH_notify_host_OK(PTInstVar pvar)
 {
 	if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
 		pvar->ssh_state.status_flags |= STATUS_HOST_OK;
-		send_session_key(pvar);
-		// \x83\x86\x81[\x83U\x94F\x8F؂\xF0\x8Ds\x82\xC1\x82Ă悢\x83^\x83C\x83~\x83\x93\x83O\x82ɂȂ\xC1\x82Ă\xA9\x82\xE7\x81A\x94F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82\xF0\x8Fo\x8C\xBB\x82\xB3\x82\xB9\x82\xE9\x81B
-		// STATUS_HOST_OK\x82\xAA\x97\xA7\x82\xBF\x81ASTATUS_DONT_SEND_USER_NAME\x82\xAA\x97\x8E\x82\xBF\x82Ă\xA2\x82Ȃ\xA2\x82ƁA
-		// \x94F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82͎\xC0\x8E\xBF\x8Eg\x82\xA6\x82Ȃ\xA2\x82̂ŁA\x82\xB1\x82̃^\x83C\x83~\x83\x93\x83O\x82Ŗ\xE2\x91\xE8\x82Ȃ\xA2\x81B
-		AUTH_advance_to_next_cred(pvar);
+
+		if (SSHv1(pvar)) {
+			send_session_key(pvar);
+			// \x83\x86\x81[\x83U\x94F\x8F؂\xF0\x8Ds\x82\xC1\x82Ă悢\x83^\x83C\x83~\x83\x93\x83O\x82ɂȂ\xC1\x82Ă\xA9\x82\xE7\x81A\x94F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82\xF0\x8Fo\x8C\xBB\x82\xB3\x82\xB9\x82\xE9\x81B
+			// STATUS_HOST_OK\x82\xAA\x97\xA7\x82\xBF\x81ASTATUS_DONT_SEND_USER_NAME\x82\xAA\x97\x8E\x82\xBF\x82Ă\xA2\x82Ȃ\xA2\x82ƁA
+			// \x94F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82͎\xC0\x8E\xBF\x8Eg\x82\xA6\x82Ȃ\xA2\x82̂ŁA\x82\xB1\x82̃^\x83C\x83~\x83\x93\x83O\x82Ŗ\xE2\x91\xE8\x82Ȃ\xA2\x81B
+			AUTH_advance_to_next_cred(pvar);
+		}
+		else { // SSH2
+			// SSH2_MSG_NEWKEYS \x82\xAA\x96\xA2\x91\x97\x90M\x82Ȃ\xE7\x82Α\x97\x82\xE9
+			if ((pvar->kex_status & KEX_FLAG_NEWKEYS_SENT) == 0) {
+				ssh2_send_newkeys(pvar);
+			}
+		}
+
 	}
 }
 
@@ -3479,8 +3481,7 @@
 		}
 
 		pvar->we_need = 0;
-		pvar->key_done = 0;
-		pvar->rekeying = 0;
+		pvar->kex_status = 0;
 
 		if (pvar->session_id != NULL) {
 			free(pvar->session_id);
@@ -3539,7 +3540,7 @@
 	unsigned int len;
 
 	// SSH2\x8C\xAE\x8C\xF0\x8A\xB7\x92\x86\x82̏ꍇ\x81A\x83p\x83P\x83b\x83g\x82\xF0\x8ÊĂ\xE9\x81B(2005.6.19 yutaka)
-	if (pvar->rekeying) {
+	if (pvar->kex_status & KEX_FLAG_REKEYING) {
 		// TODO: \x97\x9D\x91z\x82Ƃ\xB5\x82Ă̓p\x83P\x83b\x83g\x94j\x8A\xFC\x82ł͂Ȃ\xAD\x81A\x83p\x83P\x83b\x83g\x93ǂݎ\xE6\x82\xE8\x92x\x89\x84\x82ɂ\xB5\x82\xBD\x82\xA2\x82Ƃ\xB1\x82낾\x82\xAA\x81A
 		// \x8F\xAB\x97\x88\x92\xBC\x82\xB7\x82\xB1\x82Ƃɂ\xB7\x82\xE9\x81B
 		logprintf(LOG_LEVEL_INFO, "%s: now rekeying. data is not sent.", __FUNCTION__);
@@ -3765,7 +3766,7 @@
 		return;
 
 	// SSH2\x8C\xAE\x8C\xF0\x8A\xB7\x92\x86\x82̏ꍇ\x81A\x83p\x83P\x83b\x83g\x82\xF0\x8ÊĂ\xE9\x81B(2005.6.21 yutaka)
-	if (pvar->rekeying) {
+	if (pvar->kex_status & KEX_FLAG_REKEYING) {
 		// TODO: \x97\x9D\x91z\x82Ƃ\xB5\x82Ă̓p\x83P\x83b\x83g\x94j\x8A\xFC\x82ł͂Ȃ\xAD\x81A\x83p\x83P\x83b\x83g\x93ǂݎ\xE6\x82\xE8\x92x\x89\x84\x82ɂ\xB5\x82\xBD\x82\xA2\x82Ƃ\xB1\x82낾\x82\xAA\x81A
 		// \x8F\xAB\x97\x88\x92\xBC\x82\xB7\x82\xB1\x82Ƃɂ\xB7\x82\xE9\x81B
 		logprintf(LOG_LEVEL_INFO, "%s: now rekeying. data is not sent.", __FUNCTION__);
@@ -4039,7 +4040,7 @@
 			Channel_t *c;
 
 			// SSH2\x8C\xAE\x8C\xF0\x8A\xB7\x92\x86\x82̏ꍇ\x81A\x83p\x83P\x83b\x83g\x82\xF0\x8ÊĂ\xE9\x81B(2005.6.21 yutaka)
-			if (pvar->rekeying) {
+			if (pvar->kex_status & KEX_FLAG_REKEYING) {
 				// TODO: \x97\x9D\x91z\x82Ƃ\xB5\x82Ă̓p\x83P\x83b\x83g\x94j\x8A\xFC\x82ł͂Ȃ\xAD\x81A\x83p\x83P\x83b\x83g\x93ǂݎ\xE6\x82\xE8\x92x\x89\x84\x82ɂ\xB5\x82\xBD\x82\xA2\x82Ƃ\xB1\x82낾\x82\xAA\x81A
 				// \x8F\xAB\x97\x88\x92\xBC\x82\xB7\x82\xB1\x82Ƃɂ\xB7\x82\xE9\x81B
 				logprintf(LOG_LEVEL_INFO, "%s: now rekeying. channel open request is not sent.", __FUNCTION__);
@@ -4690,9 +4691,8 @@
 
 	// \x82\xB7\x82łɃL\x81[\x8C\xF0\x8A\xB7\x82\xAA\x8FI\x82\xED\x82\xC1\x82Ă\xA2\x82\xE9\x82ɂ\xE0\x8Aւ\xED\x82炸\x81A\x83T\x81[\x83o\x82\xA9\x82\xE7 SSH2_MSG_KEXINIT \x82\xAA
 	// \x91\x97\x82\xE7\x82\xEA\x82Ă\xAD\x82\xE9\x8Fꍇ\x82́A\x83L\x81[\x8Dč쐬\x82\xF0\x8Ds\x82\xA4\x81B(2004.10.24 yutaka)
-	if (pvar->key_done == 1) {
-		pvar->rekeying = 1;
-		pvar->key_done = 0;
+	if (pvar->kex_status == KEX_FLAG_KEXDONE) {
+		pvar->kex_status = KEX_FLAG_REKEYING;
 
 		// \x83T\x81[\x83o\x82\xD6SSH2_MSG_KEXINIT \x82𑗂\xE9
 		SSH2_send_kexinit(pvar);
@@ -5001,7 +5001,7 @@
 
 	// we_need\x82̌\x88\x92\xE8 (2004.11.6 yutaka)
 	// \x83L\x81[\x8Dč쐬\x82̏ꍇ\x82̓X\x83L\x83b\x83v\x82\xB7\x82\xE9\x81B
-	if (pvar->rekeying == 0) {
+	if ((pvar->kex_status & KEX_FLAG_REKEYING) == 0) {
 		choose_SSH2_key_maxlength(pvar);
 	}
 
@@ -5485,40 +5485,8 @@
 cont:
 	kex_derive_keys(pvar, current_keys, pvar->we_need, hash, share_key, pvar->session_id, pvar->session_id_len);
 
-	// KEX finish
-	begin_send_packet(pvar, SSH2_MSG_NEWKEYS, 0);
-	finish_send_packet(pvar);
+	prep_compression(pvar);
 
-	logprintf(LOG_LEVEL_VERBOSE, "%s: SSH2_MSG_NEWKEYS was sent.", __FUNCTION__);
-
-	// SSH2_MSG_NEWKEYS\x82𑗂\xE8\x8FI\x82\xED\x82\xC1\x82\xBD\x82\xA0\x82ƂɃL\x81[\x82̐ݒ肨\x82\xE6\x82эĐݒ\xE8\x82\xF0\x8Ds\x82\xA4
-	// \x91\x97\x90M\x97p\x82̈Í\x86\x8C\xAE\x82\xCD SSH2_MSG_NEWKEYS \x82̑\x97\x90M\x8C\xE3\x82ɁA\x8E\xF3\x90M\x97p\x82̂\xCD SSH2_MSG_NEWKEYS \x82\xCC
-	// \x8E\xF3\x90M\x8C\xE3\x82ɍĐݒ\xE8\x82\xF0\x8Ds\x82\xA4\x81B
-	if (pvar->rekeying == 1) { // \x83L\x81[\x82̍Đݒ\xE8
-		// \x82܂\xB8\x81A\x91\x97\x90M\x97p\x82\xBE\x82\xAF\x90ݒ肷\x82\xE9\x81B
-		ssh2_set_newkeys(pvar, MODE_OUT);
-		pvar->ssh2_keys[MODE_OUT].mac.enabled = 1;
-		pvar->ssh2_keys[MODE_OUT].comp.enabled = 1;
-		enable_send_compression(pvar);
-		if (!CRYPT_start_encryption(pvar, 1, 0)) {
-			// TODO: error
-		}
-
-	} else {
-		// \x8F\x89\x89\xF1\x90ڑ\xB1\x82̏ꍇ\x82͎\xC0\x8DۂɈÍ\x86\x83\x8B\x81[\x83`\x83\x93\x82\xAA\x90ݒ肳\x82\xEA\x82\xE9\x82̂́A\x82\xA0\x82ƂɂȂ\xC1\x82Ă\xA9\x82\xE7
-		// \x82Ȃ̂ŁiCRYPT_start_encryption\x8A֐\x94\x81j\x81A\x82\xB1\x82\xB1\x82Ō\xAE\x82̐ݒ\xE8\x82\xF0\x82\xB5\x82Ă\xB5\x82܂\xC1\x82Ă\xE0\x82悢\x81B
-		ssh2_set_newkeys(pvar, MODE_OUT);
-
-		// SSH2_MSG_NEWKEYS\x82𑗐M\x82\xB5\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
-		pvar->ssh2_keys[MODE_OUT].mac.enabled = 1;
-		pvar->ssh2_keys[MODE_OUT].comp.enabled = 1;
-
-		// \x83p\x83P\x83b\x83g\x88\xB3\x8Fk\x82\xAA\x97L\x8C\xF8\x82Ȃ珉\x8A\x{227B0B7}\x82\xE9\x81B(2005.7.9 yutaka)
-		// SSH2_MSG_NEWKEYS\x82̎\xF3\x90M\x82\xE6\x82\xE8\x91O\x82Ȃ̂ł\xB1\x82\xB1\x82\xBE\x82\xAF\x82ł悢\x81B(2006.10.30 maya)
-		prep_compression(pvar);
-		enable_compression(pvar);
-	}
-
 	SSH2_dispatch_init(3);
 	SSH2_dispatch_add_message(SSH2_MSG_NEWKEYS);
 
@@ -5525,157 +5493,57 @@
 	return TRUE;
 }
 
-static BOOL store_contents_for_known_hosts(PTInstVar pvar, enum ssh_kex_known_hosts kex_type, UINT_PTR offset)
+static void ssh2_send_newkeys(PTInstVar pvar)
 {
-	pvar->contents_after_known_hosts.payload = malloc(pvar->ssh_state.payloadlen);
-	if (pvar->contents_after_known_hosts.payload == NULL)
-		return FALSE;
-	memcpy(pvar->contents_after_known_hosts.payload, pvar->ssh_state.payload, pvar->ssh_state.payloadlen);
-	pvar->contents_after_known_hosts.payload_len = pvar->ssh_state.payloadlen;
-	pvar->contents_after_known_hosts.payload_offset = offset;
+	// send SSH2_MSG_NEWKEYS
+	begin_send_packet(pvar, SSH2_MSG_NEWKEYS, 0);
+	finish_send_packet(pvar);
 
-	pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = FALSE;
+	logprintf(LOG_LEVEL_VERBOSE, "%s: SSH2_MSG_NEWKEYS was sent.", __FUNCTION__);
 
-	// \x8F\xEE\x95񂪃Z\x83b\x83g\x82\xB3\x82\xEA\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82̔\xBB\x92\xE8\x82Ɏg\x82\xA4\x82\xBD\x82߁A\x8DŌ\xE3\x82ɐݒ肷\x82\xE9\x81B
-	pvar->contents_after_known_hosts.kex_type = kex_type;
-
-	return TRUE;
-}
-
-static void clear_contents_for_known_hosts(PTInstVar pvar)
-{
-	pvar->contents_after_known_hosts.kex_type = NONE_KNOWN_HOSTS;
-	if (pvar->contents_after_known_hosts.payload) {
-		free(pvar->contents_after_known_hosts.payload);
-		pvar->contents_after_known_hosts.payload = NULL;
+	// SSH2_MSG_NEWKEYS \x82𑗂\xE8\x8FI\x82\xED\x82\xC1\x82\xBD\x88ȍ~\x82̃p\x83P\x83b\x83g\x82͈Í\x86\x89\xBB\x82\xB3\x82\xEA\x82\xE9\x95K\x97v\x82\xAA\x97L\x82\xE9\x88ׁA
+	// \x82\xB1\x82̎\x9E\x93_\x82ő\x97\x90M\x95\xFB\x8C\xFC\x82̈Í\x86\x89\xBB\x82\xF0\x8AJ\x8En\x82\xB7\x82\xE9\x81B
+	ssh2_set_newkeys(pvar, MODE_OUT);
+	if (!CRYPT_start_encryption(pvar, 1, 0)) {
+		// TODO: error
 	}
-	pvar->contents_after_known_hosts.payload_len = 0;
-	pvar->contents_after_known_hosts.payload_offset = 0;
 
-	/* \x82\xB1\x82\xB1\x82ł͈Ӑ}\x93I\x82ɃN\x83\x8A\x83A\x82\xB5\x82Ȃ\xA2\x81B
-	 * pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = FALSE;
-	 */
-}
 
-/*
- * Diffie-Hellman Key Exchange Reply(SSH2_MSG_KEXDH_REPLY:31)
- *
- * known_hosts\x8F\x88\x97\x9D\x82̑O\x94\xBC\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x95\\x8E\xA6\x82\xB7\x82\xE9\x82Ƃ\xB1\x82\xEB\x82܂ŁB
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82ł̏\xB3\x94F\x8C\xE3\x82̏\x88\x97\x9D\x82͌㔼\x82ցB
- *
- * return TRUE: \x90\xAC\x8C\xF7
- *        FALSE: \x8E\xB8\x94s
- */
-static BOOL handle_SSH2_dh_kex_reply(PTInstVar pvar)
-{
-	char *data;
-	int len;
-	char *server_host_key_blob;
-	int bloblen;
-	char *dh_buf = NULL;
-	char *emsg = NULL, emsg_tmp[1024];  // error message
-	Key *hostkey = NULL;  // hostkey
-	BOOL result = FALSE;
-	int ret;
+	// \x93\xAF\x97l\x82ɁAMAC\x82ƃp\x83P\x83b\x83g\x88\xB3\x8Fk\x82\xE0\x82\xB1\x82̎\x9E\x93_\x82ŗL\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B
+	pvar->ssh2_keys[MODE_OUT].mac.enabled = 1;
+	pvar->ssh2_keys[MODE_OUT].comp.enabled = 1;
+	enable_send_compression(pvar);
 
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEXDH_REPLY was received.");
+	pvar->kex_status |= KEX_FLAG_NEWKEYS_SENT;
 
-	memset(&hostkey, 0, sizeof(hostkey));
+	// SSH2_MSG_NEWKEYS \x82\xF0\x8A\xF9\x82Ɏ󂯎\xE6\x82\xC1\x82Ă\xA2\x82\xBD\x82\xE7KEX\x82͊\xAE\x97\xB9\x81B\x8E\x9F\x82̏\x88\x97\x9D\x82Ɉڂ\xE9\x81B
+	if (pvar->kex_status & KEX_FLAG_NEWKEYS_RECEIVED) {
+		if ((pvar->kex_status & KEX_FLAG_REKEYING)) {
+			do_SSH2_dispatch_setup_for_transfer(pvar);
+		}
+		else {
+			// \x8F\x89\x89\xF1\x82\xCC SSH2_MSG_NEWKEYS \x82̑\x97\x8E\xF3\x90M\x82\xAA\x8A\xAE\x97\xB9\x82\xB5\x81A\x88ȍ~\x82̒ʐM\x82͈Í\x86\x89\xBB\x82\xB3\x82ꂽ\x8F\xF3\x91ԂɂȂ\xE9
+			ssh2_finish_encryption_setup(pvar);
 
-	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->ssh_state.payload;
-	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->ssh_state.payloadlen - 1;
-
-	// for debug
-	push_memdump("KEXDH_REPLY", "key exchange: receiving", data, len);
-
-	bloblen = get_uint32_MSBfirst(data);
-	data += 4;
-	server_host_key_blob = data; // for hash
-
-	push_memdump("KEXDH_REPLY", "server_host_key_blob", server_host_key_blob, bloblen);
-
-	hostkey = key_from_blob(data, bloblen);
-	if (hostkey == NULL) {
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-					"%s: key_from_blob error", __FUNCTION__);
-		emsg = emsg_tmp;
-		goto error;
+			// \x8F\x89\x89\xF1\x82̌\xAE\x8C\xF0\x8A\xB7\x8C\xE3\x82̓\x86\x81[\x83U\x94F\x8F؂\xF0\x8AJ\x8En\x82\xB7\x82\xE9
+			ssh2_prep_userauth(pvar);
+		}
+		pvar->kex_status = KEX_FLAG_KEXDONE;
 	}
-	data += bloblen;
 
-	// known_hosts\x91Ή\x9E (2006.3.20 yutaka)
-	if (hostkey->type != get_ssh2_hostkey_type_from_algorithm(pvar->hostkey_type)) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-		            "%s: type mismatch for decoded server_host_key_blob (kex:%s(%s) blob:%s)",
-		            /*__FUNCTION__*/"handle_SSH2_dh_kex_reply",
-		            get_ssh2_hostkey_type_name_from_algorithm(pvar->hostkey_type),
-		            get_ssh2_hostkey_algorithm_name(pvar->hostkey_type),
-		            get_ssh2_hostkey_type_name(hostkey->type));
-		emsg = emsg_tmp;
-		goto error;
-	}
-
-	// \x8C㔼\x8F\x88\x97\x9D\x97p\x82̃f\x81[\x83^\x82\xF0\x91ޔ\xF0\x82\xB5\x82Ă\xA8\x82\xAD
-	if (store_contents_for_known_hosts(pvar, SSH2_DH_KEX_REPLY_KNOWN_HOSTS,
-							(unsigned char *)data - pvar->ssh_state.payload) == FALSE)
-		goto error;
-
-	/*
-	 * Tera Term(SSH\x83N\x83\x89\x83C\x83A\x83\x93\x83g)\x91\xA4\x82͂\xB1\x82ꂩ\x82\xE7 known_hosts \x82ŃT\x81[\x83o\x82Ƃ̐ڑ\xB1\x82\xF0
-	 * \x8E󂯓\xFC\x82\xEA\x82\xE9\x82̂\xA9\x82\xF0\x8C\x88\x82߂邪\x81ASSH\x83T\x81[\x83o\x91\xA4\x82͂\xB7\x82łɌ\xAE\x82̏\x80\x94\x{142A82}ł\xAB\x82Ă\xA2\x82\xE9\x89”\\x90\xAB\x82\xAA\x82\xA0\x82\xE8\x81A
-	 * SSH2_MSG_NEWKEYS \x83\x81\x83b\x83Z\x81[\x83W\x82\xAA\x82\xA2\x82‘\x97\x82\xE7\x82\xEA\x82Ă\xAD\x82邩\x95\xAA\x82\xA9\x82\xE7\x82Ȃ\xA2\x81B
-	 * known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x95\\x8E\xA6\x92\x86\x82ɂ\xA8\x82\xA2\x82āA\x93\x96\x8AY\x83\x81\x83b\x83Z\x81[\x83W\x82\xF0\x8E󂯕t\x82\xAF\x82\xE7\x82\xEA\x82\xE9\x82悤\x82\xC9
-	 * \x82\xB5\x82Ă\xA8\x82\xAD\x95K\x97v\x82\xAA\x82\xA0\x82\xE9\x81B
-	 */
-	SSH2_dispatch_init(3);
-	SSH2_dispatch_add_message(SSH2_MSG_NEWKEYS);
-
-	/*
-	 * \x82\xB1\x82̂\xA0\x82\xC6 known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x94񓯊\xFA\x82ŌĂяo\x82\xB5\x81A\x82\xA2\x82\xC1\x82\xBD\x82\xF1SSH\x83T\x81[\x83o\x82Ƃ\xCC
-	 * \x83l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x88ꎞ\x92\xE2\x8E~\x82\xB3\x82\xB9\x82\xE9\x81B
-	 */
-	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
-	if (ret == TRUE) {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82͕s\x97v\x82Ȃ̂ŁA
-		 * \x91\xB1\x82\xAB\x82̏\x88\x97\x9D\x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B
-		 */
-		ret = handle_SSH2_dh_kex_reply_after_known_hosts(pvar);
-
-	} else {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA
-		 * \x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
-		 */
-
-	}
-
-	result = TRUE;
-
-error:
-	key_free(hostkey);
-
-	if (emsg)
-		notify_fatal_error(pvar, emsg, TRUE);
-
-	return result;
+	return;
 }
 
 /*
- * Diffie-Hellman Key Exchange Reply(SSH2_MSG_KEXDH_REPLY:31)
+ * Diffie-Hellman Key Exchange Reply (SSH2_MSG_KEXDH_REPLY:31)
  *
- * known_hosts\x8F\x88\x97\x9D\x82̌㔼\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xA9\x82\xE7\x8CĂяo\x82\xB3\x82\xEA\x81ASSH\x83T\x81[\x83o\x82ɃL\x81[\x8F\xEE\x95\xF1\x82𑗐M\x82\xB7\x82\xE9\x81B
- *
  * return TRUE: \x90\xAC\x8C\xF7
  *        FALSE: \x8E\xB8\x94s
  */
-BOOL handle_SSH2_dh_kex_reply_after_known_hosts(PTInstVar pvar)
+static BOOL handle_SSH2_dh_kex_reply(PTInstVar pvar)
 {
 	char *data;
 	int len;
-	int offset = 0;
 	char *server_host_key_blob;
 	int bloblen, siglen;
 	BIGNUM *server_public = NULL;
@@ -5689,20 +5557,26 @@
 	Key *hostkey = NULL;  // hostkey
 	BOOL result = FALSE;
 	BIGNUM *pub_key;
+	int ret;
 
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEXDH_REPLY is continued after known_hosts.");
+	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEXDH_REPLY was received.");
 
 	memset(&hostkey, 0, sizeof(hostkey));
 
 	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->contents_after_known_hosts.payload;
+	data = pvar->ssh_state.payload;
 	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->contents_after_known_hosts.payload_len - 1;
+	len = pvar->ssh_state.payloadlen - 1;
 
+	// for debug
+	push_memdump("KEXDH_REPLY", "key exchange: receiving", data, len);
+
 	bloblen = get_uint32_MSBfirst(data);
 	data += 4;
 	server_host_key_blob = data; // for hash
 
+	push_memdump("KEXDH_REPLY", "server_host_key_blob", server_host_key_blob, bloblen);
+
 	hostkey = key_from_blob(data, bloblen);
 	if (hostkey == NULL) {
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
@@ -5712,6 +5586,7 @@
 	}
 	data += bloblen;
 
+	// known_hosts\x91Ή\x9E (2006.3.20 yutaka)
 	if (hostkey->type != get_ssh2_hostkey_type_from_algorithm(pvar->hostkey_type)) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
 		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
 		            "%s: type mismatch for decoded server_host_key_blob (kex:%s(%s) blob:%s)",
@@ -5800,6 +5675,12 @@
 
 	result = ssh2_kex_finish(pvar, hash, hashlen, share_key, hostkey, signature, siglen);
 
+	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
+	if (ret == TRUE) {
+		// \x83z\x83X\x83g\x8C\xAE\x82̊m\x94F\x82\xAA\x90\xAC\x8C\x{1C2D42}\xBD\x82̂ŁA\x8C㑱\x82̏\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4
+		SSH_notify_host_OK(pvar);
+	}
+
 error:
 	BN_free(server_public);
 	DH_free(pvar->kexdh); pvar->kexdh = NULL;
@@ -5810,31 +5691,12 @@
 	if (emsg)
 		notify_fatal_error(pvar, emsg, TRUE);
 
-	clear_contents_for_known_hosts(pvar);
-
-	/*
-	 * SSH2_MSG_NEWKEYS \x82\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xBD\x82\xE7\x81A\x8E\xA9\x95\xAA\x82ŏ\x88\x97\x9D\x82\xF0\x8CĂяo\x82\xB7\x81B
-	 */
-	if (pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received) {
-		pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = FALSE;
-		handle_SSH2_newkeys(pvar);
-	}
-
 	return result;
 }
 
-void handle_SSH2_canel_reply_after_known_hosts(PTInstVar pvar)
-{
-	clear_contents_for_known_hosts(pvar);
-}
-
 /*
- * Diffie-Hellman Group and Key Exchange Reply(SSH2_MSG_KEX_DH_GEX_REPLY:33)
+ * Diffie-Hellman Group and Key Exchange Reply (SSH2_MSG_KEX_DH_GEX_REPLY:33)
  *
- * known_hosts\x8F\x88\x97\x9D\x82̑O\x94\xBC\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x95\\x8E\xA6\x82\xB7\x82\xE9\x82Ƃ\xB1\x82\xEB\x82܂ŁB
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82ł̏\xB3\x94F\x8C\xE3\x82̏\x88\x97\x9D\x82͌㔼\x82ցB
- *
  * return TRUE: \x90\xAC\x8C\xF7
  *        FALSE: \x8E\xB8\x94s
  */
@@ -5843,111 +5705,6 @@
 	char *data;
 	int len;
 	char *server_host_key_blob;
-	int bloblen;
-	char *dh_buf = NULL;
-	char *emsg = NULL, emsg_tmp[1024];  // error message
-	Key *hostkey = NULL;  // hostkey
-	BOOL result = FALSE;
-	int ret;
-
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_DH_GEX_REPLY was received.");
-
-	memset(&hostkey, 0, sizeof(hostkey));
-
-	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->ssh_state.payload;
-	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->ssh_state.payloadlen - 1;
-
-	// for debug
-	push_memdump("DH_GEX_REPLY", "key exchange: receiving", data, len);
-
-	bloblen = get_uint32_MSBfirst(data);
-	data += 4;
-	server_host_key_blob = data; // for hash
-
-	push_memdump("DH_GEX_REPLY", "server_host_key_blob", server_host_key_blob, bloblen);
-
-	hostkey = key_from_blob(data, bloblen);
-	if (hostkey == NULL) {
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-					"%s: key_from_blob error", __FUNCTION__);
-		emsg = emsg_tmp;
-		goto error;
-	}
-	data += bloblen;
-
-	// known_hosts\x91Ή\x9E (2006.3.20 yutaka)
-	if (hostkey->type != get_ssh2_hostkey_type_from_algorithm(pvar->hostkey_type)) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-		            "%s: type mismatch for decoded server_host_key_blob (kex:%s(%s) blob:%s)",
-		            /*__FUNCTION__*/"handle_SSH2_dh_gex_reply",
-		            get_ssh2_hostkey_type_name_from_algorithm(pvar->hostkey_type),
-		            get_ssh2_hostkey_algorithm_name(pvar->hostkey_type),
-		            get_ssh2_hostkey_type_name(hostkey->type));
-		emsg = emsg_tmp;
-		goto error;
-	}
-
-	// \x8C㔼\x8F\x88\x97\x9D\x97p\x82̃f\x81[\x83^\x82\xF0\x91ޔ\xF0\x82\xB5\x82Ă\xA8\x82\xAD
-	if (store_contents_for_known_hosts(pvar, SSH2_DH_GEX_REPLY_KNOWN_HOSTS,
-							(unsigned char *)data - pvar->ssh_state.payload) == FALSE)
-		goto error;
-
-	/*
-	 * Tera Term(SSH\x83N\x83\x89\x83C\x83A\x83\x93\x83g)\x91\xA4\x82͂\xB1\x82ꂩ\x82\xE7 known_hosts \x82ŃT\x81[\x83o\x82Ƃ̐ڑ\xB1\x82\xF0
-	 * \x8E󂯓\xFC\x82\xEA\x82\xE9\x82̂\xA9\x82\xF0\x8C\x88\x82߂邪\x81ASSH\x83T\x81[\x83o\x91\xA4\x82͂\xB7\x82łɌ\xAE\x82̏\x80\x94\x{142A82}ł\xAB\x82Ă\xA2\x82\xE9\x89”\\x90\xAB\x82\xAA\x82\xA0\x82\xE8\x81A
-	 * SSH2_MSG_NEWKEYS \x83\x81\x83b\x83Z\x81[\x83W\x82\xAA\x82\xA2\x82‘\x97\x82\xE7\x82\xEA\x82Ă\xAD\x82邩\x95\xAA\x82\xA9\x82\xE7\x82Ȃ\xA2\x81B
-	 * known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x95\\x8E\xA6\x92\x86\x82ɂ\xA8\x82\xA2\x82āA\x93\x96\x8AY\x83\x81\x83b\x83Z\x81[\x83W\x82\xF0\x8E󂯕t\x82\xAF\x82\xE7\x82\xEA\x82\xE9\x82悤\x82\xC9
-	 * \x82\xB5\x82Ă\xA8\x82\xAD\x95K\x97v\x82\xAA\x82\xA0\x82\xE9\x81B
-	 */
-	SSH2_dispatch_init(3);
-	SSH2_dispatch_add_message(SSH2_MSG_NEWKEYS);
-
-	/*
-	 * \x82\xB1\x82̂\xA0\x82\xC6 known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x94񓯊\xFA\x82ŌĂяo\x82\xB5\x81A\x82\xA2\x82\xC1\x82\xBD\x82\xF1SSH\x83T\x81[\x83o\x82Ƃ\xCC
-	 * \x83l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x88ꎞ\x92\xE2\x8E~\x82\xB3\x82\xB9\x82\xE9\x81B
-	 */
-	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
-	if (ret == TRUE) {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82͕s\x97v\x82Ȃ̂ŁA
-		 * \x91\xB1\x82\xAB\x82̏\x88\x97\x9D\x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B
-		 */
-		ret = handle_SSH2_dh_gex_reply_after_known_hosts(pvar);
-
-	} else {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA
-		 * \x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
-		 */
-
-	}
-
-	result = TRUE;
-
-error:
-	key_free(hostkey);
-
-	if (emsg)
-		notify_fatal_error(pvar, emsg, TRUE);
-
-	return result;
-}
-
-/*
- * Diffie-Hellman Group and Key Exchange Reply(SSH2_MSG_KEX_DH_GEX_REPLY:33)
- *
- * known_hosts\x8F\x88\x97\x9D\x82̌㔼\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xA9\x82\xE7\x8CĂяo\x82\xB3\x82\xEA\x81ASSH\x83T\x81[\x83o\x82ɃL\x81[\x8F\xEE\x95\xF1\x82𑗐M\x82\xB7\x82\xE9\x81B
- *
- * return TRUE: \x90\xAC\x8C\xF7
- *        FALSE: \x8E\xB8\x94s
- */
-BOOL handle_SSH2_dh_gex_reply_after_known_hosts(PTInstVar pvar)
-{
-	char *data;
-	int len;
-	int offset = 0;
-	char *server_host_key_blob;
 	int bloblen, siglen;
 	BIGNUM *server_public = NULL;
 	char *signature;
@@ -5959,17 +5716,18 @@
 	int hashlen;
 	Key *hostkey = NULL;  // hostkey
 	BOOL result = FALSE;
+	int ret;
 	BIGNUM *p, *g;
 	BIGNUM *pub_key;
 
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_DH_GEX_REPLY is continued after known_hosts.");
+	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_DH_GEX_REPLY was received.");
 
 	memset(&hostkey, 0, sizeof(hostkey));
 
 	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->contents_after_known_hosts.payload;
+	data = pvar->ssh_state.payload;
 	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->contents_after_known_hosts.payload_len - 1;
+	len = pvar->ssh_state.payloadlen - 1;
 
 	// for debug
 	push_memdump("DH_GEX_REPLY", "key exchange: receiving", data, len);
@@ -6084,6 +5842,13 @@
 
 	result = ssh2_kex_finish(pvar, hash, hashlen, share_key, hostkey, signature, siglen);
 
+	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
+	if (ret == TRUE) {
+		// \x83z\x83X\x83g\x8C\xAE\x82̊m\x94F\x82\xAA\x90\xAC\x8C\x{1C2D42}\xBD\x82̂ŁA\x8C㑱\x82̏\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4
+		SSH_notify_host_OK(pvar);
+		// known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA\x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
+	}
+
 error:
 	BN_free(server_public);
 	DH_free(pvar->kexdh); pvar->kexdh = NULL;
@@ -6094,27 +5859,13 @@
 	if (emsg)
 		notify_fatal_error(pvar, emsg, TRUE);
 
-	clear_contents_for_known_hosts(pvar);
-
-	/*
-	 * SSH2_MSG_NEWKEYS \x82\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xBD\x82\xE7\x81A\x8E\xA9\x95\xAA\x82ŏ\x88\x97\x9D\x82\xF0\x8CĂяo\x82\xB7\x81B
-	 */
-	if (pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received) {
-		pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = FALSE;
-		handle_SSH2_newkeys(pvar);
-	}
-
 	return result;
 }
 
 
 /*
- * Elliptic Curve Diffie-Hellman Key Exchange Reply(SSH2_MSG_KEX_ECDH_REPLY:31)
+ * Elliptic Curve Diffie-Hellman Key Exchange Reply (SSH2_MSG_KEX_ECDH_REPLY:31)
  *
- * known_hosts\x8F\x88\x97\x9D\x82̑O\x94\xBC\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x95\\x8E\xA6\x82\xB7\x82\xE9\x82Ƃ\xB1\x82\xEB\x82܂ŁB
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82ł̏\xB3\x94F\x8C\xE3\x82̏\x88\x97\x9D\x82͌㔼\x82ցB
- *
  * return TRUE: \x90\xAC\x8C\xF7
  *        FALSE: \x8E\xB8\x94s
  */
@@ -6123,110 +5874,6 @@
 	char *data;
 	int len;
 	char *server_host_key_blob;
-	int bloblen;
-	char *emsg = NULL, emsg_tmp[1024];  // error message
-	Key *hostkey = NULL;  // hostkey
-	BOOL result = FALSE;
-	int ret;
-
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_ECDH_REPLY was received.");
-
-	memset(&hostkey, 0, sizeof(hostkey));
-
-	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->ssh_state.payload;
-	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->ssh_state.payloadlen - 1;
-
-	// for debug
-	push_memdump("KEX_ECDH_REPLY", "key exchange: receiving", data, len);
-
-	bloblen = get_uint32_MSBfirst(data);
-	data += 4;
-	server_host_key_blob = data; // for hash
-
-	push_memdump("KEX_ECDH_REPLY", "server_host_key_blob", server_host_key_blob, bloblen);
-
-	hostkey = key_from_blob(data, bloblen);
-	if (hostkey == NULL) {
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-					"%s: key_from_blob error", __FUNCTION__);
-		emsg = emsg_tmp;
-		goto error;
-	}
-	data += bloblen;
-
-	// known_hosts\x91Ή\x9E (2006.3.20 yutaka)
-	if (hostkey->type != get_ssh2_hostkey_type_from_algorithm(pvar->hostkey_type)) {  // \x83z\x83X\x83g\x83L\x81[\x82̎\xED\x95ʔ\xE4\x8Ar
-		_snprintf_s(emsg_tmp, sizeof(emsg_tmp), _TRUNCATE,
-		            "%s: type mismatch for decoded server_host_key_blob (kex:%s(%s) blob:%s)",
-		            /*__FUNCTION__*/"handle_SSH2_ecdh_kex_reply",
-		            get_ssh2_hostkey_type_name_from_algorithm(pvar->hostkey_type),
-		            get_ssh2_hostkey_algorithm_name(pvar->hostkey_type),
-		            get_ssh2_hostkey_type_name(hostkey->type));
-		emsg = emsg_tmp;
-		goto error;
-	}
-
-	// \x8C㔼\x8F\x88\x97\x9D\x97p\x82̃f\x81[\x83^\x82\xF0\x91ޔ\xF0\x82\xB5\x82Ă\xA8\x82\xAD
-	if (store_contents_for_known_hosts(pvar, SSH2_ECDH_KEX_REPLY_KNOWN_HOSTS,
-							(unsigned char *)data - pvar->ssh_state.payload) == FALSE)
-		goto error;
-
-	/*
-	 * Tera Term(SSH\x83N\x83\x89\x83C\x83A\x83\x93\x83g)\x91\xA4\x82͂\xB1\x82ꂩ\x82\xE7 known_hosts \x82ŃT\x81[\x83o\x82Ƃ̐ڑ\xB1\x82\xF0
-	 * \x8E󂯓\xFC\x82\xEA\x82\xE9\x82̂\xA9\x82\xF0\x8C\x88\x82߂邪\x81ASSH\x83T\x81[\x83o\x91\xA4\x82͂\xB7\x82łɌ\xAE\x82̏\x80\x94\x{142A82}ł\xAB\x82Ă\xA2\x82\xE9\x89”\\x90\xAB\x82\xAA\x82\xA0\x82\xE8\x81A
-	 * SSH2_MSG_NEWKEYS \x83\x81\x83b\x83Z\x81[\x83W\x82\xAA\x82\xA2\x82‘\x97\x82\xE7\x82\xEA\x82Ă\xAD\x82邩\x95\xAA\x82\xA9\x82\xE7\x82Ȃ\xA2\x81B
-	 * known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x95\\x8E\xA6\x92\x86\x82ɂ\xA8\x82\xA2\x82āA\x93\x96\x8AY\x83\x81\x83b\x83Z\x81[\x83W\x82\xF0\x8E󂯕t\x82\xAF\x82\xE7\x82\xEA\x82\xE9\x82悤\x82\xC9
-	 * \x82\xB5\x82Ă\xA8\x82\xAD\x95K\x97v\x82\xAA\x82\xA0\x82\xE9\x81B
-	 */
-	SSH2_dispatch_init(3);
-	SSH2_dispatch_add_message(SSH2_MSG_NEWKEYS);
-
-	/*
-	 * \x82\xB1\x82̂\xA0\x82\xC6 known_hosts \x83_\x83C\x83A\x83\x8D\x83O\x82\xF0\x94񓯊\xFA\x82ŌĂяo\x82\xB5\x81A\x82\xA2\x82\xC1\x82\xBD\x82\xF1SSH\x83T\x81[\x83o\x82Ƃ\xCC
-	 * \x83l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93\x82\xF0\x88ꎞ\x92\xE2\x8E~\x82\xB3\x82\xB9\x82\xE9\x81B
-	 */
-	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
-	if (ret == TRUE) {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82͕s\x97v\x82Ȃ̂ŁA
-		 * \x91\xB1\x82\xAB\x82̏\x88\x97\x9D\x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B
-		 */
-		ret = handle_SSH2_ecdh_kex_reply_after_known_hosts(pvar);
-
-	} else {
-		/* known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA
-		 * \x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
-		 */
-
-	}
-
-	result = TRUE;
-
-error:
-	key_free(hostkey);
-
-	if (emsg)
-		notify_fatal_error(pvar, emsg, TRUE);
-
-	return result;
-}
-
-/*
- * Elliptic Curve Diffie-Hellman Key Exchange Reply(SSH2_MSG_KEX_ECDH_REPLY:31)
- *
- * known_hosts\x8F\x88\x97\x9D\x82̌㔼\x81F
- * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82\xA9\x82\xE7\x8CĂяo\x82\xB3\x82\xEA\x81ASSH\x83T\x81[\x83o\x82ɃL\x81[\x8F\xEE\x95\xF1\x82𑗐M\x82\xB7\x82\xE9\x81B
- *
- * return TRUE: \x90\xAC\x8C\xF7
- *        FALSE: \x8E\xB8\x94s
- */
-BOOL handle_SSH2_ecdh_kex_reply_after_known_hosts(PTInstVar pvar)
-{
-	char *data;
-	int len;
-	int offset = 0;
-	char *server_host_key_blob;
 	int bloblen, siglen;
 	EC_POINT *server_public = NULL;
 	const EC_GROUP *group;
@@ -6239,15 +5886,16 @@
 	int hashlen;
 	Key *hostkey = NULL;  // hostkey
 	BOOL result = FALSE;
+	int ret;
 
-	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_ECDH_REPLY is continued after known_hosts.");
+	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_KEX_ECDH_REPLY was received.");
 
 	memset(&hostkey, 0, sizeof(hostkey));
 
 	// \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x82̌\xE3\x82ɑ\xB1\x82\xAD\x83y\x83C\x83\x8D\x81[\x83h\x82̐擪
-	data = pvar->contents_after_known_hosts.payload;
+	data = pvar->ssh_state.payload;
 	// \x83y\x83C\x83\x8D\x81[\x83h\x82̒\xB7\x82\xB3; \x83\x81\x83b\x83Z\x81[\x83W\x83^\x83C\x83v\x95\xAA\x82\xCC 1 \x83o\x83C\x83g\x82\xF0\x8C\xB8\x82炷
-	len = pvar->contents_after_known_hosts.payload_len - 1;
+	len = pvar->ssh_state.payloadlen - 1;
 
 	// for debug
 	push_memdump("KEX_ECDH_REPLY", "key exchange: receiving", data, len);
@@ -6377,6 +6025,13 @@
 
 	result = ssh2_kex_finish(pvar, hash, hashlen, share_key, hostkey, signature, siglen);
 
+	ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, hostkey);
+	if (ret == TRUE) {
+		// \x83z\x83X\x83g\x8C\xAE\x82̊m\x94F\x82\xAA\x90\xAC\x8C\x{1C2D42}\xBD\x82̂ŁA\x8C㑱\x82̏\x88\x97\x9D\x82\xF0\x8Ds\x82\xA4
+		SSH_notify_host_OK(pvar);
+		// known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x82̌Ăяo\x82\xB5\x82\xBD\x82̂ŁA\x88ȍ~\x81A\x89\xBD\x82\xE0\x82\xB5\x82Ȃ\xA2\x81B
+	}
+
 error:
 	EC_POINT_clear_free(server_public);
 	EC_KEY_free(pvar->ecdh_client_key); pvar->ecdh_client_key = NULL;
@@ -6387,21 +6042,10 @@
 	if (emsg)
 		notify_fatal_error(pvar, emsg, TRUE);
 
-	clear_contents_for_known_hosts(pvar);
-
-	/*
-	 * SSH2_MSG_NEWKEYS \x82\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xBD\x82\xE7\x81A\x8E\xA9\x95\xAA\x82ŏ\x88\x97\x9D\x82\xF0\x8CĂяo\x82\xB7\x81B
-	 */
-	if (pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received) {
-		pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = FALSE;
-		handle_SSH2_newkeys(pvar);
-	}
-
 	return result;
 }
 
 
-
 // KEX\x82ɂ\xA8\x82\xA2\x82ăT\x81[\x83o\x82\xA9\x82\xE7\x95Ԃ\xC1\x82Ă\xAD\x82\xE9 31 \x94ԃ\x81\x83b\x83Z\x81[\x83W\x82ɑ΂\xB7\x82\xE9\x83n\x83\x93\x83h\x83\x89
 static BOOL handle_SSH2_dh_common_reply(PTInstVar pvar)
 {
@@ -6433,8 +6077,7 @@
 
 static void do_SSH2_dispatch_setup_for_transfer(PTInstVar pvar)
 {
-	// \x83L\x81[\x8Dč쐬\x8F\xEE\x95\xF1\x82̃N\x83\x8A\x83A (2005.6.19 yutaka)
-	pvar->rekeying = 0;
+	pvar->kex_status = KEX_FLAG_KEXDONE;
 
 	SSH2_dispatch_init(6);
 	SSH2_dispatch_add_range_message(SSH2_MSG_GLOBAL_REQUEST, SSH2_MSG_CHANNEL_FAILURE);
@@ -6444,20 +6087,6 @@
 
 static BOOL handle_SSH2_newkeys(PTInstVar pvar)
 {
-	int type = (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA) |
-	           (1 << SSH_AUTH_TIS) | (1 << SSH_AUTH_PAGEANT);
-
-
-	/*
-	 * known_hosts\x83_\x83C\x83A\x83\x8D\x83O\x95\\x8E\xA6\x92\x86\x82\xC9 SSH2_MSG_NEWKEYS \x82\xF0\x8E󂯎\xE6\x82\xC1\x82\xBD\x8Fꍇ\x82\xCD
-	 * \x8F\x88\x97\x9D\x82\xF0\x89\x84\x8A\x{20B30B9}\x82\xE9\x81B
-	 */
-	if (pvar->contents_after_known_hosts.kex_type != NONE_KNOWN_HOSTS) {
-		pvar->contents_after_known_hosts.SSH2_MSG_NEWKEYS_received = TRUE;
-		logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_NEWKEYS was postponed while known_hosts dialog is running.");
-		return TRUE;
-	}
-
 	logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_NEWKEYS was received(DH key generation is completed).");
 
 	// \x83\x8D\x83O\x8D̎\xE6\x82̏I\x97\xB9 (2005.3.7 yutaka)
@@ -6466,42 +6095,52 @@
 	}
 	finish_memdump();
 
-	// finish key exchange
-	pvar->key_done = 1;
+	pvar->kex_status |= KEX_FLAG_NEWKEYS_RECEIVED;
 
-	// \x83L\x81[\x8Dč쐬\x82Ȃ\xE7\x94F\x8F؂̓p\x83X\x82\xB7\x82\xE9\x81B
-	if (pvar->rekeying == 1) {
-		// \x82\xA9\x82A\x8E\xF3\x90M\x97p\x82̈Í\x86\x8C\xAE\x82̍Đݒ\xE8\x82\xF0\x82\xB1\x82\xB1\x82ōs\x82\xA4\x81B
-		ssh2_set_newkeys(pvar, MODE_IN);
-		pvar->ssh2_keys[MODE_IN].mac.enabled = 1;
-		pvar->ssh2_keys[MODE_IN].comp.enabled = 1;
-		enable_recv_compression(pvar);
-		if (!CRYPT_start_encryption(pvar, 0, 1)) {
-			// TODO: error
-		}
-		do_SSH2_dispatch_setup_for_transfer(pvar);
-		return TRUE;
-
-	} else {
-		// SSH2_MSG_NEWKEYS\x82\xF0\x8E󂯎\xE6\x82\xC1\x82\xBD\x8E\x9E\x93_\x82ŁAMAC\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B(2006.10.30 yutaka)
-		ssh2_set_newkeys(pvar, MODE_IN);
-		pvar->ssh2_keys[MODE_IN].mac.enabled = 1;
-		pvar->ssh2_keys[MODE_IN].comp.enabled = 1;
-
+	// SSH2_MSG_NEWKEYS \x8E\xF3\x90M\x8C\xE3\x82͑\x8A\x8E肩\x82\xE7\x82̃p\x83P\x83b\x83g\x82͈Í\x86\x89\xBB\x82\xB3\x82\xEA\x82Ă\xAD\x82\xE9\x82̂ŁA
+	// \x8E\xF3\x90M\x95\xFB\x8C\xFC\x82̈Í\x86\x89\xBB(\x95\x9C\x8D\x86)\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B
+	ssh2_set_newkeys(pvar, MODE_IN);
+	if (!CRYPT_start_encryption(pvar, 0, 1)) {
+		// TODO: error
 	}
 
-	// \x94F\x8Fؕ\xFB\x8E\xAE\x82̐ݒ\xE8
-	if (!AUTH_set_supported_auth_types(pvar, type))
-		return FALSE;
+	// \x93\xAF\x97l\x82ɁAMAC\x82\xA8\x82\xE6\x82ш\xB3\x8Fk\x82\xF0\x97L\x8C\xF8\x82ɂ\xB7\x82\xE9\x81B
+	pvar->ssh2_keys[MODE_IN].mac.enabled = 1;
+	pvar->ssh2_keys[MODE_IN].comp.enabled = 1;
+	enable_recv_compression(pvar);
 
 	SSH2_dispatch_add_message(SSH2_MSG_EXT_INFO);
 
-	SSH_notify_host_OK(pvar);
+	// SSH2_MSG_NEWKEYS \x82\xF0\x8A\xF9\x82ɑ\x97\x82\xC1\x82Ă\xA2\x82\xBD\x82\xE7KEX\x82͊\xAE\x97\xB9\x81B\x8E\x9F\x82̏\x88\x97\x9D\x82Ɉڂ\xE9\x81B
+	if (pvar->kex_status & KEX_FLAG_NEWKEYS_SENT) {
+		if (pvar->kex_status & KEX_FLAG_REKEYING) {
+			do_SSH2_dispatch_setup_for_transfer(pvar);
+		}
+		else {
+			// \x8F\x89\x89\xF1\x82\xCC SSH2_MSG_NEWKEYS \x82̑\x97\x8E\xF3\x90M\x82\xAA\x8A\xAE\x97\xB9\x82\xB5\x81A\x88ȍ~\x82̒ʐM\x82͈Í\x86\x89\xBB\x82\xB3\x82ꂽ\x8F\xF3\x91ԂɂȂ\xE9
+			ssh2_finish_encryption_setup(pvar);
 
+			// \x8F\x89\x89\xF1\x82̌\xAE\x8C\xF0\x8A\xB7\x8C\xE3\x82̓\x86\x81[\x83U\x94F\x8F؂\xF0\x8AJ\x8En\x82\xB7\x82\xE9
+			ssh2_prep_userauth(pvar);
+		}
+		pvar->kex_status = KEX_FLAG_KEXDONE;
+	}
 
 	return TRUE;
 }
 
+static void ssh2_prep_userauth(PTInstVar pvar)
+{
+	int type = (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA) |
+	           (1 << SSH_AUTH_TIS) | (1 << SSH_AUTH_PAGEANT);
+
+	// \x94F\x8Fؕ\xFB\x8E\xAE\x82̐ݒ\xE8
+	AUTH_set_supported_auth_types(pvar, type);
+
+	// \x94F\x8F؃_\x83C\x83A\x83\x8D\x83O\x82\xF0\x95\\x8E\xA6\x82\xB7\x82\xE9
+	AUTH_advance_to_next_cred(pvar);
+}
+
 // \x83\x86\x81[\x83U\x94F\x8F؂̊J\x8En
 BOOL do_SSH2_userauth(PTInstVar pvar)
 {

Modified: trunk/ttssh2/ttxssh/ssh.h
===================================================================
--- trunk/ttssh2/ttxssh/ssh.h	2022-07-17 15:40:39 UTC (rev 10072)
+++ trunk/ttssh2/ttxssh/ssh.h	2022-07-17 15:40:49 UTC (rev 10073)
@@ -434,6 +434,11 @@
 #define STATUS_INTERACTIVE                    0x10
 #define STATUS_IN_PARTIAL_ID_STRING           0x20
 
+#define KEX_FLAG_KEXDONE          0x01
+#define KEX_FLAG_REKEYING         0x02
+#define KEX_FLAG_NEWKEYS_SENT     0x04
+#define KEX_FLAG_NEWKEYS_RECEIVED 0x08
+
 void SSH_init(PTInstVar pvar);
 void SSH_open(PTInstVar pvar);
 void SSH_notify_disconnecting(PTInstVar pvar, char *reason);
@@ -620,32 +625,4 @@
 	int ref_count;
 };
 
-/*  
- * SSH bottom half after known_hosts
- */
-enum ssh_kex_known_hosts {
-	NONE_KNOWN_HOSTS = 0,
-	SSH1_PUBLIC_KEY_KNOWN_HOSTS,
-	SSH2_DH_KEX_REPLY_KNOWN_HOSTS,
-	SSH2_DH_GEX_REPLY_KNOWN_HOSTS,
-	SSH2_ECDH_KEX_REPLY_KNOWN_HOSTS,
-};
-
-typedef struct bottom_half_known_hosts {
-	enum ssh_kex_known_hosts kex_type;
-
-	unsigned char *payload;
-	int payload_len;
-	UINT_PTR payload_offset;
-
-	BOOL SSH2_MSG_NEWKEYS_received;	
-} bottom_half_known_hosts_t;
-
-void handle_SSH2_canel_reply_after_known_hosts(PTInstVar pvar);
-
-BOOL handle_server_public_key_after_known_hosts(PTInstVar pvar);
-BOOL handle_SSH2_dh_kex_reply_after_known_hosts(PTInstVar pvar);
-BOOL handle_SSH2_dh_gex_reply_after_known_hosts(PTInstVar pvar);
-BOOL handle_SSH2_ecdh_kex_reply_after_known_hosts(PTInstVar pvar);
-
 #endif /* __SSH_H */

Modified: trunk/ttssh2/ttxssh/ttxssh.h
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.h	2022-07-17 15:40:39 UTC (rev 10072)
+++ trunk/ttssh2/ttxssh/ttxssh.h	2022-07-17 15:40:49 UTC (rev 10073)
@@ -278,8 +278,7 @@
 	compression_type ctos_compression;
 	compression_type stoc_compression;
 	int we_need;
-	int key_done;
-	int rekeying;
+	int kex_status;
 	char *session_id;
 	int session_id_len;
 	SSHKeys ssh2_keys[MODE_MAX];
@@ -347,8 +346,6 @@
 	// dialog resource
 	HFONT hFontFixed;		// hosts.c\x93\xE0\x82̃_\x83C\x83A\x83\x8D\x83O\x97p
 
-	bottom_half_known_hosts_t contents_after_known_hosts;
-
 	char *server_sig_algs;
 
 } TInstVar;


ttssh2-commit メーリングリストの案内
Back to archive index