subsystem.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package sftpd
  2. import (
  3. "io"
  4. "net"
  5. "github.com/pkg/sftp"
  6. "github.com/drakkan/sftpgo/v2/common"
  7. "github.com/drakkan/sftpgo/v2/dataprovider"
  8. "github.com/drakkan/sftpgo/v2/logger"
  9. )
  10. type subsystemChannel struct {
  11. reader io.Reader
  12. writer io.Writer
  13. }
  14. func (s *subsystemChannel) Read(p []byte) (int, error) {
  15. return s.reader.Read(p)
  16. }
  17. func (s *subsystemChannel) Write(p []byte) (int, error) {
  18. return s.writer.Write(p)
  19. }
  20. func (s *subsystemChannel) Close() error {
  21. return nil
  22. }
  23. func newSubsystemChannel(reader io.Reader, writer io.Writer) *subsystemChannel {
  24. return &subsystemChannel{
  25. reader: reader,
  26. writer: writer,
  27. }
  28. }
  29. // ServeSubSystemConnection handles a connection as SSH subsystem
  30. func ServeSubSystemConnection(user *dataprovider.User, connectionID string, reader io.Reader, writer io.Writer) error {
  31. err := user.CheckFsRoot(connectionID)
  32. if err != nil {
  33. errClose := user.CloseFs()
  34. logger.Warn(logSender, connectionID, "unable to check fs root: %v close fs error: %v", err, errClose)
  35. return err
  36. }
  37. dataprovider.UpdateLastLogin(user)
  38. connection := &Connection{
  39. BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolSFTP, "", "", *user),
  40. ClientVersion: "",
  41. RemoteAddr: &net.IPAddr{},
  42. LocalAddr: &net.IPAddr{},
  43. channel: newSubsystemChannel(reader, writer),
  44. }
  45. common.Connections.Add(connection)
  46. defer common.Connections.Remove(connection.GetID())
  47. server := sftp.NewRequestServer(connection.channel, sftp.Handlers{
  48. FileGet: connection,
  49. FilePut: connection,
  50. FileCmd: connection,
  51. FileList: connection,
  52. }, sftp.WithRSAllocator())
  53. defer server.Close()
  54. return server.Serve()
  55. }