gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

certs.go (17112B)


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