a geicko-2 based round robin ranking system designed to test c++ battleship submissions battleship.dunkirk.sh
at main 19 kB view raw
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 5package ssh 6 7import ( 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 nor 20// returned by MultiAlgorithmSigner and don't appear in the Signature.Format 21// field. 22const ( 23 CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" 24 // Deprecated: DSA is only supported at insecure key sizes, and was removed 25 // from major implementations. 26 CertAlgoDSAv01 = InsecureCertAlgoDSAv01 27 // Deprecated: DSA is only supported at insecure key sizes, and was removed 28 // from major implementations. 29 InsecureCertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" 30 CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" 31 CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" 32 CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" 33 CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" 34 CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" 35 CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" 36 37 // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a 38 // Certificate.Type (or PublicKey.Type), but only in 39 // ClientConfig.HostKeyAlgorithms. 40 CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" 41 CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" 42) 43 44const ( 45 // Deprecated: use CertAlgoRSAv01. 46 CertSigAlgoRSAv01 = CertAlgoRSAv01 47 // Deprecated: use CertAlgoRSASHA256v01. 48 CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 49 // Deprecated: use CertAlgoRSASHA512v01. 50 CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 51) 52 53// Certificate types distinguish between host and user 54// certificates. The values can be set in the CertType field of 55// Certificate. 56const ( 57 UserCert = 1 58 HostCert = 2 59) 60 61// Signature represents a cryptographic signature. 62type Signature struct { 63 Format string 64 Blob []byte 65 Rest []byte `ssh:"rest"` 66} 67 68// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that 69// a certificate does not expire. 70const CertTimeInfinity = 1<<64 - 1 71 72// An Certificate represents an OpenSSH certificate as defined in 73// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the 74// PublicKey interface, so it can be unmarshaled using 75// ParsePublicKey. 76type Certificate struct { 77 Nonce []byte 78 Key PublicKey 79 Serial uint64 80 CertType uint32 81 KeyId string 82 ValidPrincipals []string 83 ValidAfter uint64 84 ValidBefore uint64 85 Permissions 86 Reserved []byte 87 SignatureKey PublicKey 88 Signature *Signature 89} 90 91// genericCertData holds the key-independent part of the certificate data. 92// Overall, certificates contain an nonce, public key fields and 93// key-independent fields. 94type genericCertData struct { 95 Serial uint64 96 CertType uint32 97 KeyId string 98 ValidPrincipals []byte 99 ValidAfter uint64 100 ValidBefore uint64 101 CriticalOptions []byte 102 Extensions []byte 103 Reserved []byte 104 SignatureKey []byte 105 Signature []byte 106} 107 108func marshalStringList(namelist []string) []byte { 109 var to []byte 110 for _, name := range namelist { 111 s := struct{ N string }{name} 112 to = append(to, Marshal(&s)...) 113 } 114 return to 115} 116 117type optionsTuple struct { 118 Key string 119 Value []byte 120} 121 122type optionsTupleValue struct { 123 Value string 124} 125 126// serialize a map of critical options or extensions 127// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, 128// we need two length prefixes for a non-empty string value 129func marshalTuples(tups map[string]string) []byte { 130 keys := make([]string, 0, len(tups)) 131 for key := range tups { 132 keys = append(keys, key) 133 } 134 sort.Strings(keys) 135 136 var ret []byte 137 for _, key := range keys { 138 s := optionsTuple{Key: key} 139 if value := tups[key]; len(value) > 0 { 140 s.Value = Marshal(&optionsTupleValue{value}) 141 } 142 ret = append(ret, Marshal(&s)...) 143 } 144 return ret 145} 146 147// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, 148// we need two length prefixes for a non-empty option value 149func parseTuples(in []byte) (map[string]string, error) { 150 tups := map[string]string{} 151 var lastKey string 152 var haveLastKey bool 153 154 for len(in) > 0 { 155 var key, val, extra []byte 156 var ok bool 157 158 if key, in, ok = parseString(in); !ok { 159 return nil, errShortRead 160 } 161 keyStr := string(key) 162 // according to [PROTOCOL.certkeys], the names must be in 163 // lexical order. 164 if haveLastKey && keyStr <= lastKey { 165 return nil, fmt.Errorf("ssh: certificate options are not in lexical order") 166 } 167 lastKey, haveLastKey = keyStr, true 168 // the next field is a data field, which if non-empty has a string embedded 169 if val, in, ok = parseString(in); !ok { 170 return nil, errShortRead 171 } 172 if len(val) > 0 { 173 val, extra, ok = parseString(val) 174 if !ok { 175 return nil, errShortRead 176 } 177 if len(extra) > 0 { 178 return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") 179 } 180 tups[keyStr] = string(val) 181 } else { 182 tups[keyStr] = "" 183 } 184 } 185 return tups, nil 186} 187 188func parseCert(in []byte, privAlgo string) (*Certificate, error) { 189 nonce, rest, ok := parseString(in) 190 if !ok { 191 return nil, errShortRead 192 } 193 194 key, rest, err := parsePubKey(rest, privAlgo) 195 if err != nil { 196 return nil, err 197 } 198 199 var g genericCertData 200 if err := Unmarshal(rest, &g); err != nil { 201 return nil, err 202 } 203 204 c := &Certificate{ 205 Nonce: nonce, 206 Key: key, 207 Serial: g.Serial, 208 CertType: g.CertType, 209 KeyId: g.KeyId, 210 ValidAfter: g.ValidAfter, 211 ValidBefore: g.ValidBefore, 212 } 213 214 for principals := g.ValidPrincipals; len(principals) > 0; { 215 principal, rest, ok := parseString(principals) 216 if !ok { 217 return nil, errShortRead 218 } 219 c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) 220 principals = rest 221 } 222 223 c.CriticalOptions, err = parseTuples(g.CriticalOptions) 224 if err != nil { 225 return nil, err 226 } 227 c.Extensions, err = parseTuples(g.Extensions) 228 if err != nil { 229 return nil, err 230 } 231 c.Reserved = g.Reserved 232 k, err := ParsePublicKey(g.SignatureKey) 233 if err != nil { 234 return nil, err 235 } 236 // The Type() function is intended to return only certificate key types, but 237 // we use certKeyAlgoNames anyway for safety, to match [Certificate.Type]. 238 if _, ok := certKeyAlgoNames[k.Type()]; ok { 239 return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", k.Type()) 240 } 241 c.SignatureKey = k 242 c.Signature, rest, ok = parseSignatureBody(g.Signature) 243 if !ok || len(rest) > 0 { 244 return nil, errors.New("ssh: signature parse error") 245 } 246 247 return c, nil 248} 249 250type openSSHCertSigner struct { 251 pub *Certificate 252 signer Signer 253} 254 255type algorithmOpenSSHCertSigner struct { 256 *openSSHCertSigner 257 algorithmSigner AlgorithmSigner 258} 259 260// NewCertSigner returns a Signer that signs with the given Certificate, whose 261// private key is held by signer. It returns an error if the public key in cert 262// doesn't match the key used by signer. 263func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { 264 if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { 265 return nil, errors.New("ssh: signer and cert have different public key") 266 } 267 268 switch s := signer.(type) { 269 case MultiAlgorithmSigner: 270 return &multiAlgorithmSigner{ 271 AlgorithmSigner: &algorithmOpenSSHCertSigner{ 272 &openSSHCertSigner{cert, signer}, s}, 273 supportedAlgorithms: s.Algorithms(), 274 }, nil 275 case AlgorithmSigner: 276 return &algorithmOpenSSHCertSigner{ 277 &openSSHCertSigner{cert, signer}, s}, nil 278 default: 279 return &openSSHCertSigner{cert, signer}, nil 280 } 281} 282 283func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { 284 return s.signer.Sign(rand, data) 285} 286 287func (s *openSSHCertSigner) PublicKey() PublicKey { 288 return s.pub 289} 290 291func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { 292 return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm) 293} 294 295const sourceAddressCriticalOption = "source-address" 296 297// CertChecker does the work of verifying a certificate. Its methods 298// can be plugged into ClientConfig.HostKeyCallback and 299// ServerConfig.PublicKeyCallback. For the CertChecker to work, 300// minimally, the IsAuthority callback should be set. 301type CertChecker struct { 302 // SupportedCriticalOptions lists the CriticalOptions that the 303 // server application layer understands. These are only used 304 // for user certificates. 305 SupportedCriticalOptions []string 306 307 // IsUserAuthority should return true if the key is recognized as an 308 // authority for user certificate. This must be set if this CertChecker 309 // will be checking user certificates. 310 IsUserAuthority func(auth PublicKey) bool 311 312 // IsHostAuthority should report whether the key is recognized as 313 // an authority for this host. This must be set if this CertChecker 314 // will be checking host certificates. 315 IsHostAuthority func(auth PublicKey, address string) bool 316 317 // Clock is used for verifying time stamps. If nil, time.Now 318 // is used. 319 Clock func() time.Time 320 321 // UserKeyFallback is called when CertChecker.Authenticate encounters a 322 // public key that is not a certificate. It must implement validation 323 // of user keys or else, if nil, all such keys are rejected. 324 UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) 325 326 // HostKeyFallback is called when CertChecker.CheckHostKey encounters a 327 // public key that is not a certificate. It must implement host key 328 // validation or else, if nil, all such keys are rejected. 329 HostKeyFallback HostKeyCallback 330 331 // IsRevoked is called for each certificate so that revocation checking 332 // can be implemented. It should return true if the given certificate 333 // is revoked and false otherwise. If nil, no certificates are 334 // considered to have been revoked. 335 IsRevoked func(cert *Certificate) bool 336} 337 338// CheckHostKey checks a host key certificate. This method can be 339// plugged into ClientConfig.HostKeyCallback. 340func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { 341 cert, ok := key.(*Certificate) 342 if !ok { 343 if c.HostKeyFallback != nil { 344 return c.HostKeyFallback(addr, remote, key) 345 } 346 return errors.New("ssh: non-certificate host key") 347 } 348 if cert.CertType != HostCert { 349 return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) 350 } 351 if !c.IsHostAuthority(cert.SignatureKey, addr) { 352 return fmt.Errorf("ssh: no authorities for hostname: %v", addr) 353 } 354 355 hostname, _, err := net.SplitHostPort(addr) 356 if err != nil { 357 return err 358 } 359 360 // Pass hostname only as principal for host certificates (consistent with OpenSSH) 361 return c.CheckCert(hostname, cert) 362} 363 364// Authenticate checks a user certificate. Authenticate can be used as 365// a value for ServerConfig.PublicKeyCallback. 366func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { 367 cert, ok := pubKey.(*Certificate) 368 if !ok { 369 if c.UserKeyFallback != nil { 370 return c.UserKeyFallback(conn, pubKey) 371 } 372 return nil, errors.New("ssh: normal key pairs not accepted") 373 } 374 375 if cert.CertType != UserCert { 376 return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) 377 } 378 if !c.IsUserAuthority(cert.SignatureKey) { 379 return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") 380 } 381 382 if err := c.CheckCert(conn.User(), cert); err != nil { 383 return nil, err 384 } 385 386 return &cert.Permissions, nil 387} 388 389// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and 390// the signature of the certificate. 391func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { 392 if c.IsRevoked != nil && c.IsRevoked(cert) { 393 return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) 394 } 395 396 for opt := range cert.CriticalOptions { 397 // sourceAddressCriticalOption will be enforced by 398 // serverAuthenticate 399 if opt == sourceAddressCriticalOption { 400 continue 401 } 402 403 found := false 404 for _, supp := range c.SupportedCriticalOptions { 405 if supp == opt { 406 found = true 407 break 408 } 409 } 410 if !found { 411 return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) 412 } 413 } 414 415 if len(cert.ValidPrincipals) > 0 { 416 // By default, certs are valid for all users/hosts. 417 found := false 418 for _, p := range cert.ValidPrincipals { 419 if p == principal { 420 found = true 421 break 422 } 423 } 424 if !found { 425 return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) 426 } 427 } 428 429 clock := c.Clock 430 if clock == nil { 431 clock = time.Now 432 } 433 434 unixNow := clock().Unix() 435 if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { 436 return fmt.Errorf("ssh: cert is not yet valid") 437 } 438 if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { 439 return fmt.Errorf("ssh: cert has expired") 440 } 441 if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { 442 return fmt.Errorf("ssh: certificate signature does not verify") 443 } 444 445 return nil 446} 447 448// SignCert signs the certificate with an authority, setting the Nonce, 449// SignatureKey, and Signature fields. If the authority implements the 450// MultiAlgorithmSigner interface the first algorithm in the list is used. This 451// is useful if you want to sign with a specific algorithm. As specified in 452// [SSH-CERTS], Section 2.1.1, authority can't be a [Certificate]. 453func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { 454 c.Nonce = make([]byte, 32) 455 if _, err := io.ReadFull(rand, c.Nonce); err != nil { 456 return err 457 } 458 // The Type() function is intended to return only certificate key types, but 459 // we use certKeyAlgoNames anyway for safety, to match [Certificate.Type]. 460 if _, ok := certKeyAlgoNames[authority.PublicKey().Type()]; ok { 461 return fmt.Errorf("ssh: certificates cannot be used as authority (public key type %q)", 462 authority.PublicKey().Type()) 463 } 464 c.SignatureKey = authority.PublicKey() 465 466 if v, ok := authority.(MultiAlgorithmSigner); ok { 467 if len(v.Algorithms()) == 0 { 468 return errors.New("the provided authority has no signature algorithm") 469 } 470 // Use the first algorithm in the list. 471 sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), v.Algorithms()[0]) 472 if err != nil { 473 return err 474 } 475 c.Signature = sig 476 return nil 477 } else if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { 478 // Default to KeyAlgoRSASHA512 for ssh-rsa signers. 479 // TODO: consider using KeyAlgoRSASHA256 as default. 480 sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) 481 if err != nil { 482 return err 483 } 484 c.Signature = sig 485 return nil 486 } 487 488 sig, err := authority.Sign(rand, c.bytesForSigning()) 489 if err != nil { 490 return err 491 } 492 c.Signature = sig 493 return nil 494} 495 496// certKeyAlgoNames is a mapping from known certificate algorithm names to the 497// corresponding public key signature algorithm. 498// 499// This map must be kept in sync with the one in agent/client.go. 500var certKeyAlgoNames = map[string]string{ 501 CertAlgoRSAv01: KeyAlgoRSA, 502 CertAlgoRSASHA256v01: KeyAlgoRSASHA256, 503 CertAlgoRSASHA512v01: KeyAlgoRSASHA512, 504 InsecureCertAlgoDSAv01: InsecureKeyAlgoDSA, 505 CertAlgoECDSA256v01: KeyAlgoECDSA256, 506 CertAlgoECDSA384v01: KeyAlgoECDSA384, 507 CertAlgoECDSA521v01: KeyAlgoECDSA521, 508 CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, 509 CertAlgoED25519v01: KeyAlgoED25519, 510 CertAlgoSKED25519v01: KeyAlgoSKED25519, 511} 512 513// underlyingAlgo returns the signature algorithm associated with algo (which is 514// an advertised or negotiated public key or host key algorithm). These are 515// usually the same, except for certificate algorithms. 516func underlyingAlgo(algo string) string { 517 if a, ok := certKeyAlgoNames[algo]; ok { 518 return a 519 } 520 return algo 521} 522 523// certificateAlgo returns the certificate algorithms that uses the provided 524// underlying signature algorithm. 525func certificateAlgo(algo string) (certAlgo string, ok bool) { 526 for certName, algoName := range certKeyAlgoNames { 527 if algoName == algo { 528 return certName, true 529 } 530 } 531 return "", false 532} 533 534func (cert *Certificate) bytesForSigning() []byte { 535 c2 := *cert 536 c2.Signature = nil 537 out := c2.Marshal() 538 // Drop trailing signature length. 539 return out[:len(out)-4] 540} 541 542// Marshal serializes c into OpenSSH's wire format. It is part of the 543// PublicKey interface. 544func (c *Certificate) Marshal() []byte { 545 generic := genericCertData{ 546 Serial: c.Serial, 547 CertType: c.CertType, 548 KeyId: c.KeyId, 549 ValidPrincipals: marshalStringList(c.ValidPrincipals), 550 ValidAfter: uint64(c.ValidAfter), 551 ValidBefore: uint64(c.ValidBefore), 552 CriticalOptions: marshalTuples(c.CriticalOptions), 553 Extensions: marshalTuples(c.Extensions), 554 Reserved: c.Reserved, 555 SignatureKey: c.SignatureKey.Marshal(), 556 } 557 if c.Signature != nil { 558 generic.Signature = Marshal(c.Signature) 559 } 560 genericBytes := Marshal(&generic) 561 keyBytes := c.Key.Marshal() 562 _, keyBytes, _ = parseString(keyBytes) 563 prefix := Marshal(&struct { 564 Name string 565 Nonce []byte 566 Key []byte `ssh:"rest"` 567 }{c.Type(), c.Nonce, keyBytes}) 568 569 result := make([]byte, 0, len(prefix)+len(genericBytes)) 570 result = append(result, prefix...) 571 result = append(result, genericBytes...) 572 return result 573} 574 575// Type returns the certificate algorithm name. It is part of the PublicKey interface. 576func (c *Certificate) Type() string { 577 certName, ok := certificateAlgo(c.Key.Type()) 578 if !ok { 579 panic("unknown certificate type for key type " + c.Key.Type()) 580 } 581 return certName 582} 583 584// Verify verifies a signature against the certificate's public 585// key. It is part of the PublicKey interface. 586func (c *Certificate) Verify(data []byte, sig *Signature) error { 587 return c.Key.Verify(data, sig) 588} 589 590func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { 591 format, in, ok := parseString(in) 592 if !ok { 593 return 594 } 595 596 out = &Signature{ 597 Format: string(format), 598 } 599 600 if out.Blob, in, ok = parseString(in); !ok { 601 return 602 } 603 604 switch out.Format { 605 case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01: 606 out.Rest = in 607 return out, nil, ok 608 } 609 610 return out, in, ok 611} 612 613func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { 614 sigBytes, rest, ok := parseString(in) 615 if !ok { 616 return 617 } 618 619 out, trailing, ok := parseSignatureBody(sigBytes) 620 if !ok || len(trailing) > 0 { 621 return nil, nil, false 622 } 623 return 624}