OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / 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         "time"
18
19         "golang.org/x/crypto/ssh"
20 )
21
22 // startAgent executes ssh-agent, and returns a Agent interface to it.
23 func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
24         if testing.Short() {
25                 // ssh-agent is not always available, and the key
26                 // types supported vary by platform.
27                 t.Skip("skipping test due to -short")
28         }
29
30         bin, err := exec.LookPath("ssh-agent")
31         if err != nil {
32                 t.Skip("could not find ssh-agent")
33         }
34
35         cmd := exec.Command(bin, "-s")
36         out, err := cmd.Output()
37         if err != nil {
38                 t.Fatalf("cmd.Output: %v", err)
39         }
40
41         /* Output looks like:
42
43                    SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
44                    SSH_AGENT_PID=15542; export SSH_AGENT_PID;
45                    echo Agent pid 15542;
46         */
47         fields := bytes.Split(out, []byte(";"))
48         line := bytes.SplitN(fields[0], []byte("="), 2)
49         line[0] = bytes.TrimLeft(line[0], "\n")
50         if string(line[0]) != "SSH_AUTH_SOCK" {
51                 t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
52         }
53         socket = string(line[1])
54
55         line = bytes.SplitN(fields[2], []byte("="), 2)
56         line[0] = bytes.TrimLeft(line[0], "\n")
57         if string(line[0]) != "SSH_AGENT_PID" {
58                 t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
59         }
60         pidStr := line[1]
61         pid, err := strconv.Atoi(string(pidStr))
62         if err != nil {
63                 t.Fatalf("Atoi(%q): %v", pidStr, err)
64         }
65
66         conn, err := net.Dial("unix", string(socket))
67         if err != nil {
68                 t.Fatalf("net.Dial: %v", err)
69         }
70
71         ac := NewClient(conn)
72         return ac, socket, func() {
73                 proc, _ := os.FindProcess(pid)
74                 if proc != nil {
75                         proc.Kill()
76                 }
77                 conn.Close()
78                 os.RemoveAll(filepath.Dir(socket))
79         }
80 }
81
82 func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
83         agent, _, cleanup := startAgent(t)
84         defer cleanup()
85
86         testAgentInterface(t, agent, key, cert, lifetimeSecs)
87 }
88
89 func testKeyring(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
90         a := NewKeyring()
91         testAgentInterface(t, a, key, cert, lifetimeSecs)
92 }
93
94 func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
95         signer, err := ssh.NewSignerFromKey(key)
96         if err != nil {
97                 t.Fatalf("NewSignerFromKey(%T): %v", key, err)
98         }
99         // The agent should start up empty.
100         if keys, err := agent.List(); err != nil {
101                 t.Fatalf("RequestIdentities: %v", err)
102         } else if len(keys) > 0 {
103                 t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
104         }
105
106         // Attempt to insert the key, with certificate if specified.
107         var pubKey ssh.PublicKey
108         if cert != nil {
109                 err = agent.Add(AddedKey{
110                         PrivateKey:   key,
111                         Certificate:  cert,
112                         Comment:      "comment",
113                         LifetimeSecs: lifetimeSecs,
114                 })
115                 pubKey = cert
116         } else {
117                 err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs})
118                 pubKey = signer.PublicKey()
119         }
120         if err != nil {
121                 t.Fatalf("insert(%T): %v", key, err)
122         }
123
124         // Did the key get inserted successfully?
125         if keys, err := agent.List(); err != nil {
126                 t.Fatalf("List: %v", err)
127         } else if len(keys) != 1 {
128                 t.Fatalf("got %v, want 1 key", keys)
129         } else if keys[0].Comment != "comment" {
130                 t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
131         } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
132                 t.Fatalf("key mismatch")
133         }
134
135         // Can the agent make a valid signature?
136         data := []byte("hello")
137         sig, err := agent.Sign(pubKey, data)
138         if err != nil {
139                 t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
140         }
141
142         if err := pubKey.Verify(data, sig); err != nil {
143                 t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
144         }
145
146         // If the key has a lifetime, is it removed when it should be?
147         if lifetimeSecs > 0 {
148                 time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond)
149                 keys, err := agent.List()
150                 if err != nil {
151                         t.Fatalf("List: %v", err)
152                 }
153                 if len(keys) > 0 {
154                         t.Fatalf("key not expired")
155                 }
156         }
157
158 }
159
160 func TestAgent(t *testing.T) {
161         for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
162                 testAgent(t, testPrivateKeys[keyType], nil, 0)
163                 testKeyring(t, testPrivateKeys[keyType], nil, 1)
164         }
165 }
166
167 func TestCert(t *testing.T) {
168         cert := &ssh.Certificate{
169                 Key:         testPublicKeys["rsa"],
170                 ValidBefore: ssh.CertTimeInfinity,
171                 CertType:    ssh.UserCert,
172         }
173         cert.SignCert(rand.Reader, testSigners["ecdsa"])
174
175         testAgent(t, testPrivateKeys["rsa"], cert, 0)
176         testKeyring(t, testPrivateKeys["rsa"], cert, 1)
177 }
178
179 // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
180 // therefore is buffered (net.Pipe deadlocks if both sides start with
181 // a write.)
182 func netPipe() (net.Conn, net.Conn, error) {
183         listener, err := net.Listen("tcp", "127.0.0.1:0")
184         if err != nil {
185                 listener, err = net.Listen("tcp", "[::1]:0")
186                 if err != nil {
187                         return nil, nil, err
188                 }
189         }
190         defer listener.Close()
191         c1, err := net.Dial("tcp", listener.Addr().String())
192         if err != nil {
193                 return nil, nil, err
194         }
195
196         c2, err := listener.Accept()
197         if err != nil {
198                 c1.Close()
199                 return nil, nil, err
200         }
201
202         return c1, c2, nil
203 }
204
205 func TestAuth(t *testing.T) {
206         agent, _, cleanup := startAgent(t)
207         defer cleanup()
208
209         a, b, err := netPipe()
210         if err != nil {
211                 t.Fatalf("netPipe: %v", err)
212         }
213
214         defer a.Close()
215         defer b.Close()
216
217         if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil {
218                 t.Errorf("Add: %v", err)
219         }
220
221         serverConf := ssh.ServerConfig{}
222         serverConf.AddHostKey(testSigners["rsa"])
223         serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
224                 if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
225                         return nil, nil
226                 }
227
228                 return nil, errors.New("pubkey rejected")
229         }
230
231         go func() {
232                 conn, _, _, err := ssh.NewServerConn(a, &serverConf)
233                 if err != nil {
234                         t.Fatalf("Server: %v", err)
235                 }
236                 conn.Close()
237         }()
238
239         conf := ssh.ClientConfig{
240                 HostKeyCallback: ssh.InsecureIgnoreHostKey(),
241         }
242         conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
243         conn, _, _, err := ssh.NewClientConn(b, "", &conf)
244         if err != nil {
245                 t.Fatalf("NewClientConn: %v", err)
246         }
247         conn.Close()
248 }
249
250 func TestLockClient(t *testing.T) {
251         agent, _, cleanup := startAgent(t)
252         defer cleanup()
253         testLockAgent(agent, t)
254 }
255
256 func testLockAgent(agent Agent, t *testing.T) {
257         if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil {
258                 t.Errorf("Add: %v", err)
259         }
260         if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil {
261                 t.Errorf("Add: %v", err)
262         }
263         if keys, err := agent.List(); err != nil {
264                 t.Errorf("List: %v", err)
265         } else if len(keys) != 2 {
266                 t.Errorf("Want 2 keys, got %v", keys)
267         }
268
269         passphrase := []byte("secret")
270         if err := agent.Lock(passphrase); err != nil {
271                 t.Errorf("Lock: %v", err)
272         }
273
274         if keys, err := agent.List(); err != nil {
275                 t.Errorf("List: %v", err)
276         } else if len(keys) != 0 {
277                 t.Errorf("Want 0 keys, got %v", keys)
278         }
279
280         signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
281         if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
282                 t.Fatalf("Sign did not fail")
283         }
284
285         if err := agent.Remove(signer.PublicKey()); err == nil {
286                 t.Fatalf("Remove did not fail")
287         }
288
289         if err := agent.RemoveAll(); err == nil {
290                 t.Fatalf("RemoveAll did not fail")
291         }
292
293         if err := agent.Unlock(nil); err == nil {
294                 t.Errorf("Unlock with wrong passphrase succeeded")
295         }
296         if err := agent.Unlock(passphrase); err != nil {
297                 t.Errorf("Unlock: %v", err)
298         }
299
300         if err := agent.Remove(signer.PublicKey()); err != nil {
301                 t.Fatalf("Remove: %v", err)
302         }
303
304         if keys, err := agent.List(); err != nil {
305                 t.Errorf("List: %v", err)
306         } else if len(keys) != 1 {
307                 t.Errorf("Want 1 keys, got %v", keys)
308         }
309 }
310
311 func TestAgentLifetime(t *testing.T) {
312         agent, _, cleanup := startAgent(t)
313         defer cleanup()
314
315         for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
316                 // Add private keys to the agent.
317                 err := agent.Add(AddedKey{
318                         PrivateKey:   testPrivateKeys[keyType],
319                         Comment:      "comment",
320                         LifetimeSecs: 1,
321                 })
322                 if err != nil {
323                         t.Fatalf("add: %v", err)
324                 }
325                 // Add certs to the agent.
326                 cert := &ssh.Certificate{
327                         Key:         testPublicKeys[keyType],
328                         ValidBefore: ssh.CertTimeInfinity,
329                         CertType:    ssh.UserCert,
330                 }
331                 cert.SignCert(rand.Reader, testSigners[keyType])
332                 err = agent.Add(AddedKey{
333                         PrivateKey:   testPrivateKeys[keyType],
334                         Certificate:  cert,
335                         Comment:      "comment",
336                         LifetimeSecs: 1,
337                 })
338                 if err != nil {
339                         t.Fatalf("add: %v", err)
340                 }
341         }
342         time.Sleep(1100 * time.Millisecond)
343         if keys, err := agent.List(); err != nil {
344                 t.Errorf("List: %v", err)
345         } else if len(keys) != 0 {
346                 t.Errorf("Want 0 keys, got %v", len(keys))
347         }
348 }