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