Advertisement
kosx

certs.go

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