ssh_test.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package cli
  2. import (
  3. "crypto/ed25519"
  4. "crypto/rand"
  5. "errors"
  6. "net"
  7. "strings"
  8. "testing"
  9. "time"
  10. "golang.org/x/crypto/ssh"
  11. "debtik/internal/auth"
  12. )
  13. func TestSSHExecReportsFailureAndPreservesLongCommands(t *testing.T) {
  14. _, private, err := ed25519.GenerateKey(rand.Reader)
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. signer, err := ssh.NewSignerFromKey(private)
  19. if err != nil {
  20. t.Fatal(err)
  21. }
  22. config := &ssh.ServerConfig{NoClientAuth: true}
  23. config.AddHostKey(signer)
  24. l, err := net.Listen("tcp", "127.0.0.1:0")
  25. if err != nil {
  26. t.Fatal(err)
  27. }
  28. defer l.Close()
  29. server := &SSHServer{executor: &Executor{}}
  30. done := make(chan struct{})
  31. go func() {
  32. defer close(done)
  33. raw, err := l.Accept()
  34. if err != nil {
  35. return
  36. }
  37. defer raw.Close()
  38. conn, chans, reqs, err := ssh.NewServerConn(raw, config)
  39. if err != nil {
  40. return
  41. }
  42. defer conn.Close()
  43. go ssh.DiscardRequests(reqs)
  44. for ch := range chans {
  45. channel, requests, err := ch.Accept()
  46. if err == nil {
  47. go server.handleSession(channel, requests, &auth.PublicUser{Role: auth.RoleFull})
  48. }
  49. }
  50. }()
  51. client, err := ssh.Dial("tcp", l.Addr().String(), &ssh.ClientConfig{User: "test", HostKeyCallback: ssh.FixedHostKey(signer.PublicKey()), Timeout: 3 * time.Second})
  52. if err != nil {
  53. t.Fatal(err)
  54. }
  55. defer func() { client.Close(); <-done }()
  56. for _, command := range []string{"/log", "/help", "unknown", "/interface print", strings.Repeat("x", 70000)} {
  57. session, err := client.NewSession()
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. output, err := session.CombinedOutput(command)
  62. session.Close()
  63. if command == "/log" || command == "/help" {
  64. if err != nil {
  65. t.Fatalf("valid command failed: %v", err)
  66. }
  67. } else {
  68. var exit *ssh.ExitError
  69. if !errors.As(err, &exit) || exit.ExitStatus() != 1 {
  70. t.Fatalf("failure reported success: %v", err)
  71. }
  72. if len(command) > 65535 && !strings.Contains(string(output), command) {
  73. t.Fatal("long command truncated")
  74. }
  75. }
  76. }
  77. }