Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5fe2a25

Browse files
committed
fix: Terminal emulation used by SSH sessions
Fixes#3371
1 parent66ad86a commit5fe2a25

File tree

15 files changed

+387
-82
lines changed

15 files changed

+387
-82
lines changed

‎.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"gonet",
3232
"gossh",
3333
"gsyslog",
34+
"GTTY",
3435
"hashicorp",
3536
"hclsyntax",
3637
"httpapi",
@@ -67,6 +68,7 @@
6768
"ntqry",
6869
"OIDC",
6970
"oneof",
71+
"opty",
7072
"paralleltest",
7173
"parameterscopeid",
7274
"pqtype",
@@ -76,6 +78,7 @@
7678
"provisionerd",
7779
"provisionersdk",
7880
"ptty",
81+
"ptys",
7982
"ptytest",
8083
"reconfig",
8184
"retrier",
@@ -87,6 +90,7 @@
8790
"sourcemapped",
8891
"Srcs",
8992
"stretchr",
93+
"STTY",
9094
"stuntest",
9195
"tailbroker",
9296
"tailcfg",
@@ -105,6 +109,7 @@
105109
"tfjson",
106110
"tfplan",
107111
"tfstate",
112+
"tios",
108113
"tparallel",
109114
"trimprefix",
110115
"tsdial",

‎agent/agent.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ func (a *agent) runStartupScript(ctx context.Context, script string) error {
374374
returnnil
375375
}
376376

377-
writer,err:=os.OpenFile(filepath.Join(os.TempDir(),"coder-startup-script.log"),os.O_CREATE|os.O_RDWR,0600)
377+
writer,err:=os.OpenFile(filepath.Join(os.TempDir(),"coder-startup-script.log"),os.O_CREATE|os.O_RDWR,0o600)
378378
iferr!=nil {
379379
returnxerrors.Errorf("open startup script log file: %w",err)
380380
}
@@ -537,6 +537,8 @@ func (a *agent) init(ctx context.Context) {
537537
},
538538
SubsystemHandlers:map[string]ssh.SubsystemHandler{
539539
"sftp":func(session ssh.Session) {
540+
session.DisablePTYEmulation()
541+
540542
server,err:=sftp.NewServer(session)
541543
iferr!=nil {
542544
a.logger.Debug(session.Context(),"initialize sftp server",slog.Error(err))
@@ -661,7 +663,8 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
661663
}
662664

663665
func (a*agent)handleSSHSession(session ssh.Session) (retErrerror) {
664-
cmd,err:=a.createCommand(session.Context(),session.RawCommand(),session.Environ())
666+
ctx:=session.Context()
667+
cmd,err:=a.createCommand(ctx,session.RawCommand(),session.Environ())
665668
iferr!=nil {
666669
returnerr
667670
}
@@ -678,32 +681,34 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
678681

679682
sshPty,windowSize,isPty:=session.Pty()
680683
ifisPty {
684+
// Disable minimal PTY emulation set by gliderlabs/ssh (NL-to-CRNL).
685+
// See https://github.com/coder/coder/issues/3371.
686+
session.DisablePTYEmulation()
687+
681688
cmd.Env=append(cmd.Env,fmt.Sprintf("TERM=%s",sshPty.Term))
682689

683690
// The pty package sets `SSH_TTY` on supported platforms.
684-
ptty,process,err:=pty.Start(cmd)
691+
ptty,process,err:=pty.Start(cmd,pty.WithPTYOptions(
692+
pty.WithSSHRequest(sshPty),
693+
pty.WithLogger(slog.Stdlib(ctx,a.logger,slog.LevelInfo)),
694+
))
685695
iferr!=nil {
686696
returnxerrors.Errorf("start command: %w",err)
687697
}
688698
deferfunc() {
689699
closeErr:=ptty.Close()
690700
ifcloseErr!=nil {
691-
a.logger.Warn(context.Background(),"failed to close tty",
692-
slog.Error(closeErr))
701+
a.logger.Warn(ctx,"failed to close tty",slog.Error(closeErr))
693702
ifretErr==nil {
694703
retErr=closeErr
695704
}
696705
}
697706
}()
698-
err=ptty.Resize(uint16(sshPty.Window.Height),uint16(sshPty.Window.Width))
699-
iferr!=nil {
700-
returnxerrors.Errorf("resize ptty: %w",err)
701-
}
702707
gofunc() {
703708
forwin:=rangewindowSize {
704709
resizeErr:=ptty.Resize(uint16(win.Height),uint16(win.Width))
705710
ifresizeErr!=nil {
706-
a.logger.Warn(context.Background(),"failed to resize tty",slog.Error(resizeErr))
711+
a.logger.Warn(ctx,"failed to resize tty",slog.Error(resizeErr))
707712
}
708713
}
709714
}()
@@ -718,8 +723,7 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
718723
// ExitErrors just mean the command we run returned a non-zero exit code, which is normal
719724
// and not something to be concerned about. But, if it's something else, we should log it.
720725
iferr!=nil&&!xerrors.As(err,&exitErr) {
721-
a.logger.Warn(context.Background(),"wait error",
722-
slog.Error(err))
726+
a.logger.Warn(ctx,"wait error",slog.Error(err))
723727
}
724728
returnerr
725729
}

‎cli/ssh.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ func ssh() *cobra.Command {
195195
// shutdown of services.
196196
defercancel()
197197

198+
ifvalidOut {
199+
// Set initial window size.
200+
width,height,err:=term.GetSize(int(stdoutFile.Fd()))
201+
iferr==nil {
202+
_=sshSession.WindowChange(height,width)
203+
}
204+
}
198205
err=sshSession.Wait()
199206
iferr!=nil {
200207
// If the connection drops unexpectedly, we get an ExitMissingError but no other

‎go.mod

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ replace github.com/tcnksm/go-httpstat => github.com/kylecarbs/go-httpstat v0.0.0
5151
// https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main
5252
replacetailscale.com =>github.com/coder/tailscalev1.1.1-0.20220907193453-fb5ba5ab658d
5353

54+
// Switch to our fork that imports fixes from http://github.com/tailscale/ssh.
55+
// See: https://github.com/coder/coder/issues/3371
56+
//
57+
// Note that http://github.com/tailscale/ssh has been merged into the Tailscale
58+
// repo as tailscale.com/tempfork/gliderlabs/ssh, however, we can't replace the
59+
// subpath and it includes changes to golang.org/x/crypto/ssh as well which
60+
// makes importing it directly a bit messy.
61+
replacegithub.com/gliderlabs/ssh =>github.com/coder/sshv0.0.0-20220811105153-fcea99919338
62+
5463
require (
5564
cdr.dev/slogv1.4.2-0.20220525200111-18dce5c2cd5f
5665
cloud.google.com/go/computev1.7.0
@@ -126,6 +135,7 @@ require (
126135
github.com/spf13/pflagv1.0.5
127136
github.com/stretchr/testifyv1.8.0
128137
github.com/tabbed/pqtypev0.1.1
138+
github.com/u-root/u-rootv0.9.0
129139
github.com/unrolled/securev1.12.0
130140
go.mozilla.org/pkcs7v0.0.0-20200128120323-432b2356ecb1
131141
go.opentelemetry.io/otelv1.8.0

‎go.sum

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ github.com/coder/glog v1.0.1-0.20220322161911-7365fe7f2cd1 h1:UqBrPWSYvRI2s5RtOu
352352
github.com/coder/glogv1.0.1-0.20220322161911-7365fe7f2cd1/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
353353
github.com/coder/retryv1.3.0 h1:5lAAwt/2Cm6lVmnfBY7sOMXcBOwcwJhmV5QGSELIVWY=
354354
github.com/coder/retryv1.3.0/go.mod h1:tXuRgZgWjUnU5LZPT4lJh4ew2elUhexhlnXzrJWdyFY=
355+
github.com/coder/sshv0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko=
356+
github.com/coder/sshv0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
355357
github.com/coder/tailscalev1.1.1-0.20220907193453-fb5ba5ab658d h1:IQ8wJn8MfDS+sesYPpn3EDAyvoGMxFvyyE9uWtcfU6w=
356358
github.com/coder/tailscalev1.1.1-0.20220907193453-fb5ba5ab658d/go.mod h1:MO+tWkQp2YIF3KBnnej/mQvgYccRS5Xk/IrEpZ4Z3BU=
357359
github.com/coder/wireguard-go/tun/netstackv0.0.0-20220823170024-a78136eb0cab h1:9yEvRWXXfyKzXu8AqywCi+tFZAoqCy4wVcsXwuvZNMc=
@@ -638,9 +640,6 @@ github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU=
638640
github.com/gin-gonic/ginv1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
639641
github.com/github/fakecav0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
640642
github.com/github/fakecav0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
641-
github.com/gliderlabs/sshv0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
642-
github.com/gliderlabs/sshv0.3.4 h1:+AXBtim7MTKaLVPgvE+3mhewYRawNLTd+jEEz/wExZw=
643-
github.com/gliderlabs/sshv0.3.4/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
644643
github.com/go-chi/chiv1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
645644
github.com/go-chi/chiv1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
646645
github.com/go-chi/chi/v5v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
@@ -1810,6 +1809,8 @@ github.com/tomarrell/wrapcheck/v2 v2.4.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2Ogf
18101809
github.com/tomasen/realipv0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
18111810
github.com/tommy-muehle/go-mnd/v2v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw=
18121811
github.com/tv42/httpunixv0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
1812+
github.com/u-root/u-rootv0.9.0 h1:1dpUzrE0FyKrNEjxpKFOkyveuV1f3T0Ko5CQg4gTkCg=
1813+
github.com/u-root/u-rootv0.9.0/go.mod h1:ewc9w6JF1ayZCVC9Y5wsrUiCBw3nMmPC3QItvrEwmew=
18131814
github.com/u-root/uiov0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
18141815
github.com/u-root/uiov0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME=
18151816
github.com/u-root/uiov0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=

‎pty/pty.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ package pty
22

33
import (
44
"io"
5+
"log"
56
"os"
7+
8+
"github.com/gliderlabs/ssh"
69
)
710

811
// PTY is a minimal interface for interacting with a TTY.
912
typePTYinterface {
1013
io.Closer
1114

15+
// Name of the TTY. Example on Linux would be "/dev/pts/1".
16+
Name()string
17+
1218
// Output handles TTY output.
1319
//
1420
// cmd.SetOutput(pty.Output()) would be used to specify a command
@@ -35,7 +41,6 @@ type PTY interface {
3541
// to Wait() on a process, this abstraction provides a goroutine-safe interface for interacting with
3642
// the process.
3743
typeProcessinterface {
38-
3944
// Wait for the command to complete. Returned error is as for exec.Cmd.Wait()
4045
Wait()error
4146

@@ -52,9 +57,33 @@ type WithFlags interface {
5257
EchoEnabled() (bool,error)
5358
}
5459

60+
// PTYOptions represents a an option for a PTY.
61+
typePTYOptionfunc(*ptyOptions)
62+
63+
typeptyOptionsstruct {
64+
logger*log.Logger
65+
sshReq*ssh.Pty
66+
}
67+
68+
// WithSSHRequest applies the ssh.Pty request to the PTY.
69+
//
70+
// Only partially supported on Windows (e.g. window size).
71+
funcWithSSHRequest(req ssh.Pty)PTYOption {
72+
returnfunc(opts*ptyOptions) {
73+
opts.sshReq=&req
74+
}
75+
}
76+
77+
// WithLogger sets a logger for logging errors.
78+
funcWithLogger(logger*log.Logger)PTYOption {
79+
returnfunc(opts*ptyOptions) {
80+
opts.logger=logger
81+
}
82+
}
83+
5584
// New constructs a new Pty.
56-
funcNew() (PTY,error) {
57-
returnnewPty()
85+
funcNew(opts...PTYOption) (PTY,error) {
86+
returnnewPty(opts...)
5887
}
5988

6089
// ReadWriter is an implementation of io.ReadWriter that wraps two separate

‎pty/pty_linux.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22

33
package pty
44

5-
import"golang.org/x/sys/unix"
5+
import (
6+
"github.com/u-root/u-root/pkg/termios"
7+
"golang.org/x/sys/unix"
8+
)
69

7-
func (p*otherPty)EchoEnabled() (bool,error) {
8-
termios,err:=unix.IoctlGetTermios(int(p.pty.Fd()),unix.TCGETS)
10+
func (p*otherPty)EchoEnabled() (echobool,errerror) {
11+
err=p.control(p.pty,func(fduintptr)error {
12+
t,err:=termios.GetTermios(fd)
13+
iferr!=nil {
14+
returnerr
15+
}
16+
17+
echo= (t.Lflag&unix.ECHO)!=0
18+
returnnil
19+
})
920
iferr!=nil {
1021
returnfalse,err
1122
}
12-
return(termios.Lflag&unix.ECHO)!=0,nil
23+
returnecho,nil
1324
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp