OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / ssh / certs.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         "bytes"
9         "errors"
10         "fmt"
11         "io"
12         "net"
13         "sort"
14         "time"
15 )
16
17 // These constants from [PROTOCOL.certkeys] represent the algorithm names
18 // for certificate types supported by this package.
19 const (
20         CertAlgoRSAv01      = "ssh-rsa-cert-v01@openssh.com"
21         CertAlgoDSAv01      = "ssh-dss-cert-v01@openssh.com"
22         CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
23         CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
24         CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
25         CertAlgoED25519v01  = "ssh-ed25519-cert-v01@openssh.com"
26 )
27
28 // Certificate types distinguish between host and user
29 // certificates. The values can be set in the CertType field of
30 // Certificate.
31 const (
32         UserCert = 1
33         HostCert = 2
34 )
35
36 // Signature represents a cryptographic signature.
37 type Signature struct {
38         Format string
39         Blob   []byte
40 }
41
42 // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
43 // a certificate does not expire.
44 const CertTimeInfinity = 1<<64 - 1
45
46 // An Certificate represents an OpenSSH certificate as defined in
47 // [PROTOCOL.certkeys]?rev=1.8.
48 type Certificate struct {
49         Nonce           []byte
50         Key             PublicKey
51         Serial          uint64
52         CertType        uint32
53         KeyId           string
54         ValidPrincipals []string
55         ValidAfter      uint64
56         ValidBefore     uint64
57         Permissions
58         Reserved     []byte
59         SignatureKey PublicKey
60         Signature    *Signature
61 }
62
63 // genericCertData holds the key-independent part of the certificate data.
64 // Overall, certificates contain an nonce, public key fields and
65 // key-independent fields.
66 type genericCertData struct {
67         Serial          uint64
68         CertType        uint32
69         KeyId           string
70         ValidPrincipals []byte
71         ValidAfter      uint64
72         ValidBefore     uint64
73         CriticalOptions []byte
74         Extensions      []byte
75         Reserved        []byte
76         SignatureKey    []byte
77         Signature       []byte
78 }
79
80 func marshalStringList(namelist []string) []byte {
81         var to []byte
82         for _, name := range namelist {
83                 s := struct{ N string }{name}
84                 to = append(to, Marshal(&s)...)
85         }
86         return to
87 }
88
89 type optionsTuple struct {
90         Key   string
91         Value []byte
92 }
93
94 type optionsTupleValue struct {
95         Value string
96 }
97
98 // serialize a map of critical options or extensions
99 // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
100 // we need two length prefixes for a non-empty string value
101 func marshalTuples(tups map[string]string) []byte {
102         keys := make([]string, 0, len(tups))
103         for key := range tups {
104                 keys = append(keys, key)
105         }
106         sort.Strings(keys)
107
108         var ret []byte
109         for _, key := range keys {
110                 s := optionsTuple{Key: key}
111                 if value := tups[key]; len(value) > 0 {
112                         s.Value = Marshal(&optionsTupleValue{value})
113                 }
114                 ret = append(ret, Marshal(&s)...)
115         }
116         return ret
117 }
118
119 // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
120 // we need two length prefixes for a non-empty option value
121 func parseTuples(in []byte) (map[string]string, error) {
122         tups := map[string]string{}
123         var lastKey string
124         var haveLastKey bool
125
126         for len(in) > 0 {
127                 var key, val, extra []byte
128                 var ok bool
129
130                 if key, in, ok = parseString(in); !ok {
131                         return nil, errShortRead
132                 }
133                 keyStr := string(key)
134                 // according to [PROTOCOL.certkeys], the names must be in
135                 // lexical order.
136                 if haveLastKey && keyStr <= lastKey {
137                         return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
138                 }
139                 lastKey, haveLastKey = keyStr, true
140                 // the next field is a data field, which if non-empty has a string embedded
141                 if val, in, ok = parseString(in); !ok {
142                         return nil, errShortRead
143                 }
144                 if len(val) > 0 {
145                         val, extra, ok = parseString(val)
146                         if !ok {
147                                 return nil, errShortRead
148                         }
149                         if len(extra) > 0 {
150                                 return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
151                         }
152                         tups[keyStr] = string(val)
153                 } else {
154                         tups[keyStr] = ""
155                 }
156         }
157         return tups, nil
158 }
159
160 func parseCert(in []byte, privAlgo string) (*Certificate, error) {
161         nonce, rest, ok := parseString(in)
162         if !ok {
163                 return nil, errShortRead
164         }
165
166         key, rest, err := parsePubKey(rest, privAlgo)
167         if err != nil {
168                 return nil, err
169         }
170
171         var g genericCertData
172         if err := Unmarshal(rest, &g); err != nil {
173                 return nil, err
174         }
175
176         c := &Certificate{
177                 Nonce:       nonce,
178                 Key:         key,
179                 Serial:      g.Serial,
180                 CertType:    g.CertType,
181                 KeyId:       g.KeyId,
182                 ValidAfter:  g.ValidAfter,
183                 ValidBefore: g.ValidBefore,
184         }
185
186         for principals := g.ValidPrincipals; len(principals) > 0; {
187                 principal, rest, ok := parseString(principals)
188                 if !ok {
189                         return nil, errShortRead
190                 }
191                 c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
192                 principals = rest
193         }
194
195         c.CriticalOptions, err = parseTuples(g.CriticalOptions)
196         if err != nil {
197                 return nil, err
198         }
199         c.Extensions, err = parseTuples(g.Extensions)
200         if err != nil {
201                 return nil, err
202         }
203         c.Reserved = g.Reserved
204         k, err := ParsePublicKey(g.SignatureKey)
205         if err != nil {
206                 return nil, err
207         }
208
209         c.SignatureKey = k
210         c.Signature, rest, ok = parseSignatureBody(g.Signature)
211         if !ok || len(rest) > 0 {
212                 return nil, errors.New("ssh: signature parse error")
213         }
214
215         return c, nil
216 }
217
218 type openSSHCertSigner struct {
219         pub    *Certificate
220         signer Signer
221 }
222
223 // NewCertSigner returns a Signer that signs with the given Certificate, whose
224 // private key is held by signer. It returns an error if the public key in cert
225 // doesn't match the key used by signer.
226 func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
227         if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
228                 return nil, errors.New("ssh: signer and cert have different public key")
229         }
230
231         return &openSSHCertSigner{cert, signer}, nil
232 }
233
234 func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
235         return s.signer.Sign(rand, data)
236 }
237
238 func (s *openSSHCertSigner) PublicKey() PublicKey {
239         return s.pub
240 }
241
242 const sourceAddressCriticalOption = "source-address"
243
244 // CertChecker does the work of verifying a certificate. Its methods
245 // can be plugged into ClientConfig.HostKeyCallback and
246 // ServerConfig.PublicKeyCallback. For the CertChecker to work,
247 // minimally, the IsAuthority callback should be set.
248 type CertChecker struct {
249         // SupportedCriticalOptions lists the CriticalOptions that the
250         // server application layer understands. These are only used
251         // for user certificates.
252         SupportedCriticalOptions []string
253
254         // IsUserAuthority should return true if the key is recognized as an
255         // authority for the given user certificate. This allows for
256         // certificates to be signed by other certificates. This must be set
257         // if this CertChecker will be checking user certificates.
258         IsUserAuthority func(auth PublicKey) bool
259
260         // IsHostAuthority should report whether the key is recognized as
261         // an authority for this host. This allows for certificates to be
262         // signed by other keys, and for those other keys to only be valid
263         // signers for particular hostnames. This must be set if this
264         // CertChecker will be checking host certificates.
265         IsHostAuthority func(auth PublicKey, address string) bool
266
267         // Clock is used for verifying time stamps. If nil, time.Now
268         // is used.
269         Clock func() time.Time
270
271         // UserKeyFallback is called when CertChecker.Authenticate encounters a
272         // public key that is not a certificate. It must implement validation
273         // of user keys or else, if nil, all such keys are rejected.
274         UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
275
276         // HostKeyFallback is called when CertChecker.CheckHostKey encounters a
277         // public key that is not a certificate. It must implement host key
278         // validation or else, if nil, all such keys are rejected.
279         HostKeyFallback HostKeyCallback
280
281         // IsRevoked is called for each certificate so that revocation checking
282         // can be implemented. It should return true if the given certificate
283         // is revoked and false otherwise. If nil, no certificates are
284         // considered to have been revoked.
285         IsRevoked func(cert *Certificate) bool
286 }
287
288 // CheckHostKey checks a host key certificate. This method can be
289 // plugged into ClientConfig.HostKeyCallback.
290 func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
291         cert, ok := key.(*Certificate)
292         if !ok {
293                 if c.HostKeyFallback != nil {
294                         return c.HostKeyFallback(addr, remote, key)
295                 }
296                 return errors.New("ssh: non-certificate host key")
297         }
298         if cert.CertType != HostCert {
299                 return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
300         }
301         if !c.IsHostAuthority(cert.SignatureKey, addr) {
302                 return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
303         }
304
305         hostname, _, err := net.SplitHostPort(addr)
306         if err != nil {
307                 return err
308         }
309
310         // Pass hostname only as principal for host certificates (consistent with OpenSSH)
311         return c.CheckCert(hostname, cert)
312 }
313
314 // Authenticate checks a user certificate. Authenticate can be used as
315 // a value for ServerConfig.PublicKeyCallback.
316 func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
317         cert, ok := pubKey.(*Certificate)
318         if !ok {
319                 if c.UserKeyFallback != nil {
320                         return c.UserKeyFallback(conn, pubKey)
321                 }
322                 return nil, errors.New("ssh: normal key pairs not accepted")
323         }
324
325         if cert.CertType != UserCert {
326                 return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
327         }
328         if !c.IsUserAuthority(cert.SignatureKey) {
329                 return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
330         }
331
332         if err := c.CheckCert(conn.User(), cert); err != nil {
333                 return nil, err
334         }
335
336         return &cert.Permissions, nil
337 }
338
339 // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
340 // the signature of the certificate.
341 func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
342         if c.IsRevoked != nil && c.IsRevoked(cert) {
343                 return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
344         }
345
346         for opt, _ := range cert.CriticalOptions {
347                 // sourceAddressCriticalOption will be enforced by
348                 // serverAuthenticate
349                 if opt == sourceAddressCriticalOption {
350                         continue
351                 }
352
353                 found := false
354                 for _, supp := range c.SupportedCriticalOptions {
355                         if supp == opt {
356                                 found = true
357                                 break
358                         }
359                 }
360                 if !found {
361                         return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
362                 }
363         }
364
365         if len(cert.ValidPrincipals) > 0 {
366                 // By default, certs are valid for all users/hosts.
367                 found := false
368                 for _, p := range cert.ValidPrincipals {
369                         if p == principal {
370                                 found = true
371                                 break
372                         }
373                 }
374                 if !found {
375                         return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
376                 }
377         }
378
379         clock := c.Clock
380         if clock == nil {
381                 clock = time.Now
382         }
383
384         unixNow := clock().Unix()
385         if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
386                 return fmt.Errorf("ssh: cert is not yet valid")
387         }
388         if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
389                 return fmt.Errorf("ssh: cert has expired")
390         }
391         if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
392                 return fmt.Errorf("ssh: certificate signature does not verify")
393         }
394
395         return nil
396 }
397
398 // SignCert sets c.SignatureKey to the authority's public key and stores a
399 // Signature, by authority, in the certificate.
400 func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
401         c.Nonce = make([]byte, 32)
402         if _, err := io.ReadFull(rand, c.Nonce); err != nil {
403                 return err
404         }
405         c.SignatureKey = authority.PublicKey()
406
407         sig, err := authority.Sign(rand, c.bytesForSigning())
408         if err != nil {
409                 return err
410         }
411         c.Signature = sig
412         return nil
413 }
414
415 var certAlgoNames = map[string]string{
416         KeyAlgoRSA:      CertAlgoRSAv01,
417         KeyAlgoDSA:      CertAlgoDSAv01,
418         KeyAlgoECDSA256: CertAlgoECDSA256v01,
419         KeyAlgoECDSA384: CertAlgoECDSA384v01,
420         KeyAlgoECDSA521: CertAlgoECDSA521v01,
421         KeyAlgoED25519:  CertAlgoED25519v01,
422 }
423
424 // certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
425 // Panics if a non-certificate algorithm is passed.
426 func certToPrivAlgo(algo string) string {
427         for privAlgo, pubAlgo := range certAlgoNames {
428                 if pubAlgo == algo {
429                         return privAlgo
430                 }
431         }
432         panic("unknown cert algorithm")
433 }
434
435 func (cert *Certificate) bytesForSigning() []byte {
436         c2 := *cert
437         c2.Signature = nil
438         out := c2.Marshal()
439         // Drop trailing signature length.
440         return out[:len(out)-4]
441 }
442
443 // Marshal serializes c into OpenSSH's wire format. It is part of the
444 // PublicKey interface.
445 func (c *Certificate) Marshal() []byte {
446         generic := genericCertData{
447                 Serial:          c.Serial,
448                 CertType:        c.CertType,
449                 KeyId:           c.KeyId,
450                 ValidPrincipals: marshalStringList(c.ValidPrincipals),
451                 ValidAfter:      uint64(c.ValidAfter),
452                 ValidBefore:     uint64(c.ValidBefore),
453                 CriticalOptions: marshalTuples(c.CriticalOptions),
454                 Extensions:      marshalTuples(c.Extensions),
455                 Reserved:        c.Reserved,
456                 SignatureKey:    c.SignatureKey.Marshal(),
457         }
458         if c.Signature != nil {
459                 generic.Signature = Marshal(c.Signature)
460         }
461         genericBytes := Marshal(&generic)
462         keyBytes := c.Key.Marshal()
463         _, keyBytes, _ = parseString(keyBytes)
464         prefix := Marshal(&struct {
465                 Name  string
466                 Nonce []byte
467                 Key   []byte `ssh:"rest"`
468         }{c.Type(), c.Nonce, keyBytes})
469
470         result := make([]byte, 0, len(prefix)+len(genericBytes))
471         result = append(result, prefix...)
472         result = append(result, genericBytes...)
473         return result
474 }
475
476 // Type returns the key name. It is part of the PublicKey interface.
477 func (c *Certificate) Type() string {
478         algo, ok := certAlgoNames[c.Key.Type()]
479         if !ok {
480                 panic("unknown cert key type " + c.Key.Type())
481         }
482         return algo
483 }
484
485 // Verify verifies a signature against the certificate's public
486 // key. It is part of the PublicKey interface.
487 func (c *Certificate) Verify(data []byte, sig *Signature) error {
488         return c.Key.Verify(data, sig)
489 }
490
491 func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
492         format, in, ok := parseString(in)
493         if !ok {
494                 return
495         }
496
497         out = &Signature{
498                 Format: string(format),
499         }
500
501         if out.Blob, in, ok = parseString(in); !ok {
502                 return
503         }
504
505         return out, in, ok
506 }
507
508 func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
509         sigBytes, rest, ok := parseString(in)
510         if !ok {
511                 return
512         }
513
514         out, trailing, ok := parseSignatureBody(sigBytes)
515         if !ok || len(trailing) > 0 {
516                 return nil, nil, false
517         }
518         return
519 }