1
2
3
4
5 package ssh
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "net"
13 "sort"
14 "time"
15 )
16
17
18
19
20
21
22 const (
23 CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
24 CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
25 CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
26 CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
27 CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
28 CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
29 CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
30 CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
31
32
33
34
35 CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
36 CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
37 )
38
39 const (
40
41 CertSigAlgoRSAv01 = CertAlgoRSAv01
42
43 CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
44
45 CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
46 )
47
48
49
50
51 const (
52 UserCert = 1
53 HostCert = 2
54 )
55
56
57 type Signature struct {
58 Format string
59 Blob []byte
60 Rest []byte `ssh:"rest"`
61 }
62
63
64
65 const CertTimeInfinity = 1<<64 - 1
66
67
68
69
70
71 type Certificate struct {
72 Nonce []byte
73 Key PublicKey
74 Serial uint64
75 CertType uint32
76 KeyId string
77 ValidPrincipals []string
78 ValidAfter uint64
79 ValidBefore uint64
80 Permissions
81 Reserved []byte
82 SignatureKey PublicKey
83 Signature *Signature
84 }
85
86
87
88
89 type genericCertData struct {
90 Serial uint64
91 CertType uint32
92 KeyId string
93 ValidPrincipals []byte
94 ValidAfter uint64
95 ValidBefore uint64
96 CriticalOptions []byte
97 Extensions []byte
98 Reserved []byte
99 SignatureKey []byte
100 Signature []byte
101 }
102
103 func marshalStringList(namelist []string) []byte {
104 var to []byte
105 for _, name := range namelist {
106 s := struct{ N string }{name}
107 to = append(to, Marshal(&s)...)
108 }
109 return to
110 }
111
112 type optionsTuple struct {
113 Key string
114 Value []byte
115 }
116
117 type optionsTupleValue struct {
118 Value string
119 }
120
121
122
123
124 func marshalTuples(tups map[string]string) []byte {
125 keys := make([]string, 0, len(tups))
126 for key := range tups {
127 keys = append(keys, key)
128 }
129 sort.Strings(keys)
130
131 var ret []byte
132 for _, key := range keys {
133 s := optionsTuple{Key: key}
134 if value := tups[key]; len(value) > 0 {
135 s.Value = Marshal(&optionsTupleValue{value})
136 }
137 ret = append(ret, Marshal(&s)...)
138 }
139 return ret
140 }
141
142
143
144 func parseTuples(in []byte) (map[string]string, error) {
145 tups := map[string]string{}
146 var lastKey string
147 var haveLastKey bool
148
149 for len(in) > 0 {
150 var key, val, extra []byte
151 var ok bool
152
153 if key, in, ok = parseString(in); !ok {
154 return nil, errShortRead
155 }
156 keyStr := string(key)
157
158
159 if haveLastKey && keyStr <= lastKey {
160 return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
161 }
162 lastKey, haveLastKey = keyStr, true
163
164 if val, in, ok = parseString(in); !ok {
165 return nil, errShortRead
166 }
167 if len(val) > 0 {
168 val, extra, ok = parseString(val)
169 if !ok {
170 return nil, errShortRead
171 }
172 if len(extra) > 0 {
173 return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
174 }
175 tups[keyStr] = string(val)
176 } else {
177 tups[keyStr] = ""
178 }
179 }
180 return tups, nil
181 }
182
183 func parseCert(in []byte, privAlgo string) (*Certificate, error) {
184 nonce, rest, ok := parseString(in)
185 if !ok {
186 return nil, errShortRead
187 }
188
189 key, rest, err := parsePubKey(rest, privAlgo)
190 if err != nil {
191 return nil, err
192 }
193
194 var g genericCertData
195 if err := Unmarshal(rest, &g); err != nil {
196 return nil, err
197 }
198
199 c := &Certificate{
200 Nonce: nonce,
201 Key: key,
202 Serial: g.Serial,
203 CertType: g.CertType,
204 KeyId: g.KeyId,
205 ValidAfter: g.ValidAfter,
206 ValidBefore: g.ValidBefore,
207 }
208
209 for principals := g.ValidPrincipals; len(principals) > 0; {
210 principal, rest, ok := parseString(principals)
211 if !ok {
212 return nil, errShortRead
213 }
214 c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
215 principals = rest
216 }
217
218 c.CriticalOptions, err = parseTuples(g.CriticalOptions)
219 if err != nil {
220 return nil, err
221 }
222 c.Extensions, err = parseTuples(g.Extensions)
223 if err != nil {
224 return nil, err
225 }
226 c.Reserved = g.Reserved
227 k, err := ParsePublicKey(g.SignatureKey)
228 if err != nil {
229 return nil, err
230 }
231
232 c.SignatureKey = k
233 c.Signature, rest, ok = parseSignatureBody(g.Signature)
234 if !ok || len(rest) > 0 {
235 return nil, errors.New("ssh: signature parse error")
236 }
237
238 return c, nil
239 }
240
241 type openSSHCertSigner struct {
242 pub *Certificate
243 signer Signer
244 }
245
246 type algorithmOpenSSHCertSigner struct {
247 *openSSHCertSigner
248 algorithmSigner AlgorithmSigner
249 }
250
251
252
253
254 func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
255 if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) {
256 return nil, errors.New("ssh: signer and cert have different public key")
257 }
258
259 switch s := signer.(type) {
260 case MultiAlgorithmSigner:
261 return &multiAlgorithmSigner{
262 AlgorithmSigner: &algorithmOpenSSHCertSigner{
263 &openSSHCertSigner{cert, signer}, s},
264 supportedAlgorithms: s.Algorithms(),
265 }, nil
266 case AlgorithmSigner:
267 return &algorithmOpenSSHCertSigner{
268 &openSSHCertSigner{cert, signer}, s}, nil
269 default:
270 return &openSSHCertSigner{cert, signer}, nil
271 }
272 }
273
274 func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
275 return s.signer.Sign(rand, data)
276 }
277
278 func (s *openSSHCertSigner) PublicKey() PublicKey {
279 return s.pub
280 }
281
282 func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
283 return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm)
284 }
285
286 const sourceAddressCriticalOption = "source-address"
287
288
289
290
291
292 type CertChecker struct {
293
294
295
296 SupportedCriticalOptions []string
297
298
299
300
301
302 IsUserAuthority func(auth PublicKey) bool
303
304
305
306
307
308
309 IsHostAuthority func(auth PublicKey, address string) bool
310
311
312
313 Clock func() time.Time
314
315
316
317
318 UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
319
320
321
322
323 HostKeyFallback HostKeyCallback
324
325
326
327
328
329 IsRevoked func(cert *Certificate) bool
330 }
331
332
333
334 func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
335 cert, ok := key.(*Certificate)
336 if !ok {
337 if c.HostKeyFallback != nil {
338 return c.HostKeyFallback(addr, remote, key)
339 }
340 return errors.New("ssh: non-certificate host key")
341 }
342 if cert.CertType != HostCert {
343 return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
344 }
345 if !c.IsHostAuthority(cert.SignatureKey, addr) {
346 return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
347 }
348
349 hostname, _, err := net.SplitHostPort(addr)
350 if err != nil {
351 return err
352 }
353
354
355 return c.CheckCert(hostname, cert)
356 }
357
358
359
360 func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
361 cert, ok := pubKey.(*Certificate)
362 if !ok {
363 if c.UserKeyFallback != nil {
364 return c.UserKeyFallback(conn, pubKey)
365 }
366 return nil, errors.New("ssh: normal key pairs not accepted")
367 }
368
369 if cert.CertType != UserCert {
370 return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
371 }
372 if !c.IsUserAuthority(cert.SignatureKey) {
373 return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
374 }
375
376 if err := c.CheckCert(conn.User(), cert); err != nil {
377 return nil, err
378 }
379
380 return &cert.Permissions, nil
381 }
382
383
384
385 func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
386 if c.IsRevoked != nil && c.IsRevoked(cert) {
387 return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)
388 }
389
390 for opt := range cert.CriticalOptions {
391
392
393 if opt == sourceAddressCriticalOption {
394 continue
395 }
396
397 found := false
398 for _, supp := range c.SupportedCriticalOptions {
399 if supp == opt {
400 found = true
401 break
402 }
403 }
404 if !found {
405 return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
406 }
407 }
408
409 if len(cert.ValidPrincipals) > 0 {
410
411 found := false
412 for _, p := range cert.ValidPrincipals {
413 if p == principal {
414 found = true
415 break
416 }
417 }
418 if !found {
419 return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
420 }
421 }
422
423 clock := c.Clock
424 if clock == nil {
425 clock = time.Now
426 }
427
428 unixNow := clock().Unix()
429 if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
430 return fmt.Errorf("ssh: cert is not yet valid")
431 }
432 if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
433 return fmt.Errorf("ssh: cert has expired")
434 }
435 if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
436 return fmt.Errorf("ssh: certificate signature does not verify")
437 }
438
439 return nil
440 }
441
442
443
444
445
446 func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
447 c.Nonce = make([]byte, 32)
448 if _, err := io.ReadFull(rand, c.Nonce); err != nil {
449 return err
450 }
451 c.SignatureKey = authority.PublicKey()
452
453 if v, ok := authority.(MultiAlgorithmSigner); ok {
454 if len(v.Algorithms()) == 0 {
455 return errors.New("the provided authority has no signature algorithm")
456 }
457
458 sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), v.Algorithms()[0])
459 if err != nil {
460 return err
461 }
462 c.Signature = sig
463 return nil
464 } else if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA {
465
466
467 sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512)
468 if err != nil {
469 return err
470 }
471 c.Signature = sig
472 return nil
473 }
474
475 sig, err := authority.Sign(rand, c.bytesForSigning())
476 if err != nil {
477 return err
478 }
479 c.Signature = sig
480 return nil
481 }
482
483
484
485
486
487 var certKeyAlgoNames = map[string]string{
488 CertAlgoRSAv01: KeyAlgoRSA,
489 CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
490 CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
491 CertAlgoDSAv01: KeyAlgoDSA,
492 CertAlgoECDSA256v01: KeyAlgoECDSA256,
493 CertAlgoECDSA384v01: KeyAlgoECDSA384,
494 CertAlgoECDSA521v01: KeyAlgoECDSA521,
495 CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
496 CertAlgoED25519v01: KeyAlgoED25519,
497 CertAlgoSKED25519v01: KeyAlgoSKED25519,
498 }
499
500
501
502
503 func underlyingAlgo(algo string) string {
504 if a, ok := certKeyAlgoNames[algo]; ok {
505 return a
506 }
507 return algo
508 }
509
510
511
512 func certificateAlgo(algo string) (certAlgo string, ok bool) {
513 for certName, algoName := range certKeyAlgoNames {
514 if algoName == algo {
515 return certName, true
516 }
517 }
518 return "", false
519 }
520
521 func (cert *Certificate) bytesForSigning() []byte {
522 c2 := *cert
523 c2.Signature = nil
524 out := c2.Marshal()
525
526 return out[:len(out)-4]
527 }
528
529
530
531 func (c *Certificate) Marshal() []byte {
532 generic := genericCertData{
533 Serial: c.Serial,
534 CertType: c.CertType,
535 KeyId: c.KeyId,
536 ValidPrincipals: marshalStringList(c.ValidPrincipals),
537 ValidAfter: uint64(c.ValidAfter),
538 ValidBefore: uint64(c.ValidBefore),
539 CriticalOptions: marshalTuples(c.CriticalOptions),
540 Extensions: marshalTuples(c.Extensions),
541 Reserved: c.Reserved,
542 SignatureKey: c.SignatureKey.Marshal(),
543 }
544 if c.Signature != nil {
545 generic.Signature = Marshal(c.Signature)
546 }
547 genericBytes := Marshal(&generic)
548 keyBytes := c.Key.Marshal()
549 _, keyBytes, _ = parseString(keyBytes)
550 prefix := Marshal(&struct {
551 Name string
552 Nonce []byte
553 Key []byte `ssh:"rest"`
554 }{c.Type(), c.Nonce, keyBytes})
555
556 result := make([]byte, 0, len(prefix)+len(genericBytes))
557 result = append(result, prefix...)
558 result = append(result, genericBytes...)
559 return result
560 }
561
562
563 func (c *Certificate) Type() string {
564 certName, ok := certificateAlgo(c.Key.Type())
565 if !ok {
566 panic("unknown certificate type for key type " + c.Key.Type())
567 }
568 return certName
569 }
570
571
572
573 func (c *Certificate) Verify(data []byte, sig *Signature) error {
574 return c.Key.Verify(data, sig)
575 }
576
577 func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
578 format, in, ok := parseString(in)
579 if !ok {
580 return
581 }
582
583 out = &Signature{
584 Format: string(format),
585 }
586
587 if out.Blob, in, ok = parseString(in); !ok {
588 return
589 }
590
591 switch out.Format {
592 case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01:
593 out.Rest = in
594 return out, nil, ok
595 }
596
597 return out, in, ok
598 }
599
600 func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
601 sigBytes, rest, ok := parseString(in)
602 if !ok {
603 return
604 }
605
606 out, trailing, ok := parseSignatureBody(sigBytes)
607 if !ok || len(trailing) > 0 {
608 return nil, nil, false
609 }
610 return
611 }
612
View as plain text