forked from gliderlabs/ssh
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathssh.go
More file actions
187 lines (155 loc) · 6.67 KB
/
ssh.go
File metadata and controls
187 lines (155 loc) · 6.67 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package ssh
import (
"crypto/subtle"
"errors"
"net"
gossh "golang.org/x/crypto/ssh"
)
type Signal string
// POSIX signals as listed in RFC 4254 Section 6.10.
const (
SIGABRT Signal = "ABRT"
SIGALRM Signal = "ALRM"
SIGFPE Signal = "FPE"
SIGHUP Signal = "HUP"
SIGILL Signal = "ILL"
SIGINT Signal = "INT"
SIGKILL Signal = "KILL"
SIGPIPE Signal = "PIPE"
SIGQUIT Signal = "QUIT"
SIGSEGV Signal = "SEGV"
SIGTERM Signal = "TERM"
SIGUSR1 Signal = "USR1"
SIGUSR2 Signal = "USR2"
)
// DefaultHandler is the default Handler used by Serve.
var DefaultHandler Handler
// ErrRejected may be returned by LocalUnixForwardingCallback or
// ReverseUnixForwardingCallback to reject a forwarding request. When
// returned, the server replies with "prohibited" rather than
// "connection failed."
var ErrRejected = errors.New("ssh: rejected")
// Option is a functional option handler for Server.
type Option func(*Server) error
// Handler is a callback for handling established SSH sessions.
type Handler func(Session)
// BannerHandler is a callback for displaying the server banner.
type BannerHandler func(ctx Context) string
// PublicKeyHandler is a callback for performing public key authentication.
type PublicKeyHandler func(ctx Context, key PublicKey) error
type NoClientAuthHandler func(ctx Context) error
// PasswordHandler is a callback for performing password authentication.
type PasswordHandler func(ctx Context, password string) bool
// KeyboardInteractiveHandler is a callback for performing keyboard-interactive authentication.
type KeyboardInteractiveHandler func(ctx Context, challenger gossh.KeyboardInteractiveChallenge) bool
// PtyCallback is a hook for allowing PTY sessions.
type PtyCallback func(ctx Context, pty Pty) bool
// SessionRequestCallback is a callback for allowing or denying SSH sessions.
type SessionRequestCallback func(sess Session, requestType string) bool
// ConnCallback is a hook for new connections before handling.
// It allows wrapping for timeouts and limiting by returning
// the net.Conn that will be used as the underlying connection.
type ConnCallback func(ctx Context, conn net.Conn) net.Conn
// LocalPortForwardingCallback is a hook for allowing port forwarding
type LocalPortForwardingCallback func(ctx Context, destinationHost string, destinationPort uint32) bool
// ReversePortForwardingCallback is a hook for allowing reverse port forwarding
type ReversePortForwardingCallback func(ctx Context, bindHost string, bindPort uint32) bool
// LocalUnixForwardingCallback is a hook for allowing unix forwarding
// (direct-streamlocal@openssh.com). The callback receives the client-requested
// socket path and returns a connection to the target socket, or an error.
//
// Returning ErrRejected (or an error wrapping it) rejects the request with
// "administratively prohibited" and the error message is sent to the client.
// Any other error rejects with "connection failed."
//
// Use NewLocalUnixForwardingCallback to create a callback with built-in path
// validation and security controls.
type LocalUnixForwardingCallback func(ctx Context, socketPath string) (net.Conn, error)
// ReverseUnixForwardingCallback is a hook for allowing reverse unix forwarding
// (streamlocal-forward@openssh.com). The callback receives the client-requested
// socket path and returns a listener bound to that path, or an error.
//
// Returning ErrRejected (or an error wrapping it) rejects the request with
// "administratively prohibited" and the error message is sent to the client.
// Any other error rejects the request silently.
//
// Use NewReverseUnixForwardingCallback to create a callback with built-in path
// validation, permission controls, and security defaults matching OpenSSH.
type ReverseUnixForwardingCallback func(ctx Context, socketPath string) (net.Listener, error)
// ServerConfigCallback is a hook for creating custom default server configs
type ServerConfigCallback func(ctx Context) *gossh.ServerConfig
// ConnectionFailedCallback is a hook for reporting failed connections
// Please note: the net.Conn is likely to be closed at this point
type ConnectionFailedCallback func(conn net.Conn, err error)
// Window represents the size of a PTY window.
//
// See https://datatracker.ietf.org/doc/html/rfc4254#section-6.2
//
// Zero dimension parameters MUST be ignored. The character/row dimensions
// override the pixel dimensions (when nonzero). Pixel dimensions refer
// to the drawable area of the window.
type Window struct {
// Width is the number of columns.
// It overrides WidthPixels.
Width int
// Height is the number of rows.
// It overrides HeightPixels.
Height int
// WidthPixels is the drawable width of the window, in pixels.
WidthPixels int
// HeightPixels is the drawable height of the window, in pixels.
HeightPixels int
}
// Pty represents a PTY request and configuration.
type Pty struct {
// Term is the TERM environment variable value.
Term string
// Window is the Window sent as part of the pty-req.
Window Window
// Modes represent a mapping of Terminal Mode opcode to value as it was
// requested by the client as part of the pty-req. These are outlined as
// part of https://datatracker.ietf.org/doc/html/rfc4254#section-8.
//
// The opcodes are defined as constants in golang.org/x/crypto/ssh (VINTR,VQUIT,etc.).
// Boolean opcodes have values 0 or 1.
Modes gossh.TerminalModes
}
// Serve accepts incoming SSH connections on the listener l, creating a new
// connection goroutine for each. The connection goroutines read requests and
// then calls handler to handle sessions. Handler is typically nil, in which
// case the DefaultHandler is used.
func Serve(l net.Listener, handler Handler, options ...Option) error {
srv := &Server{Handler: handler}
for _, option := range options {
if err := srv.SetOption(option); err != nil {
return err
}
}
return srv.Serve(l)
}
// ListenAndServe listens on the TCP network address addr and then calls Serve
// with handler to handle sessions on incoming connections. Handler is typically
// nil, in which case the DefaultHandler is used.
func ListenAndServe(addr string, handler Handler, options ...Option) error {
srv := &Server{Addr: addr, Handler: handler}
for _, option := range options {
if err := srv.SetOption(option); err != nil {
return err
}
}
return srv.ListenAndServe()
}
// Handle registers the handler as the DefaultHandler.
func Handle(handler Handler) {
DefaultHandler = handler
}
// KeysEqual is constant time compare of the keys to avoid timing attacks.
func KeysEqual(ak, bk PublicKey) bool {
// avoid panic if one of the keys is nil, return false instead
if ak == nil || bk == nil {
return false
}
a := ak.Marshal()
b := bk.Marshal()
return (len(a) == len(b) && subtle.ConstantTimeCompare(a, b) == 1)
}