certs.go 13 KB

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