main
Raw Download raw file
  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
  5package ssh
  6
  7import (
  8	"bytes"
  9	"errors"
 10	"fmt"
 11	"io"
 12	"net"
 13	"sort"
 14	"time"
 15)
 16
 17// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear
 18// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms.
 19// Unlike key algorithm names, these are not passed to AlgorithmSigner nor
 20// returned by MultiAlgorithmSigner and don't appear in the Signature.Format
 21// field.
 22const (
 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	// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
 33	// Certificate.Type (or PublicKey.Type), but only in
 34	// ClientConfig.HostKeyAlgorithms.
 35	CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
 36	CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
 37)
 38
 39const (
 40	// Deprecated: use CertAlgoRSAv01.
 41	CertSigAlgoRSAv01 = CertAlgoRSAv01
 42	// Deprecated: use CertAlgoRSASHA256v01.
 43	CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
 44	// Deprecated: use CertAlgoRSASHA512v01.
 45	CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
 46)
 47
 48// Certificate types distinguish between host and user
 49// certificates. The values can be set in the CertType field of
 50// Certificate.
 51const (
 52	UserCert = 1
 53	HostCert = 2
 54)
 55
 56// Signature represents a cryptographic signature.
 57type Signature struct {
 58	Format string
 59	Blob   []byte
 60	Rest   []byte `ssh:"rest"`
 61}
 62
 63// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
 64// a certificate does not expire.
 65const CertTimeInfinity = 1<<64 - 1
 66
 67// An Certificate represents an OpenSSH certificate as defined in
 68// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the
 69// PublicKey interface, so it can be unmarshaled using
 70// ParsePublicKey.
 71type 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// genericCertData holds the key-independent part of the certificate data.
 87// Overall, certificates contain an nonce, public key fields and
 88// key-independent fields.
 89type 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
103func 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
112type optionsTuple struct {
113	Key   string
114	Value []byte
115}
116
117type optionsTupleValue struct {
118	Value string
119}
120
121// serialize a map of critical options or extensions
122// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
123// we need two length prefixes for a non-empty string value
124func 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// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
143// we need two length prefixes for a non-empty option value
144func 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		// according to [PROTOCOL.certkeys], the names must be in
158		// lexical order.
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		// the next field is a data field, which if non-empty has a string embedded
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
183func 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
241type openSSHCertSigner struct {
242	pub    *Certificate
243	signer Signer
244}
245
246type algorithmOpenSSHCertSigner struct {
247	*openSSHCertSigner
248	algorithmSigner AlgorithmSigner
249}
250
251// NewCertSigner returns a Signer that signs with the given Certificate, whose
252// private key is held by signer. It returns an error if the public key in cert
253// doesn't match the key used by signer.
254func 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
274func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
275	return s.signer.Sign(rand, data)
276}
277
278func (s *openSSHCertSigner) PublicKey() PublicKey {
279	return s.pub
280}
281
282func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
283	return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm)
284}
285
286const sourceAddressCriticalOption = "source-address"
287
288// CertChecker does the work of verifying a certificate. Its methods
289// can be plugged into ClientConfig.HostKeyCallback and
290// ServerConfig.PublicKeyCallback. For the CertChecker to work,
291// minimally, the IsAuthority callback should be set.
292type CertChecker struct {
293	// SupportedCriticalOptions lists the CriticalOptions that the
294	// server application layer understands. These are only used
295	// for user certificates.
296	SupportedCriticalOptions []string
297
298	// IsUserAuthority should return true if the key is recognized as an
299	// authority for the given user certificate. This allows for
300	// certificates to be signed by other certificates. This must be set
301	// if this CertChecker will be checking user certificates.
302	IsUserAuthority func(auth PublicKey) bool
303
304	// IsHostAuthority should report whether the key is recognized as
305	// an authority for this host. This allows for certificates to be
306	// signed by other keys, and for those other keys to only be valid
307	// signers for particular hostnames. This must be set if this
308	// CertChecker will be checking host certificates.
309	IsHostAuthority func(auth PublicKey, address string) bool
310
311	// Clock is used for verifying time stamps. If nil, time.Now
312	// is used.
313	Clock func() time.Time
314
315	// UserKeyFallback is called when CertChecker.Authenticate encounters a
316	// public key that is not a certificate. It must implement validation
317	// of user keys or else, if nil, all such keys are rejected.
318	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
319
320	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
321	// public key that is not a certificate. It must implement host key
322	// validation or else, if nil, all such keys are rejected.
323	HostKeyFallback HostKeyCallback
324
325	// IsRevoked is called for each certificate so that revocation checking
326	// can be implemented. It should return true if the given certificate
327	// is revoked and false otherwise. If nil, no certificates are
328	// considered to have been revoked.
329	IsRevoked func(cert *Certificate) bool
330}
331
332// CheckHostKey checks a host key certificate. This method can be
333// plugged into ClientConfig.HostKeyCallback.
334func (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	// Pass hostname only as principal for host certificates (consistent with OpenSSH)
355	return c.CheckCert(hostname, cert)
356}
357
358// Authenticate checks a user certificate. Authenticate can be used as
359// a value for ServerConfig.PublicKeyCallback.
360func (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// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
384// the signature of the certificate.
385func (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		// sourceAddressCriticalOption will be enforced by
392		// serverAuthenticate
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		// By default, certs are valid for all users/hosts.
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// SignCert signs the certificate with an authority, setting the Nonce,
443// SignatureKey, and Signature fields. If the authority implements the
444// MultiAlgorithmSigner interface the first algorithm in the list is used. This
445// is useful if you want to sign with a specific algorithm.
446func (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		// Use the first algorithm in the list.
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		// Default to KeyAlgoRSASHA512 for ssh-rsa signers.
466		// TODO: consider using KeyAlgoRSASHA256 as default.
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// certKeyAlgoNames is a mapping from known certificate algorithm names to the
484// corresponding public key signature algorithm.
485//
486// This map must be kept in sync with the one in agent/client.go.
487var 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// underlyingAlgo returns the signature algorithm associated with algo (which is
501// an advertised or negotiated public key or host key algorithm). These are
502// usually the same, except for certificate algorithms.
503func underlyingAlgo(algo string) string {
504	if a, ok := certKeyAlgoNames[algo]; ok {
505		return a
506	}
507	return algo
508}
509
510// certificateAlgo returns the certificate algorithms that uses the provided
511// underlying signature algorithm.
512func 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
521func (cert *Certificate) bytesForSigning() []byte {
522	c2 := *cert
523	c2.Signature = nil
524	out := c2.Marshal()
525	// Drop trailing signature length.
526	return out[:len(out)-4]
527}
528
529// Marshal serializes c into OpenSSH's wire format. It is part of the
530// PublicKey interface.
531func (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// Type returns the certificate algorithm name. It is part of the PublicKey interface.
563func (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// Verify verifies a signature against the certificate's public
572// key. It is part of the PublicKey interface.
573func (c *Certificate) Verify(data []byte, sig *Signature) error {
574	return c.Key.Verify(data, sig)
575}
576
577func 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
600func 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}