...
1
2
3
4
5 package test
6
7 import (
8 "net"
9
10 "golang.org/x/crypto/ssh"
11 )
12
13 type exitStatusMsg struct {
14 Status uint32
15 }
16
17
18
19
20 type goTestServer struct {
21 listener net.Listener
22 config *ssh.ServerConfig
23 done <-chan struct{}
24 }
25
26 func newTestServer(config *ssh.ServerConfig) (*goTestServer, error) {
27 server := &goTestServer{
28 config: config,
29 }
30 listener, err := net.Listen("tcp", "127.0.0.1:")
31 if err != nil {
32 return nil, err
33 }
34 server.listener = listener
35 done := make(chan struct{}, 1)
36 server.done = done
37 go server.acceptConnections(done)
38
39 return server, nil
40 }
41
42 func (s *goTestServer) port() (string, error) {
43 _, port, err := net.SplitHostPort(s.listener.Addr().String())
44 return port, err
45 }
46
47 func (s *goTestServer) acceptConnections(done chan<- struct{}) {
48 defer close(done)
49
50 for {
51 c, err := s.listener.Accept()
52 if err != nil {
53 return
54 }
55 _, chans, reqs, err := ssh.NewServerConn(c, s.config)
56 if err != nil {
57 return
58 }
59 go ssh.DiscardRequests(reqs)
60 defer c.Close()
61
62 for newChannel := range chans {
63 if newChannel.ChannelType() != "session" {
64 newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
65 continue
66 }
67
68 channel, requests, err := newChannel.Accept()
69 if err != nil {
70 continue
71 }
72
73 go func(in <-chan *ssh.Request) {
74 for req := range in {
75 ok := false
76 switch req.Type {
77 case "exec":
78 ok = true
79 go func() {
80 channel.SendRequest("exit-status", false, ssh.Marshal(&exitStatusMsg{Status: 0}))
81 channel.Close()
82 }()
83 }
84 if req.WantReply {
85 req.Reply(ok, nil)
86 }
87 }
88 }(requests)
89 }
90 }
91 }
92
93 func (s *goTestServer) Close() error {
94 err := s.listener.Close()
95
96 <-s.done
97 return err
98 }
99
View as plain text