1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // Session functional tests.
18 "golang.org/x/crypto/ssh"
21 func TestRunCommandSuccess(t *testing.T) {
22 server := newServer(t)
23 defer server.Shutdown()
24 conn := server.Dial(clientConfig())
27 session, err := conn.NewSession()
29 t.Fatalf("session failed: %v", err)
32 err = session.Run("true")
34 t.Fatalf("session failed: %v", err)
38 func TestHostKeyCheck(t *testing.T) {
39 server := newServer(t)
40 defer server.Shutdown()
42 conf := clientConfig()
44 conf.HostKeyCallback = hostDB.Check
47 hostDB.keys[ssh.KeyAlgoRSA][25]++
48 hostDB.keys[ssh.KeyAlgoDSA][25]++
49 hostDB.keys[ssh.KeyAlgoECDSA256][25]++
51 conn, err := server.TryDial(conf)
54 t.Fatalf("dial should have failed.")
55 } else if !strings.Contains(err.Error(), "host key mismatch") {
56 t.Fatalf("'host key mismatch' not found in %v", err)
60 func TestRunCommandStdin(t *testing.T) {
61 server := newServer(t)
62 defer server.Shutdown()
63 conn := server.Dial(clientConfig())
66 session, err := conn.NewSession()
68 t.Fatalf("session failed: %v", err)
77 err = session.Run("true")
79 t.Fatalf("session failed: %v", err)
83 func TestRunCommandStdinError(t *testing.T) {
84 server := newServer(t)
85 defer server.Shutdown()
86 conn := server.Dial(clientConfig())
89 session, err := conn.NewSession()
91 t.Fatalf("session failed: %v", err)
98 pipeErr := errors.New("closing write end of pipe")
99 w.CloseWithError(pipeErr)
101 err = session.Run("true")
103 t.Fatalf("expected %v, found %v", pipeErr, err)
107 func TestRunCommandFailed(t *testing.T) {
108 server := newServer(t)
109 defer server.Shutdown()
110 conn := server.Dial(clientConfig())
113 session, err := conn.NewSession()
115 t.Fatalf("session failed: %v", err)
117 defer session.Close()
118 err = session.Run(`bash -c "kill -9 $$"`)
120 t.Fatalf("session succeeded: %v", err)
124 func TestRunCommandWeClosed(t *testing.T) {
125 server := newServer(t)
126 defer server.Shutdown()
127 conn := server.Dial(clientConfig())
130 session, err := conn.NewSession()
132 t.Fatalf("session failed: %v", err)
134 err = session.Shell()
136 t.Fatalf("shell failed: %v", err)
138 err = session.Close()
140 t.Fatalf("shell failed: %v", err)
144 func TestFuncLargeRead(t *testing.T) {
145 server := newServer(t)
146 defer server.Shutdown()
147 conn := server.Dial(clientConfig())
150 session, err := conn.NewSession()
152 t.Fatalf("unable to create new session: %s", err)
155 stdout, err := session.StdoutPipe()
157 t.Fatalf("unable to acquire stdout pipe: %s", err)
160 err = session.Start("dd if=/dev/urandom bs=2048 count=1024")
162 t.Fatalf("unable to execute remote command: %s", err)
165 buf := new(bytes.Buffer)
166 n, err := io.Copy(buf, stdout)
168 t.Fatalf("error reading from remote stdout: %s", err)
172 t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n)
176 func TestKeyChange(t *testing.T) {
177 server := newServer(t)
178 defer server.Shutdown()
179 conf := clientConfig()
180 hostDB := hostKeyDB()
181 conf.HostKeyCallback = hostDB.Check
182 conf.RekeyThreshold = 1024
183 conn := server.Dial(conf)
186 for i := 0; i < 4; i++ {
187 session, err := conn.NewSession()
189 t.Fatalf("unable to create new session: %s", err)
192 stdout, err := session.StdoutPipe()
194 t.Fatalf("unable to acquire stdout pipe: %s", err)
197 err = session.Start("dd if=/dev/urandom bs=1024 count=1")
199 t.Fatalf("unable to execute remote command: %s", err)
201 buf := new(bytes.Buffer)
202 n, err := io.Copy(buf, stdout)
204 t.Fatalf("error reading from remote stdout: %s", err)
209 t.Fatalf("Expected %d bytes but read only %d from remote command", want, n)
213 if changes := hostDB.checkCount; changes < 4 {
214 t.Errorf("got %d key changes, want 4", changes)
218 func TestInvalidTerminalMode(t *testing.T) {
219 server := newServer(t)
220 defer server.Shutdown()
221 conn := server.Dial(clientConfig())
224 session, err := conn.NewSession()
226 t.Fatalf("session failed: %v", err)
228 defer session.Close()
230 if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil {
231 t.Fatalf("req-pty failed: successful request with invalid mode")
235 func TestValidTerminalMode(t *testing.T) {
236 server := newServer(t)
237 defer server.Shutdown()
238 conn := server.Dial(clientConfig())
241 session, err := conn.NewSession()
243 t.Fatalf("session failed: %v", err)
245 defer session.Close()
247 stdout, err := session.StdoutPipe()
249 t.Fatalf("unable to acquire stdout pipe: %s", err)
252 stdin, err := session.StdinPipe()
254 t.Fatalf("unable to acquire stdin pipe: %s", err)
257 tm := ssh.TerminalModes{ssh.ECHO: 0}
258 if err = session.RequestPty("xterm", 80, 40, tm); err != nil {
259 t.Fatalf("req-pty failed: %s", err)
262 err = session.Shell()
264 t.Fatalf("session failed: %s", err)
267 stdin.Write([]byte("stty -a && exit\n"))
270 if _, err := io.Copy(&buf, stdout); err != nil {
271 t.Fatalf("reading failed: %s", err)
274 if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") {
275 t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput)
279 func TestCiphers(t *testing.T) {
280 var config ssh.Config
282 cipherOrder := config.Ciphers
283 // These ciphers will not be tested when commented out in cipher.go it will
284 // fallback to the next available as per line 292.
285 cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc")
287 for _, ciph := range cipherOrder {
288 server := newServer(t)
289 defer server.Shutdown()
290 conf := clientConfig()
291 conf.Ciphers = []string{ciph}
292 // Don't fail if sshd doesn't have the cipher.
293 conf.Ciphers = append(conf.Ciphers, cipherOrder...)
294 conn, err := server.TryDial(conf)
298 t.Fatalf("failed for cipher %q", ciph)
303 func TestMACs(t *testing.T) {
304 var config ssh.Config
306 macOrder := config.MACs
308 for _, mac := range macOrder {
309 server := newServer(t)
310 defer server.Shutdown()
311 conf := clientConfig()
312 conf.MACs = []string{mac}
313 // Don't fail if sshd doesn't have the MAC.
314 conf.MACs = append(conf.MACs, macOrder...)
315 if conn, err := server.TryDial(conf); err == nil {
318 t.Fatalf("failed for MAC %q", mac)
323 func TestKeyExchanges(t *testing.T) {
324 var config ssh.Config
326 kexOrder := config.KeyExchanges
327 for _, kex := range kexOrder {
328 server := newServer(t)
329 defer server.Shutdown()
330 conf := clientConfig()
331 // Don't fail if sshd doesn't have the kex.
332 conf.KeyExchanges = append([]string{kex}, kexOrder...)
333 conn, err := server.TryDial(conf)
337 t.Errorf("failed for kex %q", kex)
342 func TestClientAuthAlgorithms(t *testing.T) {
343 for _, key := range []string{
349 server := newServer(t)
350 conf := clientConfig()
352 conf.Auth = []ssh.AuthMethod{
353 ssh.PublicKeys(testSigners[key]),
356 conn, err := server.TryDial(conf)
360 t.Errorf("failed for key %q", key)