├── LICENSE ├── README.md ├── src └── cmd │ └── gsftp │ └── main.go └── vendor ├── manifest └── src ├── github.com ├── kr │ └── fs │ │ ├── LICENSE │ │ ├── Readme │ │ ├── example_test.go │ │ ├── filesystem.go │ │ ├── walk.go │ │ └── walk_test.go └── pkg │ └── sftp │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── README.md │ ├── attrs.go │ ├── attrs_test.go │ ├── client.go │ ├── client_integration_test.go │ ├── client_test.go │ ├── debug.go │ ├── example_test.go │ ├── examples │ ├── buffered-read-benchmark │ │ └── main.go │ ├── buffered-write-benchmark │ │ └── main.go │ ├── streaming-read-benchmark │ │ └── main.go │ └── streaming-write-benchmark │ │ └── main.go │ ├── packet.go │ ├── packet_test.go │ ├── release.go │ ├── sftp.go │ └── wercker.yml └── golang.org └── x └── crypto └── ssh ├── agent ├── client.go ├── client_test.go ├── forward.go ├── keyring.go ├── server.go ├── server_test.go └── testdata_test.go ├── benchmark_test.go ├── buffer.go ├── buffer_test.go ├── certs.go ├── certs_test.go ├── channel.go ├── cipher.go ├── cipher_test.go ├── client.go ├── client_auth.go ├── client_auth_test.go ├── client_test.go ├── common.go ├── connection.go ├── doc.go ├── example_test.go ├── handshake.go ├── handshake_test.go ├── kex.go ├── kex_test.go ├── keys.go ├── keys_test.go ├── mac.go ├── mempipe_test.go ├── messages.go ├── messages_test.go ├── mux.go ├── mux_test.go ├── server.go ├── session.go ├── session_test.go ├── tcpip.go ├── tcpip_test.go ├── terminal ├── terminal.go ├── terminal_test.go ├── util.go ├── util_bsd.go ├── util_linux.go └── util_windows.go ├── test ├── agent_unix_test.go ├── cert_test.go ├── doc.go ├── forward_unix_test.go ├── session_test.go ├── tcpip_test.go ├── test_unix_test.go └── testdata_test.go ├── testdata ├── doc.go └── keys.go ├── testdata_test.go ├── transport.go └── transport_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 constabulary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # example-gsftp 2 | 3 | This is a sample [`gb`](http://getgb.io/) project. 4 | 5 | ## Get the code 6 | 7 | To fetch this project 8 | 9 | git clone https://github.com/constabulary/example-gsftp 10 | 11 | # Building the code 12 | 13 | To build this project 14 | 15 | cd example-gsftp 16 | gb build 17 | 18 | If you don't have `gb` installed, [follow these instructions](http://getgb.io/docs/install/). 19 | 20 | # Run the program 21 | 22 | To run the program, build it, then run the binary `bin/gsftp`. 23 | -------------------------------------------------------------------------------- /src/cmd/gsftp/main.go: -------------------------------------------------------------------------------- 1 | // gsftp implements a simple sftp client. 2 | // 3 | // gsftp understands the following commands: 4 | // 5 | // List a directory (and its subdirectories) 6 | // gsftp ls DIR 7 | // 8 | // Fetch a remote file 9 | // gsftp fetch FILE 10 | // 11 | // Put the contents of stdin to a remote file 12 | // cat LOCALFILE | gsftp put REMOTEFILE 13 | // 14 | // Print the details of a remote file 15 | // gsftp stat FILE 16 | // 17 | // Remove a remote file 18 | // gsftp rm FILE 19 | // 20 | // Rename a file 21 | // gsftp mv OLD NEW 22 | // 23 | package main 24 | 25 | import ( 26 | "flag" 27 | "fmt" 28 | "io" 29 | "log" 30 | "net" 31 | "os" 32 | 33 | "golang.org/x/crypto/ssh" 34 | "golang.org/x/crypto/ssh/agent" 35 | 36 | "github.com/pkg/sftp" 37 | ) 38 | 39 | var ( 40 | USER = flag.String("user", os.Getenv("USER"), "ssh username") 41 | HOST = flag.String("host", "localhost", "ssh server hostname") 42 | PORT = flag.Int("port", 22, "ssh server port") 43 | PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") 44 | ) 45 | 46 | func usage() { 47 | const message = `gsftp, a simple sftp client 48 | 49 | Usage: 50 | 51 | gsftp command [arguments] 52 | 53 | gsftp understands the following commands: 54 | 55 | List a directory (and its subdirectories) 56 | gsftp ls DIR 57 | 58 | Fetch a remote file 59 | gsftp fetch FILE 60 | 61 | Put the contents of stdin to a remote file 62 | cat LOCALFILE | gsftp put REMOTEFILE 63 | 64 | Print the details of a remote file 65 | gsftp stat FILE 66 | 67 | Remove a remote file 68 | gsftp rm FILE 69 | 70 | Rename a file 71 | gsftp mv OLD NEW 72 | }` 73 | fmt.Println(message) 74 | os.Exit(2) 75 | } 76 | 77 | func init() { 78 | flag.Usage = usage 79 | flag.Parse() 80 | if len(flag.Args()) < 1 { 81 | usage() 82 | } 83 | } 84 | 85 | func main() { 86 | var auths []ssh.AuthMethod 87 | if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { 88 | auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) 89 | 90 | } 91 | if *PASS != "" { 92 | auths = append(auths, ssh.Password(*PASS)) 93 | } 94 | 95 | config := ssh.ClientConfig{ 96 | User: *USER, 97 | Auth: auths, 98 | } 99 | addr := fmt.Sprintf("%s:%d", *HOST, *PORT) 100 | conn, err := ssh.Dial("tcp", addr, &config) 101 | if err != nil { 102 | log.Fatalf("unable to connect to [%s]: %v", addr, err) 103 | } 104 | defer conn.Close() 105 | 106 | client, err := sftp.NewClient(conn) 107 | if err != nil { 108 | log.Fatalf("unable to start sftp subsytem: %v", err) 109 | } 110 | defer client.Close() 111 | switch cmd := flag.Args()[0]; cmd { 112 | case "ls": 113 | if len(flag.Args()) < 2 { 114 | log.Fatalf("%s %s: remote path required", cmd, os.Args[0]) 115 | } 116 | walker := client.Walk(flag.Args()[1]) 117 | for walker.Step() { 118 | if err := walker.Err(); err != nil { 119 | log.Println(err) 120 | continue 121 | } 122 | fmt.Println(walker.Path()) 123 | } 124 | case "fetch": 125 | if len(flag.Args()) < 2 { 126 | log.Fatalf("%s %s: remote path required", cmd, os.Args[0]) 127 | } 128 | f, err := client.Open(flag.Args()[1]) 129 | if err != nil { 130 | log.Fatal(err) 131 | } 132 | defer f.Close() 133 | if _, err := io.Copy(os.Stdout, f); err != nil { 134 | log.Fatal(err) 135 | } 136 | case "put": 137 | if len(flag.Args()) < 2 { 138 | log.Fatalf("%s %s: remote path required", cmd, os.Args[0]) 139 | } 140 | f, err := client.Create(flag.Args()[1]) 141 | if err != nil { 142 | log.Fatal(err) 143 | } 144 | defer f.Close() 145 | if _, err := io.Copy(f, os.Stdin); err != nil { 146 | log.Fatal(err) 147 | } 148 | case "stat": 149 | if len(flag.Args()) < 2 { 150 | log.Fatalf("%s %s: remote path required", cmd, os.Args[0]) 151 | } 152 | f, err := client.Open(flag.Args()[1]) 153 | if err != nil { 154 | log.Fatal(err) 155 | } 156 | defer f.Close() 157 | fi, err := f.Stat() 158 | if err != nil { 159 | log.Fatalf("unable to stat file: %v", err) 160 | } 161 | fmt.Printf("%s %d %v\n", fi.Name(), fi.Size(), fi.Mode()) 162 | case "rm": 163 | if len(flag.Args()) < 2 { 164 | log.Fatalf("%s %s: remote path required", cmd, os.Args[0]) 165 | } 166 | if err := client.Remove(flag.Args()[1]); err != nil { 167 | log.Fatalf("unable to remove file: %v", err) 168 | } 169 | case "mv": 170 | if len(flag.Args()) < 3 { 171 | log.Fatalf("%s %s: old and new name required", cmd, os.Args[0]) 172 | } 173 | if err := client.Rename(flag.Args()[1], flag.Args()[2]); err != nil { 174 | log.Fatalf("unable to rename file: %v", err) 175 | } 176 | default: 177 | log.Fatalf("unknown subcommand: %v", cmd) 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /vendor/manifest: -------------------------------------------------------------------------------- 1 | { 2 | "version": 0, 3 | "dependencies": [ 4 | { 5 | "importpath": "github.com/kr/fs", 6 | "repository": "https://github.com/kr/fs", 7 | "revision": "2788f0dbd16903de03cb8186e5c7d97b69ad387b", 8 | "branch": "master", 9 | "path": "" 10 | }, 11 | { 12 | "importpath": "golang.org/x/crypto/ssh", 13 | "repository": "https://go.googlesource.com/crypto", 14 | "revision": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b", 15 | "branch": "master", 16 | "path": "/ssh" 17 | }, 18 | { 19 | "importpath": "github.com/pkg/sftp", 20 | "repository": "https://github.com/pkg/sftp", 21 | "revision": "f234c3c6540c0358b1802f7fd90c0879af9232eb", 22 | "branch": "master", 23 | "path": "" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/Readme: -------------------------------------------------------------------------------- 1 | Filesystem Package 2 | 3 | http://godoc.org/github.com/kr/fs 4 | -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/example_test.go: -------------------------------------------------------------------------------- 1 | package fs_test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/kr/fs" 8 | ) 9 | 10 | func ExampleWalker() { 11 | walker := fs.Walk("/usr/lib") 12 | for walker.Step() { 13 | if err := walker.Err(); err != nil { 14 | fmt.Fprintln(os.Stderr, err) 15 | continue 16 | } 17 | fmt.Println(walker.Path()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/filesystem.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | // FileSystem defines the methods of an abstract filesystem. 10 | type FileSystem interface { 11 | 12 | // ReadDir reads the directory named by dirname and returns a 13 | // list of directory entries. 14 | ReadDir(dirname string) ([]os.FileInfo, error) 15 | 16 | // Lstat returns a FileInfo describing the named file. If the file is a 17 | // symbolic link, the returned FileInfo describes the symbolic link. Lstat 18 | // makes no attempt to follow the link. 19 | Lstat(name string) (os.FileInfo, error) 20 | 21 | // Join joins any number of path elements into a single path, adding a 22 | // separator if necessary. The result is Cleaned; in particular, all 23 | // empty strings are ignored. 24 | // 25 | // The separator is FileSystem specific. 26 | Join(elem ...string) string 27 | } 28 | 29 | // fs represents a FileSystem provided by the os package. 30 | type fs struct{} 31 | 32 | func (f *fs) ReadDir(dirname string) ([]os.FileInfo, error) { return ioutil.ReadDir(dirname) } 33 | 34 | func (f *fs) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } 35 | 36 | func (f *fs) Join(elem ...string) string { return filepath.Join(elem...) } 37 | -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/walk.go: -------------------------------------------------------------------------------- 1 | // Package fs provides filesystem-related functions. 2 | package fs 3 | 4 | import ( 5 | "os" 6 | ) 7 | 8 | // Walker provides a convenient interface for iterating over the 9 | // descendants of a filesystem path. 10 | // Successive calls to the Step method will step through each 11 | // file or directory in the tree, including the root. The files 12 | // are walked in lexical order, which makes the output deterministic 13 | // but means that for very large directories Walker can be inefficient. 14 | // Walker does not follow symbolic links. 15 | type Walker struct { 16 | fs FileSystem 17 | cur item 18 | stack []item 19 | descend bool 20 | } 21 | 22 | type item struct { 23 | path string 24 | info os.FileInfo 25 | err error 26 | } 27 | 28 | // Walk returns a new Walker rooted at root. 29 | func Walk(root string) *Walker { 30 | return WalkFS(root, new(fs)) 31 | } 32 | 33 | // WalkFS returns a new Walker rooted at root on the FileSystem fs. 34 | func WalkFS(root string, fs FileSystem) *Walker { 35 | info, err := fs.Lstat(root) 36 | return &Walker{ 37 | fs: fs, 38 | stack: []item{{root, info, err}}, 39 | } 40 | } 41 | 42 | // Step advances the Walker to the next file or directory, 43 | // which will then be available through the Path, Stat, 44 | // and Err methods. 45 | // It returns false when the walk stops at the end of the tree. 46 | func (w *Walker) Step() bool { 47 | if w.descend && w.cur.err == nil && w.cur.info.IsDir() { 48 | list, err := w.fs.ReadDir(w.cur.path) 49 | if err != nil { 50 | w.cur.err = err 51 | w.stack = append(w.stack, w.cur) 52 | } else { 53 | for i := len(list) - 1; i >= 0; i-- { 54 | path := w.fs.Join(w.cur.path, list[i].Name()) 55 | w.stack = append(w.stack, item{path, list[i], nil}) 56 | } 57 | } 58 | } 59 | 60 | if len(w.stack) == 0 { 61 | return false 62 | } 63 | i := len(w.stack) - 1 64 | w.cur = w.stack[i] 65 | w.stack = w.stack[:i] 66 | w.descend = true 67 | return true 68 | } 69 | 70 | // Path returns the path to the most recent file or directory 71 | // visited by a call to Step. It contains the argument to Walk 72 | // as a prefix; that is, if Walk is called with "dir", which is 73 | // a directory containing the file "a", Path will return "dir/a". 74 | func (w *Walker) Path() string { 75 | return w.cur.path 76 | } 77 | 78 | // Stat returns info for the most recent file or directory 79 | // visited by a call to Step. 80 | func (w *Walker) Stat() os.FileInfo { 81 | return w.cur.info 82 | } 83 | 84 | // Err returns the error, if any, for the most recent attempt 85 | // by Step to visit a file or directory. If a directory has 86 | // an error, w will not descend into that directory. 87 | func (w *Walker) Err() error { 88 | return w.cur.err 89 | } 90 | 91 | // SkipDir causes the currently visited directory to be skipped. 92 | // If w is not on a directory, SkipDir has no effect. 93 | func (w *Walker) SkipDir() { 94 | w.descend = false 95 | } 96 | -------------------------------------------------------------------------------- /vendor/src/github.com/kr/fs/walk_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package fs_test 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "runtime" 11 | "testing" 12 | 13 | "github.com/kr/fs" 14 | ) 15 | 16 | type PathTest struct { 17 | path, result string 18 | } 19 | 20 | type Node struct { 21 | name string 22 | entries []*Node // nil if the entry is a file 23 | mark int 24 | } 25 | 26 | var tree = &Node{ 27 | "testdata", 28 | []*Node{ 29 | {"a", nil, 0}, 30 | {"b", []*Node{}, 0}, 31 | {"c", nil, 0}, 32 | { 33 | "d", 34 | []*Node{ 35 | {"x", nil, 0}, 36 | {"y", []*Node{}, 0}, 37 | { 38 | "z", 39 | []*Node{ 40 | {"u", nil, 0}, 41 | {"v", nil, 0}, 42 | }, 43 | 0, 44 | }, 45 | }, 46 | 0, 47 | }, 48 | }, 49 | 0, 50 | } 51 | 52 | func walkTree(n *Node, path string, f func(path string, n *Node)) { 53 | f(path, n) 54 | for _, e := range n.entries { 55 | walkTree(e, filepath.Join(path, e.name), f) 56 | } 57 | } 58 | 59 | func makeTree(t *testing.T) { 60 | walkTree(tree, tree.name, func(path string, n *Node) { 61 | if n.entries == nil { 62 | fd, err := os.Create(path) 63 | if err != nil { 64 | t.Errorf("makeTree: %v", err) 65 | return 66 | } 67 | fd.Close() 68 | } else { 69 | os.Mkdir(path, 0770) 70 | } 71 | }) 72 | } 73 | 74 | func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) } 75 | 76 | func checkMarks(t *testing.T, report bool) { 77 | walkTree(tree, tree.name, func(path string, n *Node) { 78 | if n.mark != 1 && report { 79 | t.Errorf("node %s mark = %d; expected 1", path, n.mark) 80 | } 81 | n.mark = 0 82 | }) 83 | } 84 | 85 | // Assumes that each node name is unique. Good enough for a test. 86 | // If clear is true, any incoming error is cleared before return. The errors 87 | // are always accumulated, though. 88 | func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool) error { 89 | if err != nil { 90 | *errors = append(*errors, err) 91 | if clear { 92 | return nil 93 | } 94 | return err 95 | } 96 | name := info.Name() 97 | walkTree(tree, tree.name, func(path string, n *Node) { 98 | if n.name == name { 99 | n.mark++ 100 | } 101 | }) 102 | return nil 103 | } 104 | 105 | func TestWalk(t *testing.T) { 106 | makeTree(t) 107 | errors := make([]error, 0, 10) 108 | clear := true 109 | markFn := func(walker *fs.Walker) (err error) { 110 | for walker.Step() { 111 | err = mark(walker.Path(), walker.Stat(), walker.Err(), &errors, clear) 112 | if err != nil { 113 | break 114 | } 115 | } 116 | return err 117 | } 118 | // Expect no errors. 119 | err := markFn(fs.Walk(tree.name)) 120 | if err != nil { 121 | t.Fatalf("no error expected, found: %s", err) 122 | } 123 | if len(errors) != 0 { 124 | t.Fatalf("unexpected errors: %s", errors) 125 | } 126 | checkMarks(t, true) 127 | errors = errors[0:0] 128 | 129 | // Test permission errors. Only possible if we're not root 130 | // and only on some file systems (AFS, FAT). To avoid errors during 131 | // all.bash on those file systems, skip during go test -short. 132 | if os.Getuid() > 0 && !testing.Short() { 133 | // introduce 2 errors: chmod top-level directories to 0 134 | os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) 135 | os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) 136 | 137 | // 3) capture errors, expect two. 138 | // mark respective subtrees manually 139 | markTree(tree.entries[1]) 140 | markTree(tree.entries[3]) 141 | // correct double-marking of directory itself 142 | tree.entries[1].mark-- 143 | tree.entries[3].mark-- 144 | err := markFn(fs.Walk(tree.name)) 145 | if err != nil { 146 | t.Fatalf("expected no error return from Walk, got %s", err) 147 | } 148 | if len(errors) != 2 { 149 | t.Errorf("expected 2 errors, got %d: %s", len(errors), errors) 150 | } 151 | // the inaccessible subtrees were marked manually 152 | checkMarks(t, true) 153 | errors = errors[0:0] 154 | 155 | // 4) capture errors, stop after first error. 156 | // mark respective subtrees manually 157 | markTree(tree.entries[1]) 158 | markTree(tree.entries[3]) 159 | // correct double-marking of directory itself 160 | tree.entries[1].mark-- 161 | tree.entries[3].mark-- 162 | clear = false // error will stop processing 163 | err = markFn(fs.Walk(tree.name)) 164 | if err == nil { 165 | t.Fatalf("expected error return from Walk") 166 | } 167 | if len(errors) != 1 { 168 | t.Errorf("expected 1 error, got %d: %s", len(errors), errors) 169 | } 170 | // the inaccessible subtrees were marked manually 171 | checkMarks(t, false) 172 | errors = errors[0:0] 173 | 174 | // restore permissions 175 | os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) 176 | os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) 177 | } 178 | 179 | // cleanup 180 | if err := os.RemoveAll(tree.name); err != nil { 181 | t.Errorf("removeTree: %v", err) 182 | } 183 | } 184 | 185 | func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486 186 | root, err := filepath.EvalSymlinks(runtime.GOROOT()) 187 | if err != nil { 188 | t.Fatal(err) 189 | } 190 | lib := filepath.Join(root, "lib") 191 | src := filepath.Join(root, "src") 192 | seenSrc := false 193 | walker := fs.Walk(root) 194 | for walker.Step() { 195 | if walker.Err() != nil { 196 | t.Fatal(walker.Err()) 197 | } 198 | 199 | switch walker.Path() { 200 | case lib: 201 | walker.SkipDir() 202 | case src: 203 | seenSrc = true 204 | } 205 | } 206 | if !seenSrc { 207 | t.Fatalf("%q not seen", src) 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Dave Cheney 2 | Saulius Gurklys 3 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/README.md: -------------------------------------------------------------------------------- 1 | sftp 2 | ---- 3 | 4 | The `sftp` package provides support for file system operations on remote ssh servers using the SFTP subsystem. 5 | 6 | [![Build Status](https://drone.io/github.com/pkg/sftp/status.png)](https://drone.io/github.com/pkg/sftp/latest) 7 | 8 | usage and examples 9 | ------------------ 10 | 11 | See [godoc.org/github.com/pkg/sftp](http://godoc.org/github.com/pkg/sftp) for examples and usage. 12 | 13 | The basic operation of the package mirrors the facilities of the [os](http://golang.org/pkg/os) package. 14 | 15 | The Walker interface for directory traversal is heavily inspired by Keith Rarick's [fs](http://godoc.org/github.com/kr/fs) package. 16 | 17 | roadmap 18 | ------- 19 | 20 | * Currently all traffic with the server is serialized, this can be improved by allowing overlapping requests/responses. 21 | * There is way too much duplication in the Client methods. If there was an unmarshal(interface{}) method this would reduce a heap of the duplication. 22 | * Implement integration tests by talking directly to a real opensftp-server process. This shouldn't be too difficult to implement with a small refactoring to the sftp.NewClient method. These tests should be gated on an -sftp.integration test flag. _in progress_ 23 | 24 | contributing 25 | ------------ 26 | 27 | Features, Issues, and Pull Requests are always welcome. 28 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/attrs.go: -------------------------------------------------------------------------------- 1 | package sftp 2 | 3 | // ssh_FXP_ATTRS support 4 | // see http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5 5 | 6 | import ( 7 | "os" 8 | "syscall" 9 | "time" 10 | ) 11 | 12 | const ( 13 | ssh_FILEXFER_ATTR_SIZE = 0x00000001 14 | ssh_FILEXFER_ATTR_UIDGID = 0x00000002 15 | ssh_FILEXFER_ATTR_PERMISSIONS = 0x00000004 16 | ssh_FILEXFER_ATTR_ACMODTIME = 0x00000008 17 | ssh_FILEXFER_ATTR_EXTENDED = 0x80000000 18 | ) 19 | 20 | // fileInfo is an artificial type designed to satisfy os.FileInfo. 21 | type fileInfo struct { 22 | name string 23 | size int64 24 | mode os.FileMode 25 | mtime time.Time 26 | sys interface{} 27 | } 28 | 29 | // Name returns the base name of the file. 30 | func (fi *fileInfo) Name() string { return fi.name } 31 | 32 | // Size returns the length in bytes for regular files; system-dependent for others. 33 | func (fi *fileInfo) Size() int64 { return fi.size } 34 | 35 | // Mode returns file mode bits. 36 | func (fi *fileInfo) Mode() os.FileMode { return fi.mode } 37 | 38 | // ModTime returns the last modification time of the file. 39 | func (fi *fileInfo) ModTime() time.Time { return fi.mtime } 40 | 41 | // IsDir returns true if the file is a directory. 42 | func (fi *fileInfo) IsDir() bool { return fi.Mode().IsDir() } 43 | 44 | func (fi *fileInfo) Sys() interface{} { return fi.sys } 45 | 46 | // FileStat holds the original unmarshalled values from a call to READDIR or *STAT. 47 | // It is exported for the purposes of accessing the raw values via os.FileInfo.Sys() 48 | type FileStat struct { 49 | Size uint64 50 | Mode uint32 51 | Mtime uint32 52 | Atime uint32 53 | Uid uint32 54 | Gid uint32 55 | Extended []StatExtended 56 | } 57 | 58 | type StatExtended struct { 59 | ExtType string 60 | ExtData string 61 | } 62 | 63 | func fileInfoFromStat(st *FileStat, name string) os.FileInfo { 64 | fs := &fileInfo{ 65 | name: name, 66 | size: int64(st.Size), 67 | mode: toFileMode(st.Mode), 68 | mtime: time.Unix(int64(st.Mtime), 0), 69 | sys: st, 70 | } 71 | return fs 72 | } 73 | 74 | func unmarshalAttrs(b []byte) (*FileStat, []byte) { 75 | flags, b := unmarshalUint32(b) 76 | var fs FileStat 77 | if flags&ssh_FILEXFER_ATTR_SIZE == ssh_FILEXFER_ATTR_SIZE { 78 | fs.Size, b = unmarshalUint64(b) 79 | } 80 | if flags&ssh_FILEXFER_ATTR_UIDGID == ssh_FILEXFER_ATTR_UIDGID { 81 | fs.Uid, b = unmarshalUint32(b) 82 | } 83 | if flags&ssh_FILEXFER_ATTR_UIDGID == ssh_FILEXFER_ATTR_UIDGID { 84 | fs.Gid, b = unmarshalUint32(b) 85 | } 86 | if flags&ssh_FILEXFER_ATTR_PERMISSIONS == ssh_FILEXFER_ATTR_PERMISSIONS { 87 | fs.Mode, b = unmarshalUint32(b) 88 | } 89 | if flags&ssh_FILEXFER_ATTR_ACMODTIME == ssh_FILEXFER_ATTR_ACMODTIME { 90 | fs.Atime, b = unmarshalUint32(b) 91 | fs.Mtime, b = unmarshalUint32(b) 92 | } 93 | if flags&ssh_FILEXFER_ATTR_EXTENDED == ssh_FILEXFER_ATTR_EXTENDED { 94 | var count uint32 95 | count, b = unmarshalUint32(b) 96 | ext := make([]StatExtended, count, count) 97 | for i := uint32(0); i < count; i++ { 98 | var typ string 99 | var data string 100 | typ, b = unmarshalString(b) 101 | data, b = unmarshalString(b) 102 | ext[i] = StatExtended{typ, data} 103 | } 104 | fs.Extended = ext 105 | } 106 | return &fs, b 107 | } 108 | 109 | // toFileMode converts sftp filemode bits to the os.FileMode specification 110 | func toFileMode(mode uint32) os.FileMode { 111 | var fm = os.FileMode(mode & 0777) 112 | switch mode & syscall.S_IFMT { 113 | case syscall.S_IFBLK: 114 | fm |= os.ModeDevice 115 | case syscall.S_IFCHR: 116 | fm |= os.ModeDevice | os.ModeCharDevice 117 | case syscall.S_IFDIR: 118 | fm |= os.ModeDir 119 | case syscall.S_IFIFO: 120 | fm |= os.ModeNamedPipe 121 | case syscall.S_IFLNK: 122 | fm |= os.ModeSymlink 123 | case syscall.S_IFREG: 124 | // nothing to do 125 | case syscall.S_IFSOCK: 126 | fm |= os.ModeSocket 127 | } 128 | if mode&syscall.S_ISGID != 0 { 129 | fm |= os.ModeSetgid 130 | } 131 | if mode&syscall.S_ISUID != 0 { 132 | fm |= os.ModeSetuid 133 | } 134 | if mode&syscall.S_ISVTX != 0 { 135 | fm |= os.ModeSticky 136 | } 137 | return fm 138 | } 139 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/attrs_test.go: -------------------------------------------------------------------------------- 1 | package sftp 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | "reflect" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | // ensure that attrs implemenst os.FileInfo 12 | var _ os.FileInfo = new(fileInfo) 13 | 14 | var unmarshalAttrsTests = []struct { 15 | b []byte 16 | want *fileInfo 17 | rest []byte 18 | }{ 19 | {marshal(nil, struct{ Flags uint32 }{}), &fileInfo{mtime: time.Unix(int64(0), 0)}, nil}, 20 | {marshal(nil, struct { 21 | Flags uint32 22 | Size uint64 23 | }{ssh_FILEXFER_ATTR_SIZE, 20}), &fileInfo{size: 20, mtime: time.Unix(int64(0), 0)}, nil}, 24 | {marshal(nil, struct { 25 | Flags uint32 26 | Size uint64 27 | Permissions uint32 28 | }{ssh_FILEXFER_ATTR_SIZE | ssh_FILEXFER_ATTR_PERMISSIONS, 20, 0644}), &fileInfo{size: 20, mode: os.FileMode(0644), mtime: time.Unix(int64(0), 0)}, nil}, 29 | {marshal(nil, struct { 30 | Flags uint32 31 | Size uint64 32 | Uid, Gid, Permissions uint32 33 | }{ssh_FILEXFER_ATTR_SIZE | ssh_FILEXFER_ATTR_UIDGID | ssh_FILEXFER_ATTR_UIDGID | ssh_FILEXFER_ATTR_PERMISSIONS, 20, 1000, 1000, 0644}), &fileInfo{size: 20, mode: os.FileMode(0644), mtime: time.Unix(int64(0), 0)}, nil}, 34 | } 35 | 36 | func TestUnmarshalAttrs(t *testing.T) { 37 | for _, tt := range unmarshalAttrsTests { 38 | stat, rest := unmarshalAttrs(tt.b) 39 | got := fileInfoFromStat(stat, "") 40 | tt.want.sys = got.Sys() 41 | if !reflect.DeepEqual(got, tt.want) || !bytes.Equal(tt.rest, rest) { 42 | t.Errorf("unmarshalAttrs(%#v): want %#v, %#v, got: %#v, %#v", tt.b, tt.want, tt.rest, got, rest) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/client_test.go: -------------------------------------------------------------------------------- 1 | package sftp 2 | 3 | import ( 4 | "io" 5 | "os" 6 | "testing" 7 | 8 | "github.com/kr/fs" 9 | ) 10 | 11 | // assert that *Client implements fs.FileSystem 12 | var _ fs.FileSystem = new(Client) 13 | 14 | // assert that *File implements io.ReadWriteCloser 15 | var _ io.ReadWriteCloser = new(File) 16 | 17 | var ok = &StatusError{Code: ssh_FX_OK} 18 | var eof = &StatusError{Code: ssh_FX_EOF} 19 | var fail = &StatusError{Code: ssh_FX_FAILURE} 20 | 21 | var eofOrErrTests = []struct { 22 | err, want error 23 | }{ 24 | {nil, nil}, 25 | {eof, io.EOF}, 26 | {ok, ok}, 27 | {io.EOF, io.EOF}, 28 | } 29 | 30 | func TestEofOrErr(t *testing.T) { 31 | for _, tt := range eofOrErrTests { 32 | got := eofOrErr(tt.err) 33 | if got != tt.want { 34 | t.Errorf("eofOrErr(%#v): want: %#v, got: %#v", tt.err, tt.want, got) 35 | } 36 | } 37 | } 38 | 39 | var okOrErrTests = []struct { 40 | err, want error 41 | }{ 42 | {nil, nil}, 43 | {eof, eof}, 44 | {ok, nil}, 45 | {io.EOF, io.EOF}, 46 | } 47 | 48 | func TestOkOrErr(t *testing.T) { 49 | for _, tt := range okOrErrTests { 50 | got := okOrErr(tt.err) 51 | if got != tt.want { 52 | t.Errorf("okOrErr(%#v): want: %#v, got: %#v", tt.err, tt.want, got) 53 | } 54 | } 55 | } 56 | 57 | var flagsTests = []struct { 58 | flags int 59 | want uint32 60 | }{ 61 | {os.O_RDONLY, ssh_FXF_READ}, 62 | {os.O_WRONLY, ssh_FXF_WRITE}, 63 | {os.O_RDWR, ssh_FXF_READ | ssh_FXF_WRITE}, 64 | {os.O_RDWR | os.O_CREATE | os.O_TRUNC, ssh_FXF_READ | ssh_FXF_WRITE | ssh_FXF_CREAT | ssh_FXF_TRUNC}, 65 | {os.O_WRONLY | os.O_APPEND, ssh_FXF_WRITE | ssh_FXF_APPEND}, 66 | } 67 | 68 | func TestFlags(t *testing.T) { 69 | for i, tt := range flagsTests { 70 | got := flags(tt.flags) 71 | if got != tt.want { 72 | t.Errorf("test %v: flags(%x): want: %x, got: %x", i, tt.flags, tt.want, got) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/debug.go: -------------------------------------------------------------------------------- 1 | // +build debug 2 | 3 | package sftp 4 | 5 | import "log" 6 | 7 | func debug(fmt string, args ...interface{}) { 8 | log.Printf(fmt, args...) 9 | } 10 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/example_test.go: -------------------------------------------------------------------------------- 1 | package sftp_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "os/exec" 8 | 9 | "golang.org/x/crypto/ssh" 10 | 11 | "github.com/pkg/sftp" 12 | ) 13 | 14 | func Example(conn *ssh.Client) { 15 | // open an SFTP session over an existing ssh connection. 16 | sftp, err := sftp.NewClient(conn) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | defer sftp.Close() 21 | 22 | // walk a directory 23 | w := sftp.Walk("/home/user") 24 | for w.Step() { 25 | if w.Err() != nil { 26 | continue 27 | } 28 | log.Println(w.Path()) 29 | } 30 | 31 | // leave your mark 32 | f, err := sftp.Create("hello.txt") 33 | if err != nil { 34 | log.Fatal(err) 35 | } 36 | if _, err := f.Write([]byte("Hello world!")); err != nil { 37 | log.Fatal(err) 38 | } 39 | 40 | // check it's there 41 | fi, err := sftp.Lstat("hello.txt") 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | log.Println(fi) 46 | } 47 | 48 | func ExampleNewClientPipe() { 49 | // Connect to a remote host and request the sftp subsystem via the 'ssh' 50 | // command. This assumes that passwordless login is correctly configured. 51 | cmd := exec.Command("ssh", "example.com", "-s", "sftp") 52 | 53 | // send errors from ssh to stderr 54 | cmd.Stderr = os.Stderr 55 | 56 | // get stdin and stdout 57 | wr, err := cmd.StdinPipe() 58 | if err != nil { 59 | log.Fatal(err) 60 | } 61 | rd, err := cmd.StdoutPipe() 62 | if err != nil { 63 | log.Fatal(err) 64 | } 65 | 66 | // start the process 67 | if err := cmd.Start(); err != nil { 68 | log.Fatal(err) 69 | } 70 | defer cmd.Wait() 71 | 72 | // open the SFTP session 73 | client, err := sftp.NewClientPipe(rd, wr) 74 | if err != nil { 75 | log.Fatal(err) 76 | } 77 | 78 | // read a directory 79 | list, err := client.ReadDir("/") 80 | if err != nil { 81 | log.Fatal(err) 82 | } 83 | 84 | // print contents 85 | for _, item := range list { 86 | fmt.Println(item.Name()) 87 | } 88 | 89 | // close the connection 90 | client.Close() 91 | } 92 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/examples/buffered-read-benchmark/main.go: -------------------------------------------------------------------------------- 1 | // buffered-read-benchmark benchmarks the peformance of reading 2 | // from /dev/zero on the server to a []byte on the client via io.Copy. 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "net" 11 | "os" 12 | "time" 13 | 14 | "golang.org/x/crypto/ssh" 15 | "golang.org/x/crypto/ssh/agent" 16 | 17 | "github.com/pkg/sftp" 18 | ) 19 | 20 | var ( 21 | USER = flag.String("user", os.Getenv("USER"), "ssh username") 22 | HOST = flag.String("host", "localhost", "ssh server hostname") 23 | PORT = flag.Int("port", 22, "ssh server port") 24 | PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") 25 | SIZE = flag.Int("s", 1<<15, "set max packet size") 26 | ) 27 | 28 | func init() { 29 | flag.Parse() 30 | } 31 | 32 | func main() { 33 | var auths []ssh.AuthMethod 34 | if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { 35 | auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) 36 | 37 | } 38 | if *PASS != "" { 39 | auths = append(auths, ssh.Password(*PASS)) 40 | } 41 | 42 | config := ssh.ClientConfig{ 43 | User: *USER, 44 | Auth: auths, 45 | } 46 | addr := fmt.Sprintf("%s:%d", *HOST, *PORT) 47 | conn, err := ssh.Dial("tcp", addr, &config) 48 | if err != nil { 49 | log.Fatalf("unable to connect to [%s]: %v", addr, err) 50 | } 51 | defer conn.Close() 52 | 53 | c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) 54 | if err != nil { 55 | log.Fatalf("unable to start sftp subsytem: %v", err) 56 | } 57 | defer c.Close() 58 | 59 | r, err := c.Open("/dev/zero") 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | defer r.Close() 64 | 65 | const size = 1e9 66 | 67 | log.Printf("reading %v bytes", size) 68 | t1 := time.Now() 69 | n, err := io.ReadFull(r, make([]byte, size)) 70 | if err != nil { 71 | log.Fatal(err) 72 | } 73 | if n != size { 74 | log.Fatalf("copy: expected %v bytes, got %d", size, n) 75 | } 76 | log.Printf("read %v bytes in %s", size, time.Since(t1)) 77 | } 78 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/examples/buffered-write-benchmark/main.go: -------------------------------------------------------------------------------- 1 | // buffered-write-benchmark benchmarks the peformance of writing 2 | // a single large []byte on the client to /dev/null on the server via io.Copy. 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "log" 9 | "net" 10 | "os" 11 | "syscall" 12 | "time" 13 | 14 | "golang.org/x/crypto/ssh" 15 | "golang.org/x/crypto/ssh/agent" 16 | 17 | "github.com/pkg/sftp" 18 | ) 19 | 20 | var ( 21 | USER = flag.String("user", os.Getenv("USER"), "ssh username") 22 | HOST = flag.String("host", "localhost", "ssh server hostname") 23 | PORT = flag.Int("port", 22, "ssh server port") 24 | PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") 25 | SIZE = flag.Int("s", 1<<15, "set max packet size") 26 | ) 27 | 28 | func init() { 29 | flag.Parse() 30 | } 31 | 32 | func main() { 33 | var auths []ssh.AuthMethod 34 | if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { 35 | auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) 36 | 37 | } 38 | if *PASS != "" { 39 | auths = append(auths, ssh.Password(*PASS)) 40 | } 41 | 42 | config := ssh.ClientConfig{ 43 | User: *USER, 44 | Auth: auths, 45 | } 46 | addr := fmt.Sprintf("%s:%d", *HOST, *PORT) 47 | conn, err := ssh.Dial("tcp", addr, &config) 48 | if err != nil { 49 | log.Fatalf("unable to connect to [%s]: %v", addr, err) 50 | } 51 | defer conn.Close() 52 | 53 | c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) 54 | if err != nil { 55 | log.Fatalf("unable to start sftp subsytem: %v", err) 56 | } 57 | defer c.Close() 58 | 59 | w, err := c.OpenFile("/dev/null", syscall.O_WRONLY) 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | defer w.Close() 64 | 65 | f, err := os.Open("/dev/zero") 66 | if err != nil { 67 | log.Fatal(err) 68 | } 69 | defer f.Close() 70 | 71 | const size = 1e9 72 | 73 | log.Printf("writing %v bytes", size) 74 | t1 := time.Now() 75 | n, err := w.Write(make([]byte, size)) 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | if n != size { 80 | log.Fatalf("copy: expected %v bytes, got %d", size, n) 81 | } 82 | log.Printf("wrote %v bytes in %s", size, time.Since(t1)) 83 | } 84 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/examples/streaming-read-benchmark/main.go: -------------------------------------------------------------------------------- 1 | // streaming-read-benchmark benchmarks the peformance of reading 2 | // from /dev/zero on the server to /dev/null on the client via io.Copy. 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "net" 11 | "os" 12 | "syscall" 13 | "time" 14 | 15 | "golang.org/x/crypto/ssh" 16 | "golang.org/x/crypto/ssh/agent" 17 | 18 | "github.com/pkg/sftp" 19 | ) 20 | 21 | var ( 22 | USER = flag.String("user", os.Getenv("USER"), "ssh username") 23 | HOST = flag.String("host", "localhost", "ssh server hostname") 24 | PORT = flag.Int("port", 22, "ssh server port") 25 | PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") 26 | SIZE = flag.Int("s", 1<<15, "set max packet size") 27 | ) 28 | 29 | func init() { 30 | flag.Parse() 31 | } 32 | 33 | func main() { 34 | var auths []ssh.AuthMethod 35 | if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { 36 | auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) 37 | 38 | } 39 | if *PASS != "" { 40 | auths = append(auths, ssh.Password(*PASS)) 41 | } 42 | 43 | config := ssh.ClientConfig{ 44 | User: *USER, 45 | Auth: auths, 46 | } 47 | addr := fmt.Sprintf("%s:%d", *HOST, *PORT) 48 | conn, err := ssh.Dial("tcp", addr, &config) 49 | if err != nil { 50 | log.Fatalf("unable to connect to [%s]: %v", addr, err) 51 | } 52 | defer conn.Close() 53 | 54 | c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) 55 | if err != nil { 56 | log.Fatalf("unable to start sftp subsytem: %v", err) 57 | } 58 | defer c.Close() 59 | 60 | r, err := c.Open("/dev/zero") 61 | if err != nil { 62 | log.Fatal(err) 63 | } 64 | defer r.Close() 65 | 66 | w, err := os.OpenFile("/dev/null", syscall.O_WRONLY, 0600) 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | defer w.Close() 71 | 72 | const size int64 = 1e9 73 | 74 | log.Printf("reading %v bytes", size) 75 | t1 := time.Now() 76 | n, err := io.Copy(w, io.LimitReader(r, size)) 77 | if err != nil { 78 | log.Fatal(err) 79 | } 80 | if n != size { 81 | log.Fatalf("copy: expected %v bytes, got %d", size, n) 82 | } 83 | log.Printf("read %v bytes in %s", size, time.Since(t1)) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/examples/streaming-write-benchmark/main.go: -------------------------------------------------------------------------------- 1 | // streaming-write-benchmark benchmarks the peformance of writing 2 | // from /dev/zero on the client to /dev/null on the server via io.Copy. 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "net" 11 | "os" 12 | "syscall" 13 | "time" 14 | 15 | "golang.org/x/crypto/ssh" 16 | "golang.org/x/crypto/ssh/agent" 17 | 18 | "github.com/pkg/sftp" 19 | ) 20 | 21 | var ( 22 | USER = flag.String("user", os.Getenv("USER"), "ssh username") 23 | HOST = flag.String("host", "localhost", "ssh server hostname") 24 | PORT = flag.Int("port", 22, "ssh server port") 25 | PASS = flag.String("pass", os.Getenv("SOCKSIE_SSH_PASSWORD"), "ssh password") 26 | SIZE = flag.Int("s", 1<<15, "set max packet size") 27 | ) 28 | 29 | func init() { 30 | flag.Parse() 31 | } 32 | 33 | func main() { 34 | var auths []ssh.AuthMethod 35 | if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { 36 | auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers)) 37 | 38 | } 39 | if *PASS != "" { 40 | auths = append(auths, ssh.Password(*PASS)) 41 | } 42 | 43 | config := ssh.ClientConfig{ 44 | User: *USER, 45 | Auth: auths, 46 | } 47 | addr := fmt.Sprintf("%s:%d", *HOST, *PORT) 48 | conn, err := ssh.Dial("tcp", addr, &config) 49 | if err != nil { 50 | log.Fatalf("unable to connect to [%s]: %v", addr, err) 51 | } 52 | defer conn.Close() 53 | 54 | c, err := sftp.NewClient(conn, sftp.MaxPacket(*SIZE)) 55 | if err != nil { 56 | log.Fatalf("unable to start sftp subsytem: %v", err) 57 | } 58 | defer c.Close() 59 | 60 | w, err := c.OpenFile("/dev/null", syscall.O_WRONLY) 61 | if err != nil { 62 | log.Fatal(err) 63 | } 64 | defer w.Close() 65 | 66 | f, err := os.Open("/dev/zero") 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | defer f.Close() 71 | 72 | const size int64 = 1e9 73 | 74 | log.Printf("writing %v bytes", size) 75 | t1 := time.Now() 76 | n, err := io.Copy(w, io.LimitReader(f, size)) 77 | if err != nil { 78 | log.Fatal(err) 79 | } 80 | if n != size { 81 | log.Fatalf("copy: expected %v bytes, got %d", size, n) 82 | } 83 | log.Printf("wrote %v bytes in %s", size, time.Since(t1)) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/packet_test.go: -------------------------------------------------------------------------------- 1 | package sftp 2 | 3 | import ( 4 | "bytes" 5 | "encoding" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | var marshalUint32Tests = []struct { 11 | v uint32 12 | want []byte 13 | }{ 14 | {1, []byte{0, 0, 0, 1}}, 15 | {256, []byte{0, 0, 1, 0}}, 16 | {^uint32(0), []byte{255, 255, 255, 255}}, 17 | } 18 | 19 | func TestMarshalUint32(t *testing.T) { 20 | for _, tt := range marshalUint32Tests { 21 | got := marshalUint32(nil, tt.v) 22 | if !bytes.Equal(tt.want, got) { 23 | t.Errorf("marshalUint32(%d): want %v, got %v", tt.v, tt.want, got) 24 | } 25 | } 26 | } 27 | 28 | var marshalUint64Tests = []struct { 29 | v uint64 30 | want []byte 31 | }{ 32 | {1, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}}, 33 | {256, []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0}}, 34 | {^uint64(0), []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, 35 | {1 << 32, []byte{0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0}}, 36 | } 37 | 38 | func TestMarshalUint64(t *testing.T) { 39 | for _, tt := range marshalUint64Tests { 40 | got := marshalUint64(nil, tt.v) 41 | if !bytes.Equal(tt.want, got) { 42 | t.Errorf("marshalUint64(%d): want %#v, got %#v", tt.v, tt.want, got) 43 | } 44 | } 45 | } 46 | 47 | var marshalStringTests = []struct { 48 | v string 49 | want []byte 50 | }{ 51 | {"", []byte{0, 0, 0, 0}}, 52 | {"/foo", []byte{0x0, 0x0, 0x0, 0x4, 0x2f, 0x66, 0x6f, 0x6f}}, 53 | } 54 | 55 | func TestMarshalString(t *testing.T) { 56 | for _, tt := range marshalStringTests { 57 | got := marshalString(nil, tt.v) 58 | if !bytes.Equal(tt.want, got) { 59 | t.Errorf("marshalString(%q): want %#v, got %#v", tt.v, tt.want, got) 60 | } 61 | } 62 | } 63 | 64 | var marshalTests = []struct { 65 | v interface{} 66 | want []byte 67 | }{ 68 | {uint8(1), []byte{1}}, 69 | {byte(1), []byte{1}}, 70 | {uint32(1), []byte{0, 0, 0, 1}}, 71 | {uint64(1), []byte{0, 0, 0, 0, 0, 0, 0, 1}}, 72 | {"foo", []byte{0x0, 0x0, 0x0, 0x3, 0x66, 0x6f, 0x6f}}, 73 | {[]uint32{1, 2, 3, 4}, []byte{0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x4}}, 74 | } 75 | 76 | func TestMarshal(t *testing.T) { 77 | for _, tt := range marshalTests { 78 | got := marshal(nil, tt.v) 79 | if !bytes.Equal(tt.want, got) { 80 | t.Errorf("marshal(%v): want %#v, got %#v", tt.v, tt.want, got) 81 | } 82 | } 83 | } 84 | 85 | var unmarshalUint32Tests = []struct { 86 | b []byte 87 | want uint32 88 | rest []byte 89 | }{ 90 | {[]byte{0, 0, 0, 0}, 0, nil}, 91 | {[]byte{0, 0, 1, 0}, 256, nil}, 92 | {[]byte{255, 0, 0, 255}, 4278190335, nil}, 93 | } 94 | 95 | func TestUnmarshalUint32(t *testing.T) { 96 | for _, tt := range unmarshalUint32Tests { 97 | got, rest := unmarshalUint32(tt.b) 98 | if got != tt.want || !bytes.Equal(rest, tt.rest) { 99 | t.Errorf("unmarshalUint32(%v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest) 100 | } 101 | } 102 | } 103 | 104 | var unmarshalUint64Tests = []struct { 105 | b []byte 106 | want uint64 107 | rest []byte 108 | }{ 109 | {[]byte{0, 0, 0, 0, 0, 0, 0, 0}, 0, nil}, 110 | {[]byte{0, 0, 0, 0, 0, 0, 1, 0}, 256, nil}, 111 | {[]byte{255, 0, 0, 0, 0, 0, 0, 255}, 18374686479671623935, nil}, 112 | } 113 | 114 | func TestUnmarshalUint64(t *testing.T) { 115 | for _, tt := range unmarshalUint64Tests { 116 | got, rest := unmarshalUint64(tt.b) 117 | if got != tt.want || !bytes.Equal(rest, tt.rest) { 118 | t.Errorf("unmarshalUint64(%v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest) 119 | } 120 | } 121 | } 122 | 123 | var unmarshalStringTests = []struct { 124 | b []byte 125 | want string 126 | rest []byte 127 | }{ 128 | {marshalString(nil, ""), "", nil}, 129 | {marshalString(nil, "blah"), "blah", nil}, 130 | } 131 | 132 | func TestUnmarshalString(t *testing.T) { 133 | for _, tt := range unmarshalStringTests { 134 | got, rest := unmarshalString(tt.b) 135 | if got != tt.want || !bytes.Equal(rest, tt.rest) { 136 | t.Errorf("unmarshalUint64(%v): want %q, %#v, got %q, %#v", tt.b, tt.want, tt.rest, got, rest) 137 | } 138 | } 139 | } 140 | 141 | var sendPacketTests = []struct { 142 | p encoding.BinaryMarshaler 143 | want []byte 144 | }{ 145 | {sshFxInitPacket{ 146 | Version: 3, 147 | Extensions: []struct{ Name, Data string }{ 148 | {"posix-rename@openssh.com", "1"}, 149 | }, 150 | }, []byte{0x0, 0x0, 0x0, 0x26, 0x1, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x70, 0x6f, 0x73, 0x69, 0x78, 0x2d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x0, 0x1, 0x31}}, 151 | 152 | {sshFxpOpenPacket{ 153 | Id: 1, 154 | Path: "/foo", 155 | Pflags: flags(os.O_RDONLY), 156 | }, []byte{0x0, 0x0, 0x0, 0x15, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x4, 0x2f, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0}}, 157 | 158 | {sshFxpWritePacket{ 159 | Id: 124, 160 | Handle: "foo", 161 | Offset: 13, 162 | Length: uint32(len([]byte("bar"))), 163 | Data: []byte("bar"), 164 | }, []byte{0x0, 0x0, 0x0, 0x1b, 0x6, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x3, 0x66, 0x6f, 0x6f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x3, 0x62, 0x61, 0x72}}, 165 | 166 | {sshFxpSetstatPacket{ 167 | Id: 31, 168 | Path: "/bar", 169 | Flags: flags(os.O_WRONLY), 170 | Attrs: struct { 171 | Uid uint32 172 | Gid uint32 173 | }{1000, 100}, 174 | }, []byte{0x0, 0x0, 0x0, 0x19, 0x9, 0x0, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x0, 0x4, 0x2f, 0x62, 0x61, 0x72, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x3, 0xe8, 0x0, 0x0, 0x0, 0x64}}, 175 | } 176 | 177 | func TestSendPacket(t *testing.T) { 178 | for _, tt := range sendPacketTests { 179 | var w bytes.Buffer 180 | sendPacket(&w, tt.p) 181 | if got := w.Bytes(); !bytes.Equal(tt.want, got) { 182 | t.Errorf("sendPacket(%v): want %#v, got %#v", tt.p, tt.want, got) 183 | } 184 | } 185 | } 186 | 187 | func sp(p encoding.BinaryMarshaler) []byte { 188 | var w bytes.Buffer 189 | sendPacket(&w, p) 190 | return w.Bytes() 191 | } 192 | 193 | var recvPacketTests = []struct { 194 | b []byte 195 | want uint8 196 | rest []byte 197 | }{ 198 | {sp(sshFxInitPacket{ 199 | Version: 3, 200 | Extensions: []struct{ Name, Data string }{ 201 | {"posix-rename@openssh.com", "1"}, 202 | }, 203 | }), ssh_FXP_INIT, []byte{0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x18, 0x70, 0x6f, 0x73, 0x69, 0x78, 0x2d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x0, 0x1, 0x31}}, 204 | } 205 | 206 | func TestRecvPacket(t *testing.T) { 207 | for _, tt := range recvPacketTests { 208 | r := bytes.NewReader(tt.b) 209 | got, rest, _ := recvPacket(r) 210 | if got != tt.want || !bytes.Equal(rest, tt.rest) { 211 | t.Errorf("recvPacket(%#v): want %v, %#v, got %v, %#v", tt.b, tt.want, tt.rest, got, rest) 212 | } 213 | } 214 | } 215 | 216 | func BenchmarkMarshalInit(b *testing.B) { 217 | for i := 0; i < b.N; i++ { 218 | sp(sshFxInitPacket{ 219 | Version: 3, 220 | Extensions: []struct{ Name, Data string }{ 221 | {"posix-rename@openssh.com", "1"}, 222 | }, 223 | }) 224 | } 225 | } 226 | 227 | func BenchmarkMarshalOpen(b *testing.B) { 228 | for i := 0; i < b.N; i++ { 229 | sp(sshFxpOpenPacket{ 230 | Id: 1, 231 | Path: "/home/test/some/random/path", 232 | Pflags: flags(os.O_RDONLY), 233 | }) 234 | } 235 | } 236 | 237 | func BenchmarkMarshalWriteWorstCase(b *testing.B) { 238 | data := make([]byte, 32*1024) 239 | for i := 0; i < b.N; i++ { 240 | sp(sshFxpWritePacket{ 241 | Id: 1, 242 | Handle: "someopaquehandle", 243 | Offset: 0, 244 | Length: uint32(len(data)), 245 | Data: data, 246 | }) 247 | } 248 | } 249 | 250 | func BenchmarkMarshalWrite1k(b *testing.B) { 251 | data := make([]byte, 1024) 252 | for i := 0; i < b.N; i++ { 253 | sp(sshFxpWritePacket{ 254 | Id: 1, 255 | Handle: "someopaquehandle", 256 | Offset: 0, 257 | Length: uint32(len(data)), 258 | Data: data, 259 | }) 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/release.go: -------------------------------------------------------------------------------- 1 | // +build !debug 2 | 3 | package sftp 4 | 5 | func debug(fmt string, args ...interface{}) {} 6 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/sftp.go: -------------------------------------------------------------------------------- 1 | // Package sftp implements the SSH File Transfer Protocol as described in 2 | // https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt 3 | package sftp 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | const ( 10 | ssh_FXP_INIT = 1 11 | ssh_FXP_VERSION = 2 12 | ssh_FXP_OPEN = 3 13 | ssh_FXP_CLOSE = 4 14 | ssh_FXP_READ = 5 15 | ssh_FXP_WRITE = 6 16 | ssh_FXP_LSTAT = 7 17 | ssh_FXP_FSTAT = 8 18 | ssh_FXP_SETSTAT = 9 19 | ssh_FXP_FSETSTAT = 10 20 | ssh_FXP_OPENDIR = 11 21 | ssh_FXP_READDIR = 12 22 | ssh_FXP_REMOVE = 13 23 | ssh_FXP_MKDIR = 14 24 | ssh_FXP_RMDIR = 15 25 | ssh_FXP_REALPATH = 16 26 | ssh_FXP_STAT = 17 27 | ssh_FXP_RENAME = 18 28 | ssh_FXP_READLINK = 19 29 | ssh_FXP_SYMLINK = 20 30 | ssh_FXP_STATUS = 101 31 | ssh_FXP_HANDLE = 102 32 | ssh_FXP_DATA = 103 33 | ssh_FXP_NAME = 104 34 | ssh_FXP_ATTRS = 105 35 | ssh_FXP_EXTENDED = 200 36 | ssh_FXP_EXTENDED_REPLY = 201 37 | ) 38 | 39 | const ( 40 | ssh_FX_OK = 0 41 | ssh_FX_EOF = 1 42 | ssh_FX_NO_SUCH_FILE = 2 43 | ssh_FX_PERMISSION_DENIED = 3 44 | ssh_FX_FAILURE = 4 45 | ssh_FX_BAD_MESSAGE = 5 46 | ssh_FX_NO_CONNECTION = 6 47 | ssh_FX_CONNECTION_LOST = 7 48 | ssh_FX_OP_UNSUPPORTED = 8 49 | ) 50 | 51 | const ( 52 | ssh_FXF_READ = 0x00000001 53 | ssh_FXF_WRITE = 0x00000002 54 | ssh_FXF_APPEND = 0x00000004 55 | ssh_FXF_CREAT = 0x00000008 56 | ssh_FXF_TRUNC = 0x00000010 57 | ssh_FXF_EXCL = 0x00000020 58 | ) 59 | 60 | type fxp uint8 61 | 62 | func (f fxp) String() string { 63 | switch f { 64 | case ssh_FXP_INIT: 65 | return "SSH_FXP_INIT" 66 | case ssh_FXP_VERSION: 67 | return "SSH_FXP_VERSION" 68 | case ssh_FXP_OPEN: 69 | return "SSH_FXP_OPEN" 70 | case ssh_FXP_CLOSE: 71 | return "SSH_FXP_CLOSE" 72 | case ssh_FXP_READ: 73 | return "SSH_FXP_READ" 74 | case ssh_FXP_WRITE: 75 | return "SSH_FXP_WRITE" 76 | case ssh_FXP_LSTAT: 77 | return "SSH_FXP_LSTAT" 78 | case ssh_FXP_FSTAT: 79 | return "SSH_FXP_FSTAT" 80 | case ssh_FXP_SETSTAT: 81 | return "SSH_FXP_SETSTAT" 82 | case ssh_FXP_FSETSTAT: 83 | return "SSH_FXP_FSETSTAT" 84 | case ssh_FXP_OPENDIR: 85 | return "SSH_FXP_OPENDIR" 86 | case ssh_FXP_READDIR: 87 | return "SSH_FXP_READDIR" 88 | case ssh_FXP_REMOVE: 89 | return "SSH_FXP_REMOVE" 90 | case ssh_FXP_MKDIR: 91 | return "SSH_FXP_MKDIR" 92 | case ssh_FXP_RMDIR: 93 | return "SSH_FXP_RMDIR" 94 | case ssh_FXP_REALPATH: 95 | return "SSH_FXP_REALPATH" 96 | case ssh_FXP_STAT: 97 | return "SSH_FXP_STAT" 98 | case ssh_FXP_RENAME: 99 | return "SSH_FXP_RENAME" 100 | case ssh_FXP_READLINK: 101 | return "SSH_FXP_READLINK" 102 | case ssh_FXP_SYMLINK: 103 | return "SSH_FXP_SYMLINK" 104 | case ssh_FXP_STATUS: 105 | return "SSH_FXP_STATUS" 106 | case ssh_FXP_HANDLE: 107 | return "SSH_FXP_HANDLE" 108 | case ssh_FXP_DATA: 109 | return "SSH_FXP_DATA" 110 | case ssh_FXP_NAME: 111 | return "SSH_FXP_NAME" 112 | case ssh_FXP_ATTRS: 113 | return "SSH_FXP_ATTRS" 114 | case ssh_FXP_EXTENDED: 115 | return "SSH_FXP_EXTENDED" 116 | case ssh_FXP_EXTENDED_REPLY: 117 | return "SSH_FXP_EXTENDED_REPLY" 118 | default: 119 | return "unknown" 120 | } 121 | } 122 | 123 | type fx uint8 124 | 125 | func (f fx) String() string { 126 | switch f { 127 | case ssh_FX_OK: 128 | return "SSH_FX_OK" 129 | case ssh_FX_EOF: 130 | return "SSH_FX_EOF" 131 | case ssh_FX_NO_SUCH_FILE: 132 | return "SSH_FX_NO_SUCH_FILE" 133 | case ssh_FX_PERMISSION_DENIED: 134 | return "SSH_FX_PERMISSION_DENIED" 135 | case ssh_FX_FAILURE: 136 | return "SSH_FX_FAILURE" 137 | case ssh_FX_BAD_MESSAGE: 138 | return "SSH_FX_BAD_MESSAGE" 139 | case ssh_FX_NO_CONNECTION: 140 | return "SSH_FX_NO_CONNECTION" 141 | case ssh_FX_CONNECTION_LOST: 142 | return "SSH_FX_CONNECTION_LOST" 143 | case ssh_FX_OP_UNSUPPORTED: 144 | return "SSH_FX_OP_UNSUPPORTED" 145 | default: 146 | return "unknown" 147 | } 148 | } 149 | 150 | type unexpectedPacketErr struct { 151 | want, got uint8 152 | } 153 | 154 | func (u *unexpectedPacketErr) Error() string { 155 | return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got)) 156 | } 157 | 158 | func unimplementedPacketErr(u uint8) error { 159 | return fmt.Errorf("sftp: unimplemented packet type: got %v", fxp(u)) 160 | } 161 | 162 | type unexpectedIdErr struct{ want, got uint32 } 163 | 164 | func (u *unexpectedIdErr) Error() string { 165 | return fmt.Sprintf("sftp: unexpected id: want %v, got %v", u.want, u.got) 166 | } 167 | 168 | func unimplementedSeekWhence(whence int) error { 169 | return fmt.Errorf("sftp: unimplemented seek whence %v", whence) 170 | } 171 | 172 | func unexpectedCount(want, got uint32) error { 173 | return fmt.Errorf("sftp: unexpected count: want %v, got %v", want, got) 174 | } 175 | 176 | type unexpectedVersionErr struct{ want, got uint32 } 177 | 178 | func (u *unexpectedVersionErr) Error() string { 179 | return fmt.Sprintf("sftp: unexpected server version: want %v, got %v", u.want, u.got) 180 | } 181 | 182 | type StatusError struct { 183 | Code uint32 184 | msg, lang string 185 | } 186 | 187 | func (s *StatusError) Error() string { return fmt.Sprintf("sftp: %q (%v)", s.msg, fx(s.Code)) } 188 | -------------------------------------------------------------------------------- /vendor/src/github.com/pkg/sftp/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/golang 2 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/client_test.go: -------------------------------------------------------------------------------- 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 | package agent 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "errors" 11 | "net" 12 | "os" 13 | "os/exec" 14 | "path/filepath" 15 | "strconv" 16 | "testing" 17 | 18 | "golang.org/x/crypto/ssh" 19 | ) 20 | 21 | // startAgent executes ssh-agent, and returns a Agent interface to it. 22 | func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) { 23 | if testing.Short() { 24 | // ssh-agent is not always available, and the key 25 | // types supported vary by platform. 26 | t.Skip("skipping test due to -short") 27 | } 28 | 29 | bin, err := exec.LookPath("ssh-agent") 30 | if err != nil { 31 | t.Skip("could not find ssh-agent") 32 | } 33 | 34 | cmd := exec.Command(bin, "-s") 35 | out, err := cmd.Output() 36 | if err != nil { 37 | t.Fatalf("cmd.Output: %v", err) 38 | } 39 | 40 | /* Output looks like: 41 | 42 | SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; 43 | SSH_AGENT_PID=15542; export SSH_AGENT_PID; 44 | echo Agent pid 15542; 45 | */ 46 | fields := bytes.Split(out, []byte(";")) 47 | line := bytes.SplitN(fields[0], []byte("="), 2) 48 | line[0] = bytes.TrimLeft(line[0], "\n") 49 | if string(line[0]) != "SSH_AUTH_SOCK" { 50 | t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0]) 51 | } 52 | socket = string(line[1]) 53 | 54 | line = bytes.SplitN(fields[2], []byte("="), 2) 55 | line[0] = bytes.TrimLeft(line[0], "\n") 56 | if string(line[0]) != "SSH_AGENT_PID" { 57 | t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2]) 58 | } 59 | pidStr := line[1] 60 | pid, err := strconv.Atoi(string(pidStr)) 61 | if err != nil { 62 | t.Fatalf("Atoi(%q): %v", pidStr, err) 63 | } 64 | 65 | conn, err := net.Dial("unix", string(socket)) 66 | if err != nil { 67 | t.Fatalf("net.Dial: %v", err) 68 | } 69 | 70 | ac := NewClient(conn) 71 | return ac, socket, func() { 72 | proc, _ := os.FindProcess(pid) 73 | if proc != nil { 74 | proc.Kill() 75 | } 76 | conn.Close() 77 | os.RemoveAll(filepath.Dir(socket)) 78 | } 79 | } 80 | 81 | func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate) { 82 | agent, _, cleanup := startAgent(t) 83 | defer cleanup() 84 | 85 | testAgentInterface(t, agent, key, cert) 86 | } 87 | 88 | func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) { 89 | signer, err := ssh.NewSignerFromKey(key) 90 | if err != nil { 91 | t.Fatalf("NewSignerFromKey(%T): %v", key, err) 92 | } 93 | // The agent should start up empty. 94 | if keys, err := agent.List(); err != nil { 95 | t.Fatalf("RequestIdentities: %v", err) 96 | } else if len(keys) > 0 { 97 | t.Fatalf("got %d keys, want 0: %v", len(keys), keys) 98 | } 99 | 100 | // Attempt to insert the key, with certificate if specified. 101 | var pubKey ssh.PublicKey 102 | if cert != nil { 103 | err = agent.Add(key, cert, "comment") 104 | pubKey = cert 105 | } else { 106 | err = agent.Add(key, nil, "comment") 107 | pubKey = signer.PublicKey() 108 | } 109 | if err != nil { 110 | t.Fatalf("insert(%T): %v", key, err) 111 | } 112 | 113 | // Did the key get inserted successfully? 114 | if keys, err := agent.List(); err != nil { 115 | t.Fatalf("List: %v", err) 116 | } else if len(keys) != 1 { 117 | t.Fatalf("got %v, want 1 key", keys) 118 | } else if keys[0].Comment != "comment" { 119 | t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") 120 | } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { 121 | t.Fatalf("key mismatch") 122 | } 123 | 124 | // Can the agent make a valid signature? 125 | data := []byte("hello") 126 | sig, err := agent.Sign(pubKey, data) 127 | if err != nil { 128 | t.Fatalf("Sign(%s): %v", pubKey.Type(), err) 129 | } 130 | 131 | if err := pubKey.Verify(data, sig); err != nil { 132 | t.Fatalf("Verify(%s): %v", pubKey.Type(), err) 133 | } 134 | } 135 | 136 | func TestAgent(t *testing.T) { 137 | for _, keyType := range []string{"rsa", "dsa", "ecdsa"} { 138 | testAgent(t, testPrivateKeys[keyType], nil) 139 | } 140 | } 141 | 142 | func TestCert(t *testing.T) { 143 | cert := &ssh.Certificate{ 144 | Key: testPublicKeys["rsa"], 145 | ValidBefore: ssh.CertTimeInfinity, 146 | CertType: ssh.UserCert, 147 | } 148 | cert.SignCert(rand.Reader, testSigners["ecdsa"]) 149 | 150 | testAgent(t, testPrivateKeys["rsa"], cert) 151 | } 152 | 153 | // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and 154 | // therefore is buffered (net.Pipe deadlocks if both sides start with 155 | // a write.) 156 | func netPipe() (net.Conn, net.Conn, error) { 157 | listener, err := net.Listen("tcp", "127.0.0.1:0") 158 | if err != nil { 159 | return nil, nil, err 160 | } 161 | defer listener.Close() 162 | c1, err := net.Dial("tcp", listener.Addr().String()) 163 | if err != nil { 164 | return nil, nil, err 165 | } 166 | 167 | c2, err := listener.Accept() 168 | if err != nil { 169 | c1.Close() 170 | return nil, nil, err 171 | } 172 | 173 | return c1, c2, nil 174 | } 175 | 176 | func TestAuth(t *testing.T) { 177 | a, b, err := netPipe() 178 | if err != nil { 179 | t.Fatalf("netPipe: %v", err) 180 | } 181 | 182 | defer a.Close() 183 | defer b.Close() 184 | 185 | agent, _, cleanup := startAgent(t) 186 | defer cleanup() 187 | 188 | if err := agent.Add(testPrivateKeys["rsa"], nil, "comment"); err != nil { 189 | t.Errorf("Add: %v", err) 190 | } 191 | 192 | serverConf := ssh.ServerConfig{} 193 | serverConf.AddHostKey(testSigners["rsa"]) 194 | serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { 195 | if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { 196 | return nil, nil 197 | } 198 | 199 | return nil, errors.New("pubkey rejected") 200 | } 201 | 202 | go func() { 203 | conn, _, _, err := ssh.NewServerConn(a, &serverConf) 204 | if err != nil { 205 | t.Fatalf("Server: %v", err) 206 | } 207 | conn.Close() 208 | }() 209 | 210 | conf := ssh.ClientConfig{} 211 | conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) 212 | conn, _, _, err := ssh.NewClientConn(b, "", &conf) 213 | if err != nil { 214 | t.Fatalf("NewClientConn: %v", err) 215 | } 216 | conn.Close() 217 | } 218 | 219 | func TestLockClient(t *testing.T) { 220 | agent, _, cleanup := startAgent(t) 221 | defer cleanup() 222 | testLockAgent(agent, t) 223 | } 224 | 225 | func testLockAgent(agent Agent, t *testing.T) { 226 | if err := agent.Add(testPrivateKeys["rsa"], nil, "comment 1"); err != nil { 227 | t.Errorf("Add: %v", err) 228 | } 229 | if err := agent.Add(testPrivateKeys["dsa"], nil, "comment dsa"); err != nil { 230 | t.Errorf("Add: %v", err) 231 | } 232 | if keys, err := agent.List(); err != nil { 233 | t.Errorf("List: %v", err) 234 | } else if len(keys) != 2 { 235 | t.Errorf("Want 2 keys, got %v", keys) 236 | } 237 | 238 | passphrase := []byte("secret") 239 | if err := agent.Lock(passphrase); err != nil { 240 | t.Errorf("Lock: %v", err) 241 | } 242 | 243 | if keys, err := agent.List(); err != nil { 244 | t.Errorf("List: %v", err) 245 | } else if len(keys) != 0 { 246 | t.Errorf("Want 0 keys, got %v", keys) 247 | } 248 | 249 | signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"]) 250 | if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil { 251 | t.Fatalf("Sign did not fail") 252 | } 253 | 254 | if err := agent.Remove(signer.PublicKey()); err == nil { 255 | t.Fatalf("Remove did not fail") 256 | } 257 | 258 | if err := agent.RemoveAll(); err == nil { 259 | t.Fatalf("RemoveAll did not fail") 260 | } 261 | 262 | if err := agent.Unlock(nil); err == nil { 263 | t.Errorf("Unlock with wrong passphrase succeeded") 264 | } 265 | if err := agent.Unlock(passphrase); err != nil { 266 | t.Errorf("Unlock: %v", err) 267 | } 268 | 269 | if err := agent.Remove(signer.PublicKey()); err != nil { 270 | t.Fatalf("Remove: %v", err) 271 | } 272 | 273 | if keys, err := agent.List(); err != nil { 274 | t.Errorf("List: %v", err) 275 | } else if len(keys) != 1 { 276 | t.Errorf("Want 1 keys, got %v", keys) 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/forward.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package agent 6 | 7 | import ( 8 | "errors" 9 | "io" 10 | "net" 11 | "sync" 12 | 13 | "golang.org/x/crypto/ssh" 14 | ) 15 | 16 | // RequestAgentForwarding sets up agent forwarding for the session. 17 | // ForwardToAgent or ForwardToRemote should be called to route 18 | // the authentication requests. 19 | func RequestAgentForwarding(session *ssh.Session) error { 20 | ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) 21 | if err != nil { 22 | return err 23 | } 24 | if !ok { 25 | return errors.New("forwarding request denied") 26 | } 27 | return nil 28 | } 29 | 30 | // ForwardToAgent routes authentication requests to the given keyring. 31 | func ForwardToAgent(client *ssh.Client, keyring Agent) error { 32 | channels := client.HandleChannelOpen(channelType) 33 | if channels == nil { 34 | return errors.New("agent: already have handler for " + channelType) 35 | } 36 | 37 | go func() { 38 | for ch := range channels { 39 | channel, reqs, err := ch.Accept() 40 | if err != nil { 41 | continue 42 | } 43 | go ssh.DiscardRequests(reqs) 44 | go func() { 45 | ServeAgent(keyring, channel) 46 | channel.Close() 47 | }() 48 | } 49 | }() 50 | return nil 51 | } 52 | 53 | const channelType = "auth-agent@openssh.com" 54 | 55 | // ForwardToRemote routes authentication requests to the ssh-agent 56 | // process serving on the given unix socket. 57 | func ForwardToRemote(client *ssh.Client, addr string) error { 58 | channels := client.HandleChannelOpen(channelType) 59 | if channels == nil { 60 | return errors.New("agent: already have handler for " + channelType) 61 | } 62 | conn, err := net.Dial("unix", addr) 63 | if err != nil { 64 | return err 65 | } 66 | conn.Close() 67 | 68 | go func() { 69 | for ch := range channels { 70 | channel, reqs, err := ch.Accept() 71 | if err != nil { 72 | continue 73 | } 74 | go ssh.DiscardRequests(reqs) 75 | go forwardUnixSocket(channel, addr) 76 | } 77 | }() 78 | return nil 79 | } 80 | 81 | func forwardUnixSocket(channel ssh.Channel, addr string) { 82 | conn, err := net.Dial("unix", addr) 83 | if err != nil { 84 | return 85 | } 86 | 87 | var wg sync.WaitGroup 88 | wg.Add(2) 89 | go func() { 90 | io.Copy(conn, channel) 91 | conn.(*net.UnixConn).CloseWrite() 92 | wg.Done() 93 | }() 94 | go func() { 95 | io.Copy(channel, conn) 96 | channel.CloseWrite() 97 | wg.Done() 98 | }() 99 | 100 | wg.Wait() 101 | conn.Close() 102 | channel.Close() 103 | } 104 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/keyring.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package agent 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "crypto/subtle" 11 | "errors" 12 | "fmt" 13 | "sync" 14 | 15 | "golang.org/x/crypto/ssh" 16 | ) 17 | 18 | type privKey struct { 19 | signer ssh.Signer 20 | comment string 21 | } 22 | 23 | type keyring struct { 24 | mu sync.Mutex 25 | keys []privKey 26 | 27 | locked bool 28 | passphrase []byte 29 | } 30 | 31 | var errLocked = errors.New("agent: locked") 32 | 33 | // NewKeyring returns an Agent that holds keys in memory. It is safe 34 | // for concurrent use by multiple goroutines. 35 | func NewKeyring() Agent { 36 | return &keyring{} 37 | } 38 | 39 | // RemoveAll removes all identities. 40 | func (r *keyring) RemoveAll() error { 41 | r.mu.Lock() 42 | defer r.mu.Unlock() 43 | if r.locked { 44 | return errLocked 45 | } 46 | 47 | r.keys = nil 48 | return nil 49 | } 50 | 51 | // Remove removes all identities with the given public key. 52 | func (r *keyring) Remove(key ssh.PublicKey) error { 53 | r.mu.Lock() 54 | defer r.mu.Unlock() 55 | if r.locked { 56 | return errLocked 57 | } 58 | 59 | want := key.Marshal() 60 | found := false 61 | for i := 0; i < len(r.keys); { 62 | if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { 63 | found = true 64 | r.keys[i] = r.keys[len(r.keys)-1] 65 | r.keys = r.keys[len(r.keys)-1:] 66 | continue 67 | } else { 68 | i++ 69 | } 70 | } 71 | 72 | if !found { 73 | return errors.New("agent: key not found") 74 | } 75 | return nil 76 | } 77 | 78 | // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. 79 | func (r *keyring) Lock(passphrase []byte) error { 80 | r.mu.Lock() 81 | defer r.mu.Unlock() 82 | if r.locked { 83 | return errLocked 84 | } 85 | 86 | r.locked = true 87 | r.passphrase = passphrase 88 | return nil 89 | } 90 | 91 | // Unlock undoes the effect of Lock 92 | func (r *keyring) Unlock(passphrase []byte) error { 93 | r.mu.Lock() 94 | defer r.mu.Unlock() 95 | if !r.locked { 96 | return errors.New("agent: not locked") 97 | } 98 | if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { 99 | return fmt.Errorf("agent: incorrect passphrase") 100 | } 101 | 102 | r.locked = false 103 | r.passphrase = nil 104 | return nil 105 | } 106 | 107 | // List returns the identities known to the agent. 108 | func (r *keyring) List() ([]*Key, error) { 109 | r.mu.Lock() 110 | defer r.mu.Unlock() 111 | if r.locked { 112 | // section 2.7: locked agents return empty. 113 | return nil, nil 114 | } 115 | 116 | var ids []*Key 117 | for _, k := range r.keys { 118 | pub := k.signer.PublicKey() 119 | ids = append(ids, &Key{ 120 | Format: pub.Type(), 121 | Blob: pub.Marshal(), 122 | Comment: k.comment}) 123 | } 124 | return ids, nil 125 | } 126 | 127 | // Insert adds a private key to the keyring. If a certificate 128 | // is given, that certificate is added as public key. 129 | func (r *keyring) Add(priv interface{}, cert *ssh.Certificate, comment string) error { 130 | r.mu.Lock() 131 | defer r.mu.Unlock() 132 | if r.locked { 133 | return errLocked 134 | } 135 | signer, err := ssh.NewSignerFromKey(priv) 136 | 137 | if err != nil { 138 | return err 139 | } 140 | 141 | if cert != nil { 142 | signer, err = ssh.NewCertSigner(cert, signer) 143 | if err != nil { 144 | return err 145 | } 146 | } 147 | 148 | r.keys = append(r.keys, privKey{signer, comment}) 149 | 150 | return nil 151 | } 152 | 153 | // Sign returns a signature for the data. 154 | func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { 155 | r.mu.Lock() 156 | defer r.mu.Unlock() 157 | if r.locked { 158 | return nil, errLocked 159 | } 160 | 161 | wanted := key.Marshal() 162 | for _, k := range r.keys { 163 | if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { 164 | return k.signer.Sign(rand.Reader, data) 165 | } 166 | } 167 | return nil, errors.New("not found") 168 | } 169 | 170 | // Signers returns signers for all the known keys. 171 | func (r *keyring) Signers() ([]ssh.Signer, error) { 172 | r.mu.Lock() 173 | defer r.mu.Unlock() 174 | if r.locked { 175 | return nil, errLocked 176 | } 177 | 178 | s := make([]ssh.Signer, 0, len(r.keys)) 179 | for _, k := range r.keys { 180 | s = append(s, k.signer) 181 | } 182 | return s, nil 183 | } 184 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/server.go: -------------------------------------------------------------------------------- 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 | package agent 6 | 7 | import ( 8 | "crypto/rsa" 9 | "encoding/binary" 10 | "fmt" 11 | "io" 12 | "log" 13 | "math/big" 14 | 15 | "golang.org/x/crypto/ssh" 16 | ) 17 | 18 | // Server wraps an Agent and uses it to implement the agent side of 19 | // the SSH-agent, wire protocol. 20 | type server struct { 21 | agent Agent 22 | } 23 | 24 | func (s *server) processRequestBytes(reqData []byte) []byte { 25 | rep, err := s.processRequest(reqData) 26 | if err != nil { 27 | if err != errLocked { 28 | // TODO(hanwen): provide better logging interface? 29 | log.Printf("agent %d: %v", reqData[0], err) 30 | } 31 | return []byte{agentFailure} 32 | } 33 | 34 | if err == nil && rep == nil { 35 | return []byte{agentSuccess} 36 | } 37 | 38 | return ssh.Marshal(rep) 39 | } 40 | 41 | func marshalKey(k *Key) []byte { 42 | var record struct { 43 | Blob []byte 44 | Comment string 45 | } 46 | record.Blob = k.Marshal() 47 | record.Comment = k.Comment 48 | 49 | return ssh.Marshal(&record) 50 | } 51 | 52 | type agentV1IdentityMsg struct { 53 | Numkeys uint32 `sshtype:"2"` 54 | } 55 | 56 | type agentRemoveIdentityMsg struct { 57 | KeyBlob []byte `sshtype:"18"` 58 | } 59 | 60 | type agentLockMsg struct { 61 | Passphrase []byte `sshtype:"22"` 62 | } 63 | 64 | type agentUnlockMsg struct { 65 | Passphrase []byte `sshtype:"23"` 66 | } 67 | 68 | func (s *server) processRequest(data []byte) (interface{}, error) { 69 | switch data[0] { 70 | case agentRequestV1Identities: 71 | return &agentV1IdentityMsg{0}, nil 72 | case agentRemoveIdentity: 73 | var req agentRemoveIdentityMsg 74 | if err := ssh.Unmarshal(data, &req); err != nil { 75 | return nil, err 76 | } 77 | 78 | var wk wireKey 79 | if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { 80 | return nil, err 81 | } 82 | 83 | return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) 84 | 85 | case agentRemoveAllIdentities: 86 | return nil, s.agent.RemoveAll() 87 | 88 | case agentLock: 89 | var req agentLockMsg 90 | if err := ssh.Unmarshal(data, &req); err != nil { 91 | return nil, err 92 | } 93 | 94 | return nil, s.agent.Lock(req.Passphrase) 95 | 96 | case agentUnlock: 97 | var req agentLockMsg 98 | if err := ssh.Unmarshal(data, &req); err != nil { 99 | return nil, err 100 | } 101 | return nil, s.agent.Unlock(req.Passphrase) 102 | 103 | case agentSignRequest: 104 | var req signRequestAgentMsg 105 | if err := ssh.Unmarshal(data, &req); err != nil { 106 | return nil, err 107 | } 108 | 109 | var wk wireKey 110 | if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { 111 | return nil, err 112 | } 113 | 114 | k := &Key{ 115 | Format: wk.Format, 116 | Blob: req.KeyBlob, 117 | } 118 | 119 | sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags. 120 | if err != nil { 121 | return nil, err 122 | } 123 | return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil 124 | case agentRequestIdentities: 125 | keys, err := s.agent.List() 126 | if err != nil { 127 | return nil, err 128 | } 129 | 130 | rep := identitiesAnswerAgentMsg{ 131 | NumKeys: uint32(len(keys)), 132 | } 133 | for _, k := range keys { 134 | rep.Keys = append(rep.Keys, marshalKey(k)...) 135 | } 136 | return rep, nil 137 | case agentAddIdentity: 138 | return nil, s.insertIdentity(data) 139 | } 140 | 141 | return nil, fmt.Errorf("unknown opcode %d", data[0]) 142 | } 143 | 144 | func (s *server) insertIdentity(req []byte) error { 145 | var record struct { 146 | Type string `sshtype:"17"` 147 | Rest []byte `ssh:"rest"` 148 | } 149 | if err := ssh.Unmarshal(req, &record); err != nil { 150 | return err 151 | } 152 | 153 | switch record.Type { 154 | case ssh.KeyAlgoRSA: 155 | var k rsaKeyMsg 156 | if err := ssh.Unmarshal(req, &k); err != nil { 157 | return err 158 | } 159 | 160 | priv := rsa.PrivateKey{ 161 | PublicKey: rsa.PublicKey{ 162 | E: int(k.E.Int64()), 163 | N: k.N, 164 | }, 165 | D: k.D, 166 | Primes: []*big.Int{k.P, k.Q}, 167 | } 168 | priv.Precompute() 169 | 170 | return s.agent.Add(&priv, nil, k.Comments) 171 | } 172 | return fmt.Errorf("not implemented: %s", record.Type) 173 | } 174 | 175 | // ServeAgent serves the agent protocol on the given connection. It 176 | // returns when an I/O error occurs. 177 | func ServeAgent(agent Agent, c io.ReadWriter) error { 178 | s := &server{agent} 179 | 180 | var length [4]byte 181 | for { 182 | if _, err := io.ReadFull(c, length[:]); err != nil { 183 | return err 184 | } 185 | l := binary.BigEndian.Uint32(length[:]) 186 | if l > maxAgentResponseBytes { 187 | // We also cap requests. 188 | return fmt.Errorf("agent: request too large: %d", l) 189 | } 190 | 191 | req := make([]byte, l) 192 | if _, err := io.ReadFull(c, req); err != nil { 193 | return err 194 | } 195 | 196 | repData := s.processRequestBytes(req) 197 | if len(repData) > maxAgentResponseBytes { 198 | return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) 199 | } 200 | 201 | binary.BigEndian.PutUint32(length[:], uint32(len(repData))) 202 | if _, err := c.Write(length[:]); err != nil { 203 | return err 204 | } 205 | if _, err := c.Write(repData); err != nil { 206 | return err 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/server_test.go: -------------------------------------------------------------------------------- 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 | package agent 6 | 7 | import ( 8 | "testing" 9 | 10 | "golang.org/x/crypto/ssh" 11 | ) 12 | 13 | func TestServer(t *testing.T) { 14 | c1, c2, err := netPipe() 15 | if err != nil { 16 | t.Fatalf("netPipe: %v", err) 17 | } 18 | defer c1.Close() 19 | defer c2.Close() 20 | client := NewClient(c1) 21 | 22 | go ServeAgent(NewKeyring(), c2) 23 | 24 | testAgentInterface(t, client, testPrivateKeys["rsa"], nil) 25 | } 26 | 27 | func TestLockServer(t *testing.T) { 28 | testLockAgent(NewKeyring(), t) 29 | } 30 | 31 | func TestSetupForwardAgent(t *testing.T) { 32 | a, b, err := netPipe() 33 | if err != nil { 34 | t.Fatalf("netPipe: %v", err) 35 | } 36 | 37 | defer a.Close() 38 | defer b.Close() 39 | 40 | _, socket, cleanup := startAgent(t) 41 | defer cleanup() 42 | 43 | serverConf := ssh.ServerConfig{ 44 | NoClientAuth: true, 45 | } 46 | serverConf.AddHostKey(testSigners["rsa"]) 47 | incoming := make(chan *ssh.ServerConn, 1) 48 | go func() { 49 | conn, _, _, err := ssh.NewServerConn(a, &serverConf) 50 | if err != nil { 51 | t.Fatalf("Server: %v", err) 52 | } 53 | incoming <- conn 54 | }() 55 | 56 | conf := ssh.ClientConfig{} 57 | conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) 58 | if err != nil { 59 | t.Fatalf("NewClientConn: %v", err) 60 | } 61 | client := ssh.NewClient(conn, chans, reqs) 62 | 63 | if err := ForwardToRemote(client, socket); err != nil { 64 | t.Fatalf("SetupForwardAgent: %v", err) 65 | } 66 | 67 | server := <-incoming 68 | ch, reqs, err := server.OpenChannel(channelType, nil) 69 | if err != nil { 70 | t.Fatalf("OpenChannel(%q): %v", channelType, err) 71 | } 72 | go ssh.DiscardRequests(reqs) 73 | 74 | agentClient := NewClient(ch) 75 | testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil) 76 | conn.Close() 77 | } 78 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/agent/testdata_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: 6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three 7 | // instances. 8 | 9 | package agent 10 | 11 | import ( 12 | "crypto/rand" 13 | "fmt" 14 | 15 | "golang.org/x/crypto/ssh" 16 | "golang.org/x/crypto/ssh/testdata" 17 | ) 18 | 19 | var ( 20 | testPrivateKeys map[string]interface{} 21 | testSigners map[string]ssh.Signer 22 | testPublicKeys map[string]ssh.PublicKey 23 | ) 24 | 25 | func init() { 26 | var err error 27 | 28 | n := len(testdata.PEMBytes) 29 | testPrivateKeys = make(map[string]interface{}, n) 30 | testSigners = make(map[string]ssh.Signer, n) 31 | testPublicKeys = make(map[string]ssh.PublicKey, n) 32 | for t, k := range testdata.PEMBytes { 33 | testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) 34 | if err != nil { 35 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) 36 | } 37 | testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) 38 | if err != nil { 39 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) 40 | } 41 | testPublicKeys[t] = testSigners[t].PublicKey() 42 | } 43 | 44 | // Create a cert and sign it for use in tests. 45 | testCert := &ssh.Certificate{ 46 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 47 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage 48 | ValidAfter: 0, // unix epoch 49 | ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. 50 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 51 | Key: testPublicKeys["ecdsa"], 52 | SignatureKey: testPublicKeys["rsa"], 53 | Permissions: ssh.Permissions{ 54 | CriticalOptions: map[string]string{}, 55 | Extensions: map[string]string{}, 56 | }, 57 | } 58 | testCert.SignCert(rand.Reader, testSigners["rsa"]) 59 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] 60 | testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) 61 | if err != nil { 62 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/benchmark_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "errors" 9 | "io" 10 | "net" 11 | "testing" 12 | ) 13 | 14 | type server struct { 15 | *ServerConn 16 | chans <-chan NewChannel 17 | } 18 | 19 | func newServer(c net.Conn, conf *ServerConfig) (*server, error) { 20 | sconn, chans, reqs, err := NewServerConn(c, conf) 21 | if err != nil { 22 | return nil, err 23 | } 24 | go DiscardRequests(reqs) 25 | return &server{sconn, chans}, nil 26 | } 27 | 28 | func (s *server) Accept() (NewChannel, error) { 29 | n, ok := <-s.chans 30 | if !ok { 31 | return nil, io.EOF 32 | } 33 | return n, nil 34 | } 35 | 36 | func sshPipe() (Conn, *server, error) { 37 | c1, c2, err := netPipe() 38 | if err != nil { 39 | return nil, nil, err 40 | } 41 | 42 | clientConf := ClientConfig{ 43 | User: "user", 44 | } 45 | serverConf := ServerConfig{ 46 | NoClientAuth: true, 47 | } 48 | serverConf.AddHostKey(testSigners["ecdsa"]) 49 | done := make(chan *server, 1) 50 | go func() { 51 | server, err := newServer(c2, &serverConf) 52 | if err != nil { 53 | done <- nil 54 | } 55 | done <- server 56 | }() 57 | 58 | client, _, reqs, err := NewClientConn(c1, "", &clientConf) 59 | if err != nil { 60 | return nil, nil, err 61 | } 62 | 63 | server := <-done 64 | if server == nil { 65 | return nil, nil, errors.New("server handshake failed.") 66 | } 67 | go DiscardRequests(reqs) 68 | 69 | return client, server, nil 70 | } 71 | 72 | func BenchmarkEndToEnd(b *testing.B) { 73 | b.StopTimer() 74 | 75 | client, server, err := sshPipe() 76 | if err != nil { 77 | b.Fatalf("sshPipe: %v", err) 78 | } 79 | 80 | defer client.Close() 81 | defer server.Close() 82 | 83 | size := (1 << 20) 84 | input := make([]byte, size) 85 | output := make([]byte, size) 86 | b.SetBytes(int64(size)) 87 | done := make(chan int, 1) 88 | 89 | go func() { 90 | newCh, err := server.Accept() 91 | if err != nil { 92 | b.Fatalf("Client: %v", err) 93 | } 94 | ch, incoming, err := newCh.Accept() 95 | go DiscardRequests(incoming) 96 | for i := 0; i < b.N; i++ { 97 | if _, err := io.ReadFull(ch, output); err != nil { 98 | b.Fatalf("ReadFull: %v", err) 99 | } 100 | } 101 | ch.Close() 102 | done <- 1 103 | }() 104 | 105 | ch, in, err := client.OpenChannel("speed", nil) 106 | if err != nil { 107 | b.Fatalf("OpenChannel: %v", err) 108 | } 109 | go DiscardRequests(in) 110 | 111 | b.ResetTimer() 112 | b.StartTimer() 113 | for i := 0; i < b.N; i++ { 114 | if _, err := ch.Write(input); err != nil { 115 | b.Fatalf("WriteFull: %v", err) 116 | } 117 | } 118 | ch.Close() 119 | b.StopTimer() 120 | 121 | <-done 122 | } 123 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/buffer.go: -------------------------------------------------------------------------------- 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 | package ssh 6 | 7 | import ( 8 | "io" 9 | "sync" 10 | ) 11 | 12 | // buffer provides a linked list buffer for data exchange 13 | // between producer and consumer. Theoretically the buffer is 14 | // of unlimited capacity as it does no allocation of its own. 15 | type buffer struct { 16 | // protects concurrent access to head, tail and closed 17 | *sync.Cond 18 | 19 | head *element // the buffer that will be read first 20 | tail *element // the buffer that will be read last 21 | 22 | closed bool 23 | } 24 | 25 | // An element represents a single link in a linked list. 26 | type element struct { 27 | buf []byte 28 | next *element 29 | } 30 | 31 | // newBuffer returns an empty buffer that is not closed. 32 | func newBuffer() *buffer { 33 | e := new(element) 34 | b := &buffer{ 35 | Cond: newCond(), 36 | head: e, 37 | tail: e, 38 | } 39 | return b 40 | } 41 | 42 | // write makes buf available for Read to receive. 43 | // buf must not be modified after the call to write. 44 | func (b *buffer) write(buf []byte) { 45 | b.Cond.L.Lock() 46 | e := &element{buf: buf} 47 | b.tail.next = e 48 | b.tail = e 49 | b.Cond.Signal() 50 | b.Cond.L.Unlock() 51 | } 52 | 53 | // eof closes the buffer. Reads from the buffer once all 54 | // the data has been consumed will receive os.EOF. 55 | func (b *buffer) eof() error { 56 | b.Cond.L.Lock() 57 | b.closed = true 58 | b.Cond.Signal() 59 | b.Cond.L.Unlock() 60 | return nil 61 | } 62 | 63 | // Read reads data from the internal buffer in buf. Reads will block 64 | // if no data is available, or until the buffer is closed. 65 | func (b *buffer) Read(buf []byte) (n int, err error) { 66 | b.Cond.L.Lock() 67 | defer b.Cond.L.Unlock() 68 | 69 | for len(buf) > 0 { 70 | // if there is data in b.head, copy it 71 | if len(b.head.buf) > 0 { 72 | r := copy(buf, b.head.buf) 73 | buf, b.head.buf = buf[r:], b.head.buf[r:] 74 | n += r 75 | continue 76 | } 77 | // if there is a next buffer, make it the head 78 | if len(b.head.buf) == 0 && b.head != b.tail { 79 | b.head = b.head.next 80 | continue 81 | } 82 | 83 | // if at least one byte has been copied, return 84 | if n > 0 { 85 | break 86 | } 87 | 88 | // if nothing was read, and there is nothing outstanding 89 | // check to see if the buffer is closed. 90 | if b.closed { 91 | err = io.EOF 92 | break 93 | } 94 | // out of buffers, wait for producer 95 | b.Cond.Wait() 96 | } 97 | return 98 | } 99 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/buffer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "io" 9 | "testing" 10 | ) 11 | 12 | var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") 13 | 14 | func TestBufferReadwrite(t *testing.T) { 15 | b := newBuffer() 16 | b.write(alphabet[:10]) 17 | r, _ := b.Read(make([]byte, 10)) 18 | if r != 10 { 19 | t.Fatalf("Expected written == read == 10, written: 10, read %d", r) 20 | } 21 | 22 | b = newBuffer() 23 | b.write(alphabet[:5]) 24 | r, _ = b.Read(make([]byte, 10)) 25 | if r != 5 { 26 | t.Fatalf("Expected written == read == 5, written: 5, read %d", r) 27 | } 28 | 29 | b = newBuffer() 30 | b.write(alphabet[:10]) 31 | r, _ = b.Read(make([]byte, 5)) 32 | if r != 5 { 33 | t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) 34 | } 35 | 36 | b = newBuffer() 37 | b.write(alphabet[:5]) 38 | b.write(alphabet[5:15]) 39 | r, _ = b.Read(make([]byte, 10)) 40 | r2, _ := b.Read(make([]byte, 10)) 41 | if r != 10 || r2 != 5 || 15 != r+r2 { 42 | t.Fatal("Expected written == read == 15") 43 | } 44 | } 45 | 46 | func TestBufferClose(t *testing.T) { 47 | b := newBuffer() 48 | b.write(alphabet[:10]) 49 | b.eof() 50 | _, err := b.Read(make([]byte, 5)) 51 | if err != nil { 52 | t.Fatal("expected read of 5 to not return EOF") 53 | } 54 | b = newBuffer() 55 | b.write(alphabet[:10]) 56 | b.eof() 57 | r, err := b.Read(make([]byte, 5)) 58 | r2, err2 := b.Read(make([]byte, 10)) 59 | if r != 5 || r2 != 5 || err != nil || err2 != nil { 60 | t.Fatal("expected reads of 5 and 5") 61 | } 62 | 63 | b = newBuffer() 64 | b.write(alphabet[:10]) 65 | b.eof() 66 | r, err = b.Read(make([]byte, 5)) 67 | r2, err2 = b.Read(make([]byte, 10)) 68 | r3, err3 := b.Read(make([]byte, 10)) 69 | if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { 70 | t.Fatal("expected reads of 5 and 5 and 0, with EOF") 71 | } 72 | 73 | b = newBuffer() 74 | b.write(make([]byte, 5)) 75 | b.write(make([]byte, 10)) 76 | b.eof() 77 | r, err = b.Read(make([]byte, 9)) 78 | r2, err2 = b.Read(make([]byte, 3)) 79 | r3, err3 = b.Read(make([]byte, 3)) 80 | r4, err4 := b.Read(make([]byte, 10)) 81 | if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { 82 | t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) 83 | } 84 | if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { 85 | t.Fatal("Expected written == read == 15", r, r2, r3, r4) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/certs_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "reflect" 11 | "testing" 12 | "time" 13 | ) 14 | 15 | // Cert generated by ssh-keygen 6.0p1 Debian-4. 16 | // % ssh-keygen -s ca-key -I test user-key 17 | const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` 18 | 19 | func TestParseCert(t *testing.T) { 20 | authKeyBytes := []byte(exampleSSHCert) 21 | 22 | key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) 23 | if err != nil { 24 | t.Fatalf("ParseAuthorizedKey: %v", err) 25 | } 26 | if len(rest) > 0 { 27 | t.Errorf("rest: got %q, want empty", rest) 28 | } 29 | 30 | if _, ok := key.(*Certificate); !ok { 31 | t.Fatalf("got %v (%T), want *Certificate", key, key) 32 | } 33 | 34 | marshaled := MarshalAuthorizedKey(key) 35 | // Before comparison, remove the trailing newline that 36 | // MarshalAuthorizedKey adds. 37 | marshaled = marshaled[:len(marshaled)-1] 38 | if !bytes.Equal(authKeyBytes, marshaled) { 39 | t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) 40 | } 41 | } 42 | 43 | // Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 44 | // % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub 45 | // user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN 46 | // Critical Options: 47 | // force-command /bin/sleep 48 | // source-address 192.168.1.0/24 49 | // Extensions: 50 | // permit-X11-forwarding 51 | // permit-agent-forwarding 52 | // permit-port-forwarding 53 | // permit-pty 54 | // permit-user-rc 55 | const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` 56 | 57 | func TestParseCertWithOptions(t *testing.T) { 58 | opts := map[string]string{ 59 | "source-address": "192.168.1.0/24", 60 | "force-command": "/bin/sleep", 61 | } 62 | exts := map[string]string{ 63 | "permit-X11-forwarding": "", 64 | "permit-agent-forwarding": "", 65 | "permit-port-forwarding": "", 66 | "permit-pty": "", 67 | "permit-user-rc": "", 68 | } 69 | authKeyBytes := []byte(exampleSSHCertWithOptions) 70 | 71 | key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) 72 | if err != nil { 73 | t.Fatalf("ParseAuthorizedKey: %v", err) 74 | } 75 | if len(rest) > 0 { 76 | t.Errorf("rest: got %q, want empty", rest) 77 | } 78 | cert, ok := key.(*Certificate) 79 | if !ok { 80 | t.Fatalf("got %v (%T), want *Certificate", key, key) 81 | } 82 | if !reflect.DeepEqual(cert.CriticalOptions, opts) { 83 | t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) 84 | } 85 | if !reflect.DeepEqual(cert.Extensions, exts) { 86 | t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) 87 | } 88 | marshaled := MarshalAuthorizedKey(key) 89 | // Before comparison, remove the trailing newline that 90 | // MarshalAuthorizedKey adds. 91 | marshaled = marshaled[:len(marshaled)-1] 92 | if !bytes.Equal(authKeyBytes, marshaled) { 93 | t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) 94 | } 95 | } 96 | 97 | func TestValidateCert(t *testing.T) { 98 | key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) 99 | if err != nil { 100 | t.Fatalf("ParseAuthorizedKey: %v", err) 101 | } 102 | validCert, ok := key.(*Certificate) 103 | if !ok { 104 | t.Fatalf("got %v (%T), want *Certificate", key, key) 105 | } 106 | checker := CertChecker{} 107 | checker.IsAuthority = func(k PublicKey) bool { 108 | return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) 109 | } 110 | 111 | if err := checker.CheckCert("user", validCert); err != nil { 112 | t.Errorf("Unable to validate certificate: %v", err) 113 | } 114 | invalidCert := &Certificate{ 115 | Key: testPublicKeys["rsa"], 116 | SignatureKey: testPublicKeys["ecdsa"], 117 | ValidBefore: CertTimeInfinity, 118 | Signature: &Signature{}, 119 | } 120 | if err := checker.CheckCert("user", invalidCert); err == nil { 121 | t.Error("Invalid cert signature passed validation") 122 | } 123 | } 124 | 125 | func TestValidateCertTime(t *testing.T) { 126 | cert := Certificate{ 127 | ValidPrincipals: []string{"user"}, 128 | Key: testPublicKeys["rsa"], 129 | ValidAfter: 50, 130 | ValidBefore: 100, 131 | } 132 | 133 | cert.SignCert(rand.Reader, testSigners["ecdsa"]) 134 | 135 | for ts, ok := range map[int64]bool{ 136 | 25: false, 137 | 50: true, 138 | 99: true, 139 | 100: false, 140 | 125: false, 141 | } { 142 | checker := CertChecker{ 143 | Clock: func() time.Time { return time.Unix(ts, 0) }, 144 | } 145 | checker.IsAuthority = func(k PublicKey) bool { 146 | return bytes.Equal(k.Marshal(), 147 | testPublicKeys["ecdsa"].Marshal()) 148 | } 149 | 150 | if v := checker.CheckCert("user", &cert); (v == nil) != ok { 151 | t.Errorf("Authenticate(%d): %v", ts, v) 152 | } 153 | } 154 | } 155 | 156 | // TODO(hanwen): tests for 157 | // 158 | // host keys: 159 | // * fallbacks 160 | 161 | func TestHostKeyCert(t *testing.T) { 162 | cert := &Certificate{ 163 | ValidPrincipals: []string{"hostname", "hostname.domain"}, 164 | Key: testPublicKeys["rsa"], 165 | ValidBefore: CertTimeInfinity, 166 | CertType: HostCert, 167 | } 168 | cert.SignCert(rand.Reader, testSigners["ecdsa"]) 169 | 170 | checker := &CertChecker{ 171 | IsAuthority: func(p PublicKey) bool { 172 | return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) 173 | }, 174 | } 175 | 176 | certSigner, err := NewCertSigner(cert, testSigners["rsa"]) 177 | if err != nil { 178 | t.Errorf("NewCertSigner: %v", err) 179 | } 180 | 181 | for _, name := range []string{"hostname", "otherhost"} { 182 | c1, c2, err := netPipe() 183 | if err != nil { 184 | t.Fatalf("netPipe: %v", err) 185 | } 186 | defer c1.Close() 187 | defer c2.Close() 188 | 189 | go func() { 190 | conf := ServerConfig{ 191 | NoClientAuth: true, 192 | } 193 | conf.AddHostKey(certSigner) 194 | _, _, _, err := NewServerConn(c1, &conf) 195 | if err != nil { 196 | t.Fatalf("NewServerConn: %v", err) 197 | } 198 | }() 199 | 200 | config := &ClientConfig{ 201 | User: "user", 202 | HostKeyCallback: checker.CheckHostKey, 203 | } 204 | _, _, _, err = NewClientConn(c2, name, config) 205 | 206 | succeed := name == "hostname" 207 | if (err == nil) != succeed { 208 | t.Fatalf("NewClientConn(%q): %v", name, err) 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/cipher_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "crypto" 10 | "crypto/aes" 11 | "crypto/rand" 12 | "testing" 13 | ) 14 | 15 | func TestDefaultCiphersExist(t *testing.T) { 16 | for _, cipherAlgo := range supportedCiphers { 17 | if _, ok := cipherModes[cipherAlgo]; !ok { 18 | t.Errorf("default cipher %q is unknown", cipherAlgo) 19 | } 20 | } 21 | } 22 | 23 | func TestPacketCiphers(t *testing.T) { 24 | // Still test aes128cbc cipher althought it's commented out. 25 | cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} 26 | defer delete(cipherModes, aes128cbcID) 27 | 28 | for cipher := range cipherModes { 29 | kr := &kexResult{Hash: crypto.SHA1} 30 | algs := directionAlgorithms{ 31 | Cipher: cipher, 32 | MAC: "hmac-sha1", 33 | Compression: "none", 34 | } 35 | client, err := newPacketCipher(clientKeys, algs, kr) 36 | if err != nil { 37 | t.Errorf("newPacketCipher(client, %q): %v", cipher, err) 38 | continue 39 | } 40 | server, err := newPacketCipher(clientKeys, algs, kr) 41 | if err != nil { 42 | t.Errorf("newPacketCipher(client, %q): %v", cipher, err) 43 | continue 44 | } 45 | 46 | want := "bla bla" 47 | input := []byte(want) 48 | buf := &bytes.Buffer{} 49 | if err := client.writePacket(0, buf, rand.Reader, input); err != nil { 50 | t.Errorf("writePacket(%q): %v", cipher, err) 51 | continue 52 | } 53 | 54 | packet, err := server.readPacket(0, buf) 55 | if err != nil { 56 | t.Errorf("readPacket(%q): %v", cipher, err) 57 | continue 58 | } 59 | 60 | if string(packet) != want { 61 | t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want) 62 | } 63 | } 64 | } 65 | 66 | func TestCBCOracleCounterMeasure(t *testing.T) { 67 | cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} 68 | defer delete(cipherModes, aes128cbcID) 69 | 70 | kr := &kexResult{Hash: crypto.SHA1} 71 | algs := directionAlgorithms{ 72 | Cipher: aes128cbcID, 73 | MAC: "hmac-sha1", 74 | Compression: "none", 75 | } 76 | client, err := newPacketCipher(clientKeys, algs, kr) 77 | if err != nil { 78 | t.Fatalf("newPacketCipher(client): %v", err) 79 | } 80 | 81 | want := "bla bla" 82 | input := []byte(want) 83 | buf := &bytes.Buffer{} 84 | if err := client.writePacket(0, buf, rand.Reader, input); err != nil { 85 | t.Errorf("writePacket: %v", err) 86 | } 87 | 88 | packetSize := buf.Len() 89 | buf.Write(make([]byte, 2*maxPacket)) 90 | 91 | // We corrupt each byte, but this usually will only test the 92 | // 'packet too large' or 'MAC failure' cases. 93 | lastRead := -1 94 | for i := 0; i < packetSize; i++ { 95 | server, err := newPacketCipher(clientKeys, algs, kr) 96 | if err != nil { 97 | t.Fatalf("newPacketCipher(client): %v", err) 98 | } 99 | 100 | fresh := &bytes.Buffer{} 101 | fresh.Write(buf.Bytes()) 102 | fresh.Bytes()[i] ^= 0x01 103 | 104 | before := fresh.Len() 105 | _, err = server.readPacket(0, fresh) 106 | if err == nil { 107 | t.Errorf("corrupt byte %d: readPacket succeeded ", i) 108 | continue 109 | } 110 | if _, ok := err.(cbcError); !ok { 111 | t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) 112 | continue 113 | } 114 | 115 | after := fresh.Len() 116 | bytesRead := before - after 117 | if bytesRead < maxPacket { 118 | t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) 119 | continue 120 | } 121 | 122 | if i > 0 && bytesRead != lastRead { 123 | t.Errorf("corrupt byte %d: want %d, got %d bytes read", bytesRead, lastRead) 124 | } 125 | lastRead = bytesRead 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "net" 11 | "sync" 12 | ) 13 | 14 | // Client implements a traditional SSH client that supports shells, 15 | // subprocesses, port forwarding and tunneled dialing. 16 | type Client struct { 17 | Conn 18 | 19 | forwards forwardList // forwarded tcpip connections from the remote side 20 | mu sync.Mutex 21 | channelHandlers map[string]chan NewChannel 22 | } 23 | 24 | // HandleChannelOpen returns a channel on which NewChannel requests 25 | // for the given type are sent. If the type already is being handled, 26 | // nil is returned. The channel is closed when the connection is closed. 27 | func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { 28 | c.mu.Lock() 29 | defer c.mu.Unlock() 30 | if c.channelHandlers == nil { 31 | // The SSH channel has been closed. 32 | c := make(chan NewChannel) 33 | close(c) 34 | return c 35 | } 36 | 37 | ch := c.channelHandlers[channelType] 38 | if ch != nil { 39 | return nil 40 | } 41 | 42 | ch = make(chan NewChannel, 16) 43 | c.channelHandlers[channelType] = ch 44 | return ch 45 | } 46 | 47 | // NewClient creates a Client on top of the given connection. 48 | func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { 49 | conn := &Client{ 50 | Conn: c, 51 | channelHandlers: make(map[string]chan NewChannel, 1), 52 | } 53 | 54 | go conn.handleGlobalRequests(reqs) 55 | go conn.handleChannelOpens(chans) 56 | go func() { 57 | conn.Wait() 58 | conn.forwards.closeAll() 59 | }() 60 | go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) 61 | return conn 62 | } 63 | 64 | // NewClientConn establishes an authenticated SSH connection using c 65 | // as the underlying transport. The Request and NewChannel channels 66 | // must be serviced or the connection will hang. 67 | func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { 68 | fullConf := *config 69 | fullConf.SetDefaults() 70 | conn := &connection{ 71 | sshConn: sshConn{conn: c}, 72 | } 73 | 74 | if err := conn.clientHandshake(addr, &fullConf); err != nil { 75 | c.Close() 76 | return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) 77 | } 78 | conn.mux = newMux(conn.transport) 79 | return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil 80 | } 81 | 82 | // clientHandshake performs the client side key exchange. See RFC 4253 Section 83 | // 7. 84 | func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { 85 | if config.ClientVersion != "" { 86 | c.clientVersion = []byte(config.ClientVersion) 87 | } else { 88 | c.clientVersion = []byte(packageVersion) 89 | } 90 | var err error 91 | c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) 92 | if err != nil { 93 | return err 94 | } 95 | 96 | c.transport = newClientTransport( 97 | newTransport(c.sshConn.conn, config.Rand, true /* is client */), 98 | c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) 99 | if err := c.transport.requestKeyChange(); err != nil { 100 | return err 101 | } 102 | 103 | if packet, err := c.transport.readPacket(); err != nil { 104 | return err 105 | } else if packet[0] != msgNewKeys { 106 | return unexpectedMessageError(msgNewKeys, packet[0]) 107 | } 108 | 109 | // We just did the key change, so the session ID is established. 110 | c.sessionID = c.transport.getSessionID() 111 | 112 | return c.clientAuthenticate(config) 113 | } 114 | 115 | // verifyHostKeySignature verifies the host key obtained in the key 116 | // exchange. 117 | func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { 118 | sig, rest, ok := parseSignatureBody(result.Signature) 119 | if len(rest) > 0 || !ok { 120 | return errors.New("ssh: signature parse error") 121 | } 122 | 123 | return hostKey.Verify(result.H, sig) 124 | } 125 | 126 | // NewSession opens a new Session for this client. (A session is a remote 127 | // execution of a program.) 128 | func (c *Client) NewSession() (*Session, error) { 129 | ch, in, err := c.OpenChannel("session", nil) 130 | if err != nil { 131 | return nil, err 132 | } 133 | return newSession(ch, in) 134 | } 135 | 136 | func (c *Client) handleGlobalRequests(incoming <-chan *Request) { 137 | for r := range incoming { 138 | // This handles keepalive messages and matches 139 | // the behaviour of OpenSSH. 140 | r.Reply(false, nil) 141 | } 142 | } 143 | 144 | // handleChannelOpens channel open messages from the remote side. 145 | func (c *Client) handleChannelOpens(in <-chan NewChannel) { 146 | for ch := range in { 147 | c.mu.Lock() 148 | handler := c.channelHandlers[ch.ChannelType()] 149 | c.mu.Unlock() 150 | 151 | if handler != nil { 152 | handler <- ch 153 | } else { 154 | ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) 155 | } 156 | } 157 | 158 | c.mu.Lock() 159 | for _, ch := range c.channelHandlers { 160 | close(ch) 161 | } 162 | c.channelHandlers = nil 163 | c.mu.Unlock() 164 | } 165 | 166 | // Dial starts a client connection to the given SSH server. It is a 167 | // convenience function that connects to the given network address, 168 | // initiates the SSH handshake, and then sets up a Client. For access 169 | // to incoming channels and requests, use net.Dial with NewClientConn 170 | // instead. 171 | func Dial(network, addr string, config *ClientConfig) (*Client, error) { 172 | conn, err := net.Dial(network, addr) 173 | if err != nil { 174 | return nil, err 175 | } 176 | c, chans, reqs, err := NewClientConn(conn, addr, config) 177 | if err != nil { 178 | return nil, err 179 | } 180 | return NewClient(c, chans, reqs), nil 181 | } 182 | 183 | // A ClientConfig structure is used to configure a Client. It must not be 184 | // modified after having been passed to an SSH function. 185 | type ClientConfig struct { 186 | // Config contains configuration that is shared between clients and 187 | // servers. 188 | Config 189 | 190 | // User contains the username to authenticate as. 191 | User string 192 | 193 | // Auth contains possible authentication methods to use with the 194 | // server. Only the first instance of a particular RFC 4252 method will 195 | // be used during authentication. 196 | Auth []AuthMethod 197 | 198 | // HostKeyCallback, if not nil, is called during the cryptographic 199 | // handshake to validate the server's host key. A nil HostKeyCallback 200 | // implies that all host keys are accepted. 201 | HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error 202 | 203 | // ClientVersion contains the version identification string that will 204 | // be used for the connection. If empty, a reasonable default is used. 205 | ClientVersion string 206 | } 207 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package ssh 6 | 7 | import ( 8 | "net" 9 | "testing" 10 | ) 11 | 12 | func testClientVersion(t *testing.T, config *ClientConfig, expected string) { 13 | clientConn, serverConn := net.Pipe() 14 | defer clientConn.Close() 15 | receivedVersion := make(chan string, 1) 16 | go func() { 17 | version, err := readVersion(serverConn) 18 | if err != nil { 19 | receivedVersion <- "" 20 | } else { 21 | receivedVersion <- string(version) 22 | } 23 | serverConn.Close() 24 | }() 25 | NewClientConn(clientConn, "", config) 26 | actual := <-receivedVersion 27 | if actual != expected { 28 | t.Fatalf("got %s; want %s", actual, expected) 29 | } 30 | } 31 | 32 | func TestCustomClientVersion(t *testing.T) { 33 | version := "Test-Client-Version-0.0" 34 | testClientVersion(t, &ClientConfig{ClientVersion: version}, version) 35 | } 36 | 37 | func TestDefaultClientVersion(t *testing.T) { 38 | testClientVersion(t, &ClientConfig{}, packageVersion) 39 | } 40 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/connection.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "fmt" 9 | "net" 10 | ) 11 | 12 | // OpenChannelError is returned if the other side rejects an 13 | // OpenChannel request. 14 | type OpenChannelError struct { 15 | Reason RejectionReason 16 | Message string 17 | } 18 | 19 | func (e *OpenChannelError) Error() string { 20 | return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) 21 | } 22 | 23 | // ConnMetadata holds metadata for the connection. 24 | type ConnMetadata interface { 25 | // User returns the user ID for this connection. 26 | // It is empty if no authentication is used. 27 | User() string 28 | 29 | // SessionID returns the sesson hash, also denoted by H. 30 | SessionID() []byte 31 | 32 | // ClientVersion returns the client's version string as hashed 33 | // into the session ID. 34 | ClientVersion() []byte 35 | 36 | // ServerVersion returns the client's version string as hashed 37 | // into the session ID. 38 | ServerVersion() []byte 39 | 40 | // RemoteAddr returns the remote address for this connection. 41 | RemoteAddr() net.Addr 42 | 43 | // LocalAddr returns the local address for this connection. 44 | LocalAddr() net.Addr 45 | } 46 | 47 | // Conn represents an SSH connection for both server and client roles. 48 | // Conn is the basis for implementing an application layer, such 49 | // as ClientConn, which implements the traditional shell access for 50 | // clients. 51 | type Conn interface { 52 | ConnMetadata 53 | 54 | // SendRequest sends a global request, and returns the 55 | // reply. If wantReply is true, it returns the response status 56 | // and payload. See also RFC4254, section 4. 57 | SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) 58 | 59 | // OpenChannel tries to open an channel. If the request is 60 | // rejected, it returns *OpenChannelError. On success it returns 61 | // the SSH Channel and a Go channel for incoming, out-of-band 62 | // requests. The Go channel must be serviced, or the 63 | // connection will hang. 64 | OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) 65 | 66 | // Close closes the underlying network connection 67 | Close() error 68 | 69 | // Wait blocks until the connection has shut down, and returns the 70 | // error causing the shutdown. 71 | Wait() error 72 | 73 | // TODO(hanwen): consider exposing: 74 | // RequestKeyChange 75 | // Disconnect 76 | } 77 | 78 | // DiscardRequests consumes and rejects all requests from the 79 | // passed-in channel. 80 | func DiscardRequests(in <-chan *Request) { 81 | for req := range in { 82 | if req.WantReply { 83 | req.Reply(false, nil) 84 | } 85 | } 86 | } 87 | 88 | // A connection represents an incoming connection. 89 | type connection struct { 90 | transport *handshakeTransport 91 | sshConn 92 | 93 | // The connection protocol. 94 | *mux 95 | } 96 | 97 | func (c *connection) Close() error { 98 | return c.sshConn.conn.Close() 99 | } 100 | 101 | // sshconn provides net.Conn metadata, but disallows direct reads and 102 | // writes. 103 | type sshConn struct { 104 | conn net.Conn 105 | 106 | user string 107 | sessionID []byte 108 | clientVersion []byte 109 | serverVersion []byte 110 | } 111 | 112 | func dup(src []byte) []byte { 113 | dst := make([]byte, len(src)) 114 | copy(dst, src) 115 | return dst 116 | } 117 | 118 | func (c *sshConn) User() string { 119 | return c.user 120 | } 121 | 122 | func (c *sshConn) RemoteAddr() net.Addr { 123 | return c.conn.RemoteAddr() 124 | } 125 | 126 | func (c *sshConn) Close() error { 127 | return c.conn.Close() 128 | } 129 | 130 | func (c *sshConn) LocalAddr() net.Addr { 131 | return c.conn.LocalAddr() 132 | } 133 | 134 | func (c *sshConn) SessionID() []byte { 135 | return dup(c.sessionID) 136 | } 137 | 138 | func (c *sshConn) ClientVersion() []byte { 139 | return dup(c.clientVersion) 140 | } 141 | 142 | func (c *sshConn) ServerVersion() []byte { 143 | return dup(c.serverVersion) 144 | } 145 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | /* 6 | Package ssh implements an SSH client and server. 7 | 8 | SSH is a transport security protocol, an authentication protocol and a 9 | family of application protocols. The most typical application level 10 | protocol is a remote shell and this is specifically implemented. However, 11 | the multiplexed nature of SSH is exposed to users that wish to support 12 | others. 13 | 14 | References: 15 | [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD 16 | [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 17 | */ 18 | package ssh // import "golang.org/x/crypto/ssh" 19 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh_test 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io/ioutil" 11 | "log" 12 | "net" 13 | "net/http" 14 | 15 | "golang.org/x/crypto/ssh" 16 | "golang.org/x/crypto/ssh/terminal" 17 | ) 18 | 19 | func ExampleNewServerConn() { 20 | // An SSH server is represented by a ServerConfig, which holds 21 | // certificate details and handles authentication of ServerConns. 22 | config := &ssh.ServerConfig{ 23 | PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { 24 | // Should use constant-time compare (or better, salt+hash) in 25 | // a production setting. 26 | if c.User() == "testuser" && string(pass) == "tiger" { 27 | return nil, nil 28 | } 29 | return nil, fmt.Errorf("password rejected for %q", c.User()) 30 | }, 31 | } 32 | 33 | privateBytes, err := ioutil.ReadFile("id_rsa") 34 | if err != nil { 35 | panic("Failed to load private key") 36 | } 37 | 38 | private, err := ssh.ParsePrivateKey(privateBytes) 39 | if err != nil { 40 | panic("Failed to parse private key") 41 | } 42 | 43 | config.AddHostKey(private) 44 | 45 | // Once a ServerConfig has been configured, connections can be 46 | // accepted. 47 | listener, err := net.Listen("tcp", "0.0.0.0:2022") 48 | if err != nil { 49 | panic("failed to listen for connection") 50 | } 51 | nConn, err := listener.Accept() 52 | if err != nil { 53 | panic("failed to accept incoming connection") 54 | } 55 | 56 | // Before use, a handshake must be performed on the incoming 57 | // net.Conn. 58 | _, chans, reqs, err := ssh.NewServerConn(nConn, config) 59 | if err != nil { 60 | panic("failed to handshake") 61 | } 62 | // The incoming Request channel must be serviced. 63 | go ssh.DiscardRequests(reqs) 64 | 65 | // Service the incoming Channel channel. 66 | for newChannel := range chans { 67 | // Channels have a type, depending on the application level 68 | // protocol intended. In the case of a shell, the type is 69 | // "session" and ServerShell may be used to present a simple 70 | // terminal interface. 71 | if newChannel.ChannelType() != "session" { 72 | newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") 73 | continue 74 | } 75 | channel, requests, err := newChannel.Accept() 76 | if err != nil { 77 | panic("could not accept channel.") 78 | } 79 | 80 | // Sessions have out-of-band requests such as "shell", 81 | // "pty-req" and "env". Here we handle only the 82 | // "shell" request. 83 | go func(in <-chan *ssh.Request) { 84 | for req := range in { 85 | ok := false 86 | switch req.Type { 87 | case "shell": 88 | ok = true 89 | if len(req.Payload) > 0 { 90 | // We don't accept any 91 | // commands, only the 92 | // default shell. 93 | ok = false 94 | } 95 | } 96 | req.Reply(ok, nil) 97 | } 98 | }(requests) 99 | 100 | term := terminal.NewTerminal(channel, "> ") 101 | 102 | go func() { 103 | defer channel.Close() 104 | for { 105 | line, err := term.ReadLine() 106 | if err != nil { 107 | break 108 | } 109 | fmt.Println(line) 110 | } 111 | }() 112 | } 113 | } 114 | 115 | func ExampleDial() { 116 | // An SSH client is represented with a ClientConn. Currently only 117 | // the "password" authentication method is supported. 118 | // 119 | // To authenticate with the remote server you must pass at least one 120 | // implementation of AuthMethod via the Auth field in ClientConfig. 121 | config := &ssh.ClientConfig{ 122 | User: "username", 123 | Auth: []ssh.AuthMethod{ 124 | ssh.Password("yourpassword"), 125 | }, 126 | } 127 | client, err := ssh.Dial("tcp", "yourserver.com:22", config) 128 | if err != nil { 129 | panic("Failed to dial: " + err.Error()) 130 | } 131 | 132 | // Each ClientConn can support multiple interactive sessions, 133 | // represented by a Session. 134 | session, err := client.NewSession() 135 | if err != nil { 136 | panic("Failed to create session: " + err.Error()) 137 | } 138 | defer session.Close() 139 | 140 | // Once a Session is created, you can execute a single command on 141 | // the remote side using the Run method. 142 | var b bytes.Buffer 143 | session.Stdout = &b 144 | if err := session.Run("/usr/bin/whoami"); err != nil { 145 | panic("Failed to run: " + err.Error()) 146 | } 147 | fmt.Println(b.String()) 148 | } 149 | 150 | func ExampleClient_Listen() { 151 | config := &ssh.ClientConfig{ 152 | User: "username", 153 | Auth: []ssh.AuthMethod{ 154 | ssh.Password("password"), 155 | }, 156 | } 157 | // Dial your ssh server. 158 | conn, err := ssh.Dial("tcp", "localhost:22", config) 159 | if err != nil { 160 | log.Fatalf("unable to connect: %s", err) 161 | } 162 | defer conn.Close() 163 | 164 | // Request the remote side to open port 8080 on all interfaces. 165 | l, err := conn.Listen("tcp", "0.0.0.0:8080") 166 | if err != nil { 167 | log.Fatalf("unable to register tcp forward: %v", err) 168 | } 169 | defer l.Close() 170 | 171 | // Serve HTTP with your SSH server acting as a reverse proxy. 172 | http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 173 | fmt.Fprintf(resp, "Hello world!\n") 174 | })) 175 | } 176 | 177 | func ExampleSession_RequestPty() { 178 | // Create client config 179 | config := &ssh.ClientConfig{ 180 | User: "username", 181 | Auth: []ssh.AuthMethod{ 182 | ssh.Password("password"), 183 | }, 184 | } 185 | // Connect to ssh server 186 | conn, err := ssh.Dial("tcp", "localhost:22", config) 187 | if err != nil { 188 | log.Fatalf("unable to connect: %s", err) 189 | } 190 | defer conn.Close() 191 | // Create a session 192 | session, err := conn.NewSession() 193 | if err != nil { 194 | log.Fatalf("unable to create session: %s", err) 195 | } 196 | defer session.Close() 197 | // Set up terminal modes 198 | modes := ssh.TerminalModes{ 199 | ssh.ECHO: 0, // disable echoing 200 | ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud 201 | ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud 202 | } 203 | // Request pseudo terminal 204 | if err := session.RequestPty("xterm", 80, 40, modes); err != nil { 205 | log.Fatalf("request for pseudo terminal failed: %s", err) 206 | } 207 | // Start remote shell 208 | if err := session.Shell(); err != nil { 209 | log.Fatalf("failed to start shell: %s", err) 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/handshake_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "fmt" 11 | "net" 12 | "testing" 13 | ) 14 | 15 | type testChecker struct { 16 | calls []string 17 | } 18 | 19 | func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { 20 | if dialAddr == "bad" { 21 | return fmt.Errorf("dialAddr is bad") 22 | } 23 | 24 | if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { 25 | return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) 26 | } 27 | 28 | t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) 29 | 30 | return nil 31 | } 32 | 33 | // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and 34 | // therefore is buffered (net.Pipe deadlocks if both sides start with 35 | // a write.) 36 | func netPipe() (net.Conn, net.Conn, error) { 37 | listener, err := net.Listen("tcp", "127.0.0.1:0") 38 | if err != nil { 39 | return nil, nil, err 40 | } 41 | defer listener.Close() 42 | c1, err := net.Dial("tcp", listener.Addr().String()) 43 | if err != nil { 44 | return nil, nil, err 45 | } 46 | 47 | c2, err := listener.Accept() 48 | if err != nil { 49 | c1.Close() 50 | return nil, nil, err 51 | } 52 | 53 | return c1, c2, nil 54 | } 55 | 56 | func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) { 57 | a, b, err := netPipe() 58 | if err != nil { 59 | return nil, nil, err 60 | } 61 | 62 | trC := newTransport(a, rand.Reader, true) 63 | trS := newTransport(b, rand.Reader, false) 64 | clientConf.SetDefaults() 65 | 66 | v := []byte("version") 67 | client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) 68 | 69 | serverConf := &ServerConfig{} 70 | serverConf.AddHostKey(testSigners["ecdsa"]) 71 | serverConf.SetDefaults() 72 | server = newServerTransport(trS, v, v, serverConf) 73 | 74 | return client, server, nil 75 | } 76 | 77 | func TestHandshakeBasic(t *testing.T) { 78 | checker := &testChecker{} 79 | trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr") 80 | if err != nil { 81 | t.Fatalf("handshakePair: %v", err) 82 | } 83 | 84 | defer trC.Close() 85 | defer trS.Close() 86 | 87 | go func() { 88 | // Client writes a bunch of stuff, and does a key 89 | // change in the middle. This should not confuse the 90 | // handshake in progress 91 | for i := 0; i < 10; i++ { 92 | p := []byte{msgRequestSuccess, byte(i)} 93 | if err := trC.writePacket(p); err != nil { 94 | t.Fatalf("sendPacket: %v", err) 95 | } 96 | if i == 5 { 97 | // halfway through, we request a key change. 98 | _, _, err := trC.sendKexInit() 99 | if err != nil { 100 | t.Fatalf("sendKexInit: %v", err) 101 | } 102 | } 103 | } 104 | trC.Close() 105 | }() 106 | 107 | // Server checks that client messages come in cleanly 108 | i := 0 109 | for { 110 | p, err := trS.readPacket() 111 | if err != nil { 112 | break 113 | } 114 | if p[0] == msgNewKeys { 115 | continue 116 | } 117 | want := []byte{msgRequestSuccess, byte(i)} 118 | if bytes.Compare(p, want) != 0 { 119 | t.Errorf("message %d: got %q, want %q", i, p, want) 120 | } 121 | i++ 122 | } 123 | if i != 10 { 124 | t.Errorf("received %d messages, want 10.", i) 125 | } 126 | 127 | // If all went well, we registered exactly 1 key change. 128 | if len(checker.calls) != 1 { 129 | t.Fatalf("got %d host key checks, want 1", len(checker.calls)) 130 | } 131 | 132 | pub := testSigners["ecdsa"].PublicKey() 133 | want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal()) 134 | if want != checker.calls[0] { 135 | t.Errorf("got %q want %q for host key check", checker.calls[0], want) 136 | } 137 | } 138 | 139 | func TestHandshakeError(t *testing.T) { 140 | checker := &testChecker{} 141 | trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad") 142 | if err != nil { 143 | t.Fatalf("handshakePair: %v", err) 144 | } 145 | defer trC.Close() 146 | defer trS.Close() 147 | 148 | // send a packet 149 | packet := []byte{msgRequestSuccess, 42} 150 | if err := trC.writePacket(packet); err != nil { 151 | t.Errorf("writePacket: %v", err) 152 | } 153 | 154 | // Now request a key change. 155 | _, _, err = trC.sendKexInit() 156 | if err != nil { 157 | t.Errorf("sendKexInit: %v", err) 158 | } 159 | 160 | // the key change will fail, and afterwards we can't write. 161 | if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil { 162 | t.Errorf("writePacket after botched rekey succeeded.") 163 | } 164 | 165 | readback, err := trS.readPacket() 166 | if err != nil { 167 | t.Fatalf("server closed too soon: %v", err) 168 | } 169 | if bytes.Compare(readback, packet) != 0 { 170 | t.Errorf("got %q want %q", readback, packet) 171 | } 172 | readback, err = trS.readPacket() 173 | if err == nil { 174 | t.Errorf("got a message %q after failed key change", readback) 175 | } 176 | } 177 | 178 | func TestHandshakeTwice(t *testing.T) { 179 | checker := &testChecker{} 180 | trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr") 181 | if err != nil { 182 | t.Fatalf("handshakePair: %v", err) 183 | } 184 | 185 | defer trC.Close() 186 | defer trS.Close() 187 | 188 | // send a packet 189 | packet := make([]byte, 5) 190 | packet[0] = msgRequestSuccess 191 | if err := trC.writePacket(packet); err != nil { 192 | t.Errorf("writePacket: %v", err) 193 | } 194 | 195 | // Now request a key change. 196 | _, _, err = trC.sendKexInit() 197 | if err != nil { 198 | t.Errorf("sendKexInit: %v", err) 199 | } 200 | 201 | // Send another packet. Use a fresh one, since writePacket destroys. 202 | packet = make([]byte, 5) 203 | packet[0] = msgRequestSuccess 204 | if err := trC.writePacket(packet); err != nil { 205 | t.Errorf("writePacket: %v", err) 206 | } 207 | 208 | // 2nd key change. 209 | _, _, err = trC.sendKexInit() 210 | if err != nil { 211 | t.Errorf("sendKexInit: %v", err) 212 | } 213 | 214 | packet = make([]byte, 5) 215 | packet[0] = msgRequestSuccess 216 | if err := trC.writePacket(packet); err != nil { 217 | t.Errorf("writePacket: %v", err) 218 | } 219 | 220 | packet = make([]byte, 5) 221 | packet[0] = msgRequestSuccess 222 | for i := 0; i < 5; i++ { 223 | msg, err := trS.readPacket() 224 | if err != nil { 225 | t.Fatalf("server closed too soon: %v", err) 226 | } 227 | if msg[0] == msgNewKeys { 228 | continue 229 | } 230 | 231 | if bytes.Compare(msg, packet) != 0 { 232 | t.Errorf("packet %d: got %q want %q", i, msg, packet) 233 | } 234 | } 235 | if len(checker.calls) != 2 { 236 | t.Errorf("got %d key changes, want 2", len(checker.calls)) 237 | } 238 | } 239 | 240 | func TestHandshakeAutoRekeyWrite(t *testing.T) { 241 | checker := &testChecker{} 242 | clientConf := &ClientConfig{HostKeyCallback: checker.Check} 243 | clientConf.RekeyThreshold = 500 244 | trC, trS, err := handshakePair(clientConf, "addr") 245 | if err != nil { 246 | t.Fatalf("handshakePair: %v", err) 247 | } 248 | defer trC.Close() 249 | defer trS.Close() 250 | 251 | for i := 0; i < 5; i++ { 252 | packet := make([]byte, 251) 253 | packet[0] = msgRequestSuccess 254 | if err := trC.writePacket(packet); err != nil { 255 | t.Errorf("writePacket: %v", err) 256 | } 257 | } 258 | 259 | j := 0 260 | for ; j < 5; j++ { 261 | _, err := trS.readPacket() 262 | if err != nil { 263 | break 264 | } 265 | } 266 | 267 | if j != 5 { 268 | t.Errorf("got %d, want 5 messages", j) 269 | } 270 | 271 | if len(checker.calls) != 2 { 272 | t.Errorf("got %d key changes, wanted 2", len(checker.calls)) 273 | } 274 | } 275 | 276 | type syncChecker struct { 277 | called chan int 278 | } 279 | 280 | func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { 281 | t.called <- 1 282 | return nil 283 | } 284 | 285 | func TestHandshakeAutoRekeyRead(t *testing.T) { 286 | sync := &syncChecker{make(chan int, 2)} 287 | clientConf := &ClientConfig{ 288 | HostKeyCallback: sync.Check, 289 | } 290 | clientConf.RekeyThreshold = 500 291 | 292 | trC, trS, err := handshakePair(clientConf, "addr") 293 | if err != nil { 294 | t.Fatalf("handshakePair: %v", err) 295 | } 296 | defer trC.Close() 297 | defer trS.Close() 298 | 299 | packet := make([]byte, 501) 300 | packet[0] = msgRequestSuccess 301 | if err := trS.writePacket(packet); err != nil { 302 | t.Fatalf("writePacket: %v", err) 303 | } 304 | // While we read out the packet, a key change will be 305 | // initiated. 306 | if _, err := trC.readPacket(); err != nil { 307 | t.Fatalf("readPacket(client): %v", err) 308 | } 309 | 310 | <-sync.called 311 | } 312 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/kex_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | // Key exchange tests. 8 | 9 | import ( 10 | "crypto/rand" 11 | "reflect" 12 | "testing" 13 | ) 14 | 15 | func TestKexes(t *testing.T) { 16 | type kexResultErr struct { 17 | result *kexResult 18 | err error 19 | } 20 | 21 | for name, kex := range kexAlgoMap { 22 | a, b := memPipe() 23 | 24 | s := make(chan kexResultErr, 1) 25 | c := make(chan kexResultErr, 1) 26 | var magics handshakeMagics 27 | go func() { 28 | r, e := kex.Client(a, rand.Reader, &magics) 29 | c <- kexResultErr{r, e} 30 | }() 31 | go func() { 32 | r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"]) 33 | s <- kexResultErr{r, e} 34 | }() 35 | 36 | clientRes := <-c 37 | serverRes := <-s 38 | if clientRes.err != nil { 39 | t.Errorf("client: %v", clientRes.err) 40 | } 41 | if serverRes.err != nil { 42 | t.Errorf("server: %v", serverRes.err) 43 | } 44 | if !reflect.DeepEqual(clientRes.result, serverRes.result) { 45 | t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/keys_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "crypto/dsa" 10 | "crypto/ecdsa" 11 | "crypto/elliptic" 12 | "crypto/rand" 13 | "crypto/rsa" 14 | "encoding/base64" 15 | "fmt" 16 | "reflect" 17 | "strings" 18 | "testing" 19 | 20 | "golang.org/x/crypto/ssh/testdata" 21 | ) 22 | 23 | func rawKey(pub PublicKey) interface{} { 24 | switch k := pub.(type) { 25 | case *rsaPublicKey: 26 | return (*rsa.PublicKey)(k) 27 | case *dsaPublicKey: 28 | return (*dsa.PublicKey)(k) 29 | case *ecdsaPublicKey: 30 | return (*ecdsa.PublicKey)(k) 31 | case *Certificate: 32 | return k 33 | } 34 | panic("unknown key type") 35 | } 36 | 37 | func TestKeyMarshalParse(t *testing.T) { 38 | for _, priv := range testSigners { 39 | pub := priv.PublicKey() 40 | roundtrip, err := ParsePublicKey(pub.Marshal()) 41 | if err != nil { 42 | t.Errorf("ParsePublicKey(%T): %v", pub, err) 43 | } 44 | 45 | k1 := rawKey(pub) 46 | k2 := rawKey(roundtrip) 47 | 48 | if !reflect.DeepEqual(k1, k2) { 49 | t.Errorf("got %#v in roundtrip, want %#v", k2, k1) 50 | } 51 | } 52 | } 53 | 54 | func TestUnsupportedCurves(t *testing.T) { 55 | raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) 56 | if err != nil { 57 | t.Fatalf("GenerateKey: %v", err) 58 | } 59 | 60 | if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P256") { 61 | t.Fatalf("NewPrivateKey should not succeed with P224, got: %v", err) 62 | } 63 | 64 | if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P256") { 65 | t.Fatalf("NewPublicKey should not succeed with P224, got: %v", err) 66 | } 67 | } 68 | 69 | func TestNewPublicKey(t *testing.T) { 70 | for _, k := range testSigners { 71 | raw := rawKey(k.PublicKey()) 72 | // Skip certificates, as NewPublicKey does not support them. 73 | if _, ok := raw.(*Certificate); ok { 74 | continue 75 | } 76 | pub, err := NewPublicKey(raw) 77 | if err != nil { 78 | t.Errorf("NewPublicKey(%#v): %v", raw, err) 79 | } 80 | if !reflect.DeepEqual(k.PublicKey(), pub) { 81 | t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) 82 | } 83 | } 84 | } 85 | 86 | func TestKeySignVerify(t *testing.T) { 87 | for _, priv := range testSigners { 88 | pub := priv.PublicKey() 89 | 90 | data := []byte("sign me") 91 | sig, err := priv.Sign(rand.Reader, data) 92 | if err != nil { 93 | t.Fatalf("Sign(%T): %v", priv, err) 94 | } 95 | 96 | if err := pub.Verify(data, sig); err != nil { 97 | t.Errorf("publicKey.Verify(%T): %v", priv, err) 98 | } 99 | sig.Blob[5]++ 100 | if err := pub.Verify(data, sig); err == nil { 101 | t.Errorf("publicKey.Verify on broken sig did not fail") 102 | } 103 | } 104 | } 105 | 106 | func TestParseRSAPrivateKey(t *testing.T) { 107 | key := testPrivateKeys["rsa"] 108 | 109 | rsa, ok := key.(*rsa.PrivateKey) 110 | if !ok { 111 | t.Fatalf("got %T, want *rsa.PrivateKey", rsa) 112 | } 113 | 114 | if err := rsa.Validate(); err != nil { 115 | t.Errorf("Validate: %v", err) 116 | } 117 | } 118 | 119 | func TestParseECPrivateKey(t *testing.T) { 120 | key := testPrivateKeys["ecdsa"] 121 | 122 | ecKey, ok := key.(*ecdsa.PrivateKey) 123 | if !ok { 124 | t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) 125 | } 126 | 127 | if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { 128 | t.Fatalf("public key does not validate.") 129 | } 130 | } 131 | 132 | func TestParseDSA(t *testing.T) { 133 | // We actually exercise the ParsePrivateKey codepath here, as opposed to 134 | // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go 135 | // uses. 136 | s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) 137 | if err != nil { 138 | t.Fatalf("ParsePrivateKey returned error: %s", err) 139 | } 140 | 141 | data := []byte("sign me") 142 | sig, err := s.Sign(rand.Reader, data) 143 | if err != nil { 144 | t.Fatalf("dsa.Sign: %v", err) 145 | } 146 | 147 | if err := s.PublicKey().Verify(data, sig); err != nil { 148 | t.Errorf("Verify failed: %v", err) 149 | } 150 | } 151 | 152 | // Tests for authorized_keys parsing. 153 | 154 | // getTestKey returns a public key, and its base64 encoding. 155 | func getTestKey() (PublicKey, string) { 156 | k := testPublicKeys["rsa"] 157 | 158 | b := &bytes.Buffer{} 159 | e := base64.NewEncoder(base64.StdEncoding, b) 160 | e.Write(k.Marshal()) 161 | e.Close() 162 | 163 | return k, b.String() 164 | } 165 | 166 | func TestMarshalParsePublicKey(t *testing.T) { 167 | pub, pubSerialized := getTestKey() 168 | line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) 169 | 170 | authKeys := MarshalAuthorizedKey(pub) 171 | actualFields := strings.Fields(string(authKeys)) 172 | if len(actualFields) == 0 { 173 | t.Fatalf("failed authKeys: %v", authKeys) 174 | } 175 | 176 | // drop the comment 177 | expectedFields := strings.Fields(line)[0:2] 178 | 179 | if !reflect.DeepEqual(actualFields, expectedFields) { 180 | t.Errorf("got %v, expected %v", actualFields, expectedFields) 181 | } 182 | 183 | actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) 184 | if err != nil { 185 | t.Fatalf("cannot parse %v: %v", line, err) 186 | } 187 | if !reflect.DeepEqual(actPub, pub) { 188 | t.Errorf("got %v, expected %v", actPub, pub) 189 | } 190 | } 191 | 192 | type authResult struct { 193 | pubKey PublicKey 194 | options []string 195 | comments string 196 | rest string 197 | ok bool 198 | } 199 | 200 | func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) { 201 | rest := authKeys 202 | var values []authResult 203 | for len(rest) > 0 { 204 | var r authResult 205 | var err error 206 | r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) 207 | r.ok = (err == nil) 208 | t.Log(err) 209 | r.rest = string(rest) 210 | values = append(values, r) 211 | } 212 | 213 | if !reflect.DeepEqual(values, expected) { 214 | t.Errorf("got %#v, expected %#v", values, expected) 215 | } 216 | } 217 | 218 | func TestAuthorizedKeyBasic(t *testing.T) { 219 | pub, pubSerialized := getTestKey() 220 | line := "ssh-rsa " + pubSerialized + " user@host" 221 | testAuthorizedKeys(t, []byte(line), 222 | []authResult{ 223 | {pub, nil, "user@host", "", true}, 224 | }) 225 | } 226 | 227 | func TestAuth(t *testing.T) { 228 | pub, pubSerialized := getTestKey() 229 | authWithOptions := []string{ 230 | `# comments to ignore before any keys...`, 231 | ``, 232 | `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, 233 | `# comments to ignore, along with a blank line`, 234 | ``, 235 | `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, 236 | ``, 237 | `# more comments, plus a invalid entry`, 238 | `ssh-rsa data-that-will-not-parse user@host3`, 239 | } 240 | for _, eol := range []string{"\n", "\r\n"} { 241 | authOptions := strings.Join(authWithOptions, eol) 242 | rest2 := strings.Join(authWithOptions[3:], eol) 243 | rest3 := strings.Join(authWithOptions[6:], eol) 244 | testAuthorizedKeys(t, []byte(authOptions), []authResult{ 245 | {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, 246 | {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, 247 | {nil, nil, "", "", false}, 248 | }) 249 | } 250 | } 251 | 252 | func TestAuthWithQuotedSpaceInEnv(t *testing.T) { 253 | pub, pubSerialized := getTestKey() 254 | authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) 255 | testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{ 256 | {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, 257 | }) 258 | } 259 | 260 | func TestAuthWithQuotedCommaInEnv(t *testing.T) { 261 | pub, pubSerialized := getTestKey() 262 | authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) 263 | testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{ 264 | {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, 265 | }) 266 | } 267 | 268 | func TestAuthWithQuotedQuoteInEnv(t *testing.T) { 269 | pub, pubSerialized := getTestKey() 270 | authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) 271 | authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) 272 | testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{ 273 | {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, 274 | }) 275 | 276 | testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{ 277 | {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, 278 | }) 279 | } 280 | 281 | func TestAuthWithInvalidSpace(t *testing.T) { 282 | _, pubSerialized := getTestKey() 283 | authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host 284 | #more to follow but still no valid keys`) 285 | testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{ 286 | {nil, nil, "", "", false}, 287 | }) 288 | } 289 | 290 | func TestAuthWithMissingQuote(t *testing.T) { 291 | pub, pubSerialized := getTestKey() 292 | authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host 293 | env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) 294 | 295 | testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{ 296 | {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, 297 | }) 298 | } 299 | 300 | func TestInvalidEntry(t *testing.T) { 301 | authInvalid := []byte(`ssh-rsa`) 302 | _, _, _, _, err := ParseAuthorizedKey(authInvalid) 303 | if err == nil { 304 | t.Errorf("got valid entry for %q", authInvalid) 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/mac.go: -------------------------------------------------------------------------------- 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 | package ssh 6 | 7 | // Message authentication support 8 | 9 | import ( 10 | "crypto/hmac" 11 | "crypto/sha1" 12 | "crypto/sha256" 13 | "hash" 14 | ) 15 | 16 | type macMode struct { 17 | keySize int 18 | new func(key []byte) hash.Hash 19 | } 20 | 21 | // truncatingMAC wraps around a hash.Hash and truncates the output digest to 22 | // a given size. 23 | type truncatingMAC struct { 24 | length int 25 | hmac hash.Hash 26 | } 27 | 28 | func (t truncatingMAC) Write(data []byte) (int, error) { 29 | return t.hmac.Write(data) 30 | } 31 | 32 | func (t truncatingMAC) Sum(in []byte) []byte { 33 | out := t.hmac.Sum(in) 34 | return out[:len(in)+t.length] 35 | } 36 | 37 | func (t truncatingMAC) Reset() { 38 | t.hmac.Reset() 39 | } 40 | 41 | func (t truncatingMAC) Size() int { 42 | return t.length 43 | } 44 | 45 | func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } 46 | 47 | var macModes = map[string]*macMode{ 48 | "hmac-sha2-256": {32, func(key []byte) hash.Hash { 49 | return hmac.New(sha256.New, key) 50 | }}, 51 | "hmac-sha1": {20, func(key []byte) hash.Hash { 52 | return hmac.New(sha1.New, key) 53 | }}, 54 | "hmac-sha1-96": {20, func(key []byte) hash.Hash { 55 | return truncatingMAC{12, hmac.New(sha1.New, key)} 56 | }}, 57 | } 58 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/mempipe_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "io" 9 | "sync" 10 | "testing" 11 | ) 12 | 13 | // An in-memory packetConn. It is safe to call Close and writePacket 14 | // from different goroutines. 15 | type memTransport struct { 16 | eof bool 17 | pending [][]byte 18 | write *memTransport 19 | sync.Mutex 20 | *sync.Cond 21 | } 22 | 23 | func (t *memTransport) readPacket() ([]byte, error) { 24 | t.Lock() 25 | defer t.Unlock() 26 | for { 27 | if len(t.pending) > 0 { 28 | r := t.pending[0] 29 | t.pending = t.pending[1:] 30 | return r, nil 31 | } 32 | if t.eof { 33 | return nil, io.EOF 34 | } 35 | t.Cond.Wait() 36 | } 37 | } 38 | 39 | func (t *memTransport) closeSelf() error { 40 | t.Lock() 41 | defer t.Unlock() 42 | if t.eof { 43 | return io.EOF 44 | } 45 | t.eof = true 46 | t.Cond.Broadcast() 47 | return nil 48 | } 49 | 50 | func (t *memTransport) Close() error { 51 | err := t.write.closeSelf() 52 | t.closeSelf() 53 | return err 54 | } 55 | 56 | func (t *memTransport) writePacket(p []byte) error { 57 | t.write.Lock() 58 | defer t.write.Unlock() 59 | if t.write.eof { 60 | return io.EOF 61 | } 62 | c := make([]byte, len(p)) 63 | copy(c, p) 64 | t.write.pending = append(t.write.pending, c) 65 | t.write.Cond.Signal() 66 | return nil 67 | } 68 | 69 | func memPipe() (a, b packetConn) { 70 | t1 := memTransport{} 71 | t2 := memTransport{} 72 | t1.write = &t2 73 | t2.write = &t1 74 | t1.Cond = sync.NewCond(&t1.Mutex) 75 | t2.Cond = sync.NewCond(&t2.Mutex) 76 | return &t1, &t2 77 | } 78 | 79 | func TestmemPipe(t *testing.T) { 80 | a, b := memPipe() 81 | if err := a.writePacket([]byte{42}); err != nil { 82 | t.Fatalf("writePacket: %v", err) 83 | } 84 | if err := a.Close(); err != nil { 85 | t.Fatal("Close: ", err) 86 | } 87 | p, err := b.readPacket() 88 | if err != nil { 89 | t.Fatal("readPacket: ", err) 90 | } 91 | if len(p) != 1 || p[0] != 42 { 92 | t.Fatalf("got %v, want {42}", p) 93 | } 94 | p, err = b.readPacket() 95 | if err != io.EOF { 96 | t.Fatalf("got %v, %v, want EOF", p, err) 97 | } 98 | } 99 | 100 | func TestDoubleClose(t *testing.T) { 101 | a, _ := memPipe() 102 | err := a.Close() 103 | if err != nil { 104 | t.Errorf("Close: %v", err) 105 | } 106 | err = a.Close() 107 | if err != io.EOF { 108 | t.Errorf("expect EOF on double close.") 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/messages_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "math/big" 10 | "math/rand" 11 | "reflect" 12 | "testing" 13 | "testing/quick" 14 | ) 15 | 16 | var intLengthTests = []struct { 17 | val, length int 18 | }{ 19 | {0, 4 + 0}, 20 | {1, 4 + 1}, 21 | {127, 4 + 1}, 22 | {128, 4 + 2}, 23 | {-1, 4 + 1}, 24 | } 25 | 26 | func TestIntLength(t *testing.T) { 27 | for _, test := range intLengthTests { 28 | v := new(big.Int).SetInt64(int64(test.val)) 29 | length := intLength(v) 30 | if length != test.length { 31 | t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) 32 | } 33 | } 34 | } 35 | 36 | type msgAllTypes struct { 37 | Bool bool `sshtype:"21"` 38 | Array [16]byte 39 | Uint64 uint64 40 | Uint32 uint32 41 | Uint8 uint8 42 | String string 43 | Strings []string 44 | Bytes []byte 45 | Int *big.Int 46 | Rest []byte `ssh:"rest"` 47 | } 48 | 49 | func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { 50 | m := &msgAllTypes{} 51 | m.Bool = rand.Intn(2) == 1 52 | randomBytes(m.Array[:], rand) 53 | m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) 54 | m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) 55 | m.Uint8 = uint8(rand.Intn(1 << 8)) 56 | m.String = string(m.Array[:]) 57 | m.Strings = randomNameList(rand) 58 | m.Bytes = m.Array[:] 59 | m.Int = randomInt(rand) 60 | m.Rest = m.Array[:] 61 | return reflect.ValueOf(m) 62 | } 63 | 64 | func TestMarshalUnmarshal(t *testing.T) { 65 | rand := rand.New(rand.NewSource(0)) 66 | iface := &msgAllTypes{} 67 | ty := reflect.ValueOf(iface).Type() 68 | 69 | n := 100 70 | if testing.Short() { 71 | n = 5 72 | } 73 | for j := 0; j < n; j++ { 74 | v, ok := quick.Value(ty, rand) 75 | if !ok { 76 | t.Errorf("failed to create value") 77 | break 78 | } 79 | 80 | m1 := v.Elem().Interface() 81 | m2 := iface 82 | 83 | marshaled := Marshal(m1) 84 | if err := Unmarshal(marshaled, m2); err != nil { 85 | t.Errorf("Unmarshal %#v: %s", m1, err) 86 | break 87 | } 88 | 89 | if !reflect.DeepEqual(v.Interface(), m2) { 90 | t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) 91 | break 92 | } 93 | } 94 | } 95 | 96 | func TestUnmarshalEmptyPacket(t *testing.T) { 97 | var b []byte 98 | var m channelRequestSuccessMsg 99 | if err := Unmarshal(b, &m); err == nil { 100 | t.Fatalf("unmarshal of empty slice succeeded") 101 | } 102 | } 103 | 104 | func TestUnmarshalUnexpectedPacket(t *testing.T) { 105 | type S struct { 106 | I uint32 `sshtype:"43"` 107 | S string 108 | B bool 109 | } 110 | 111 | s := S{11, "hello", true} 112 | packet := Marshal(s) 113 | packet[0] = 42 114 | roundtrip := S{} 115 | err := Unmarshal(packet, &roundtrip) 116 | if err == nil { 117 | t.Fatal("expected error, not nil") 118 | } 119 | } 120 | 121 | func TestMarshalPtr(t *testing.T) { 122 | s := struct { 123 | S string 124 | }{"hello"} 125 | 126 | m1 := Marshal(s) 127 | m2 := Marshal(&s) 128 | if !bytes.Equal(m1, m2) { 129 | t.Errorf("got %q, want %q for marshaled pointer", m2, m1) 130 | } 131 | } 132 | 133 | func TestBareMarshalUnmarshal(t *testing.T) { 134 | type S struct { 135 | I uint32 136 | S string 137 | B bool 138 | } 139 | 140 | s := S{42, "hello", true} 141 | packet := Marshal(s) 142 | roundtrip := S{} 143 | Unmarshal(packet, &roundtrip) 144 | 145 | if !reflect.DeepEqual(s, roundtrip) { 146 | t.Errorf("got %#v, want %#v", roundtrip, s) 147 | } 148 | } 149 | 150 | func TestBareMarshal(t *testing.T) { 151 | type S2 struct { 152 | I uint32 153 | } 154 | s := S2{42} 155 | packet := Marshal(s) 156 | i, rest, ok := parseUint32(packet) 157 | if len(rest) > 0 || !ok { 158 | t.Errorf("parseInt(%q): parse error", packet) 159 | } 160 | if i != s.I { 161 | t.Errorf("got %d, want %d", i, s.I) 162 | } 163 | } 164 | 165 | func randomBytes(out []byte, rand *rand.Rand) { 166 | for i := 0; i < len(out); i++ { 167 | out[i] = byte(rand.Int31()) 168 | } 169 | } 170 | 171 | func randomNameList(rand *rand.Rand) []string { 172 | ret := make([]string, rand.Int31()&15) 173 | for i := range ret { 174 | s := make([]byte, 1+(rand.Int31()&15)) 175 | for j := range s { 176 | s[j] = 'a' + uint8(rand.Int31()&15) 177 | } 178 | ret[i] = string(s) 179 | } 180 | return ret 181 | } 182 | 183 | func randomInt(rand *rand.Rand) *big.Int { 184 | return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) 185 | } 186 | 187 | func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { 188 | ki := &kexInitMsg{} 189 | randomBytes(ki.Cookie[:], rand) 190 | ki.KexAlgos = randomNameList(rand) 191 | ki.ServerHostKeyAlgos = randomNameList(rand) 192 | ki.CiphersClientServer = randomNameList(rand) 193 | ki.CiphersServerClient = randomNameList(rand) 194 | ki.MACsClientServer = randomNameList(rand) 195 | ki.MACsServerClient = randomNameList(rand) 196 | ki.CompressionClientServer = randomNameList(rand) 197 | ki.CompressionServerClient = randomNameList(rand) 198 | ki.LanguagesClientServer = randomNameList(rand) 199 | ki.LanguagesServerClient = randomNameList(rand) 200 | if rand.Int31()&1 == 1 { 201 | ki.FirstKexFollows = true 202 | } 203 | return reflect.ValueOf(ki) 204 | } 205 | 206 | func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { 207 | dhi := &kexDHInitMsg{} 208 | dhi.X = randomInt(rand) 209 | return reflect.ValueOf(dhi) 210 | } 211 | 212 | var ( 213 | _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() 214 | _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() 215 | 216 | _kexInit = Marshal(_kexInitMsg) 217 | _kexDHInit = Marshal(_kexDHInitMsg) 218 | ) 219 | 220 | func BenchmarkMarshalKexInitMsg(b *testing.B) { 221 | for i := 0; i < b.N; i++ { 222 | Marshal(_kexInitMsg) 223 | } 224 | } 225 | 226 | func BenchmarkUnmarshalKexInitMsg(b *testing.B) { 227 | m := new(kexInitMsg) 228 | for i := 0; i < b.N; i++ { 229 | Unmarshal(_kexInit, m) 230 | } 231 | } 232 | 233 | func BenchmarkMarshalKexDHInitMsg(b *testing.B) { 234 | for i := 0; i < b.N; i++ { 235 | Marshal(_kexDHInitMsg) 236 | } 237 | } 238 | 239 | func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { 240 | m := new(kexDHInitMsg) 241 | for i := 0; i < b.N; i++ { 242 | Unmarshal(_kexDHInit, m) 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/mux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package ssh 6 | 7 | import ( 8 | "encoding/binary" 9 | "fmt" 10 | "io" 11 | "log" 12 | "sync" 13 | "sync/atomic" 14 | ) 15 | 16 | // debugMux, if set, causes messages in the connection protocol to be 17 | // logged. 18 | const debugMux = false 19 | 20 | // chanList is a thread safe channel list. 21 | type chanList struct { 22 | // protects concurrent access to chans 23 | sync.Mutex 24 | 25 | // chans are indexed by the local id of the channel, which the 26 | // other side should send in the PeersId field. 27 | chans []*channel 28 | 29 | // This is a debugging aid: it offsets all IDs by this 30 | // amount. This helps distinguish otherwise identical 31 | // server/client muxes 32 | offset uint32 33 | } 34 | 35 | // Assigns a channel ID to the given channel. 36 | func (c *chanList) add(ch *channel) uint32 { 37 | c.Lock() 38 | defer c.Unlock() 39 | for i := range c.chans { 40 | if c.chans[i] == nil { 41 | c.chans[i] = ch 42 | return uint32(i) + c.offset 43 | } 44 | } 45 | c.chans = append(c.chans, ch) 46 | return uint32(len(c.chans)-1) + c.offset 47 | } 48 | 49 | // getChan returns the channel for the given ID. 50 | func (c *chanList) getChan(id uint32) *channel { 51 | id -= c.offset 52 | 53 | c.Lock() 54 | defer c.Unlock() 55 | if id < uint32(len(c.chans)) { 56 | return c.chans[id] 57 | } 58 | return nil 59 | } 60 | 61 | func (c *chanList) remove(id uint32) { 62 | id -= c.offset 63 | c.Lock() 64 | if id < uint32(len(c.chans)) { 65 | c.chans[id] = nil 66 | } 67 | c.Unlock() 68 | } 69 | 70 | // dropAll forgets all channels it knows, returning them in a slice. 71 | func (c *chanList) dropAll() []*channel { 72 | c.Lock() 73 | defer c.Unlock() 74 | var r []*channel 75 | 76 | for _, ch := range c.chans { 77 | if ch == nil { 78 | continue 79 | } 80 | r = append(r, ch) 81 | } 82 | c.chans = nil 83 | return r 84 | } 85 | 86 | // mux represents the state for the SSH connection protocol, which 87 | // multiplexes many channels onto a single packet transport. 88 | type mux struct { 89 | conn packetConn 90 | chanList chanList 91 | 92 | incomingChannels chan NewChannel 93 | 94 | globalSentMu sync.Mutex 95 | globalResponses chan interface{} 96 | incomingRequests chan *Request 97 | 98 | errCond *sync.Cond 99 | err error 100 | } 101 | 102 | // When debugging, each new chanList instantiation has a different 103 | // offset. 104 | var globalOff uint32 105 | 106 | func (m *mux) Wait() error { 107 | m.errCond.L.Lock() 108 | defer m.errCond.L.Unlock() 109 | for m.err == nil { 110 | m.errCond.Wait() 111 | } 112 | return m.err 113 | } 114 | 115 | // newMux returns a mux that runs over the given connection. 116 | func newMux(p packetConn) *mux { 117 | m := &mux{ 118 | conn: p, 119 | incomingChannels: make(chan NewChannel, 16), 120 | globalResponses: make(chan interface{}, 1), 121 | incomingRequests: make(chan *Request, 16), 122 | errCond: newCond(), 123 | } 124 | if debugMux { 125 | m.chanList.offset = atomic.AddUint32(&globalOff, 1) 126 | } 127 | 128 | go m.loop() 129 | return m 130 | } 131 | 132 | func (m *mux) sendMessage(msg interface{}) error { 133 | p := Marshal(msg) 134 | return m.conn.writePacket(p) 135 | } 136 | 137 | func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { 138 | if wantReply { 139 | m.globalSentMu.Lock() 140 | defer m.globalSentMu.Unlock() 141 | } 142 | 143 | if err := m.sendMessage(globalRequestMsg{ 144 | Type: name, 145 | WantReply: wantReply, 146 | Data: payload, 147 | }); err != nil { 148 | return false, nil, err 149 | } 150 | 151 | if !wantReply { 152 | return false, nil, nil 153 | } 154 | 155 | msg, ok := <-m.globalResponses 156 | if !ok { 157 | return false, nil, io.EOF 158 | } 159 | switch msg := msg.(type) { 160 | case *globalRequestFailureMsg: 161 | return false, msg.Data, nil 162 | case *globalRequestSuccessMsg: 163 | return true, msg.Data, nil 164 | default: 165 | return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) 166 | } 167 | } 168 | 169 | // ackRequest must be called after processing a global request that 170 | // has WantReply set. 171 | func (m *mux) ackRequest(ok bool, data []byte) error { 172 | if ok { 173 | return m.sendMessage(globalRequestSuccessMsg{Data: data}) 174 | } 175 | return m.sendMessage(globalRequestFailureMsg{Data: data}) 176 | } 177 | 178 | // TODO(hanwen): Disconnect is a transport layer message. We should 179 | // probably send and receive Disconnect somewhere in the transport 180 | // code. 181 | 182 | // Disconnect sends a disconnect message. 183 | func (m *mux) Disconnect(reason uint32, message string) error { 184 | return m.sendMessage(disconnectMsg{ 185 | Reason: reason, 186 | Message: message, 187 | }) 188 | } 189 | 190 | func (m *mux) Close() error { 191 | return m.conn.Close() 192 | } 193 | 194 | // loop runs the connection machine. It will process packets until an 195 | // error is encountered. To synchronize on loop exit, use mux.Wait. 196 | func (m *mux) loop() { 197 | var err error 198 | for err == nil { 199 | err = m.onePacket() 200 | } 201 | 202 | for _, ch := range m.chanList.dropAll() { 203 | ch.close() 204 | } 205 | 206 | close(m.incomingChannels) 207 | close(m.incomingRequests) 208 | close(m.globalResponses) 209 | 210 | m.conn.Close() 211 | 212 | m.errCond.L.Lock() 213 | m.err = err 214 | m.errCond.Broadcast() 215 | m.errCond.L.Unlock() 216 | 217 | if debugMux { 218 | log.Println("loop exit", err) 219 | } 220 | } 221 | 222 | // onePacket reads and processes one packet. 223 | func (m *mux) onePacket() error { 224 | packet, err := m.conn.readPacket() 225 | if err != nil { 226 | return err 227 | } 228 | 229 | if debugMux { 230 | if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { 231 | log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) 232 | } else { 233 | p, _ := decode(packet) 234 | log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) 235 | } 236 | } 237 | 238 | switch packet[0] { 239 | case msgNewKeys: 240 | // Ignore notification of key change. 241 | return nil 242 | case msgDisconnect: 243 | return m.handleDisconnect(packet) 244 | case msgChannelOpen: 245 | return m.handleChannelOpen(packet) 246 | case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: 247 | return m.handleGlobalPacket(packet) 248 | } 249 | 250 | // assume a channel packet. 251 | if len(packet) < 5 { 252 | return parseError(packet[0]) 253 | } 254 | id := binary.BigEndian.Uint32(packet[1:]) 255 | ch := m.chanList.getChan(id) 256 | if ch == nil { 257 | return fmt.Errorf("ssh: invalid channel %d", id) 258 | } 259 | 260 | return ch.handlePacket(packet) 261 | } 262 | 263 | func (m *mux) handleDisconnect(packet []byte) error { 264 | var d disconnectMsg 265 | if err := Unmarshal(packet, &d); err != nil { 266 | return err 267 | } 268 | 269 | if debugMux { 270 | log.Printf("caught disconnect: %v", d) 271 | } 272 | return &d 273 | } 274 | 275 | func (m *mux) handleGlobalPacket(packet []byte) error { 276 | msg, err := decode(packet) 277 | if err != nil { 278 | return err 279 | } 280 | 281 | switch msg := msg.(type) { 282 | case *globalRequestMsg: 283 | m.incomingRequests <- &Request{ 284 | Type: msg.Type, 285 | WantReply: msg.WantReply, 286 | Payload: msg.Data, 287 | mux: m, 288 | } 289 | case *globalRequestSuccessMsg, *globalRequestFailureMsg: 290 | m.globalResponses <- msg 291 | default: 292 | panic(fmt.Sprintf("not a global message %#v", msg)) 293 | } 294 | 295 | return nil 296 | } 297 | 298 | // handleChannelOpen schedules a channel to be Accept()ed. 299 | func (m *mux) handleChannelOpen(packet []byte) error { 300 | var msg channelOpenMsg 301 | if err := Unmarshal(packet, &msg); err != nil { 302 | return err 303 | } 304 | 305 | if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { 306 | failMsg := channelOpenFailureMsg{ 307 | PeersId: msg.PeersId, 308 | Reason: ConnectionFailed, 309 | Message: "invalid request", 310 | Language: "en_US.UTF-8", 311 | } 312 | return m.sendMessage(failMsg) 313 | } 314 | 315 | c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) 316 | c.remoteId = msg.PeersId 317 | c.maxRemotePayload = msg.MaxPacketSize 318 | c.remoteWin.add(msg.PeersWindow) 319 | m.incomingChannels <- c 320 | return nil 321 | } 322 | 323 | func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { 324 | ch, err := m.openChannel(chanType, extra) 325 | if err != nil { 326 | return nil, nil, err 327 | } 328 | 329 | return ch, ch.incomingRequests, nil 330 | } 331 | 332 | func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { 333 | ch := m.newChannel(chanType, channelOutbound, extra) 334 | 335 | ch.maxIncomingPayload = channelMaxPacket 336 | 337 | open := channelOpenMsg{ 338 | ChanType: chanType, 339 | PeersWindow: ch.myWindow, 340 | MaxPacketSize: ch.maxIncomingPayload, 341 | TypeSpecificData: extra, 342 | PeersId: ch.localId, 343 | } 344 | if err := m.sendMessage(open); err != nil { 345 | return nil, err 346 | } 347 | 348 | switch msg := (<-ch.msg).(type) { 349 | case *channelOpenConfirmMsg: 350 | return ch, nil 351 | case *channelOpenFailureMsg: 352 | return nil, &OpenChannelError{msg.Reason, msg.Message} 353 | default: 354 | return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/tcpip_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package ssh 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestAutoPortListenBroken(t *testing.T) { 12 | broken := "SSH-2.0-OpenSSH_5.9hh11" 13 | works := "SSH-2.0-OpenSSH_6.1" 14 | if !isBrokenOpenSSHVersion(broken) { 15 | t.Errorf("version %q not marked as broken", broken) 16 | } 17 | if isBrokenOpenSSHVersion(works) { 18 | t.Errorf("version %q marked as broken", works) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/terminal/terminal_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package terminal 6 | 7 | import ( 8 | "io" 9 | "testing" 10 | ) 11 | 12 | type MockTerminal struct { 13 | toSend []byte 14 | bytesPerRead int 15 | received []byte 16 | } 17 | 18 | func (c *MockTerminal) Read(data []byte) (n int, err error) { 19 | n = len(data) 20 | if n == 0 { 21 | return 22 | } 23 | if n > len(c.toSend) { 24 | n = len(c.toSend) 25 | } 26 | if n == 0 { 27 | return 0, io.EOF 28 | } 29 | if c.bytesPerRead > 0 && n > c.bytesPerRead { 30 | n = c.bytesPerRead 31 | } 32 | copy(data, c.toSend[:n]) 33 | c.toSend = c.toSend[n:] 34 | return 35 | } 36 | 37 | func (c *MockTerminal) Write(data []byte) (n int, err error) { 38 | c.received = append(c.received, data...) 39 | return len(data), nil 40 | } 41 | 42 | func TestClose(t *testing.T) { 43 | c := &MockTerminal{} 44 | ss := NewTerminal(c, "> ") 45 | line, err := ss.ReadLine() 46 | if line != "" { 47 | t.Errorf("Expected empty line but got: %s", line) 48 | } 49 | if err != io.EOF { 50 | t.Errorf("Error should have been EOF but got: %s", err) 51 | } 52 | } 53 | 54 | var keyPressTests = []struct { 55 | in string 56 | line string 57 | err error 58 | throwAwayLines int 59 | }{ 60 | { 61 | err: io.EOF, 62 | }, 63 | { 64 | in: "\r", 65 | line: "", 66 | }, 67 | { 68 | in: "foo\r", 69 | line: "foo", 70 | }, 71 | { 72 | in: "a\x1b[Cb\r", // right 73 | line: "ab", 74 | }, 75 | { 76 | in: "a\x1b[Db\r", // left 77 | line: "ba", 78 | }, 79 | { 80 | in: "a\177b\r", // backspace 81 | line: "b", 82 | }, 83 | { 84 | in: "\x1b[A\r", // up 85 | }, 86 | { 87 | in: "\x1b[B\r", // down 88 | }, 89 | { 90 | in: "line\x1b[A\x1b[B\r", // up then down 91 | line: "line", 92 | }, 93 | { 94 | in: "line1\rline2\x1b[A\r", // recall previous line. 95 | line: "line1", 96 | throwAwayLines: 1, 97 | }, 98 | { 99 | // recall two previous lines and append. 100 | in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r", 101 | line: "line1xxx", 102 | throwAwayLines: 2, 103 | }, 104 | { 105 | // Ctrl-A to move to beginning of line followed by ^K to kill 106 | // line. 107 | in: "a b \001\013\r", 108 | line: "", 109 | }, 110 | { 111 | // Ctrl-A to move to beginning of line, Ctrl-E to move to end, 112 | // finally ^K to kill nothing. 113 | in: "a b \001\005\013\r", 114 | line: "a b ", 115 | }, 116 | { 117 | in: "\027\r", 118 | line: "", 119 | }, 120 | { 121 | in: "a\027\r", 122 | line: "", 123 | }, 124 | { 125 | in: "a \027\r", 126 | line: "", 127 | }, 128 | { 129 | in: "a b\027\r", 130 | line: "a ", 131 | }, 132 | { 133 | in: "a b \027\r", 134 | line: "a ", 135 | }, 136 | { 137 | in: "one two thr\x1b[D\027\r", 138 | line: "one two r", 139 | }, 140 | { 141 | in: "\013\r", 142 | line: "", 143 | }, 144 | { 145 | in: "a\013\r", 146 | line: "a", 147 | }, 148 | { 149 | in: "ab\x1b[D\013\r", 150 | line: "a", 151 | }, 152 | { 153 | in: "Ξεσκεπάζω\r", 154 | line: "Ξεσκεπάζω", 155 | }, 156 | { 157 | in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace. 158 | line: "", 159 | throwAwayLines: 1, 160 | }, 161 | { 162 | in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter. 163 | line: "£", 164 | throwAwayLines: 1, 165 | }, 166 | { 167 | // Ctrl-D at the end of the line should be ignored. 168 | in: "a\004\r", 169 | line: "a", 170 | }, 171 | { 172 | // a, b, left, Ctrl-D should erase the b. 173 | in: "ab\x1b[D\004\r", 174 | line: "a", 175 | }, 176 | { 177 | // a, b, c, d, left, left, ^U should erase to the beginning of 178 | // the line. 179 | in: "abcd\x1b[D\x1b[D\025\r", 180 | line: "cd", 181 | }, 182 | { 183 | // Bracketed paste mode: control sequences should be returned 184 | // verbatim in paste mode. 185 | in: "abc\x1b[200~de\177f\x1b[201~\177\r", 186 | line: "abcde\177", 187 | }, 188 | { 189 | // Enter in bracketed paste mode should still work. 190 | in: "abc\x1b[200~d\refg\x1b[201~h\r", 191 | line: "efgh", 192 | throwAwayLines: 1, 193 | }, 194 | { 195 | // Lines consisting entirely of pasted data should be indicated as such. 196 | in: "\x1b[200~a\r", 197 | line: "a", 198 | err: ErrPasteIndicator, 199 | }, 200 | } 201 | 202 | func TestKeyPresses(t *testing.T) { 203 | for i, test := range keyPressTests { 204 | for j := 1; j < len(test.in); j++ { 205 | c := &MockTerminal{ 206 | toSend: []byte(test.in), 207 | bytesPerRead: j, 208 | } 209 | ss := NewTerminal(c, "> ") 210 | for k := 0; k < test.throwAwayLines; k++ { 211 | _, err := ss.ReadLine() 212 | if err != nil { 213 | t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err) 214 | } 215 | } 216 | line, err := ss.ReadLine() 217 | if line != test.line { 218 | t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line) 219 | break 220 | } 221 | if err != test.err { 222 | t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) 223 | break 224 | } 225 | } 226 | } 227 | } 228 | 229 | func TestPasswordNotSaved(t *testing.T) { 230 | c := &MockTerminal{ 231 | toSend: []byte("password\r\x1b[A\r"), 232 | bytesPerRead: 1, 233 | } 234 | ss := NewTerminal(c, "> ") 235 | pw, _ := ss.ReadPassword("> ") 236 | if pw != "password" { 237 | t.Fatalf("failed to read password, got %s", pw) 238 | } 239 | line, _ := ss.ReadLine() 240 | if len(line) > 0 { 241 | t.Fatalf("password was saved in history") 242 | } 243 | } 244 | 245 | var setSizeTests = []struct { 246 | width, height int 247 | }{ 248 | {40, 13}, 249 | {80, 24}, 250 | {132, 43}, 251 | } 252 | 253 | func TestTerminalSetSize(t *testing.T) { 254 | for _, setSize := range setSizeTests { 255 | c := &MockTerminal{ 256 | toSend: []byte("password\r\x1b[A\r"), 257 | bytesPerRead: 1, 258 | } 259 | ss := NewTerminal(c, "> ") 260 | ss.SetSize(setSize.width, setSize.height) 261 | pw, _ := ss.ReadPassword("Password: ") 262 | if pw != "password" { 263 | t.Fatalf("failed to read password, got %s", pw) 264 | } 265 | if string(c.received) != "Password: \r\n" { 266 | t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received) 267 | } 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/terminal/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 darwin dragonfly freebsd linux,!appengine netbsd openbsd 6 | 7 | // Package terminal provides support functions for dealing with terminals, as 8 | // commonly found on UNIX systems. 9 | // 10 | // Putting a terminal into raw mode is the most common requirement: 11 | // 12 | // oldState, err := terminal.MakeRaw(0) 13 | // if err != nil { 14 | // panic(err) 15 | // } 16 | // defer terminal.Restore(0, oldState) 17 | package terminal // import "golang.org/x/crypto/ssh/terminal" 18 | 19 | import ( 20 | "io" 21 | "syscall" 22 | "unsafe" 23 | ) 24 | 25 | // State contains the state of a terminal. 26 | type State struct { 27 | termios syscall.Termios 28 | } 29 | 30 | // IsTerminal returns true if the given file descriptor is a terminal. 31 | func IsTerminal(fd int) bool { 32 | var termios syscall.Termios 33 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 34 | return err == 0 35 | } 36 | 37 | // MakeRaw put the terminal connected to the given file descriptor into raw 38 | // mode and returns the previous state of the terminal so that it can be 39 | // restored. 40 | func MakeRaw(fd int) (*State, error) { 41 | var oldState State 42 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { 43 | return nil, err 44 | } 45 | 46 | newState := oldState.termios 47 | newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF 48 | newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG 49 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { 50 | return nil, err 51 | } 52 | 53 | return &oldState, nil 54 | } 55 | 56 | // GetState returns the current state of a terminal which may be useful to 57 | // restore the terminal after a signal. 58 | func GetState(fd int) (*State, error) { 59 | var oldState State 60 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { 61 | return nil, err 62 | } 63 | 64 | return &oldState, nil 65 | } 66 | 67 | // Restore restores the terminal connected to the given file descriptor to a 68 | // previous state. 69 | func Restore(fd int, state *State) error { 70 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) 71 | return err 72 | } 73 | 74 | // GetSize returns the dimensions of the given terminal. 75 | func GetSize(fd int) (width, height int, err error) { 76 | var dimensions [4]uint16 77 | 78 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { 79 | return -1, -1, err 80 | } 81 | return int(dimensions[1]), int(dimensions[0]), nil 82 | } 83 | 84 | // ReadPassword reads a line of input from a terminal without local echo. This 85 | // is commonly used for inputting passwords and other sensitive data. The slice 86 | // returned does not include the \n. 87 | func ReadPassword(fd int) ([]byte, error) { 88 | var oldState syscall.Termios 89 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { 90 | return nil, err 91 | } 92 | 93 | newState := oldState 94 | newState.Lflag &^= syscall.ECHO 95 | newState.Lflag |= syscall.ICANON | syscall.ISIG 96 | newState.Iflag |= syscall.ICRNL 97 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { 98 | return nil, err 99 | } 100 | 101 | defer func() { 102 | syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) 103 | }() 104 | 105 | var buf [16]byte 106 | var ret []byte 107 | for { 108 | n, err := syscall.Read(fd, buf[:]) 109 | if err != nil { 110 | return nil, err 111 | } 112 | if n == 0 { 113 | if len(ret) == 0 { 114 | return nil, io.EOF 115 | } 116 | break 117 | } 118 | if buf[n-1] == '\n' { 119 | n-- 120 | } 121 | ret = append(ret, buf[:n]...) 122 | if n < len(buf) { 123 | break 124 | } 125 | } 126 | 127 | return ret, nil 128 | } 129 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/terminal/util_bsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 darwin dragonfly freebsd netbsd openbsd 6 | 7 | package terminal 8 | 9 | import "syscall" 10 | 11 | const ioctlReadTermios = syscall.TIOCGETA 12 | const ioctlWriteTermios = syscall.TIOCSETA 13 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/terminal/util_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 | package terminal 6 | 7 | // These constants are declared here, rather than importing 8 | // them from the syscall package as some syscall packages, even 9 | // on linux, for example gccgo, do not declare them. 10 | const ioctlReadTermios = 0x5401 // syscall.TCGETS 11 | const ioctlWriteTermios = 0x5402 // syscall.TCSETS 12 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/terminal/util_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 terminal provides support functions for dealing with terminals, as 8 | // commonly found on UNIX systems. 9 | // 10 | // Putting a terminal into raw mode is the most common requirement: 11 | // 12 | // oldState, err := terminal.MakeRaw(0) 13 | // if err != nil { 14 | // panic(err) 15 | // } 16 | // defer terminal.Restore(0, oldState) 17 | package terminal 18 | 19 | import ( 20 | "io" 21 | "syscall" 22 | "unsafe" 23 | ) 24 | 25 | const ( 26 | enableLineInput = 2 27 | enableEchoInput = 4 28 | enableProcessedInput = 1 29 | enableWindowInput = 8 30 | enableMouseInput = 16 31 | enableInsertMode = 32 32 | enableQuickEditMode = 64 33 | enableExtendedFlags = 128 34 | enableAutoPosition = 256 35 | enableProcessedOutput = 1 36 | enableWrapAtEolOutput = 2 37 | ) 38 | 39 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 40 | 41 | var ( 42 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 43 | procSetConsoleMode = kernel32.NewProc("SetConsoleMode") 44 | procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") 45 | ) 46 | 47 | type ( 48 | short int16 49 | word uint16 50 | 51 | coord struct { 52 | x short 53 | y short 54 | } 55 | smallRect struct { 56 | left short 57 | top short 58 | right short 59 | bottom short 60 | } 61 | consoleScreenBufferInfo struct { 62 | size coord 63 | cursorPosition coord 64 | attributes word 65 | window smallRect 66 | maximumWindowSize coord 67 | } 68 | ) 69 | 70 | type State struct { 71 | mode uint32 72 | } 73 | 74 | // IsTerminal returns true if the given file descriptor is a terminal. 75 | func IsTerminal(fd int) bool { 76 | var st uint32 77 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 78 | return r != 0 && e == 0 79 | } 80 | 81 | // MakeRaw put the terminal connected to the given file descriptor into raw 82 | // mode and returns the previous state of the terminal so that it can be 83 | // restored. 84 | func MakeRaw(fd int) (*State, error) { 85 | var st uint32 86 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 87 | if e != 0 { 88 | return nil, error(e) 89 | } 90 | st &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) 91 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) 92 | if e != 0 { 93 | return nil, error(e) 94 | } 95 | return &State{st}, nil 96 | } 97 | 98 | // GetState returns the current state of a terminal which may be useful to 99 | // restore the terminal after a signal. 100 | func GetState(fd int) (*State, error) { 101 | var st uint32 102 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 103 | if e != 0 { 104 | return nil, error(e) 105 | } 106 | return &State{st}, nil 107 | } 108 | 109 | // Restore restores the terminal connected to the given file descriptor to a 110 | // previous state. 111 | func Restore(fd int, state *State) error { 112 | _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) 113 | return err 114 | } 115 | 116 | // GetSize returns the dimensions of the given terminal. 117 | func GetSize(fd int) (width, height int, err error) { 118 | var info consoleScreenBufferInfo 119 | _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) 120 | if e != 0 { 121 | return 0, 0, error(e) 122 | } 123 | return int(info.size.x), int(info.size.y), nil 124 | } 125 | 126 | // ReadPassword reads a line of input from a terminal without local echo. This 127 | // is commonly used for inputting passwords and other sensitive data. The slice 128 | // returned does not include the \n. 129 | func ReadPassword(fd int) ([]byte, error) { 130 | var st uint32 131 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 132 | if e != 0 { 133 | return nil, error(e) 134 | } 135 | old := st 136 | 137 | st &^= (enableEchoInput) 138 | st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) 139 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) 140 | if e != 0 { 141 | return nil, error(e) 142 | } 143 | 144 | defer func() { 145 | syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) 146 | }() 147 | 148 | var buf [16]byte 149 | var ret []byte 150 | for { 151 | n, err := syscall.Read(syscall.Handle(fd), buf[:]) 152 | if err != nil { 153 | return nil, err 154 | } 155 | if n == 0 { 156 | if len(ret) == 0 { 157 | return nil, io.EOF 158 | } 159 | break 160 | } 161 | if buf[n-1] == '\n' { 162 | n-- 163 | } 164 | if n > 0 && buf[n-1] == '\r' { 165 | n-- 166 | } 167 | ret = append(ret, buf[:n]...) 168 | if n < len(buf) { 169 | break 170 | } 171 | } 172 | 173 | return ret, nil 174 | } 175 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/agent_unix_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 darwin dragonfly freebsd linux netbsd openbsd 6 | 7 | package test 8 | 9 | import ( 10 | "bytes" 11 | "testing" 12 | 13 | "golang.org/x/crypto/ssh" 14 | "golang.org/x/crypto/ssh/agent" 15 | ) 16 | 17 | func TestAgentForward(t *testing.T) { 18 | server := newServer(t) 19 | defer server.Shutdown() 20 | conn := server.Dial(clientConfig()) 21 | defer conn.Close() 22 | 23 | keyring := agent.NewKeyring() 24 | keyring.Add(testPrivateKeys["dsa"], nil, "") 25 | pub := testPublicKeys["dsa"] 26 | 27 | sess, err := conn.NewSession() 28 | if err != nil { 29 | t.Fatalf("NewSession: %v", err) 30 | } 31 | if err := agent.RequestAgentForwarding(sess); err != nil { 32 | t.Fatalf("RequestAgentForwarding: %v", err) 33 | } 34 | 35 | if err := agent.ForwardToAgent(conn, keyring); err != nil { 36 | t.Fatalf("SetupForwardKeyring: %v", err) 37 | } 38 | out, err := sess.CombinedOutput("ssh-add -L") 39 | if err != nil { 40 | t.Fatalf("running ssh-add: %v, out %s", err, out) 41 | } 42 | key, _, _, _, err := ssh.ParseAuthorizedKey(out) 43 | if err != nil { 44 | t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) 45 | } 46 | 47 | if !bytes.Equal(key.Marshal(), pub.Marshal()) { 48 | t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/cert_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 darwin dragonfly freebsd linux netbsd openbsd 6 | 7 | package test 8 | 9 | import ( 10 | "crypto/rand" 11 | "testing" 12 | 13 | "golang.org/x/crypto/ssh" 14 | ) 15 | 16 | func TestCertLogin(t *testing.T) { 17 | s := newServer(t) 18 | defer s.Shutdown() 19 | 20 | // Use a key different from the default. 21 | clientKey := testSigners["dsa"] 22 | caAuthKey := testSigners["ecdsa"] 23 | cert := &ssh.Certificate{ 24 | Key: clientKey.PublicKey(), 25 | ValidPrincipals: []string{username()}, 26 | CertType: ssh.UserCert, 27 | ValidBefore: ssh.CertTimeInfinity, 28 | } 29 | if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { 30 | t.Fatalf("SetSignature: %v", err) 31 | } 32 | 33 | certSigner, err := ssh.NewCertSigner(cert, clientKey) 34 | if err != nil { 35 | t.Fatalf("NewCertSigner: %v", err) 36 | } 37 | 38 | conf := &ssh.ClientConfig{ 39 | User: username(), 40 | } 41 | conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) 42 | client, err := s.TryDial(conf) 43 | if err != nil { 44 | t.Fatalf("TryDial: %v", err) 45 | } 46 | client.Close() 47 | } 48 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/doc.go: -------------------------------------------------------------------------------- 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 | // This package contains integration tests for the 6 | // golang.org/x/crypto/ssh package. 7 | package test // import "golang.org/x/crypto/ssh/test" 8 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/forward_unix_test.go: -------------------------------------------------------------------------------- 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 darwin dragonfly freebsd linux netbsd openbsd 6 | 7 | package test 8 | 9 | import ( 10 | "bytes" 11 | "io" 12 | "io/ioutil" 13 | "math/rand" 14 | "net" 15 | "testing" 16 | "time" 17 | ) 18 | 19 | func TestPortForward(t *testing.T) { 20 | server := newServer(t) 21 | defer server.Shutdown() 22 | conn := server.Dial(clientConfig()) 23 | defer conn.Close() 24 | 25 | sshListener, err := conn.Listen("tcp", "localhost:0") 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | go func() { 31 | sshConn, err := sshListener.Accept() 32 | if err != nil { 33 | t.Fatalf("listen.Accept failed: %v", err) 34 | } 35 | 36 | _, err = io.Copy(sshConn, sshConn) 37 | if err != nil && err != io.EOF { 38 | t.Fatalf("ssh client copy: %v", err) 39 | } 40 | sshConn.Close() 41 | }() 42 | 43 | forwardedAddr := sshListener.Addr().String() 44 | tcpConn, err := net.Dial("tcp", forwardedAddr) 45 | if err != nil { 46 | t.Fatalf("TCP dial failed: %v", err) 47 | } 48 | 49 | readChan := make(chan []byte) 50 | go func() { 51 | data, _ := ioutil.ReadAll(tcpConn) 52 | readChan <- data 53 | }() 54 | 55 | // Invent some data. 56 | data := make([]byte, 100*1000) 57 | for i := range data { 58 | data[i] = byte(i % 255) 59 | } 60 | 61 | var sent []byte 62 | for len(sent) < 1000*1000 { 63 | // Send random sized chunks 64 | m := rand.Intn(len(data)) 65 | n, err := tcpConn.Write(data[:m]) 66 | if err != nil { 67 | break 68 | } 69 | sent = append(sent, data[:n]...) 70 | } 71 | if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil { 72 | t.Errorf("tcpConn.CloseWrite: %v", err) 73 | } 74 | 75 | read := <-readChan 76 | 77 | if len(sent) != len(read) { 78 | t.Fatalf("got %d bytes, want %d", len(read), len(sent)) 79 | } 80 | if bytes.Compare(sent, read) != 0 { 81 | t.Fatalf("read back data does not match") 82 | } 83 | 84 | if err := sshListener.Close(); err != nil { 85 | t.Fatalf("sshListener.Close: %v", err) 86 | } 87 | 88 | // Check that the forward disappeared. 89 | tcpConn, err = net.Dial("tcp", forwardedAddr) 90 | if err == nil { 91 | tcpConn.Close() 92 | t.Errorf("still listening to %s after closing", forwardedAddr) 93 | } 94 | } 95 | 96 | func TestAcceptClose(t *testing.T) { 97 | server := newServer(t) 98 | defer server.Shutdown() 99 | conn := server.Dial(clientConfig()) 100 | 101 | sshListener, err := conn.Listen("tcp", "localhost:0") 102 | if err != nil { 103 | t.Fatal(err) 104 | } 105 | 106 | quit := make(chan error, 1) 107 | go func() { 108 | for { 109 | c, err := sshListener.Accept() 110 | if err != nil { 111 | quit <- err 112 | break 113 | } 114 | c.Close() 115 | } 116 | }() 117 | sshListener.Close() 118 | 119 | select { 120 | case <-time.After(1 * time.Second): 121 | t.Errorf("timeout: listener did not close.") 122 | case err := <-quit: 123 | t.Logf("quit as expected (error %v)", err) 124 | } 125 | } 126 | 127 | // Check that listeners exit if the underlying client transport dies. 128 | func TestPortForwardConnectionClose(t *testing.T) { 129 | server := newServer(t) 130 | defer server.Shutdown() 131 | conn := server.Dial(clientConfig()) 132 | 133 | sshListener, err := conn.Listen("tcp", "localhost:0") 134 | if err != nil { 135 | t.Fatal(err) 136 | } 137 | 138 | quit := make(chan error, 1) 139 | go func() { 140 | for { 141 | c, err := sshListener.Accept() 142 | if err != nil { 143 | quit <- err 144 | break 145 | } 146 | c.Close() 147 | } 148 | }() 149 | 150 | // It would be even nicer if we closed the server side, but it 151 | // is more involved as the fd for that side is dup()ed. 152 | server.clientConn.Close() 153 | 154 | select { 155 | case <-time.After(1 * time.Second): 156 | t.Errorf("timeout: listener did not close.") 157 | case err := <-quit: 158 | t.Logf("quit as expected (error %v)", err) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/session_test.go: -------------------------------------------------------------------------------- 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 | // This cipher 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") 286 | 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 doesnt have the cipher. 293 | conf.Ciphers = append(conf.Ciphers, cipherOrder...) 294 | conn, err := server.TryDial(conf) 295 | if err == nil { 296 | conn.Close() 297 | } else { 298 | t.Fatalf("failed for cipher %q", ciph) 299 | } 300 | } 301 | } 302 | 303 | func TestMACs(t *testing.T) { 304 | var config ssh.Config 305 | config.SetDefaults() 306 | macOrder := config.MACs 307 | 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 doesnt have the MAC. 314 | conf.MACs = append(conf.MACs, macOrder...) 315 | if conn, err := server.TryDial(conf); err == nil { 316 | conn.Close() 317 | } else { 318 | t.Fatalf("failed for MAC %q", mac) 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/tcpip_test.go: -------------------------------------------------------------------------------- 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 | // direct-tcpip functional tests 10 | 11 | import ( 12 | "io" 13 | "net" 14 | "testing" 15 | ) 16 | 17 | func TestDial(t *testing.T) { 18 | server := newServer(t) 19 | defer server.Shutdown() 20 | sshConn := server.Dial(clientConfig()) 21 | defer sshConn.Close() 22 | 23 | l, err := net.Listen("tcp", "127.0.0.1:0") 24 | if err != nil { 25 | t.Fatalf("Listen: %v", err) 26 | } 27 | defer l.Close() 28 | 29 | go func() { 30 | for { 31 | c, err := l.Accept() 32 | if err != nil { 33 | break 34 | } 35 | 36 | io.WriteString(c, c.RemoteAddr().String()) 37 | c.Close() 38 | } 39 | }() 40 | 41 | conn, err := sshConn.Dial("tcp", l.Addr().String()) 42 | if err != nil { 43 | t.Fatalf("Dial: %v", err) 44 | } 45 | defer conn.Close() 46 | } 47 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/test_unix_test.go: -------------------------------------------------------------------------------- 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 darwin dragonfly freebsd linux netbsd openbsd plan9 6 | 7 | package test 8 | 9 | // functional test harness for unix. 10 | 11 | import ( 12 | "bytes" 13 | "fmt" 14 | "io/ioutil" 15 | "log" 16 | "net" 17 | "os" 18 | "os/exec" 19 | "os/user" 20 | "path/filepath" 21 | "testing" 22 | "text/template" 23 | 24 | "golang.org/x/crypto/ssh" 25 | "golang.org/x/crypto/ssh/testdata" 26 | ) 27 | 28 | const sshd_config = ` 29 | Protocol 2 30 | HostKey {{.Dir}}/id_rsa 31 | HostKey {{.Dir}}/id_dsa 32 | HostKey {{.Dir}}/id_ecdsa 33 | Pidfile {{.Dir}}/sshd.pid 34 | #UsePrivilegeSeparation no 35 | KeyRegenerationInterval 3600 36 | ServerKeyBits 768 37 | SyslogFacility AUTH 38 | LogLevel DEBUG2 39 | LoginGraceTime 120 40 | PermitRootLogin no 41 | StrictModes no 42 | RSAAuthentication yes 43 | PubkeyAuthentication yes 44 | AuthorizedKeysFile {{.Dir}}/id_user.pub 45 | TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub 46 | IgnoreRhosts yes 47 | RhostsRSAAuthentication no 48 | HostbasedAuthentication no 49 | ` 50 | 51 | var configTmpl = template.Must(template.New("").Parse(sshd_config)) 52 | 53 | type server struct { 54 | t *testing.T 55 | cleanup func() // executed during Shutdown 56 | configfile string 57 | cmd *exec.Cmd 58 | output bytes.Buffer // holds stderr from sshd process 59 | 60 | // Client half of the network connection. 61 | clientConn net.Conn 62 | } 63 | 64 | func username() string { 65 | var username string 66 | if user, err := user.Current(); err == nil { 67 | username = user.Username 68 | } else { 69 | // user.Current() currently requires cgo. If an error is 70 | // returned attempt to get the username from the environment. 71 | log.Printf("user.Current: %v; falling back on $USER", err) 72 | username = os.Getenv("USER") 73 | } 74 | if username == "" { 75 | panic("Unable to get username") 76 | } 77 | return username 78 | } 79 | 80 | type storedHostKey struct { 81 | // keys map from an algorithm string to binary key data. 82 | keys map[string][]byte 83 | 84 | // checkCount counts the Check calls. Used for testing 85 | // rekeying. 86 | checkCount int 87 | } 88 | 89 | func (k *storedHostKey) Add(key ssh.PublicKey) { 90 | if k.keys == nil { 91 | k.keys = map[string][]byte{} 92 | } 93 | k.keys[key.Type()] = key.Marshal() 94 | } 95 | 96 | func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { 97 | k.checkCount++ 98 | algo := key.Type() 99 | 100 | if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { 101 | return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) 102 | } 103 | return nil 104 | } 105 | 106 | func hostKeyDB() *storedHostKey { 107 | keyChecker := &storedHostKey{} 108 | keyChecker.Add(testPublicKeys["ecdsa"]) 109 | keyChecker.Add(testPublicKeys["rsa"]) 110 | keyChecker.Add(testPublicKeys["dsa"]) 111 | return keyChecker 112 | } 113 | 114 | func clientConfig() *ssh.ClientConfig { 115 | config := &ssh.ClientConfig{ 116 | User: username(), 117 | Auth: []ssh.AuthMethod{ 118 | ssh.PublicKeys(testSigners["user"]), 119 | }, 120 | HostKeyCallback: hostKeyDB().Check, 121 | } 122 | return config 123 | } 124 | 125 | // unixConnection creates two halves of a connected net.UnixConn. It 126 | // is used for connecting the Go SSH client with sshd without opening 127 | // ports. 128 | func unixConnection() (*net.UnixConn, *net.UnixConn, error) { 129 | dir, err := ioutil.TempDir("", "unixConnection") 130 | if err != nil { 131 | return nil, nil, err 132 | } 133 | defer os.Remove(dir) 134 | 135 | addr := filepath.Join(dir, "ssh") 136 | listener, err := net.Listen("unix", addr) 137 | if err != nil { 138 | return nil, nil, err 139 | } 140 | defer listener.Close() 141 | c1, err := net.Dial("unix", addr) 142 | if err != nil { 143 | return nil, nil, err 144 | } 145 | 146 | c2, err := listener.Accept() 147 | if err != nil { 148 | c1.Close() 149 | return nil, nil, err 150 | } 151 | 152 | return c1.(*net.UnixConn), c2.(*net.UnixConn), nil 153 | } 154 | 155 | func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { 156 | sshd, err := exec.LookPath("sshd") 157 | if err != nil { 158 | s.t.Skipf("skipping test: %v", err) 159 | } 160 | 161 | c1, c2, err := unixConnection() 162 | if err != nil { 163 | s.t.Fatalf("unixConnection: %v", err) 164 | } 165 | 166 | s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e") 167 | f, err := c2.File() 168 | if err != nil { 169 | s.t.Fatalf("UnixConn.File: %v", err) 170 | } 171 | defer f.Close() 172 | s.cmd.Stdin = f 173 | s.cmd.Stdout = f 174 | s.cmd.Stderr = &s.output 175 | if err := s.cmd.Start(); err != nil { 176 | s.t.Fail() 177 | s.Shutdown() 178 | s.t.Fatalf("s.cmd.Start: %v", err) 179 | } 180 | s.clientConn = c1 181 | conn, chans, reqs, err := ssh.NewClientConn(c1, "", config) 182 | if err != nil { 183 | return nil, err 184 | } 185 | return ssh.NewClient(conn, chans, reqs), nil 186 | } 187 | 188 | func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { 189 | conn, err := s.TryDial(config) 190 | if err != nil { 191 | s.t.Fail() 192 | s.Shutdown() 193 | s.t.Fatalf("ssh.Client: %v", err) 194 | } 195 | return conn 196 | } 197 | 198 | func (s *server) Shutdown() { 199 | if s.cmd != nil && s.cmd.Process != nil { 200 | // Don't check for errors; if it fails it's most 201 | // likely "os: process already finished", and we don't 202 | // care about that. Use os.Interrupt, so child 203 | // processes are killed too. 204 | s.cmd.Process.Signal(os.Interrupt) 205 | s.cmd.Wait() 206 | } 207 | if s.t.Failed() { 208 | // log any output from sshd process 209 | s.t.Logf("sshd: %s", s.output.String()) 210 | } 211 | s.cleanup() 212 | } 213 | 214 | func writeFile(path string, contents []byte) { 215 | f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) 216 | if err != nil { 217 | panic(err) 218 | } 219 | defer f.Close() 220 | if _, err := f.Write(contents); err != nil { 221 | panic(err) 222 | } 223 | } 224 | 225 | // newServer returns a new mock ssh server. 226 | func newServer(t *testing.T) *server { 227 | if testing.Short() { 228 | t.Skip("skipping test due to -short") 229 | } 230 | dir, err := ioutil.TempDir("", "sshtest") 231 | if err != nil { 232 | t.Fatal(err) 233 | } 234 | f, err := os.Create(filepath.Join(dir, "sshd_config")) 235 | if err != nil { 236 | t.Fatal(err) 237 | } 238 | err = configTmpl.Execute(f, map[string]string{ 239 | "Dir": dir, 240 | }) 241 | if err != nil { 242 | t.Fatal(err) 243 | } 244 | f.Close() 245 | 246 | for k, v := range testdata.PEMBytes { 247 | filename := "id_" + k 248 | writeFile(filepath.Join(dir, filename), v) 249 | writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) 250 | } 251 | 252 | return &server{ 253 | t: t, 254 | configfile: f.Name(), 255 | cleanup: func() { 256 | if err := os.RemoveAll(dir); err != nil { 257 | t.Error(err) 258 | } 259 | }, 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/test/testdata_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: 6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three 7 | // instances. 8 | 9 | package test 10 | 11 | import ( 12 | "crypto/rand" 13 | "fmt" 14 | 15 | "golang.org/x/crypto/ssh" 16 | "golang.org/x/crypto/ssh/testdata" 17 | ) 18 | 19 | var ( 20 | testPrivateKeys map[string]interface{} 21 | testSigners map[string]ssh.Signer 22 | testPublicKeys map[string]ssh.PublicKey 23 | ) 24 | 25 | func init() { 26 | var err error 27 | 28 | n := len(testdata.PEMBytes) 29 | testPrivateKeys = make(map[string]interface{}, n) 30 | testSigners = make(map[string]ssh.Signer, n) 31 | testPublicKeys = make(map[string]ssh.PublicKey, n) 32 | for t, k := range testdata.PEMBytes { 33 | testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) 34 | if err != nil { 35 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) 36 | } 37 | testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) 38 | if err != nil { 39 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) 40 | } 41 | testPublicKeys[t] = testSigners[t].PublicKey() 42 | } 43 | 44 | // Create a cert and sign it for use in tests. 45 | testCert := &ssh.Certificate{ 46 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 47 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage 48 | ValidAfter: 0, // unix epoch 49 | ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. 50 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 51 | Key: testPublicKeys["ecdsa"], 52 | SignatureKey: testPublicKeys["rsa"], 53 | Permissions: ssh.Permissions{ 54 | CriticalOptions: map[string]string{}, 55 | Extensions: map[string]string{}, 56 | }, 57 | } 58 | testCert.SignCert(rand.Reader, testSigners["rsa"]) 59 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] 60 | testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) 61 | if err != nil { 62 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/testdata/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // This package contains test data shared between the various subpackages of 6 | // the golang.org/x/crypto/ssh package. Under no circumstance should 7 | // this data be used for production code. 8 | package testdata // import "golang.org/x/crypto/ssh/testdata" 9 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/testdata/keys.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | package testdata 6 | 7 | var PEMBytes = map[string][]byte{ 8 | "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- 9 | MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB 10 | lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 11 | EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD 12 | nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV 13 | 2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r 14 | juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr 15 | FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz 16 | DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj 17 | nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY 18 | Fmsr0W6fHB9nhS4/UXM8 19 | -----END DSA PRIVATE KEY----- 20 | `), 21 | "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- 22 | MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 23 | AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ 24 | 6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== 25 | -----END EC PRIVATE KEY----- 26 | `), 27 | "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- 28 | MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld 29 | r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ 30 | tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC 31 | nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW 32 | 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB 33 | y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr 34 | rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg== 35 | -----END RSA PRIVATE KEY----- 36 | `), 37 | "user": []byte(`-----BEGIN EC PRIVATE KEY----- 38 | MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 39 | AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD 40 | PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== 41 | -----END EC PRIVATE KEY----- 42 | `), 43 | } 44 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/testdata_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 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 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places: 6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three 7 | // instances. 8 | 9 | package ssh 10 | 11 | import ( 12 | "crypto/rand" 13 | "fmt" 14 | 15 | "golang.org/x/crypto/ssh/testdata" 16 | ) 17 | 18 | var ( 19 | testPrivateKeys map[string]interface{} 20 | testSigners map[string]Signer 21 | testPublicKeys map[string]PublicKey 22 | ) 23 | 24 | func init() { 25 | var err error 26 | 27 | n := len(testdata.PEMBytes) 28 | testPrivateKeys = make(map[string]interface{}, n) 29 | testSigners = make(map[string]Signer, n) 30 | testPublicKeys = make(map[string]PublicKey, n) 31 | for t, k := range testdata.PEMBytes { 32 | testPrivateKeys[t], err = ParseRawPrivateKey(k) 33 | if err != nil { 34 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) 35 | } 36 | testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) 37 | if err != nil { 38 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) 39 | } 40 | testPublicKeys[t] = testSigners[t].PublicKey() 41 | } 42 | 43 | // Create a cert and sign it for use in tests. 44 | testCert := &Certificate{ 45 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 46 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage 47 | ValidAfter: 0, // unix epoch 48 | ValidBefore: CertTimeInfinity, // The end of currently representable time. 49 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 50 | Key: testPublicKeys["ecdsa"], 51 | SignatureKey: testPublicKeys["rsa"], 52 | Permissions: Permissions{ 53 | CriticalOptions: map[string]string{}, 54 | Extensions: map[string]string{}, 55 | }, 56 | } 57 | testCert.SignCert(rand.Reader, testSigners["rsa"]) 58 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] 59 | testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) 60 | if err != nil { 61 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/transport.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "bufio" 9 | "errors" 10 | "io" 11 | ) 12 | 13 | const ( 14 | gcmCipherID = "aes128-gcm@openssh.com" 15 | aes128cbcID = "aes128-cbc" 16 | ) 17 | 18 | // packetConn represents a transport that implements packet based 19 | // operations. 20 | type packetConn interface { 21 | // Encrypt and send a packet of data to the remote peer. 22 | writePacket(packet []byte) error 23 | 24 | // Read a packet from the connection 25 | readPacket() ([]byte, error) 26 | 27 | // Close closes the write-side of the connection. 28 | Close() error 29 | } 30 | 31 | // transport is the keyingTransport that implements the SSH packet 32 | // protocol. 33 | type transport struct { 34 | reader connectionState 35 | writer connectionState 36 | 37 | bufReader *bufio.Reader 38 | bufWriter *bufio.Writer 39 | rand io.Reader 40 | 41 | io.Closer 42 | 43 | // Initial H used for the session ID. Once assigned this does 44 | // not change, even during subsequent key exchanges. 45 | sessionID []byte 46 | } 47 | 48 | // getSessionID returns the ID of the SSH connection. The return value 49 | // should not be modified. 50 | func (t *transport) getSessionID() []byte { 51 | if t.sessionID == nil { 52 | panic("session ID not set yet") 53 | } 54 | return t.sessionID 55 | } 56 | 57 | // packetCipher represents a combination of SSH encryption/MAC 58 | // protocol. A single instance should be used for one direction only. 59 | type packetCipher interface { 60 | // writePacket encrypts the packet and writes it to w. The 61 | // contents of the packet are generally scrambled. 62 | writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error 63 | 64 | // readPacket reads and decrypts a packet of data. The 65 | // returned packet may be overwritten by future calls of 66 | // readPacket. 67 | readPacket(seqnum uint32, r io.Reader) ([]byte, error) 68 | } 69 | 70 | // connectionState represents one side (read or write) of the 71 | // connection. This is necessary because each direction has its own 72 | // keys, and can even have its own algorithms 73 | type connectionState struct { 74 | packetCipher 75 | seqNum uint32 76 | dir direction 77 | pendingKeyChange chan packetCipher 78 | } 79 | 80 | // prepareKeyChange sets up key material for a keychange. The key changes in 81 | // both directions are triggered by reading and writing a msgNewKey packet 82 | // respectively. 83 | func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { 84 | if t.sessionID == nil { 85 | t.sessionID = kexResult.H 86 | } 87 | 88 | kexResult.SessionID = t.sessionID 89 | 90 | if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { 91 | return err 92 | } else { 93 | t.reader.pendingKeyChange <- ciph 94 | } 95 | 96 | if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil { 97 | return err 98 | } else { 99 | t.writer.pendingKeyChange <- ciph 100 | } 101 | 102 | return nil 103 | } 104 | 105 | // Read and decrypt next packet. 106 | func (t *transport) readPacket() ([]byte, error) { 107 | return t.reader.readPacket(t.bufReader) 108 | } 109 | 110 | func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { 111 | packet, err := s.packetCipher.readPacket(s.seqNum, r) 112 | s.seqNum++ 113 | if err == nil && len(packet) == 0 { 114 | err = errors.New("ssh: zero length packet") 115 | } 116 | 117 | if len(packet) > 0 && packet[0] == msgNewKeys { 118 | select { 119 | case cipher := <-s.pendingKeyChange: 120 | s.packetCipher = cipher 121 | default: 122 | return nil, errors.New("ssh: got bogus newkeys message.") 123 | } 124 | } 125 | 126 | // The packet may point to an internal buffer, so copy the 127 | // packet out here. 128 | fresh := make([]byte, len(packet)) 129 | copy(fresh, packet) 130 | 131 | return fresh, err 132 | } 133 | 134 | func (t *transport) writePacket(packet []byte) error { 135 | return t.writer.writePacket(t.bufWriter, t.rand, packet) 136 | } 137 | 138 | func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { 139 | changeKeys := len(packet) > 0 && packet[0] == msgNewKeys 140 | 141 | err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) 142 | if err != nil { 143 | return err 144 | } 145 | if err = w.Flush(); err != nil { 146 | return err 147 | } 148 | s.seqNum++ 149 | if changeKeys { 150 | select { 151 | case cipher := <-s.pendingKeyChange: 152 | s.packetCipher = cipher 153 | default: 154 | panic("ssh: no key material for msgNewKeys") 155 | } 156 | } 157 | return err 158 | } 159 | 160 | func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { 161 | t := &transport{ 162 | bufReader: bufio.NewReader(rwc), 163 | bufWriter: bufio.NewWriter(rwc), 164 | rand: rand, 165 | reader: connectionState{ 166 | packetCipher: &streamPacketCipher{cipher: noneCipher{}}, 167 | pendingKeyChange: make(chan packetCipher, 1), 168 | }, 169 | writer: connectionState{ 170 | packetCipher: &streamPacketCipher{cipher: noneCipher{}}, 171 | pendingKeyChange: make(chan packetCipher, 1), 172 | }, 173 | Closer: rwc, 174 | } 175 | if isClient { 176 | t.reader.dir = serverKeys 177 | t.writer.dir = clientKeys 178 | } else { 179 | t.reader.dir = clientKeys 180 | t.writer.dir = serverKeys 181 | } 182 | 183 | return t 184 | } 185 | 186 | type direction struct { 187 | ivTag []byte 188 | keyTag []byte 189 | macKeyTag []byte 190 | } 191 | 192 | var ( 193 | serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} 194 | clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} 195 | ) 196 | 197 | // generateKeys generates key material for IV, MAC and encryption. 198 | func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { 199 | cipherMode := cipherModes[algs.Cipher] 200 | macMode := macModes[algs.MAC] 201 | 202 | iv = make([]byte, cipherMode.ivSize) 203 | key = make([]byte, cipherMode.keySize) 204 | macKey = make([]byte, macMode.keySize) 205 | 206 | generateKeyMaterial(iv, d.ivTag, kex) 207 | generateKeyMaterial(key, d.keyTag, kex) 208 | generateKeyMaterial(macKey, d.macKeyTag, kex) 209 | return 210 | } 211 | 212 | // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as 213 | // described in RFC 4253, section 6.4. direction should either be serverKeys 214 | // (to setup server->client keys) or clientKeys (for client->server keys). 215 | func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { 216 | iv, key, macKey := generateKeys(d, algs, kex) 217 | 218 | if algs.Cipher == gcmCipherID { 219 | return newGCMCipher(iv, key, macKey) 220 | } 221 | 222 | if algs.Cipher == aes128cbcID { 223 | return newAESCBCCipher(iv, key, macKey, algs) 224 | } 225 | 226 | c := &streamPacketCipher{ 227 | mac: macModes[algs.MAC].new(macKey), 228 | } 229 | c.macResult = make([]byte, c.mac.Size()) 230 | 231 | var err error 232 | c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) 233 | if err != nil { 234 | return nil, err 235 | } 236 | 237 | return c, nil 238 | } 239 | 240 | // generateKeyMaterial fills out with key material generated from tag, K, H 241 | // and sessionId, as specified in RFC 4253, section 7.2. 242 | func generateKeyMaterial(out, tag []byte, r *kexResult) { 243 | var digestsSoFar []byte 244 | 245 | h := r.Hash.New() 246 | for len(out) > 0 { 247 | h.Reset() 248 | h.Write(r.K) 249 | h.Write(r.H) 250 | 251 | if len(digestsSoFar) == 0 { 252 | h.Write(tag) 253 | h.Write(r.SessionID) 254 | } else { 255 | h.Write(digestsSoFar) 256 | } 257 | 258 | digest := h.Sum(nil) 259 | n := copy(out, digest) 260 | out = out[n:] 261 | if len(out) > 0 { 262 | digestsSoFar = append(digestsSoFar, digest...) 263 | } 264 | } 265 | } 266 | 267 | const packageVersion = "SSH-2.0-Go" 268 | 269 | // Sends and receives a version line. The versionLine string should 270 | // be US ASCII, start with "SSH-2.0-", and should not include a 271 | // newline. exchangeVersions returns the other side's version line. 272 | func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { 273 | // Contrary to the RFC, we do not ignore lines that don't 274 | // start with "SSH-2.0-" to make the library usable with 275 | // nonconforming servers. 276 | for _, c := range versionLine { 277 | // The spec disallows non US-ASCII chars, and 278 | // specifically forbids null chars. 279 | if c < 32 { 280 | return nil, errors.New("ssh: junk character in version line") 281 | } 282 | } 283 | if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { 284 | return 285 | } 286 | 287 | them, err = readVersion(rw) 288 | return them, err 289 | } 290 | 291 | // maxVersionStringBytes is the maximum number of bytes that we'll 292 | // accept as a version string. RFC 4253 section 4.2 limits this at 255 293 | // chars 294 | const maxVersionStringBytes = 255 295 | 296 | // Read version string as specified by RFC 4253, section 4.2. 297 | func readVersion(r io.Reader) ([]byte, error) { 298 | versionString := make([]byte, 0, 64) 299 | var ok bool 300 | var buf [1]byte 301 | 302 | for len(versionString) < maxVersionStringBytes { 303 | _, err := io.ReadFull(r, buf[:]) 304 | if err != nil { 305 | return nil, err 306 | } 307 | // The RFC says that the version should be terminated with \r\n 308 | // but several SSH servers actually only send a \n. 309 | if buf[0] == '\n' { 310 | ok = true 311 | break 312 | } 313 | 314 | // non ASCII chars are disallowed, but we are lenient, 315 | // since Go doesn't use null-terminated strings. 316 | 317 | // The RFC allows a comment after a space, however, 318 | // all of it (version and comments) goes into the 319 | // session hash. 320 | versionString = append(versionString, buf[0]) 321 | } 322 | 323 | if !ok { 324 | return nil, errors.New("ssh: overflow reading version string") 325 | } 326 | 327 | // There might be a '\r' on the end which we should remove. 328 | if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { 329 | versionString = versionString[:len(versionString)-1] 330 | } 331 | return versionString, nil 332 | } 333 | -------------------------------------------------------------------------------- /vendor/src/golang.org/x/crypto/ssh/transport_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 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 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/binary" 11 | "strings" 12 | "testing" 13 | ) 14 | 15 | func TestReadVersion(t *testing.T) { 16 | longversion := strings.Repeat("SSH-2.0-bla", 50)[:253] 17 | cases := map[string]string{ 18 | "SSH-2.0-bla\r\n": "SSH-2.0-bla", 19 | "SSH-2.0-bla\n": "SSH-2.0-bla", 20 | longversion + "\r\n": longversion, 21 | } 22 | 23 | for in, want := range cases { 24 | result, err := readVersion(bytes.NewBufferString(in)) 25 | if err != nil { 26 | t.Errorf("readVersion(%q): %s", in, err) 27 | } 28 | got := string(result) 29 | if got != want { 30 | t.Errorf("got %q, want %q", got, want) 31 | } 32 | } 33 | } 34 | 35 | func TestReadVersionError(t *testing.T) { 36 | longversion := strings.Repeat("SSH-2.0-bla", 50)[:253] 37 | cases := []string{ 38 | longversion + "too-long\r\n", 39 | } 40 | for _, in := range cases { 41 | if _, err := readVersion(bytes.NewBufferString(in)); err == nil { 42 | t.Errorf("readVersion(%q) should have failed", in) 43 | } 44 | } 45 | } 46 | 47 | func TestExchangeVersionsBasic(t *testing.T) { 48 | v := "SSH-2.0-bla" 49 | buf := bytes.NewBufferString(v + "\r\n") 50 | them, err := exchangeVersions(buf, []byte("xyz")) 51 | if err != nil { 52 | t.Errorf("exchangeVersions: %v", err) 53 | } 54 | 55 | if want := "SSH-2.0-bla"; string(them) != want { 56 | t.Errorf("got %q want %q for our version", them, want) 57 | } 58 | } 59 | 60 | func TestExchangeVersions(t *testing.T) { 61 | cases := []string{ 62 | "not\x000allowed", 63 | "not allowed\n", 64 | } 65 | for _, c := range cases { 66 | buf := bytes.NewBufferString("SSH-2.0-bla\r\n") 67 | if _, err := exchangeVersions(buf, []byte(c)); err == nil { 68 | t.Errorf("exchangeVersions(%q): should have failed", c) 69 | } 70 | } 71 | } 72 | 73 | type closerBuffer struct { 74 | bytes.Buffer 75 | } 76 | 77 | func (b *closerBuffer) Close() error { 78 | return nil 79 | } 80 | 81 | func TestTransportMaxPacketWrite(t *testing.T) { 82 | buf := &closerBuffer{} 83 | tr := newTransport(buf, rand.Reader, true) 84 | huge := make([]byte, maxPacket+1) 85 | err := tr.writePacket(huge) 86 | if err == nil { 87 | t.Errorf("transport accepted write for a huge packet.") 88 | } 89 | } 90 | 91 | func TestTransportMaxPacketReader(t *testing.T) { 92 | var header [5]byte 93 | huge := make([]byte, maxPacket+128) 94 | binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) 95 | // padding. 96 | header[4] = 0 97 | 98 | buf := &closerBuffer{} 99 | buf.Write(header[:]) 100 | buf.Write(huge) 101 | 102 | tr := newTransport(buf, rand.Reader, true) 103 | _, err := tr.readPacket() 104 | if err == nil { 105 | t.Errorf("transport succeeded reading huge packet.") 106 | } else if !strings.Contains(err.Error(), "large") { 107 | t.Errorf("got %q, should mention %q", err.Error(), "large") 108 | } 109 | } 110 | --------------------------------------------------------------------------------