OSDN Git Service

new repo
[bytom/vapor.git] / vendor / 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.IsUserAuthority = 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.IsUserAuthority = 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", "otherhost"},
164                 Key:             testPublicKeys["rsa"],
165                 ValidBefore:     CertTimeInfinity,
166                 CertType:        HostCert,
167         }
168         cert.SignCert(rand.Reader, testSigners["ecdsa"])
169
170         checker := &CertChecker{
171                 IsHostAuthority: func(p PublicKey, addr string) bool {
172                         return addr == "hostname:22" && 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 _, test := range []struct {
182                 addr    string
183                 succeed bool
184         }{
185                 {addr: "hostname:22", succeed: true},
186                 {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22'
187                 {addr: "lasthost:22", succeed: false},
188         } {
189                 c1, c2, err := netPipe()
190                 if err != nil {
191                         t.Fatalf("netPipe: %v", err)
192                 }
193                 defer c1.Close()
194                 defer c2.Close()
195
196                 errc := make(chan error)
197
198                 go func() {
199                         conf := ServerConfig{
200                                 NoClientAuth: true,
201                         }
202                         conf.AddHostKey(certSigner)
203                         _, _, _, err := NewServerConn(c1, &conf)
204                         errc <- err
205                 }()
206
207                 config := &ClientConfig{
208                         User:            "user",
209                         HostKeyCallback: checker.CheckHostKey,
210                 }
211                 _, _, _, err = NewClientConn(c2, test.addr, config)
212
213                 if (err == nil) != test.succeed {
214                         t.Fatalf("NewClientConn(%q): %v", test.addr, err)
215                 }
216
217                 err = <-errc
218                 if (err == nil) != test.succeed {
219                         t.Fatalf("NewServerConn(%q): %v", test.addr, err)
220                 }
221         }
222 }