2021-11-19 01:07:30 +00:00
|
|
|
package glider_ssh
|
2016-10-03 21:54:17 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/subtle"
|
|
|
|
"net"
|
2019-02-23 02:11:43 +00:00
|
|
|
|
|
|
|
gossh "golang.org/x/crypto/ssh"
|
2016-10-03 21:54:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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"
|
|
|
|
)
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// DefaultHandler is the default Handler used by Serve.
|
|
|
|
var DefaultHandler Handler
|
2016-10-03 21:54:17 +00:00
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// Option is a functional option handler for Server.
|
2016-10-03 21:54:17 +00:00
|
|
|
type Option func(*Server) error
|
2016-11-29 23:23:42 +00:00
|
|
|
|
|
|
|
// Handler is a callback for handling established SSH sessions.
|
2016-10-03 21:54:17 +00:00
|
|
|
type Handler func(Session)
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// PublicKeyHandler is a callback for performing public key authentication.
|
2017-03-14 19:13:03 +00:00
|
|
|
type PublicKeyHandler func(ctx Context, key PublicKey) bool
|
2016-11-29 23:23:42 +00:00
|
|
|
|
|
|
|
// PasswordHandler is a callback for performing password authentication.
|
2017-03-14 19:13:03 +00:00
|
|
|
type PasswordHandler func(ctx Context, password string) bool
|
2016-11-29 23:23:42 +00:00
|
|
|
|
2019-01-06 04:25:33 +00:00
|
|
|
// KeyboardInteractiveHandler is a callback for performing keyboard-interactive authentication.
|
2019-01-06 21:09:35 +00:00
|
|
|
type KeyboardInteractiveHandler func(ctx Context, challenger gossh.KeyboardInteractiveChallenge) bool
|
2019-01-06 04:25:33 +00:00
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// PtyCallback is a hook for allowing PTY sessions.
|
2017-03-14 19:13:03 +00:00
|
|
|
type PtyCallback func(ctx Context, pty Pty) bool
|
2016-10-03 21:54:17 +00:00
|
|
|
|
2019-02-23 02:11:43 +00:00
|
|
|
// SessionRequestCallback is a callback for allowing or denying SSH sessions.
|
|
|
|
type SessionRequestCallback func(sess Session, requestType string) bool
|
|
|
|
|
2017-07-12 17:27:56 +00:00
|
|
|
// 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.
|
2019-10-08 21:39:01 +00:00
|
|
|
type ConnCallback func(ctx Context, conn net.Conn) net.Conn
|
2017-07-12 17:27:56 +00:00
|
|
|
|
2017-04-28 22:54:12 +00:00
|
|
|
// LocalPortForwardingCallback is a hook for allowing port forwarding
|
|
|
|
type LocalPortForwardingCallback func(ctx Context, destinationHost string, destinationPort uint32) bool
|
|
|
|
|
Remote forwarding (#88)
* context: fixed documentation to be more specific about ContextKeyConn being the key for a gossh.ServerConn
Signed-off-by: Jeff Lindsay <progrium@gmail.com>
* server: fixes handler setup, changed to interface based handlers, added global request handler map
* tcpip: working remote forwarding
Signed-off-by: Jeff Lindsay <progrium@gmail.com>
* context: docs typo
Signed-off-by: Jeff Lindsay <progrium@gmail.com>
* session: always reply to unblock clients trying something
Signed-off-by: Jeff Lindsay <progrium@gmail.com>
* tcpip: stop listening when ssh clients disconnect
Signed-off-by: Jeff Lindsay <progrium@gmail.com>
* Remote forwarding (#87)
* Update generateSigner key size to 2048 (#62)
Fixes #58
* Add syntax highlighting to readme (#67)
* small api updates (#69)
These updates make it easier to implement and pass custom Session and
Context implementations
No compatibilty breaking, all tests pass
* Move channelHandlers to avoid data race (#59)
* Update tests to work with go 1.10+ (#73)
Fixes #72
* Update shutdown to use a WaitGroup rather than sleeping (#74)
* Fix race condition in TestServerClose (#75)
In test server close, 3 things need to happen in order:
- Client session start
- Server.Close
- Client session exit (With io.EOF)
This fix ensures the client won't do anything until after the call to
close which ensure's we'll get io.EOF rather than a different error.
* Update circleci config to test multiple go versions
* Update CircleCI config to test 1.9 and the latest
The x/crypto/ssh library dropped support go < 1.9 as that's the first
version to have the math/bits library.
https://github.com/golang/crypto/commit/83c378c48d6ee2ca9c20551b599aa74cb7765785
* Wait for connections to finish when shutting down
PR #74 introduced a WaitGroup for listeners, but it doesn't wait for
open connections before closing the server. This patch waits until all
conns are closed before returning from Shutdown.
* Support port forwarding of literal IPv6 addresses (#85)
* Support port forwarding of literal IPv6 addresses
To disambiguate between colons as host:port separators and as IPv6 address separators, literal IPv6 addresses use square brackets around the address (https://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers). So host ::1, port 22 is written as [::1]:22, and therefore a simple concatenation of host, colon, and port doesn't work. Fortunately net.JoinHostPort already implements this functionality, so with a bit of type gymnastics we can generate dest in an IPv6-safe way.
* Support port forwarding of literal IPv6 addresses
To disambiguate between colons as host:port separators and as IPv6 address separators, literal IPv6 addresses use square brackets around the address (https://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers). So host ::1, port 22 is written as [::1]:22, and therefore a simple concatenation of host, colon, and port doesn't work. Fortunately net.JoinHostPort already implements this functionality, so with a bit of type gymnastics we can generate dest in an IPv6-safe way.
* Reverse port forwarding callback added
* garbage removed
2018-11-13 16:04:02 +00:00
|
|
|
// ReversePortForwardingCallback is a hook for allowing reverse port forwarding
|
|
|
|
type ReversePortForwardingCallback func(ctx Context, bindHost string, bindPort uint32) bool
|
|
|
|
|
2019-06-19 09:06:24 +00:00
|
|
|
// ServerConfigCallback is a hook for creating custom default server configs
|
|
|
|
type ServerConfigCallback func(ctx Context) *gossh.ServerConfig
|
2019-02-21 19:57:56 +00:00
|
|
|
|
2020-12-12 13:16:31 +00:00
|
|
|
// 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)
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// Window represents the size of a PTY window.
|
2016-10-03 21:54:17 +00:00
|
|
|
type Window struct {
|
|
|
|
Width int
|
|
|
|
Height int
|
|
|
|
}
|
|
|
|
|
2017-02-16 00:08:25 +00:00
|
|
|
// Pty represents a PTY request and configuration.
|
2016-10-03 21:54:17 +00:00
|
|
|
type Pty struct {
|
2017-02-16 00:08:25 +00:00
|
|
|
Term string
|
2016-10-03 21:54:17 +00:00
|
|
|
Window Window
|
2017-02-16 00:08:25 +00:00
|
|
|
// HELP WANTED: terminal modes!
|
2016-10-03 21:54:17 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// 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.
|
2021-11-19 00:05:48 +00:00
|
|
|
func Serve(l net.Listener, handler Handler, options ...Option) (*Server, error) {
|
2016-10-03 21:54:17 +00:00
|
|
|
srv := &Server{Handler: handler}
|
|
|
|
for _, option := range options {
|
|
|
|
if err := srv.SetOption(option); err != nil {
|
2021-11-19 00:05:48 +00:00
|
|
|
return nil, err
|
2016-10-03 21:54:17 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-19 00:05:48 +00:00
|
|
|
return srv, srv.Serve(l)
|
2016-10-03 21:54:17 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// 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.
|
2016-10-03 21:54:17 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// Handle registers the handler as the DefaultHandler.
|
2016-10-03 21:54:17 +00:00
|
|
|
func Handle(handler Handler) {
|
2016-11-29 23:23:42 +00:00
|
|
|
DefaultHandler = handler
|
2016-10-03 21:54:17 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 23:23:42 +00:00
|
|
|
// KeysEqual is constant time compare of the keys to avoid timing attacks.
|
2016-10-03 21:54:17 +00:00
|
|
|
func KeysEqual(ak, bk PublicKey) bool {
|
2016-12-17 21:36:48 +00:00
|
|
|
|
|
|
|
//avoid panic if one of the keys is nil, return false instead
|
|
|
|
if ak == nil || bk == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-10-05 00:06:46 +00:00
|
|
|
a := ak.Marshal()
|
|
|
|
b := bk.Marshal()
|
2016-10-03 21:54:17 +00:00
|
|
|
return (len(a) == len(b) && subtle.ConstantTimeCompare(a, b) == 1)
|
|
|
|
}
|