diff options
| author | Lena <lena@omega> | 2026-07-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-07-01 00:00:00 +0000 |
| commit | 04fede70866f209a8cb9dfe8736872fc25009336 (patch) | |
| tree | 90636fd1c94d13354752d7a15d64b69eb5822c49 /ci | |
| parent | fb3199b4a993be16804129111c0bb35cc39a70f3 (diff) | |
| download | rsend-04fede70866f209a8cb9dfe8736872fc25009336.tar.gz | |
ci: remove unused testsshd
Nothing referenced it: the rsh tests run their own in-process SSH
server (sshserver_test.go), which testsshd largely duplicated.
Diffstat (limited to 'ci')
| -rw-r--r-- | ci/testsshd/go.mod | 7 | ||||
| -rw-r--r-- | ci/testsshd/go.sum | 6 | ||||
| -rw-r--r-- | ci/testsshd/main.go | 149 |
3 files changed, 0 insertions, 162 deletions
diff --git a/ci/testsshd/go.mod b/ci/testsshd/go.mod deleted file mode 100644 index 88ccdc7..0000000 --- a/ci/testsshd/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module rsend/ci/testsshd - -go 1.25.0 - -require golang.org/x/crypto v0.53.0 - -require golang.org/x/sys v0.46.0 // indirect diff --git a/ci/testsshd/go.sum b/ci/testsshd/go.sum deleted file mode 100644 index 68cadc1..0000000 --- a/ci/testsshd/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= -golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= -golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= -golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= diff --git a/ci/testsshd/main.go b/ci/testsshd/main.go deleted file mode 100644 index 19a53ac..0000000 --- a/ci/testsshd/main.go +++ /dev/null @@ -1,149 +0,0 @@ -// testsshd is a minimal SSH server for rsend integration tests: one host key, -// an authorized_keys allowlist, and command execution via /bin/sh (so it runs -// the remote rsync). It is not a product component; it stands in for a real -// sshd so the full push path can be exercised on a device or in CI. -package main - -import ( - "flag" - "io" - "log" - "net" - "os" - "os/exec" - - "golang.org/x/crypto/ssh" -) - -func main() { - addr := flag.String("addr", "127.0.0.1:2222", "listen address") - hostKeyPath := flag.String("hostkey", "", "OpenSSH private host key (required)") - authPath := flag.String("authorized", "", "authorized_keys file (required)") - flag.Parse() - - if *hostKeyPath == "" || *authPath == "" { - log.Fatal("testsshd: -hostkey and -authorized are required") - } - - hostKey := mustSigner(*hostKeyPath) - allowed := mustAuthorized(*authPath) - - cfg := &ssh.ServerConfig{ - PublicKeyCallback: func(_ ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { - if allowed[string(key.Marshal())] { - return &ssh.Permissions{}, nil - } - return nil, io.EOF - }, - } - cfg.AddHostKey(hostKey) - - ln, err := net.Listen("tcp", *addr) - if err != nil { - log.Fatalf("testsshd: listen: %v", err) - } - log.Printf("testsshd: listening on %s", ln.Addr()) - for { - c, err := ln.Accept() - if err != nil { - log.Fatalf("testsshd: accept: %v", err) - } - go handle(c, cfg) - } -} - -func mustSigner(path string) ssh.Signer { - b, err := os.ReadFile(path) - if err != nil { - log.Fatalf("testsshd: read host key: %v", err) - } - s, err := ssh.ParsePrivateKey(b) - if err != nil { - log.Fatalf("testsshd: parse host key: %v", err) - } - return s -} - -func mustAuthorized(path string) map[string]bool { - b, err := os.ReadFile(path) - if err != nil { - log.Fatalf("testsshd: read authorized_keys: %v", err) - } - m := map[string]bool{} - for len(b) > 0 { - key, _, _, rest, err := ssh.ParseAuthorizedKey(b) - if err != nil { - break - } - m[string(key.Marshal())] = true - b = rest - } - if len(m) == 0 { - log.Fatal("testsshd: no authorized keys") - } - return m -} - -func handle(nConn net.Conn, cfg *ssh.ServerConfig) { - conn, chans, reqs, err := ssh.NewServerConn(nConn, cfg) - if err != nil { - return - } - defer conn.Close() - go ssh.DiscardRequests(reqs) - for nc := range chans { - if nc.ChannelType() != "session" { - nc.Reject(ssh.UnknownChannelType, "only session") - continue - } - ch, requests, err := nc.Accept() - if err != nil { - return - } - go session(ch, requests) - } -} - -func session(ch ssh.Channel, requests <-chan *ssh.Request) { - for req := range requests { - if req.Type != "exec" { - if req.WantReply { - req.Reply(false, nil) - } - continue - } - var payload struct{ Command string } - ssh.Unmarshal(req.Payload, &payload) - if req.WantReply { - req.Reply(true, nil) - } - code := run(payload.Command, ch) - ch.SendRequest("exit-status", false, ssh.Marshal(struct{ Status uint32 }{uint32(code)})) - ch.Close() - return - } -} - -func run(cmd string, ch ssh.Channel) int { - c := exec.Command("/bin/sh", "-c", cmd) - c.Stdout = ch - c.Stderr = ch.Stderr() - in, err := c.StdinPipe() - if err != nil { - return 1 - } - if err := c.Start(); err != nil { - return 1 - } - go func() { - io.Copy(in, ch) - in.Close() - }() - if err := c.Wait(); err != nil { - if ee, ok := err.(*exec.ExitError); ok { - return ee.ExitCode() - } - return 1 - } - return 0 -} |