forked from gitlabhq/gitlab-runner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stub_ssh_server.go
89 lines (72 loc) · 1.63 KB
/
stub_ssh_server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package ssh
import (
"fmt"
"net"
"strconv"
"strings"
"github.com/tevino/abool"
cryptoSSH "golang.org/x/crypto/ssh"
)
type StubSSHServer struct {
User string
Password string
Config *cryptoSSH.ServerConfig
stop chan bool
shouldExit *abool.AtomicBool
}
func NewStubServer(user, pass string, privateKey []byte) (*StubSSHServer, error) {
server := &StubSSHServer{
User: user,
Password: pass,
Config: &cryptoSSH.ServerConfig{
PasswordCallback: func(conn cryptoSSH.ConnMetadata, password []byte) (*cryptoSSH.Permissions, error) {
if conn.User() == user && string(password) == pass {
return nil, nil
}
return nil, fmt.Errorf("wrong password for %q", conn.User())
},
},
stop: make(chan bool),
shouldExit: abool.New(),
}
key, err := cryptoSSH.ParsePrivateKey(privateKey)
if err != nil {
return nil, err
}
server.Config.AddHostKey(key)
return server, nil
}
func (s *StubSSHServer) Start() (int, error) {
listener, err := net.Listen("tcp", "127.0.0.1:")
if err != nil {
return 0, err
}
go func() {
<-s.stop
s.shouldExit.Set()
listener.Close()
}()
address := strings.SplitN(listener.Addr().String(), ":", 2)
go s.mainLoop(listener)
return strconv.Atoi(address[1])
}
func (s *StubSSHServer) Stop() {
s.stop <- true
}
func (s *StubSSHServer) mainLoop(listener net.Listener) {
for {
if s.shouldExit.IsSet() {
return
}
conn, err := listener.Accept()
if err != nil {
continue
}
if s.shouldExit.IsSet() {
return
}
//upgrade to ssh connection
cryptoSSH.NewServerConn(conn, s.Config)
// This is enough just for handling incoming connections
}
}