コード例 #1
0
ファイル: handler.go プロジェクト: pgrew/kappa
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)
		}
	}
}
コード例 #2
0
ファイル: server.go プロジェクト: pgrew/kappa
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
}