@@ -10,23 +10,31 @@ import os
1010struct AgentAuthenticator : SSHAuthenticator {
1111 private static let logger = Logger ( subsystem: " com.TablePro " , category: " AgentAuthenticator " )
1212
13+ /// Protects setenv/unsetenv of SSH_AUTH_SOCK across concurrent tunnel setups
14+ private static let agentSocketLock = NSLock ( )
15+
1316 let socketPath : String ?
1417
1518 func authenticate( session: OpaquePointer , username: String ) throws {
1619 // Save original SSH_AUTH_SOCK so we can restore it
1720 let originalSocketPath = ProcessInfo . processInfo. environment [ " SSH_AUTH_SOCK " ]
21+ let needsSocketOverride = socketPath != nil
1822
19- if let socketPath {
20- Self . logger. debug ( " Using custom SSH agent socket: \( socketPath, privacy: . private) " )
21- setenv ( " SSH_AUTH_SOCK " , socketPath, 1 )
23+ if needsSocketOverride {
24+ Self . agentSocketLock. lock ( )
25+ Self . logger. debug ( " Using custom SSH agent socket: \( socketPath!, privacy: . private) " )
26+ setenv ( " SSH_AUTH_SOCK " , socketPath!, 1 )
2227 }
2328
2429 defer {
25- // Restore original SSH_AUTH_SOCK
26- if let originalSocketPath {
27- setenv ( " SSH_AUTH_SOCK " , originalSocketPath, 1 )
28- } else if socketPath != nil {
29- unsetenv ( " SSH_AUTH_SOCK " )
30+ if needsSocketOverride {
31+ // Restore original SSH_AUTH_SOCK
32+ if let originalSocketPath {
33+ setenv ( " SSH_AUTH_SOCK " , originalSocketPath, 1 )
34+ } else {
35+ unsetenv ( " SSH_AUTH_SOCK " )
36+ }
37+ Self . agentSocketLock. unlock ( )
3038 }
3139 }
3240
0 commit comments