2015-05-30 15:19:10 +00:00
package easyssh
import (
"net"
"golang.org/x/crypto/ssh"
)
// Server represents an SSH Server. The SSH ServerConfig must be provided
type Server struct {
Addr string
Config * ssh . ServerConfig
Handler ConnHandler
* ssh . ServerConn
}
// ListenAndServe listens on the TCP address s.Addr and then calls Serve to handle requests on incoming connections. If s.Addr is blank, ":ssh" is used
func ( s * Server ) ListenAndServe ( ) error {
addr := s . Addr
if addr == "" {
addr = ":ssh"
}
ln , err := net . Listen ( "tcp" , addr )
if err != nil {
return err
}
return s . Serve ( ln . ( * net . TCPListener ) )
}
// Serve accepts incoming connections on the provided listener.and reads global SSH Channel and Out-of-band requests and calls s,ConnHandler to handle them
func ( s * Server ) Serve ( l net . Listener ) error {
defer l . Close ( )
2016-07-30 12:35:10 +00:00
logger . Print ( "SSH Server started listening on: " , l . Addr ( ) )
2015-05-30 15:19:10 +00:00
for {
tcpConn , err := l . Accept ( )
if err != nil {
return err
}
c , err := s . newConn ( tcpConn )
if err != nil {
continue
}
go c . serve ( )
}
}
// HandleOpenChannel requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler
func ( s * Server ) HandleOpenChannel ( channelName string , handler ChannelMultipleRequestsHandler , data ... byte ) error {
ch , reqs , err := s . OpenChannel ( channelName , data )
if err != nil {
return err
}
handler . HandleMultipleRequests ( reqs , s . ServerConn , channelName , ch )
return nil
}
// HandleOpenChannelFunc requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler function
2016-07-30 12:35:10 +00:00
func ( s * Server ) HandleOpenChannelFunc ( channelName string , handler func ( reqs <- chan * ssh . Request , sshConn ssh . Conn , channelType string , channel ssh . Channel ) , data ... byte ) error {
2015-05-30 15:19:10 +00:00
return s . HandleOpenChannel ( channelName , ChannelMultipleRequestsHandlerFunc ( handler ) , data ... )
}
type conn struct {
server * Server
remoteAddr string
conn net . Conn
}
func ( c * conn ) serve ( ) {
sshConn , chans , reqs , err := ssh . NewServerConn ( c . conn , c . server . Config )
if err != nil {
return
}
c . server . ServerConn = sshConn
2016-07-30 12:35:10 +00:00
logger . Print ( "New ssh connection from: " , c . conn . RemoteAddr ( ) )
2015-05-30 15:19:10 +00:00
go func ( ) {
sshConn . Wait ( )
2016-07-30 12:35:10 +00:00
logger . Print ( "Closing ssh connection from: " , c . conn . RemoteAddr ( ) )
2015-05-30 15:19:10 +00:00
if c . conn != nil {
c . conn . Close ( )
//c.conn = nil
}
} ( )
// Use default ConnHandler if one isn't provided
serverHandler { c . server } . HandleSSHConn ( sshConn , chans , reqs )
}
func ( s * Server ) newConn ( netConn net . Conn ) ( * conn , error ) {
c := new ( conn )
c . remoteAddr = netConn . RemoteAddr ( ) . String ( )
c . server = s
c . conn = netConn
return c , nil
}
// NewSessionServerHandler creates a ConnHandler to provide a more standard SSH server providing sessions
func NewSessionServerHandler ( ) * SSHConnHandler {
s := SSHConnHandler { }
channelHandler := NewChannelsMux ( )
channelHandler . HandleChannel ( SessionRequest , SessionHandler ( ) )
s . MultipleChannelsHandler = channelHandler
return & s
}
// NewStandardSSHServerHandler returns a server handler that can deal with ssh sessions and both local and remote port forwarding
func NewStandardSSHServerHandler ( ) * SSHConnHandler {
s := NewSSHConnHandler ( )
chHandler := NewChannelsMux ( )
chHandler . HandleChannel ( SessionRequest , SessionHandler ( ) )
chHandler . HandleChannel ( DirectForwardRequest , DirectPortForwardHandler ( ) )
s . MultipleChannelsHandler = chHandler
globalHandler := NewGlobalMultipleRequestsMux ( )
globalHandler . HandleRequest ( RemoteForwardRequest , TCPIPForwardRequestHandler ( ) )
s . GlobalMultipleRequestsHandler = globalHandler
return s
}
// ListenAndServe listens on the given tcp address addr and then calls Serve with handler.
// If handler is nil, the DefaultServerHandler is used.
func ListenAndServe ( addr string , conf * ssh . ServerConfig , handler ConnHandler ) error {
s := & Server { addr , conf , handler , nil }
return s . ListenAndServe ( )
}
// Serve accepts incoming SSH connections on the listener l.
// If handler is nil, the DefaultServerHandler is used.
func Serve ( l net . Listener , conf * ssh . ServerConfig , handler ConnHandler ) error {
s := & Server { Config : conf , Handler : handler }
return s . Serve ( l )
}
type serverHandler struct {
s * Server
}
// ServeSSH is a wrapper, tests if the server has a ServerHandler, and if not uses the default one
func ( s serverHandler ) HandleSSHConn ( conn * ssh . ServerConn , chans <- chan ssh . NewChannel , reqs <- chan * ssh . Request ) {
handler := s . s . Handler
if handler == nil {
handler = DefaultSSHConnHandler
}
handler . HandleSSHConn ( conn , chans , reqs )
}