1
2
3
4
5 package ssh
6
7 import (
8 "bytes"
9 "crypto/ecdsa"
10 "crypto/elliptic"
11 "crypto/rand"
12 "fmt"
13 "io"
14 "net"
15 "reflect"
16 "testing"
17 "time"
18 )
19
20
21
22 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=`
23
24 func TestParseCert(t *testing.T) {
25 authKeyBytes := []byte(exampleSSHCert)
26
27 key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
28 if err != nil {
29 t.Fatalf("ParseAuthorizedKey: %v", err)
30 }
31 if len(rest) > 0 {
32 t.Errorf("rest: got %q, want empty", rest)
33 }
34
35 if _, ok := key.(*Certificate); !ok {
36 t.Fatalf("got %v (%T), want *Certificate", key, key)
37 }
38
39 marshaled := MarshalAuthorizedKey(key)
40
41
42 marshaled = marshaled[:len(marshaled)-1]
43 if !bytes.Equal(authKeyBytes, marshaled) {
44 t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
45 }
46 }
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 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`
64
65 func TestParseCertWithOptions(t *testing.T) {
66 opts := map[string]string{
67 "source-address": "192.168.1.0/24",
68 "force-command": "/bin/sleep",
69 }
70 exts := map[string]string{
71 "permit-X11-forwarding": "",
72 "permit-agent-forwarding": "",
73 "permit-port-forwarding": "",
74 "permit-pty": "",
75 "permit-user-rc": "",
76 }
77 authKeyBytes := []byte(exampleSSHCertWithOptions)
78
79 key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
80 if err != nil {
81 t.Fatalf("ParseAuthorizedKey: %v", err)
82 }
83 if len(rest) > 0 {
84 t.Errorf("rest: got %q, want empty", rest)
85 }
86 cert, ok := key.(*Certificate)
87 if !ok {
88 t.Fatalf("got %v (%T), want *Certificate", key, key)
89 }
90 if !reflect.DeepEqual(cert.CriticalOptions, opts) {
91 t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts)
92 }
93 if !reflect.DeepEqual(cert.Extensions, exts) {
94 t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts)
95 }
96 marshaled := MarshalAuthorizedKey(key)
97
98
99 marshaled = marshaled[:len(marshaled)-1]
100 if !bytes.Equal(authKeyBytes, marshaled) {
101 t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
102 }
103 }
104
105 func TestValidateCert(t *testing.T) {
106 key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
107 if err != nil {
108 t.Fatalf("ParseAuthorizedKey: %v", err)
109 }
110 validCert, ok := key.(*Certificate)
111 if !ok {
112 t.Fatalf("got %v (%T), want *Certificate", key, key)
113 }
114 checker := CertChecker{}
115 checker.IsUserAuthority = func(k PublicKey) bool {
116 return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
117 }
118
119 if err := checker.CheckCert("user", validCert); err != nil {
120 t.Errorf("Unable to validate certificate: %v", err)
121 }
122 invalidCert := &Certificate{
123 Key: testPublicKeys["rsa"],
124 SignatureKey: testPublicKeys["ecdsa"],
125 ValidBefore: CertTimeInfinity,
126 Signature: &Signature{},
127 }
128 if err := checker.CheckCert("user", invalidCert); err == nil {
129 t.Error("Invalid cert signature passed validation")
130 }
131 }
132
133 func TestValidateCertTime(t *testing.T) {
134 cert := Certificate{
135 ValidPrincipals: []string{"user"},
136 Key: testPublicKeys["rsa"],
137 ValidAfter: 50,
138 ValidBefore: 100,
139 }
140
141 cert.SignCert(rand.Reader, testSigners["ecdsa"])
142
143 for ts, ok := range map[int64]bool{
144 25: false,
145 50: true,
146 99: true,
147 100: false,
148 125: false,
149 } {
150 checker := CertChecker{
151 Clock: func() time.Time { return time.Unix(ts, 0) },
152 }
153 checker.IsUserAuthority = func(k PublicKey) bool {
154 return bytes.Equal(k.Marshal(),
155 testPublicKeys["ecdsa"].Marshal())
156 }
157
158 if v := checker.CheckCert("user", &cert); (v == nil) != ok {
159 t.Errorf("Authenticate(%d): %v", ts, v)
160 }
161 }
162 }
163
164
165
166
167
168
169 func TestHostKeyCert(t *testing.T) {
170 cert := &Certificate{
171 ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"},
172 Key: testPublicKeys["rsa"],
173 ValidBefore: CertTimeInfinity,
174 CertType: HostCert,
175 }
176 cert.SignCert(rand.Reader, testSigners["ecdsa"])
177
178 checker := &CertChecker{
179 IsHostAuthority: func(p PublicKey, addr string) bool {
180 return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
181 },
182 }
183
184 certSigner, err := NewCertSigner(cert, testSigners["rsa"])
185 if err != nil {
186 t.Errorf("NewCertSigner: %v", err)
187 }
188
189 for _, test := range []struct {
190 addr string
191 succeed bool
192 certSignerAlgorithms []string
193 clientHostKeyAlgorithms []string
194 }{
195 {addr: "hostname:22", succeed: true},
196 {
197 addr: "hostname:22",
198 succeed: true,
199 certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512},
200 clientHostKeyAlgorithms: []string{CertAlgoRSASHA512v01},
201 },
202 {
203 addr: "hostname:22",
204 succeed: false,
205 certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512},
206 clientHostKeyAlgorithms: []string{CertAlgoRSAv01},
207 },
208 {
209 addr: "hostname:22",
210 succeed: false,
211 certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512},
212 clientHostKeyAlgorithms: []string{KeyAlgoRSASHA512},
213 },
214 {addr: "otherhost:22", succeed: false},
215 {addr: "lasthost:22", succeed: false},
216 } {
217 c1, c2, err := netPipe()
218 if err != nil {
219 t.Fatalf("netPipe: %v", err)
220 }
221 defer c1.Close()
222 defer c2.Close()
223
224 errc := make(chan error)
225
226 go func() {
227 conf := ServerConfig{
228 NoClientAuth: true,
229 }
230 if len(test.certSignerAlgorithms) > 0 {
231 mas, err := NewSignerWithAlgorithms(certSigner.(AlgorithmSigner), test.certSignerAlgorithms)
232 if err != nil {
233 errc <- err
234 return
235 }
236 conf.AddHostKey(mas)
237 } else {
238 conf.AddHostKey(certSigner)
239 }
240 _, _, _, err := NewServerConn(c1, &conf)
241 errc <- err
242 }()
243
244 config := &ClientConfig{
245 User: "user",
246 HostKeyCallback: checker.CheckHostKey,
247 HostKeyAlgorithms: test.clientHostKeyAlgorithms,
248 }
249 _, _, _, err = NewClientConn(c2, test.addr, config)
250
251 if (err == nil) != test.succeed {
252 t.Errorf("NewClientConn(%q): %v", test.addr, err)
253 }
254
255 err = <-errc
256 if (err == nil) != test.succeed {
257 t.Errorf("NewServerConn(%q): %v", test.addr, err)
258 }
259 }
260 }
261
262 type legacyRSASigner struct {
263 Signer
264 }
265
266 func (s *legacyRSASigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
267 v, ok := s.Signer.(AlgorithmSigner)
268 if !ok {
269 return nil, fmt.Errorf("invalid signer")
270 }
271 return v.SignWithAlgorithm(rand, data, KeyAlgoRSA)
272 }
273
274 func TestCertTypes(t *testing.T) {
275 algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner)
276 if !ok {
277 t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
278 }
279 multiAlgoSignerSHA256, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256})
280 if err != nil {
281 t.Fatalf("unable to create multi algorithm signer SHA256: %v", err)
282 }
283
284 multiAlgoSignerSHA512, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256})
285 if err != nil {
286 t.Fatalf("unable to create multi algorithm signer SHA512: %v", err)
287 }
288
289 var testVars = []struct {
290 name string
291 signer Signer
292 algo string
293 }{
294 {CertAlgoECDSA256v01, testSigners["ecdsap256"], ""},
295 {CertAlgoECDSA384v01, testSigners["ecdsap384"], ""},
296 {CertAlgoECDSA521v01, testSigners["ecdsap521"], ""},
297 {CertAlgoED25519v01, testSigners["ed25519"], ""},
298 {CertAlgoRSAv01, testSigners["rsa"], KeyAlgoRSASHA256},
299 {"legacyRSASigner", &legacyRSASigner{testSigners["rsa"]}, KeyAlgoRSA},
300 {"multiAlgoRSASignerSHA256", multiAlgoSignerSHA256, KeyAlgoRSASHA256},
301 {"multiAlgoRSASignerSHA512", multiAlgoSignerSHA512, KeyAlgoRSASHA512},
302 {CertAlgoDSAv01, testSigners["dsa"], ""},
303 }
304
305 k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
306 if err != nil {
307 t.Fatalf("error generating host key: %v", err)
308 }
309
310 signer, err := NewSignerFromKey(k)
311 if err != nil {
312 t.Fatalf("error generating signer for ssh listener: %v", err)
313 }
314
315 conf := &ServerConfig{
316 PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) {
317 return new(Permissions), nil
318 },
319 }
320 conf.AddHostKey(signer)
321
322 for _, m := range testVars {
323 t.Run(m.name, func(t *testing.T) {
324
325 c1, c2, err := netPipe()
326 if err != nil {
327 t.Fatalf("netPipe: %v", err)
328 }
329 defer c1.Close()
330 defer c2.Close()
331
332 go NewServerConn(c1, conf)
333
334 priv := m.signer
335 if err != nil {
336 t.Fatalf("error generating ssh pubkey: %v", err)
337 }
338
339 cert := &Certificate{
340 CertType: UserCert,
341 Key: priv.PublicKey(),
342 }
343 cert.SignCert(rand.Reader, priv)
344
345 certSigner, err := NewCertSigner(cert, priv)
346 if err != nil {
347 t.Fatalf("error generating cert signer: %v", err)
348 }
349
350 if m.algo != "" && cert.Signature.Format != m.algo {
351 t.Errorf("expected %q signature format, got %q", m.algo, cert.Signature.Format)
352 }
353
354 config := &ClientConfig{
355 User: "user",
356 HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil },
357 Auth: []AuthMethod{PublicKeys(certSigner)},
358 }
359
360 _, _, _, err = NewClientConn(c2, "", config)
361 if err != nil {
362 t.Fatalf("error connecting: %v", err)
363 }
364 })
365 }
366 }
367
368 func TestCertSignWithMultiAlgorithmSigner(t *testing.T) {
369 type testcase struct {
370 sigAlgo string
371 algoritms []string
372 }
373 cases := []testcase{
374 {
375 sigAlgo: KeyAlgoRSA,
376 algoritms: []string{KeyAlgoRSA, KeyAlgoRSASHA512},
377 },
378 {
379 sigAlgo: KeyAlgoRSASHA256,
380 algoritms: []string{KeyAlgoRSASHA256, KeyAlgoRSA, KeyAlgoRSASHA512},
381 },
382 {
383 sigAlgo: KeyAlgoRSASHA512,
384 algoritms: []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256},
385 },
386 }
387
388 cert := &Certificate{
389 Key: testPublicKeys["rsa"],
390 ValidBefore: CertTimeInfinity,
391 CertType: UserCert,
392 }
393
394 for _, c := range cases {
395 t.Run(c.sigAlgo, func(t *testing.T) {
396 signer, err := NewSignerWithAlgorithms(testSigners["rsa"].(AlgorithmSigner), c.algoritms)
397 if err != nil {
398 t.Fatalf("NewSignerWithAlgorithms error: %v", err)
399 }
400 if err := cert.SignCert(rand.Reader, signer); err != nil {
401 t.Fatalf("SignCert error: %v", err)
402 }
403 if cert.Signature.Format != c.sigAlgo {
404 t.Fatalf("got signature format %q, want %q", cert.Signature.Format, c.sigAlgo)
405 }
406 })
407 }
408 }
409
View as plain text