func handleTCPConnection(logger log.Logger, conn net.Conn, sshConfig *ssh.ServerConfig, system datamodel.System) { // Open SSH connection sshConn, channels, requests, err := ssh.NewServerConn(conn, sshConfig) if err != nil { logger.Warn("SSH handshake failed") return } // Get user if exists, otherwise return error users, _ := system.Users() user, _ := users.Get(sshConn.Permissions.Extensions["username"]) logger.Debug("Handshake successful") defer sshConn.Conn.Close() // Discard requests go ssh.DiscardRequests(requests) for ch := range channels { t := ch.ChannelType() if t != "session" && t != "kappa-client" { logger.Info("UnknownChannelType", "type", t) ch.Reject(ssh.UnknownChannelType, t) break } // Accept channel channel, requests, err := ch.Accept() if err != nil { logger.Warn("Error creating channel") continue } if t == "session" { go handleSessionRequests(logger, channel, requests, system, user) } else if t == "kappa-client" { go handleChannelRequests(logger, channel, requests, system, user) } } }
func NewSSHServer(logger log.Logger, sys datamodel.System, privateKey ssh.Signer, roots *x509.CertPool) (server SSHServer, err error) { // Get user store users, err := sys.Users() // Create server config sshConfig := &ssh.ServerConfig{ NoClientAuth: false, PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (perm *ssh.Permissions, err error) { // Get user if exists, otherwise return error user, err := users.Get(conn.User()) if err != nil { return } // Check keyring for public key if keyring := user.KeyRing(); !keyring.Contains(key.Marshal()) { err = fmt.Errorf("invalid public key") return } // Add pubkey and username to permissions perm = &ssh.Permissions{ Extensions: map[string]string{ "pubkey": string(key.Marshal()), "username": conn.User(), }, } return }, AuthLogCallback: func(conn ssh.ConnMetadata, method string, err error) { if err != nil { logger.Info("Login attempt", "user", conn.User(), "method", method, "error", err.Error()) } else { logger.Info("Successful login", "user", conn.User(), "method", method) } }, } sshConfig.AddHostKey(privateKey) // Get ssh bind addr bind := viper.GetString("SSHListen") if bind == "" { err = fmt.Errorf("Empty SSH bind address") return } // Open SSH socket logger.Info("Starting SSH server", "addr", bind) sshAddr, err := net.ResolveTCPAddr("tcp", bind) if err != nil { err = fmt.Errorf("Invalid tcp address") return } // Create listener listener, err := net.ListenTCP("tcp", sshAddr) if err != nil { return } server.logger = logger server.sshConfig = sshConfig server.listener = listener server.system = sys return }