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 }