diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-10 18:03:29 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-10 18:03:29 +0300 |
| commit | 28f6319b77d35c6da6b99ad7e35d0d5602dc2ee6 (patch) | |
| tree | 687b2c38755a087694cacacb73cd73b8ef244ce7 /internal/ssh/client | |
| parent | 13b21feb07c86f65760f7338f284f3b492364cd9 (diff) | |
Fix known-hosts trust deadlock, host key stat, and optional nozstd build
- stdout logger: release mutex while waiting on pause resume so prompt
callbacks can log (fixes hang after trusting new hosts; known_hosts
was written but Resume never ran).
- known hosts callback: stop borrowing the SSH dial throttle channel
(could block or interact badly with parallel handshakes).
- host key path: use errors.Is(..., fs.ErrNotExist) for RootedPath.Stat
wrapped errors; stat errors now fail fast instead of mis-read.
- public key path: same ErrNotExist check for authorized_keys miss.
- Build: optional DTAIL_NO_ZSTD=yes / nozstd tag for CGO-free builds;
split zstd readers into tagged files.
- Docs/examples: firewalld note for port 2222, log prune timer+script,
SSHBindAddress note, dserver unit disabled-by-default comment;
firewalld helper script example.
- Regression test for stdout pause/mutex behavior.
Made-with: Cursor
Diffstat (limited to 'internal/ssh/client')
| -rw-r--r-- | internal/ssh/client/authmethods.go | 8 | ||||
| -rw-r--r-- | internal/ssh/client/knownhostscallback.go | 9 | ||||
| -rw-r--r-- | internal/ssh/client/knownhostscallback_test.go | 5 |
3 files changed, 6 insertions, 16 deletions
diff --git a/internal/ssh/client/authmethods.go b/internal/ssh/client/authmethods.go index 7ac4d0c..3cd1bb3 100644 --- a/internal/ssh/client/authmethods.go +++ b/internal/ssh/client/authmethods.go @@ -18,7 +18,7 @@ var ( // InitSSHAuthMethods initialises all known SSH auth methods on the client side. func InitSSHAuthMethods(sshAuthMethods []gossh.AuthMethod, - hostKeyCallback gossh.HostKeyCallback, trustAllHosts bool, throttleCh chan struct{}, + hostKeyCallback gossh.HostKeyCallback, trustAllHosts bool, privateKeyPath string, agentKeyIndex int) ([]gossh.AuthMethod, HostKeyCallback) { if len(sshAuthMethods) > 0 { @@ -28,10 +28,10 @@ func InitSSHAuthMethods(sshAuthMethods []gossh.AuthMethod, } return sshAuthMethods, simpleCallback } - return initKnownHostsAuthMethods(trustAllHosts, throttleCh, privateKeyPath, agentKeyIndex) + return initKnownHostsAuthMethods(trustAllHosts, privateKeyPath, agentKeyIndex) } -func initKnownHostsAuthMethods(trustAllHosts bool, throttleCh chan struct{}, +func initKnownHostsAuthMethods(trustAllHosts bool, privateKeyPath string, agentKeyIndex int) ([]gossh.AuthMethod, HostKeyCallback) { knownHostsFile := fmt.Sprintf("%s/.ssh/known_hosts", os.Getenv("HOME")) @@ -40,7 +40,7 @@ func initKnownHostsAuthMethods(trustAllHosts bool, throttleCh chan struct{}, knownHostsFile = "./known_hosts" } - knownHostsCallback, err := NewKnownHostsCallback(knownHostsFile, trustAllHosts, throttleCh) + knownHostsCallback, err := NewKnownHostsCallback(knownHostsFile, trustAllHosts) if err != nil { dlog.Client.FatalPanic(knownHostsFile, err) } diff --git a/internal/ssh/client/knownhostscallback.go b/internal/ssh/client/knownhostscallback.go index 174f6aa..da1b29b 100644 --- a/internal/ssh/client/knownhostscallback.go +++ b/internal/ssh/client/knownhostscallback.go @@ -41,7 +41,6 @@ type KnownHostsCallback struct { knownHostsPath string knownHostsFile fs.RootedPath unknownCh chan unknownHost - throttleCh chan struct{} trustAllHostsCh chan struct{} untrustedHosts map[string]bool mutex *sync.Mutex @@ -50,8 +49,7 @@ type KnownHostsCallback struct { var _ HostKeyCallback = (*KnownHostsCallback)(nil) // NewKnownHostsCallback returns a new wrapper. -func NewKnownHostsCallback(knownHostsPath string, trustAllHosts bool, - throttleCh chan struct{}) (HostKeyCallback, error) { +func NewKnownHostsCallback(knownHostsPath string, trustAllHosts bool) (HostKeyCallback, error) { knownHostsFile, err := fs.NewRootedPath(knownHostsPath) if err != nil { @@ -65,7 +63,6 @@ func NewKnownHostsCallback(knownHostsPath string, trustAllHosts bool, knownHostsFile: knownHostsFile, unknownCh: make(chan unknownHost), trustAllHostsCh: make(chan struct{}), - throttleCh: throttleCh, untrustedHosts: untrustedHosts, mutex: &sync.Mutex{}, } @@ -103,10 +100,6 @@ func (c *KnownHostsCallback) Wrap() ssh.HostKeyCallback { // OK return nil } - // Make sure that interactive user callback does not interfere with - // SSH connection throttler. - <-c.throttleCh - defer func() { c.throttleCh <- struct{}{} }() unknown := unknownHost{ server: server, diff --git a/internal/ssh/client/knownhostscallback_test.go b/internal/ssh/client/knownhostscallback_test.go index 596aea8..1765598 100644 --- a/internal/ssh/client/knownhostscallback_test.go +++ b/internal/ssh/client/knownhostscallback_test.go @@ -112,10 +112,7 @@ func TestTrustHostsRejectsEscapingKnownHostsSymlink(t *testing.T) { func testKnownHostsCallback(t *testing.T, knownHostsPath string) *KnownHostsCallback { t.Helper() - throttleCh := make(chan struct{}, 1) - throttleCh <- struct{}{} - - callback, err := NewKnownHostsCallback(knownHostsPath, false, throttleCh) + callback, err := NewKnownHostsCallback(knownHostsPath, false) if err != nil { t.Fatalf("NewKnownHostsCallback failed: %v", err) } |
