github.com/ssube/gitlab-ci-multi-runner@v1.2.1-0.20160607142738-b8d1285632e6/Godeps/_workspace/src/golang.org/x/crypto/ssh/certs.go (about)

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