From 72d128998b322b546980a2021b2d84fbcf195940 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sat, 20 Jul 2024 10:43:38 +0200 Subject: [PATCH] First agent version, passing in external listener fo ssh so it can be used later with yamux as well. --- cmd/agent/agent.go | 102 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100755 cmd/agent/agent.go diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go new file mode 100755 index 0000000..cd00d59 --- /dev/null +++ b/cmd/agent/agent.go @@ -0,0 +1,102 @@ +package main + +import ( + "fmt" + "io" + "log" + "net" + "os" + "os/exec" + "syscall" + "unsafe" + + "github.com/creack/pty" + "github.com/gliderlabs/ssh" + "github.com/pkg/sftp" +) + +func SftpHandler(sess ssh.Session) { + debugStream := io.Discard + serverOptions := []sftp.ServerOption{ + sftp.WithDebug(debugStream), + } + server, err := sftp.NewServer( + sess, + serverOptions..., + ) + if err != nil { + log.Printf("sftp tcpserver init error: %s\n", err) + return + }F + if err := server.Serve(); err == io.EOF { + server.Close() + fmt.Println("sftp client exited session.") + } else if err != nil { + fmt.Println("sftp tcpserver completed with error:", err) + } +} + +func passwordAuth(ctx ssh.Context, password string) bool { + // Replace with your own logic to validate username and password + return ctx.User() == "abc" && password == "123" +} + +func setWinsize(f *os.File, w, h int) { + syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), + uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) +} + +func main() { + ssh.Handle(func(s ssh.Session) { + cmd := exec.Command("bash") + ptyReq, winCh, isPty := s.Pty() + if isPty { + cmd.Env = append(os.Environ(), fmt.Sprintf("TERM=%s", ptyReq.Term)) + f, err := pty.Start(cmd) + if err != nil { + panic(err) + } + go func() { + for win := range winCh { + setWinsize(f, win.Width, win.Height) + } + }() + go func() { + io.Copy(f, s) // stdin + }() + io.Copy(s, f) // stdout + cmd.Wait() + } else { + io.WriteString(s, "No PTY requested.\n") + s.Exit(1) + } + }) + + log.Println("starting ssh tcpserver on port 2222...") + server := ssh.Server{ + Addr: ":2222", + PasswordHandler: passwordAuth, + SubsystemHandlers: map[string]ssh.SubsystemHandler{ + "sftp": SftpHandler, + }, + } + + listener, err := net.Listen("tcp", ":2222") + if err != nil { + log.Fatal(err) + } + + server.Serve(listener) + + //for { + // conn, err := listener.Accept() + // if err != nil { + // log.Println("Failed to accept connection:", err) + // continue + // } + // log.Println("Got connection") + // go server.HandleConn(conn) + //} + + //log.Fatal(server.ListenAndServe()) +}