From f11d54199cf997bfb57f818d7020e10db847238f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Thu, 22 Feb 2024 22:06:32 -0500
Subject: [PATCH] Catch when cryptFlushData() says the channel is closed.

Also, fix an unlikely race condition.  This, combined with the
cryptlib patches, fixes various weird SSH hangs resulting from
partial reads of the SSH packet headers... a rare event that's
very hard to trigger.  Special thanks to MeaTLoTioN for reporting
this, and running a BBS that manages to trigger it reliably.

Check out The Quantum Wormhole and say thanks!
---
 src/syncterm/ssh.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c
index be1f65ba89..98265d4308 100644
--- a/src/syncterm/ssh.c
+++ b/src/syncterm/ssh.c
@@ -58,10 +58,10 @@ init_crypt(void)
 		cryptlib_error_message(status, "initializing cryptlib");
 }
 
-static void
+static int
 FlushData(CRYPT_SESSION sess)
 {
-	(void)cryptFlushData(sess);
+	return cryptFlushData(sess);
 }
 
 void
@@ -175,7 +175,10 @@ ssh_input_thread(void *args)
 	conn_api.input_thread_running = 1;
 	while (ssh_active && !conn_api.terminate) {
 		pthread_mutex_lock(&ssh_mutex);
-		FlushData(ssh_session);
+		if (FlushData(ssh_session) == CRYPT_ERROR_COMPLETE) {
+			pthread_mutex_unlock(&ssh_mutex);
+			break;
+		}
 		if (ssh_channel != -1) {
 			if (!check_channel_open(&ssh_channel))
 				ssh_channel = -1;
@@ -200,7 +203,10 @@ ssh_input_thread(void *args)
 			continue;
 
 		pthread_mutex_lock(&ssh_mutex);
-		FlushData(ssh_session);
+		if (FlushData(ssh_session) == CRYPT_ERROR_COMPLETE) {
+			pthread_mutex_unlock(&ssh_mutex);
+			break;
+		}
 
 		// Check channels are active...
 		if (ssh_channel != -1) {
@@ -215,6 +221,7 @@ ssh_input_thread(void *args)
 				pthread_mutex_unlock(&ssh_mutex);
 				sftpc_finish(oldstate);
 				oldstate = NULL;
+				pthread_mutex_lock(&ssh_mutex);
 			}
 		}
 		if (ssh_channel == -1 && sftp_channel == -1) {
-- 
GitLab