github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/session_test.go (about)

     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.
     4  
     5  // +build !windows
     6  
     7  package test
     8  
     9  // Session functional tests.
    10  
    11  import (
    12  	"bytes"
    13  	"errors"
    14  	"io"
    15  	"strings"
    16  	"testing"
    17  
    18  	"golang.org/x/crypto/ssh"
    19  )
    20  
    21  func TestRunCommandSuccess(t *testing.T) {
    22  	server := newServer(t)
    23  	defer server.Shutdown()
    24  	conn := server.Dial(clientConfig())
    25  	defer conn.Close()
    26  
    27  	session, err := conn.NewSession()
    28  	if err != nil {
    29  		t.Fatalf("session failed: %v", err)
    30  	}
    31  	defer session.Close()
    32  	err = session.Run("true")
    33  	if err != nil {
    34  		t.Fatalf("session failed: %v", err)
    35  	}
    36  }
    37  
    38  func TestHostKeyCheck(t *testing.T) {
    39  	server := newServer(t)
    40  	defer server.Shutdown()
    41  
    42  	conf := clientConfig()
    43  	hostDB := hostKeyDB()
    44  	conf.HostKeyCallback = hostDB.Check
    45  
    46  	// change the keys.
    47  	hostDB.keys[ssh.KeyAlgoRSA][25]++
    48  	hostDB.keys[ssh.KeyAlgoDSA][25]++
    49  	hostDB.keys[ssh.KeyAlgoECDSA256][25]++
    50  
    51  	conn, err := server.TryDial(conf)
    52  	if err == nil {
    53  		conn.Close()
    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)
    57  	}
    58  }
    59  
    60  func TestRunCommandStdin(t *testing.T) {
    61  	server := newServer(t)
    62  	defer server.Shutdown()
    63  	conn := server.Dial(clientConfig())
    64  	defer conn.Close()
    65  
    66  	session, err := conn.NewSession()
    67  	if err != nil {
    68  		t.Fatalf("session failed: %v", err)
    69  	}
    70  	defer session.Close()
    71  
    72  	r, w := io.Pipe()
    73  	defer r.Close()
    74  	defer w.Close()
    75  	session.Stdin = r
    76  
    77  	err = session.Run("true")
    78  	if err != nil {
    79  		t.Fatalf("session failed: %v", err)
    80  	}
    81  }
    82  
    83  func TestRunCommandStdinError(t *testing.T) {
    84  	server := newServer(t)
    85  	defer server.Shutdown()
    86  	conn := server.Dial(clientConfig())
    87  	defer conn.Close()
    88  
    89  	session, err := conn.NewSession()
    90  	if err != nil {
    91  		t.Fatalf("session failed: %v", err)
    92  	}
    93  	defer session.Close()
    94  
    95  	r, w := io.Pipe()
    96  	defer r.Close()
    97  	session.Stdin = r
    98  	pipeErr := errors.New("closing write end of pipe")
    99  	w.CloseWithError(pipeErr)
   100  
   101  	err = session.Run("true")
   102  	if err != pipeErr {
   103  		t.Fatalf("expected %v, found %v", pipeErr, err)
   104  	}
   105  }
   106  
   107  func TestRunCommandFailed(t *testing.T) {
   108  	server := newServer(t)
   109  	defer server.Shutdown()
   110  	conn := server.Dial(clientConfig())
   111  	defer conn.Close()
   112  
   113  	session, err := conn.NewSession()
   114  	if err != nil {
   115  		t.Fatalf("session failed: %v", err)
   116  	}
   117  	defer session.Close()
   118  	err = session.Run(`bash -c "kill -9 $$"`)
   119  	if err == nil {
   120  		t.Fatalf("session succeeded: %v", err)
   121  	}
   122  }
   123  
   124  func TestRunCommandWeClosed(t *testing.T) {
   125  	server := newServer(t)
   126  	defer server.Shutdown()
   127  	conn := server.Dial(clientConfig())
   128  	defer conn.Close()
   129  
   130  	session, err := conn.NewSession()
   131  	if err != nil {
   132  		t.Fatalf("session failed: %v", err)
   133  	}
   134  	err = session.Shell()
   135  	if err != nil {
   136  		t.Fatalf("shell failed: %v", err)
   137  	}
   138  	err = session.Close()
   139  	if err != nil {
   140  		t.Fatalf("shell failed: %v", err)
   141  	}
   142  }
   143  
   144  func TestFuncLargeRead(t *testing.T) {
   145  	server := newServer(t)
   146  	defer server.Shutdown()
   147  	conn := server.Dial(clientConfig())
   148  	defer conn.Close()
   149  
   150  	session, err := conn.NewSession()
   151  	if err != nil {
   152  		t.Fatalf("unable to create new session: %s", err)
   153  	}
   154  
   155  	stdout, err := session.StdoutPipe()
   156  	if err != nil {
   157  		t.Fatalf("unable to acquire stdout pipe: %s", err)
   158  	}
   159  
   160  	err = session.Start("dd if=/dev/urandom bs=2048 count=1024")
   161  	if err != nil {
   162  		t.Fatalf("unable to execute remote command: %s", err)
   163  	}
   164  
   165  	buf := new(bytes.Buffer)
   166  	n, err := io.Copy(buf, stdout)
   167  	if err != nil {
   168  		t.Fatalf("error reading from remote stdout: %s", err)
   169  	}
   170  
   171  	if n != 2048*1024 {
   172  		t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n)
   173  	}
   174  }
   175  
   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)
   184  	defer conn.Close()
   185  
   186  	for i := 0; i < 4; i++ {
   187  		session, err := conn.NewSession()
   188  		if err != nil {
   189  			t.Fatalf("unable to create new session: %s", err)
   190  		}
   191  
   192  		stdout, err := session.StdoutPipe()
   193  		if err != nil {
   194  			t.Fatalf("unable to acquire stdout pipe: %s", err)
   195  		}
   196  
   197  		err = session.Start("dd if=/dev/urandom bs=1024 count=1")
   198  		if err != nil {
   199  			t.Fatalf("unable to execute remote command: %s", err)
   200  		}
   201  		buf := new(bytes.Buffer)
   202  		n, err := io.Copy(buf, stdout)
   203  		if err != nil {
   204  			t.Fatalf("error reading from remote stdout: %s", err)
   205  		}
   206  
   207  		want := int64(1024)
   208  		if n != want {
   209  			t.Fatalf("Expected %d bytes but read only %d from remote command", want, n)
   210  		}
   211  	}
   212  
   213  	if changes := hostDB.checkCount; changes < 4 {
   214  		t.Errorf("got %d key changes, want 4", changes)
   215  	}
   216  }
   217  
   218  func TestInvalidTerminalMode(t *testing.T) {
   219  	server := newServer(t)
   220  	defer server.Shutdown()
   221  	conn := server.Dial(clientConfig())
   222  	defer conn.Close()
   223  
   224  	session, err := conn.NewSession()
   225  	if err != nil {
   226  		t.Fatalf("session failed: %v", err)
   227  	}
   228  	defer session.Close()
   229  
   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")
   232  	}
   233  }
   234  
   235  func TestValidTerminalMode(t *testing.T) {
   236  	server := newServer(t)
   237  	defer server.Shutdown()
   238  	conn := server.Dial(clientConfig())
   239  	defer conn.Close()
   240  
   241  	session, err := conn.NewSession()
   242  	if err != nil {
   243  		t.Fatalf("session failed: %v", err)
   244  	}
   245  	defer session.Close()
   246  
   247  	stdout, err := session.StdoutPipe()
   248  	if err != nil {
   249  		t.Fatalf("unable to acquire stdout pipe: %s", err)
   250  	}
   251  
   252  	stdin, err := session.StdinPipe()
   253  	if err != nil {
   254  		t.Fatalf("unable to acquire stdin pipe: %s", err)
   255  	}
   256  
   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)
   260  	}
   261  
   262  	err = session.Shell()
   263  	if err != nil {
   264  		t.Fatalf("session failed: %s", err)
   265  	}
   266  
   267  	stdin.Write([]byte("stty -a && exit\n"))
   268  
   269  	var buf bytes.Buffer
   270  	if _, err := io.Copy(&buf, stdout); err != nil {
   271  		t.Fatalf("reading failed: %s", err)
   272  	}
   273  
   274  	if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") {
   275  		t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput)
   276  	}
   277  }
   278  
   279  func TestCiphers(t *testing.T) {
   280  	var config ssh.Config
   281  	config.SetDefaults()
   282  	cipherOrder := config.Ciphers
   283  
   284  	for _, ciph := range cipherOrder {
   285  		server := newServer(t)
   286  		defer server.Shutdown()
   287  		conf := clientConfig()
   288  		conf.Ciphers = []string{ciph}
   289  		// Don't fail if sshd doesnt have the cipher.
   290  		conf.Ciphers = append(conf.Ciphers, cipherOrder...)
   291  		conn, err := server.TryDial(conf)
   292  		if err == nil {
   293  			conn.Close()
   294  		} else {
   295  			t.Fatalf("failed for cipher %q", ciph)
   296  		}
   297  	}
   298  }
   299  
   300  func TestMACs(t *testing.T) {
   301  	var config ssh.Config
   302  	config.SetDefaults()
   303  	macOrder := config.MACs
   304  
   305  	for _, mac := range macOrder {
   306  		server := newServer(t)
   307  		defer server.Shutdown()
   308  		conf := clientConfig()
   309  		conf.MACs = []string{mac}
   310  		// Don't fail if sshd doesnt have the MAC.
   311  		conf.MACs = append(conf.MACs, macOrder...)
   312  		if conn, err := server.TryDial(conf); err == nil {
   313  			conn.Close()
   314  		} else {
   315  			t.Fatalf("failed for MAC %q", mac)
   316  		}
   317  	}
   318  }