main pico / pkg / send / protocols / sftp / sftp.go
Antonio Mika  ·  2026-10-10
 1package sftp
 2
 3import (
 4	"errors"
 5	"fmt"
 6	"io"
 7
 8	"github.com/picosh/pico/pkg/pssh"
 9	"github.com/picosh/pico/pkg/send/utils"
10	"github.com/pkg/sftp"
11)
12
13// func SSHOption(writeHandler utils.CopyFromClientHandler) ssh.Option {
14// 	return func(server *ssh.Server) error {
15// 		if server.SubsystemHandlers == nil {
16// 			server.SubsystemHandlers = map[string]ssh.SubsystemHandler{}
17// 		}
18
19// 		server.SubsystemHandlers["sftp"] = SubsystemHandler(writeHandler)
20// 		return nil
21// 	}
22// }
23
24func Middleware(writeHandler utils.CopyFromClientHandler) pssh.SSHServerMiddleware {
25	return func(next pssh.SSHServerHandler) pssh.SSHServerHandler {
26		return func(session *pssh.SSHServerConnSession) error {
27			logger := writeHandler.GetLogger(session).With(
28				"sftp", true,
29			)
30
31			defer func() {
32				if r := recover(); r != nil {
33					logger.Error("error running sftp middleware", "err", r)
34					_, _ = fmt.Fprintln(session, "error running sftp middleware, check the flags you are using")
35				}
36			}()
37
38			err := writeHandler.Validate(session)
39			if err != nil {
40				_, _ = fmt.Fprintln(session.Stderr(), err)
41				return err
42			}
43
44			handler := &handlererr{
45				Handler: &handler{
46					session:      session,
47					writeHandler: writeHandler,
48					pending:      map[string]*pendingFile{},
49					ignored:      map[string]int{},
50					hidden:       map[string]*pendingFile{},
51				},
52			}
53
54			handlers := sftp.Handlers{
55				FilePut:  handler,
56				FileList: handler,
57				FileGet:  handler,
58				FileCmd:  handler,
59			}
60
61			requestServer := sftp.NewRequestServer(session, handlers)
62
63			err = requestServer.Serve()
64			if err != nil && !errors.Is(err, io.EOF) {
65				_, _ = fmt.Fprintln(session.Stderr(), err)
66				logger.Error("Error serving sftp subsystem", "err", err)
67			}
68
69			return err
70		}
71	}
72}