@@ -15,7 +15,8 @@ internal enum HostKeyVerifier {
1515 private static let logger = Logger ( subsystem: " com.TablePro " , category: " HostKeyVerifier " )
1616
1717 /// Verify the host key, prompting the user if needed.
18- /// Uses `withCheckedContinuation` to await UI prompts without blocking the cooperative thread pool.
18+ /// This method blocks the calling thread while showing UI prompts.
19+ /// Must be called from a background thread.
1920 /// - Parameters:
2021 /// - keyData: The raw host key bytes from the SSH session
2122 /// - keyType: The key type string (e.g. "ssh-rsa", "ssh-ed25519")
@@ -27,7 +28,7 @@ internal enum HostKeyVerifier {
2728 keyType: String ,
2829 hostname: String ,
2930 port: Int
30- ) async throws {
31+ ) throws {
3132 let result = HostKeyStore . shared. verify (
3233 keyData: keyData,
3334 keyType: keyType,
@@ -42,7 +43,7 @@ internal enum HostKeyVerifier {
4243
4344 case . unknown( let fingerprint, let keyType) :
4445 logger. info ( " Unknown host key for [ \( hostname) ]: \( port) , prompting user " )
45- let accepted = await promptUnknownHost (
46+ let accepted = promptUnknownHost (
4647 hostname: hostname,
4748 port: port,
4849 fingerprint: fingerprint,
@@ -61,7 +62,7 @@ internal enum HostKeyVerifier {
6162
6263 case . mismatch( let expected, let actual) :
6364 logger. warning ( " Host key mismatch for [ \( hostname) ]: \( port) " )
64- let accepted = await promptHostKeyMismatch (
65+ let accepted = promptHostKeyMismatch (
6566 hostname: hostname,
6667 port: port,
6768 expected: expected,
@@ -82,14 +83,17 @@ internal enum HostKeyVerifier {
8283
8384 // MARK: - UI Prompts
8485
85- /// Show a dialog asking the user whether to trust an unknown host.
86- /// Suspends until the user responds, without blocking any thread .
86+ /// Show a dialog asking the user whether to trust an unknown host
87+ /// Blocks the calling thread until the user responds .
8788 private static func promptUnknownHost(
8889 hostname: String ,
8990 port: Int ,
9091 fingerprint: String ,
9192 keyType: String
92- ) async -> Bool {
93+ ) -> Bool {
94+ let semaphore = DispatchSemaphore ( value: 0 )
95+ var accepted = false
96+
9397 let hostDisplay = " [ \( hostname) ]: \( port) "
9498 let title = String ( localized: " Unknown SSH Host " )
9599 let message = String ( localized: """
@@ -101,7 +105,7 @@ internal enum HostKeyVerifier {
101105 Are you sure you want to continue connecting?
102106 """ )
103107
104- return await MainActor . run {
108+ DispatchQueue . main . async {
105109 let alert = NSAlert ( )
106110 alert. messageText = title
107111 alert. informativeText = message
@@ -110,18 +114,25 @@ internal enum HostKeyVerifier {
110114 alert. addButton ( withTitle: String ( localized: " Cancel " ) )
111115
112116 let response = alert. runModal ( )
113- return response == . alertFirstButtonReturn
117+ accepted = ( response == . alertFirstButtonReturn)
118+ semaphore. signal ( )
114119 }
120+
121+ semaphore. wait ( )
122+ return accepted
115123 }
116124
117- /// Show a warning dialog about a changed host key (potential MITM attack).
118- /// Suspends until the user responds, without blocking any thread .
125+ /// Show a warning dialog about a changed host key (potential MITM attack)
126+ /// Blocks the calling thread until the user responds .
119127 private static func promptHostKeyMismatch(
120128 hostname: String ,
121129 port: Int ,
122130 expected: String ,
123131 actual: String
124- ) async -> Bool {
132+ ) -> Bool {
133+ let semaphore = DispatchSemaphore ( value: 0 )
134+ var accepted = false
135+
125136 let hostDisplay = " [ \( hostname) ]: \( port) "
126137 let title = String ( localized: " SSH Host Key Changed " )
127138 let message = String ( localized: """
@@ -133,7 +144,7 @@ internal enum HostKeyVerifier {
133144 Current fingerprint: \( actual)
134145 """ )
135146
136- return await MainActor . run {
147+ DispatchQueue . main . async {
137148 let alert = NSAlert ( )
138149 alert. messageText = title
139150 alert. informativeText = message
@@ -146,7 +157,11 @@ internal enum HostKeyVerifier {
146157 alert. buttons [ 0 ] . keyEquivalent = " "
147158
148159 let response = alert. runModal ( )
149- return response == . alertFirstButtonReturn
160+ accepted = ( response == . alertFirstButtonReturn)
161+ semaphore. signal ( )
150162 }
163+
164+ semaphore. wait ( )
165+ return accepted
151166 }
152167}
0 commit comments