Skip to content

Commit c6a4cf0

Browse files
authored
Merge pull request #172 from Infisical/fix-status-code
fix: status code propagation
2 parents 86c69cd + b8e8d59 commit c6a4cf0

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

packages/pam/handlers/ssh/proxy.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,26 +241,42 @@ func (p *SSHProxy) handleChannel(ctx context.Context, newChannel ssh.NewChannel,
241241
p.handleChannelRequests(serverRequests, clientChannel, sessionID, channelType, chState)
242242
}()
243243

244-
// Proxy data bidirectionally with logging
245-
errChan := make(chan error, 2)
244+
clientToServerDone := make(chan error, 1)
245+
serverToClientDone := make(chan error, 1)
246246

247247
// Client to Server
248248
go func() {
249249
err := p.proxyData(clientChannel, serverChannel, "client→server", sessionID, true, chState)
250-
errChan <- err
250+
// Send EOF so the remote process exits and delivers exit-status.
251+
serverChannel.CloseWrite() //nolint:errcheck
252+
clientToServerDone <- err
251253
}()
252254

253255
// Server to Client
254256
go func() {
255257
err := p.proxyData(serverChannel, clientChannel, "server→client", sessionID, false, chState)
256-
errChan <- err
258+
serverToClientDone <- err
257259
}()
258260

259-
// Wait for either direction to finish or context cancellation
261+
// When client→server finishes first (SCP), wait for server→client to deliver
262+
// the response. When server→client finishes first (exec), proceed immediately
263+
// since the client→server goroutine may be blocked on stdin that never arrives.
260264
select {
261-
case err := <-errChan:
265+
case err := <-clientToServerDone:
262266
if err != nil && err != io.EOF {
263-
log.Debug().Err(err).Str("sessionID", sessionID).Msg("Channel proxy error")
267+
log.Debug().Err(err).Str("sessionID", sessionID).Msg("client→server proxy error")
268+
}
269+
select {
270+
case err := <-serverToClientDone:
271+
if err != nil && err != io.EOF {
272+
log.Debug().Err(err).Str("sessionID", sessionID).Msg("server→client proxy error")
273+
}
274+
case <-time.After(3 * time.Second):
275+
case <-ctx.Done():
276+
}
277+
case err := <-serverToClientDone:
278+
if err != nil && err != io.EOF {
279+
log.Debug().Err(err).Str("sessionID", sessionID).Msg("server→client proxy error")
264280
}
265281
case <-ctx.Done():
266282
log.Info().Str("sessionID", sessionID).Msg("Channel cancelled by context")
@@ -269,7 +285,7 @@ func (p *SSHProxy) handleChannel(ctx context.Context, newChannel ssh.NewChannel,
269285
// Brief window for exit-status to be forwarded before channel teardown.
270286
select {
271287
case <-serverReqDone:
272-
case <-time.After(500 * time.Millisecond):
288+
case <-time.After(3 * time.Second):
273289
}
274290
clientChannel.Close()
275291
serverChannel.Close()

0 commit comments

Comments
 (0)