diff --git a/Makefile b/Makefile index 2267fad6bdcc5..41d9457b187d0 100644 --- a/Makefile +++ b/Makefile @@ -351,7 +351,10 @@ buildbox: # proto generates GRPC defs from service definitions .PHONY: grpc grpc: buildbox - docker run -v $(shell pwd):/go/src/github.com/gravitational/teleport $(BUILDBOX_TAG) make -C /go/src/github.com/gravitational/teleport buildbox-grpc + docker run \ + --rm \ + -v $(shell pwd):/go/src/github.com/gravitational/teleport $(BUILDBOX_TAG) \ + make -C /go/src/github.com/gravitational/teleport buildbox-grpc # proto generates GRPC stuff inside buildbox .PHONY: buildbox-grpc diff --git a/integration/helpers.go b/integration/helpers.go index 6af9338988368..4c3eb46c1f35d 100644 --- a/integration/helpers.go +++ b/integration/helpers.go @@ -187,6 +187,7 @@ func NewInstance(cfg InstanceConfig) *TeleInstance { cert, err := keygen.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: cfg.Priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: cfg.Pub, HostID: cfg.HostID, NodeName: cfg.NodeName, @@ -255,11 +256,25 @@ func (s *InstanceSecrets) GetRoles() []services.Role { // case we always return hard-coded userCA + hostCA (and they share keys // for simplicity) func (s *InstanceSecrets) GetCAs() []services.CertAuthority { - hostCA := services.NewCertAuthority(services.HostCA, s.SiteName, [][]byte{s.PrivKey}, [][]byte{s.PubKey}, []string{}) + hostCA := services.NewCertAuthority( + services.HostCA, + s.SiteName, + [][]byte{s.PrivKey}, + [][]byte{s.PubKey}, + []string{}, + services.CertAuthoritySpecV2_RSA_SHA2_512, + ) hostCA.SetTLSKeyPairs([]services.TLSKeyPair{{Cert: s.TLSCACert, Key: s.PrivKey}}) return []services.CertAuthority{ hostCA, - services.NewCertAuthority(services.UserCA, s.SiteName, [][]byte{s.PrivKey}, [][]byte{s.PubKey}, []string{services.RoleNameForCertAuthority(s.SiteName)}), + services.NewCertAuthority( + services.UserCA, + s.SiteName, + [][]byte{s.PrivKey}, + [][]byte{s.PubKey}, + []string{services.RoleNameForCertAuthority(s.SiteName)}, + services.CertAuthoritySpecV2_RSA_SHA2_512, + ), } } diff --git a/integration/integration_test.go b/integration/integration_test.go index 6775b79878c95..218e19f5d192e 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -3442,6 +3442,153 @@ func (s *IntSuite) TestRotateTrustedClusters(c *check.C) { } } +// TestRotateChangeSigningAlg tests the change of CA signing algorithm on +// manual rotation. +func (s *IntSuite) TestRotateChangeSigningAlg(c *check.C) { + // Start with an instance using default signing alg. + tconf := rotationConfig(true) + t := NewInstance(InstanceConfig{ClusterName: Site, HostID: HostID, NodeName: Host, Ports: s.getPorts(5), Priv: s.priv, Pub: s.pub}) + logins := []string{s.me.Username} + for _, login := range logins { + t.AddUser(login, []string{login}) + } + config, err := t.GenerateConfig(nil, tconf) + c.Assert(err, check.IsNil) + + serviceC := make(chan *service.TeleportProcess, 20) + runErrCh := make(chan error, 1) + + restart := func(svc *service.TeleportProcess, cancel func()) (*service.TeleportProcess, func()) { + if svc != nil && cancel != nil { + // shut down the service + cancel() + // close the service without waiting for the connections to drain + err := svc.Close() + c.Assert(err, check.IsNil) + err = svc.Wait() + c.Assert(err, check.IsNil) + + select { + case err := <-runErrCh: + c.Assert(err, check.IsNil) + case <-time.After(20 * time.Second): + c.Fatalf("failed to shut down the server") + } + } + + ctx, cancel := context.WithCancel(context.Background()) + go func() { + runErrCh <- service.Run(ctx, *config, func(cfg *service.Config) (service.Process, error) { + svc, err := service.NewTeleport(cfg) + if err == nil { + serviceC <- svc + } + return svc, err + }) + }() + + svc, err = waitForProcessStart(serviceC) + c.Assert(err, check.IsNil) + return svc, cancel + } + + assertSigningAlg := func(svc *service.TeleportProcess, alg string) { + hostCA, err := svc.GetAuthServer().GetCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: Site}, false) + c.Assert(err, check.IsNil) + c.Assert(hostCA.GetSigningAlg(), check.Equals, alg) + + userCA, err := svc.GetAuthServer().GetCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: Site}, false) + c.Assert(err, check.IsNil) + c.Assert(userCA.GetSigningAlg(), check.Equals, alg) + } + + rotate := func(svc *service.TeleportProcess, mode string) *service.TeleportProcess { + c.Logf("rotation phase: %q", services.RotationPhaseInit) + err = svc.GetAuthServer().RotateCertAuthority(auth.RotateRequest{ + TargetPhase: services.RotationPhaseInit, + Mode: mode, + }) + c.Assert(err, check.IsNil) + + // wait until service phase update to be broadcasted (init phase does not trigger reload) + err = waitForProcessEvent(svc, service.TeleportPhaseChangeEvent, 10*time.Second) + c.Assert(err, check.IsNil) + + c.Logf("rotation phase: %q", services.RotationPhaseUpdateClients) + err = svc.GetAuthServer().RotateCertAuthority(auth.RotateRequest{ + TargetPhase: services.RotationPhaseUpdateClients, + Mode: mode, + }) + c.Assert(err, check.IsNil) + + // wait until service reload + svc, err = waitForReload(serviceC, svc) + c.Assert(err, check.IsNil) + + c.Logf("rotation phase: %q", services.RotationPhaseUpdateServers) + err = svc.GetAuthServer().RotateCertAuthority(auth.RotateRequest{ + TargetPhase: services.RotationPhaseUpdateServers, + Mode: mode, + }) + c.Assert(err, check.IsNil) + + // wait until service reloaded + svc, err = waitForReload(serviceC, svc) + c.Assert(err, check.IsNil) + + c.Logf("rotation phase: %q", services.RotationPhaseStandby) + err = svc.GetAuthServer().RotateCertAuthority(auth.RotateRequest{ + TargetPhase: services.RotationPhaseStandby, + Mode: mode, + }) + c.Assert(err, check.IsNil) + + // wait until service reloaded + svc, err = waitForReload(serviceC, svc) + c.Assert(err, check.IsNil) + + return svc + } + + // Start the instance. + svc, cancel := restart(nil, nil) + + c.Log("default signature algorithm due to empty config value") + // Verify the default signing algorithm with config value empty. + assertSigningAlg(svc, defaults.CASignatureAlgorithm) + + c.Log("change signature algorithm with custom config value and manual rotation") + // Change the signing algorithm in config file. + signingAlg := ssh.SigAlgoRSA + config.CASignatureAlgorithm = &signingAlg + svc, cancel = restart(svc, cancel) + // Do a manual rotation - this should change the signing algorithm. + svc = rotate(svc, services.RotationModeManual) + assertSigningAlg(svc, ssh.SigAlgoRSA) + + c.Log("preserve signature algorithm with empty config value and manual rotation") + // Unset the config value. + config.CASignatureAlgorithm = nil + svc, cancel = restart(svc, cancel) + + // Do a manual rotation - this should leave the signing algorithm + // unaffected because config value is not set. + svc = rotate(svc, services.RotationModeManual) + assertSigningAlg(svc, ssh.SigAlgoRSA) + + // shut down the service + cancel() + // close the service without waiting for the connections to drain + svc.Close() + + select { + case err := <-runErrCh: + c.Assert(err, check.IsNil) + case <-time.After(20 * time.Second): + c.Fatalf("failed to shut down the server") + } +} + // rotationConfig sets up default config used for CA rotation tests func rotationConfig(disableWebService bool) *service.Config { tconf := service.MakeDefaultConfig() diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 43e7b05f38f93..e29b0b1afb22c 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -106,6 +106,7 @@ func NewAuthServer(cfg *InitConfig, opts ...AuthServerOption) (*AuthServer, erro oidcClients: make(map[string]*oidcClient), samlProviders: make(map[string]*samlProvider), githubClients: make(map[string]*githubClient), + caSigningAlg: cfg.CASigningAlg, cancelFunc: cancelFunc, closeCtx: closeCtx, AuthServices: AuthServices{ @@ -207,6 +208,9 @@ type AuthServer struct { // cipherSuites is a list of ciphersuites that the auth server supports. cipherSuites []uint16 + // caSigningAlg is an SSH signing algorithm to use when generating new CAs. + caSigningAlg *string + // cache is a fast cache that allows auth server // to use cache for most frequent operations, // if not set, cache uses itself @@ -370,6 +374,7 @@ func (s *AuthServer) GenerateHostCert(hostPublicKey []byte, hostID, nodeName str // create and sign! return s.Authority.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: caPrivateKey, + CASigningAlg: ca.GetSigningAlg(), PublicHostKey: hostPublicKey, HostID: hostID, NodeName: nodeName, @@ -507,6 +512,7 @@ func (s *AuthServer) generateUserCert(req certRequest) (*certs, error) { } sshCert, err := s.Authority.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: privateKey, + CASigningAlg: ca.GetSigningAlg(), PublicUserKey: req.publicKey, Username: req.user.GetName(), AllowedLogins: allowedLogins, @@ -1013,6 +1019,7 @@ func (s *AuthServer) GenerateServerKeys(req GenerateServerKeysRequest) (*PackedK // generate hostSSH certificate hostSSHCert, err := s.Authority.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: caPrivateKey, + CASigningAlg: ca.GetSigningAlg(), PublicHostKey: pubSSHKey, HostID: req.HostID, NodeName: req.NodeName, diff --git a/lib/auth/init.go b/lib/auth/init.go index 61c5aba405fcd..48fdb61517f25 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -138,6 +138,11 @@ type InitConfig struct { // CipherSuites is a list of ciphersuites that the auth server supports. CipherSuites []uint16 + + // CASigningAlg is a signing algorithm used for SSH (certificate and + // handshake) signatures for both host and user CAs. This option only + // affects newly-created CAs. + CASigningAlg *string } // Init instantiates and configures an instance of AuthServer @@ -315,6 +320,10 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) { if err != nil { return nil, trace.Wrap(err) } + sigAlg := defaults.CASignatureAlgorithm + if cfg.CASigningAlg != nil && *cfg.CASigningAlg != "" { + sigAlg = *cfg.CASigningAlg + } userCA := &services.CertAuthorityV2{ Kind: services.KindCertAuthority, @@ -327,6 +336,7 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) { ClusterName: cfg.ClusterName.GetClusterName(), Type: services.UserCA, SigningKeys: [][]byte{priv}, + SigningAlg: services.ParseSigningAlg(sigAlg), CheckingKeys: [][]byte{pub}, TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}}, }, @@ -370,6 +380,11 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) { if err != nil { return nil, trace.Wrap(err) } + sigAlg := defaults.CASignatureAlgorithm + if cfg.CASigningAlg != nil && *cfg.CASigningAlg != "" { + sigAlg = *cfg.CASigningAlg + } + hostCA = &services.CertAuthorityV2{ Kind: services.KindCertAuthority, Version: services.V2, @@ -381,6 +396,7 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) { ClusterName: cfg.ClusterName.GetClusterName(), Type: services.HostCA, SigningKeys: [][]byte{priv}, + SigningAlg: services.ParseSigningAlg(sigAlg), CheckingKeys: [][]byte{pub}, TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}}, }, diff --git a/lib/auth/init_test.go b/lib/auth/init_test.go index c9f8e5e451937..a7ea17c73bde5 100644 --- a/lib/auth/init_test.go +++ b/lib/auth/init_test.go @@ -18,7 +18,6 @@ package auth import ( "context" - "fmt" "io/ioutil" "os" "testing" @@ -30,6 +29,7 @@ import ( "github.com/gravitational/teleport/lib/auth/testauthority" "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/backend/lite" + "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" @@ -42,8 +42,6 @@ type AuthInitSuite struct { } var _ = Suite(&AuthInitSuite{}) -var _ = testing.Verbose -var _ = fmt.Printf func (s *AuthInitSuite) SetUpSuite(c *C) { utils.InitLoggerForTests(testing.Verbose()) @@ -72,6 +70,7 @@ func (s *AuthInitSuite) TestReadIdentity(c *C) { cert, err := t.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "id1", NodeName: "node-name", @@ -93,6 +92,7 @@ func (s *AuthInitSuite) TestReadIdentity(c *C) { expiryDate := time.Now().Add(ttl) bytes, err := t.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "id1", NodeName: "node-name", @@ -120,6 +120,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) { // missing authority domain cert, err := t.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "id2", NodeName: "", @@ -135,6 +136,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) { // missing host uuid cert, err = t.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "example.com", NodeName: "", @@ -150,6 +152,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) { // unrecognized role cert, err = t.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "example.com", NodeName: "", @@ -201,6 +204,7 @@ func (s *AuthInitSuite) TestAuthPreference(c *C) { } as, err := Init(ac) c.Assert(err, IsNil) + defer as.Close() cap, err := as.GetAuthPreference() c.Assert(err, IsNil) @@ -238,6 +242,7 @@ func (s *AuthInitSuite) TestClusterID(c *C) { AuthPreference: authPreference, }) c.Assert(err, IsNil) + defer authServer.Close() cc, err := authServer.GetClusterConfig() c.Assert(err, IsNil) @@ -257,6 +262,7 @@ func (s *AuthInitSuite) TestClusterID(c *C) { AuthPreference: authPreference, }) c.Assert(err, IsNil) + defer authServer.Close() cc, err = authServer.GetClusterConfig() c.Assert(err, IsNil) @@ -278,7 +284,7 @@ func (s *AuthInitSuite) TestClusterName(c *C) { }) c.Assert(err, IsNil) - _, err = Init(InitConfig{ + authServer, err := Init(InitConfig{ DataDir: c.MkDir(), HostUUID: "00000000-0000-0000-0000-000000000000", NodeName: "foo", @@ -290,6 +296,7 @@ func (s *AuthInitSuite) TestClusterName(c *C) { AuthPreference: authPreference, }) c.Assert(err, IsNil) + defer authServer.Close() // Start the auth server with a different cluster name. The auth server // should start, but with the original name. @@ -298,7 +305,7 @@ func (s *AuthInitSuite) TestClusterName(c *C) { }) c.Assert(err, IsNil) - authServer, err := Init(InitConfig{ + authServer, err = Init(InitConfig{ DataDir: c.MkDir(), HostUUID: "00000000-0000-0000-0000-000000000000", NodeName: "foo", @@ -310,13 +317,76 @@ func (s *AuthInitSuite) TestClusterName(c *C) { AuthPreference: authPreference, }) c.Assert(err, IsNil) + defer authServer.Close() cn, err := authServer.GetClusterName() c.Assert(err, IsNil) c.Assert(cn.GetClusterName(), Equals, "me.localhost") } -// DELETE IN: 4.3.0 -func (s *AuthInitSuite) TestRoleOptions(c *C) { - // TODO: Implement. +func (s *AuthInitSuite) TestCASigningAlg(c *C) { + bk, err := lite.New(context.TODO(), backend.Params{"path": c.MkDir()}) + c.Assert(err, IsNil) + + clusterName, err := services.NewClusterName(services.ClusterNameSpecV2{ + ClusterName: "me.localhost", + }) + c.Assert(err, IsNil) + + authPreference, err := services.NewAuthPreference(services.AuthPreferenceSpecV2{ + Type: "local", + }) + c.Assert(err, IsNil) + + conf := InitConfig{ + DataDir: c.MkDir(), + HostUUID: "00000000-0000-0000-0000-000000000000", + NodeName: "foo", + Backend: bk, + Authority: testauthority.New(), + ClusterConfig: services.DefaultClusterConfig(), + ClusterName: clusterName, + StaticTokens: services.DefaultStaticTokens(), + AuthPreference: authPreference, + } + + verifyCAs := func(auth *AuthServer, alg string) { + hostCAs, err := auth.GetCertAuthorities(services.HostCA, false) + c.Assert(err, IsNil) + for _, ca := range hostCAs { + c.Assert(ca.GetSigningAlg(), Equals, alg) + } + userCAs, err := auth.GetCertAuthorities(services.UserCA, false) + c.Assert(err, IsNil) + for _, ca := range userCAs { + c.Assert(ca.GetSigningAlg(), Equals, alg) + } + } + + // Start a new server without specifying a signing alg. + auth, err := Init(conf) + c.Assert(err, IsNil) + verifyCAs(auth, ssh.SigAlgoRSASHA2512) + + c.Assert(auth.Close(), IsNil) + + // Reset the auth server state. + conf.Backend, err = lite.New(context.TODO(), backend.Params{"path": c.MkDir()}) + c.Assert(err, IsNil) + conf.DataDir = c.MkDir() + + // Start a new server with non-default signing alg. + signingAlg := ssh.SigAlgoRSA + conf.CASigningAlg = &signingAlg + auth, err = Init(conf) + c.Assert(err, IsNil) + defer auth.Close() + verifyCAs(auth, ssh.SigAlgoRSA) + + // Start again, using a different alg. This should not change the existing + // CA. + signingAlg = ssh.SigAlgoRSASHA2256 + auth, err = Init(conf) + c.Assert(err, IsNil) + verifyCAs(auth, ssh.SigAlgoRSA) } diff --git a/lib/auth/native/native.go b/lib/auth/native/native.go index 4d16a247be6ef..992dee1186248 100644 --- a/lib/auth/native/native.go +++ b/lib/auth/native/native.go @@ -28,8 +28,8 @@ import ( "golang.org/x/crypto/ssh" "github.com/gravitational/teleport" - "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/lib/wrappers" @@ -193,6 +193,7 @@ func (k *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) { if err != nil { return nil, trace.Wrap(err) } + signer = sshutils.AlgSigner(signer, c.CASigningAlg) // Build a valid list of principals from the HostID and NodeName and then // add in any additional principals passed in. @@ -234,11 +235,8 @@ func (k *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) { // GenerateUserCert generates a host certificate with the passed in parameters. // The private key of the CA to sign the certificate must be provided. func (k *Keygen) GenerateUserCert(c services.UserCertParams) ([]byte, error) { - if c.TTL < defaults.MinCertDuration { - return nil, trace.BadParameter("wrong certificate TTL") - } - if len(c.AllowedLogins) == 0 { - return nil, trace.BadParameter("allowedLogins: need allowed OS logins") + if err := c.Check(); err != nil { + return nil, trace.Wrap(err, "error validating UserCertParams") } pubKey, _, _, _, err := ssh.ParseAuthorizedKey(c.PublicUserKey) if err != nil { @@ -307,6 +305,7 @@ func (k *Keygen) GenerateUserCert(c services.UserCertParams) ([]byte, error) { if err != nil { return nil, trace.Wrap(err) } + signer = sshutils.AlgSigner(signer, c.CASigningAlg) if err := cert.SignCert(rand.Reader, signer); err != nil { return nil, trace.Wrap(err) } diff --git a/lib/auth/native/native_test.go b/lib/auth/native/native_test.go index 58194d3ee99d7..3e92fa6b1f4ab 100644 --- a/lib/auth/native/native_test.go +++ b/lib/auth/native/native_test.go @@ -26,6 +26,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/lib/auth/test" + "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" @@ -47,7 +48,11 @@ func (s *NativeSuite) SetUpSuite(c *check.C) { fakeClock := clockwork.NewFakeClockAt(time.Date(2016, 9, 8, 7, 6, 5, 0, time.UTC)) - a, err := New(context.TODO(), PrecomputeKeys(1), SetClock(fakeClock)) + a, err := New( + context.TODO(), + PrecomputeKeys(1), + SetClock(fakeClock), + ) c.Assert(err, check.IsNil) s.suite = &test.AuthSuite{ @@ -167,6 +172,7 @@ func (s *NativeSuite) TestBuildPrincipals(c *check.C) { hostCertificateBytes, err := s.suite.A.GenerateHostCert( services.HostCertParams{ PrivateCASigningKey: caPrivateKey, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: hostPublicKey, HostID: tt.inHostID, NodeName: tt.inNodeName, @@ -214,6 +220,7 @@ func (s *NativeSuite) TestUserCertCompatibility(c *check.C) { userCertificateBytes, err := s.suite.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"centos", "root"}, @@ -230,7 +237,8 @@ func (s *NativeSuite) TestUserCertCompatibility(c *check.C) { userCertificate, ok := publicKey.(*ssh.Certificate) c.Assert(ok, check.Equals, true, comment) - + // Check that the signature algorithm is correct. + c.Assert(userCertificate.Signature.Format, check.Equals, defaults.CASignatureAlgorithm) // check if we added the roles extension _, ok = userCertificate.Extensions[teleport.CertExtensionTeleportRoles] c.Assert(ok, check.Equals, tt.outHasRoles, comment) diff --git a/lib/auth/rotate.go b/lib/auth/rotate.go index 824de9febbe32..fd5a788ad80f2 100644 --- a/lib/auth/rotate.go +++ b/lib/auth/rotate.go @@ -121,6 +121,8 @@ type rotationReq struct { // privateKey is passed by tests to supply private key for cert authorities // instead of generating them on each iteration privateKey []byte + // caSigningAlg is an SSH signing algorithm to use with the new CA. + caSigningAlg *string } // RotateCertAuthority starts or restarts certificate authority rotation process. @@ -214,13 +216,14 @@ func (a *AuthServer) RotateCertAuthority(req RotateRequest) error { return trace.Wrap(err) } rotated, err := processRotationRequest(rotationReq{ - ca: existing, - clock: a.clock, - targetPhase: req.TargetPhase, - schedule: *req.Schedule, - gracePeriod: *req.GracePeriod, - mode: req.Mode, - privateKey: a.privateKey, + ca: existing, + clock: a.clock, + targetPhase: req.TargetPhase, + schedule: *req.Schedule, + gracePeriod: *req.GracePeriod, + mode: req.Mode, + privateKey: a.privateKey, + caSigningAlg: a.caSigningAlg, }) if err != nil { return trace.Wrap(err) @@ -546,6 +549,12 @@ func startNewRotation(req rotationReq, ca services.CertAuthority) error { } ca.SetTLSKeyPairs(keyPairs) ca.SetRotation(rotation) + // caSigningAlg is only set when signing algorithm was explicitly set in + // the config file. When config file doesn't set a value, preserve the + // signing algorithm of the existing CA. + if req.caSigningAlg != nil { + ca.SetSigningAlg(*req.caSigningAlg) + } return nil } diff --git a/lib/auth/test/suite.go b/lib/auth/test/suite.go index 8b27960df8bfc..b54e141f8b6c1 100644 --- a/lib/auth/test/suite.go +++ b/lib/auth/test/suite.go @@ -21,6 +21,7 @@ import ( "time" "github.com/gravitational/teleport" + "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/sshca" @@ -64,6 +65,7 @@ func (s *AuthSuite) GenerateHostCert(c *check.C) { cert, err := s.A.GenerateHostCert( services.HostCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: pub, HostID: "00000000-0000-0000-0000-000000000000", NodeName: "auth.example.com", @@ -94,6 +96,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) { cert, err := s.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"centos", "root"}, @@ -123,6 +126,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) { _, err = s.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"root"}, @@ -135,6 +139,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) { _, err = s.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"root"}, @@ -147,6 +152,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) { _, err = s.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"root"}, @@ -160,6 +166,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) { inRoles := []string{"role-1", "role-2"} cert, err = s.A.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: priv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: "user", AllowedLogins: []string{"root"}, diff --git a/lib/auth/testauthority/testauthority.go b/lib/auth/testauthority/testauthority.go index 4326434c2d388..0ff5e986c6789 100644 --- a/lib/auth/testauthority/testauthority.go +++ b/lib/auth/testauthority/testauthority.go @@ -24,6 +24,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/lib/auth/native" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/lib/wrappers" @@ -74,6 +75,7 @@ func (n *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) { if err != nil { return nil, err } + signer = sshutils.AlgSigner(signer, c.CASigningAlg) if err := cert.SignCert(rand.Reader, signer); err != nil { return nil, err } @@ -101,6 +103,7 @@ func (n *Keygen) GenerateUserCert(c services.UserCertParams) ([]byte, error) { if err != nil { return nil, err } + signer = sshutils.AlgSigner(signer, c.CASigningAlg) cert.Permissions.Extensions = map[string]string{ teleport.CertExtensionPermitPTY: "", teleport.CertExtensionPermitPortForwarding: "", diff --git a/lib/client/api_test.go b/lib/client/api_test.go index 52051bc98cfff..644e56010041c 100644 --- a/lib/client/api_test.go +++ b/lib/client/api_test.go @@ -321,7 +321,7 @@ func (t *testCertGetter) GetTrustedCA(ctx context.Context, clusterName string) ( for _, clusterName := range t.clusterNames { // Only the cluster name is checked in tests, pass in nil for the keys. - cas = append(cas, services.NewCertAuthority(services.HostCA, clusterName, nil, nil, nil)) + cas = append(cas, services.NewCertAuthority(services.HostCA, clusterName, nil, nil, nil, services.CertAuthoritySpecV2_UNKNOWN)) } return cas, nil diff --git a/lib/client/keyagent_test.go b/lib/client/keyagent_test.go index c6e1c690683fa..47ed07fdc068c 100644 --- a/lib/client/keyagent_test.go +++ b/lib/client/keyagent_test.go @@ -31,6 +31,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/lib/auth/testauthority" + "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/fixtures" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/sshutils" @@ -239,6 +240,7 @@ func (s *KeyAgentTestSuite) TestHostCertVerification(c *check.C) { c.Assert(err, check.IsNil) hostCertBytes, err := keygen.GenerateHostCert(services.HostCertParams{ PrivateCASigningKey: caPriv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicHostKey: hostPub, HostID: "5ff40d80-9007-4f28-8f49-7d4fda2f574d", NodeName: "server01", @@ -429,6 +431,7 @@ func (s *KeyAgentTestSuite) makeKey(username string, allowedLogins []string, ttl certificate, err := keygen.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: pemBytes, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: publicKey, Username: username, AllowedLogins: allowedLogins, diff --git a/lib/client/keystore_test.go b/lib/client/keystore_test.go index ee77ddb2f6541..bac99b82335d0 100644 --- a/lib/client/keystore_test.go +++ b/lib/client/keystore_test.go @@ -242,6 +242,7 @@ func (s *KeyStoreTestSuite) makeSignedKey(c *check.C, makeExpired bool) *Key { cert, err = s.keygen.GenerateUserCert(services.UserCertParams{ PrivateCASigningKey: CAPriv, + CASigningAlg: defaults.CASignatureAlgorithm, PublicUserKey: pub, Username: username, AllowedLogins: allowedLogins, diff --git a/lib/config/configuration.go b/lib/config/configuration.go index ca8565f4e2212..89e85268bb08e 100644 --- a/lib/config/configuration.go +++ b/lib/config/configuration.go @@ -287,6 +287,9 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error { if fc.MACAlgorithms != nil { cfg.MACAlgorithms = fc.MACAlgorithms } + if fc.CASignatureAlgorithm != nil { + cfg.CASignatureAlgorithm = fc.CASignatureAlgorithm + } // Read in how nodes will validate the CA. if fc.CAPin != "" { @@ -662,7 +665,9 @@ func parseAuthorizedKeys(bytes []byte, allowedLogins []string) (services.CertAut clusterName, nil, [][]byte{ssh.MarshalAuthorizedKey(pubkey)}, - nil) + nil, + services.CertAuthoritySpecV2_UNKNOWN, + ) // transform old allowed logins into roles role := services.RoleForCertAuthority(ca) diff --git a/lib/config/configuration_test.go b/lib/config/configuration_test.go index be7b725ec92d3..9ebfa07b6b921 100644 --- a/lib/config/configuration_test.go +++ b/lib/config/configuration_test.go @@ -329,19 +329,19 @@ func (s *ConfigTestSuite) TestTrustedClusters(c *check.C) { // TestFileConfigCheck makes sure we don't start with invalid settings. func (s *ConfigTestSuite) TestFileConfigCheck(c *check.C) { tests := []struct { - inConfigString string - outError bool + desc string + inConfig string + outError bool }{ - // 0 - all defaults, valid { - ` + desc: "all defaults, valid", + inConfig: ` teleport: `, - false, }, - // 1 - invalid cipher, not valid { - ` + desc: "invalid cipher, not valid", + inConfig: ` teleport: ciphers: - aes256-ctr @@ -351,15 +351,29 @@ teleport: mac_algos: - hmac-sha2-256-etm@openssh.com `, - true, + outError: true, + }, + { + desc: "change CA signature alg, valid", + inConfig: ` +teleport: + ca_signature_algo: ssh-rsa +`, + }, + { + desc: "invalid CA signature alg, not valid", + inConfig: ` +teleport: + ca_signature_algo: foobar +`, + outError: true, }, } - // run tests - for i, tt := range tests { - comment := check.Commentf("Test %v", i) + for _, tt := range tests { + comment := check.Commentf(tt.desc) - _, err := ReadConfig(bytes.NewBufferString(tt.inConfigString)) + _, err := ReadConfig(bytes.NewBufferString(tt.inConfig)) if tt.outError { c.Assert(err, check.NotNil, comment) } else { diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index 59b3a97c08a7e..b3e628dd6c981 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -138,6 +138,7 @@ var ( "ciphers": false, "kex_algos": false, "mac_algos": false, + "ca_signature_algo": false, "connector_name": false, "session_recording": false, "read_capacity_units": false, @@ -164,6 +165,12 @@ var ( } ) +var validCASigAlgos = []string{ + ssh.SigAlgoRSA, + ssh.SigAlgoRSASHA2256, + ssh.SigAlgoRSASHA2512, +} + // FileConfig structre represents the teleport configuration stored in a config file // in YAML format (usually /etc/teleport.yaml) // @@ -329,19 +336,22 @@ func (conf *FileConfig) Check() error { for _, c := range conf.Ciphers { if !utils.SliceContainsStr(sc.Ciphers, c) { - return trace.BadParameter("cipher %q not supported", c) + return trace.BadParameter("cipher algorithm %q is not supported; supported algorithms: %q", c, sc.Ciphers) } } for _, k := range conf.KEXAlgorithms { if !utils.SliceContainsStr(sc.KeyExchanges, k) { - return trace.BadParameter("KEX %q not supported", k) + return trace.BadParameter("KEX algorithm %q is not supported; supported algorithms: %q", k, sc.KeyExchanges) } } for _, m := range conf.MACAlgorithms { if !utils.SliceContainsStr(sc.MACs, m) { - return trace.BadParameter("MAC %q not supported", m) + return trace.BadParameter("MAC algorithm %q is not supported; supported algorithms: %q", m, sc.MACs) } } + if conf.CASignatureAlgorithm != nil && !utils.SliceContainsStr(validCASigAlgos, *conf.CASignatureAlgorithm) { + return trace.BadParameter("CA signature algorithm %q is not supported; supported algorithms: %q", *conf.CASignatureAlgorithm, validCASigAlgos) + } return nil } @@ -399,6 +409,11 @@ type Global struct { // the server supports. If omitted the defaults will be used. MACAlgorithms []string `yaml:"mac_algos,omitempty"` + // CASignatureAlgorithm is an SSH Certificate Authority (CA) signature + // algorithm that the server uses for signing user and host certificates. + // If omitted, the default will be used. + CASignatureAlgorithm *string `yaml:"ca_signature_algo,omitempty"` + // CAPin is the SKPI hash of the CA used to verify the Auth Server. CAPin string `yaml:"ca_pin"` } diff --git a/lib/defaults/defaults.go b/lib/defaults/defaults.go index 291bc41195b25..dc361691fc1dd 100644 --- a/lib/defaults/defaults.go +++ b/lib/defaults/defaults.go @@ -26,6 +26,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/utils" + "golang.org/x/crypto/ssh" ) // Default port numbers used by all teleport tools @@ -345,6 +346,10 @@ var ( // NodeQueueSize is node service queue size NodeQueueSize = 128 + + // CASignatureAlgorithm is the default signing algorithm to use when + // creating new SSH CAs. + CASignatureAlgorithm = ssh.SigAlgoRSASHA2512 ) // Default connection limits, they can be applied separately on any of the Teleport diff --git a/lib/reversetunnel/peer.go b/lib/reversetunnel/peer.go index 48045797a1706..0f8b7100f8568 100644 --- a/lib/reversetunnel/peer.go +++ b/lib/reversetunnel/peer.go @@ -19,6 +19,7 @@ package reversetunnel import ( "fmt" "net" + "sync" "time" "github.com/gravitational/teleport" @@ -50,7 +51,7 @@ func (p *clusterPeers) GetTunnelsCount() int { func (p *clusterPeers) pickPeer() (*clusterPeer, error) { var currentPeer *clusterPeer for _, peer := range p.peers { - if currentPeer == nil || peer.connInfo.GetLastHeartbeat().After(currentPeer.connInfo.GetLastHeartbeat()) { + if currentPeer == nil || peer.getConnInfo().GetLastHeartbeat().After(currentPeer.getConnInfo().GetLastHeartbeat()) { currentPeer = peer } } @@ -65,12 +66,12 @@ func (p *clusterPeers) updatePeer(conn services.TunnelConnection) bool { if !ok { return false } - peer.connInfo = conn + peer.setConnInfo(conn) return true } func (p *clusterPeers) addPeer(peer *clusterPeer) { - p.peers[peer.connInfo.GetName()] = peer + p.peers[peer.getConnInfo().GetName()] = peer } func (p *clusterPeers) removePeer(connInfo services.TunnelConnection) { @@ -156,7 +157,9 @@ func newClusterPeer(srv *server, connInfo services.TunnelConnection, offlineThre // clusterPeer is a remote cluster that has established // a tunnel to the peers type clusterPeer struct { - log *log.Entry + log *log.Entry + + mu sync.Mutex connInfo services.TunnelConnection srv *server @@ -168,6 +171,18 @@ type clusterPeer struct { offlineThreshold time.Duration } +func (s *clusterPeer) getConnInfo() services.TunnelConnection { + s.mu.Lock() + defer s.mu.Unlock() + return s.connInfo +} + +func (s *clusterPeer) setConnInfo(ci services.TunnelConnection) { + s.mu.Lock() + defer s.mu.Unlock() + s.connInfo = ci +} + func (s *clusterPeer) CachingAccessPoint() (auth.AccessPoint, error) { return nil, trace.ConnectionProblem(nil, "unable to fetch access point, this proxy %v has not been discovered yet, try again later", s) } @@ -177,18 +192,26 @@ func (s *clusterPeer) GetClient() (auth.ClientI, error) { } func (s *clusterPeer) String() string { + s.mu.Lock() + defer s.mu.Unlock() return fmt.Sprintf("clusterPeer(%v)", s.connInfo) } func (s *clusterPeer) GetStatus() string { + s.mu.Lock() + defer s.mu.Unlock() return services.TunnelConnectionStatus(s.clock, s.connInfo, s.offlineThreshold) } func (s *clusterPeer) GetName() string { + s.mu.Lock() + defer s.mu.Unlock() return s.connInfo.GetClusterName() } func (s *clusterPeer) GetLastConnected() time.Time { + s.mu.Lock() + defer s.mu.Unlock() return s.connInfo.GetLastHeartbeat() } diff --git a/lib/service/cfg.go b/lib/service/cfg.go index 837117ccee481..9c6de592108b8 100644 --- a/lib/service/cfg.go +++ b/lib/service/cfg.go @@ -141,6 +141,11 @@ type Config struct { // the server supports. If omitted the defaults will be used. MACAlgorithms []string + // CASignatureAlgorithm is an SSH Certificate Authority (CA) signature + // algorithm that the server uses for signing user and host certificates. + // If omitted, the default will be used. + CASignatureAlgorithm *string + // DiagnosticAddr is an address for diagnostic and healthz endpoint service DiagnosticAddr utils.NetAddr diff --git a/lib/service/cfg_test.go b/lib/service/cfg_test.go index b52c904289537..ecf5fb8a1ab16 100644 --- a/lib/service/cfg_test.go +++ b/lib/service/cfg_test.go @@ -56,6 +56,29 @@ func (s *ConfigSuite) TestDefaultConfig(c *check.C) { c.Error("default hostname wasn't properly set") } + // crypto settings + c.Assert(config.CipherSuites, check.DeepEquals, utils.DefaultCipherSuites()) + // Unfortunately the below algos don't have exported constants in + // golang.org/x/crypto/ssh for us to use. + c.Assert(config.Ciphers, check.DeepEquals, []string{ + "aes128-gcm@openssh.com", + "chacha20-poly1305@openssh.com", + "aes128-ctr", + "aes192-ctr", + "aes256-ctr", + }) + c.Assert(config.KEXAlgorithms, check.DeepEquals, []string{ + "curve25519-sha256@libssh.org", + "ecdh-sha2-nistp256", + "ecdh-sha2-nistp384", + "ecdh-sha2-nistp521", + }) + c.Assert(config.MACAlgorithms, check.DeepEquals, []string{ + "hmac-sha2-256-etm@openssh.com", + "hmac-sha2-256", + }) + c.Assert(config.CASignatureAlgorithm, check.IsNil) + // auth section auth := config.Auth c.Assert(auth.SSHAddr, check.DeepEquals, localAuthAddr) diff --git a/lib/service/service.go b/lib/service/service.go index c87d0e6b6513a..eeb8d61cdc869 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -1003,6 +1003,7 @@ func (process *TeleportProcess) initAuthService() error { OIDCConnectors: cfg.OIDCConnectors, AuditLog: process.auditLog, CipherSuites: cfg.CipherSuites, + CASigningAlg: cfg.CASignatureAlgorithm, }) if err != nil { return trace.Wrap(err) diff --git a/lib/services/authority.go b/lib/services/authority.go index 7a13596060437..176a4e3f91d44 100644 --- a/lib/services/authority.go +++ b/lib/services/authority.go @@ -24,6 +24,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/lib/wrappers" @@ -38,6 +39,8 @@ import ( type HostCertParams struct { // PrivateCASigningKey is the private key of the CA that will sign the public key of the host PrivateCASigningKey []byte + // CASigningAlg is the signature algorithm used by the CA private key. + CASigningAlg string // PublicHostKey is the public key of the host PublicHostKey []byte // HostID is used by Teleport to uniquely identify a node within a cluster @@ -55,7 +58,10 @@ type HostCertParams struct { } // Check checks parameters for errors -func (c *HostCertParams) Check() error { +func (c HostCertParams) Check() error { + if len(c.PrivateCASigningKey) == 0 || c.CASigningAlg == "" { + return trace.BadParameter("PrivateCASigningKey and CASigningAlg are required") + } if c.HostID == "" && len(c.Principals) == 0 { return trace.BadParameter("HostID [%q] or Principals [%q] are required", c.HostID, c.Principals) @@ -89,6 +95,8 @@ type ChangePasswordReq struct { type UserCertParams struct { // PrivateCASigningKey is the private key of the CA that will sign the public key of the user PrivateCASigningKey []byte + // CASigningAlg is the signature algorithm used by the CA private key. + CASigningAlg string // PublicUserKey is the public key of the user PublicUserKey []byte // TTL defines how long a certificate is valid for @@ -118,6 +126,19 @@ type UserCertParams struct { ActiveRequests RequestIDs } +func (c UserCertParams) Check() error { + if len(c.PrivateCASigningKey) == 0 || c.CASigningAlg == "" { + return trace.BadParameter("PrivateCASigningKey and CASigningAlg are required") + } + if c.TTL < defaults.MinCertDuration { + return trace.BadParameter("TTL can't be less than %v", defaults.MinCertDuration) + } + if len(c.AllowedLogins) == 0 { + return trace.BadParameter("AllowedLogins are required") + } + return nil +} + // CertRoles defines certificate roles type CertRoles struct { // Version is current version of the roles @@ -174,7 +195,7 @@ type CertAuthority interface { GetClusterName() string // GetCheckingKeys returns public keys to check signature GetCheckingKeys() [][]byte - // GetSigning keys returns signing keys + // GetSigningKeys returns signing keys GetSigningKeys() [][]byte // CombinedMapping is used to specify combined mapping from legacy property Roles // and new property RoleMap @@ -220,6 +241,10 @@ type CertAuthority interface { GetRotation() Rotation // SetRotation sets rotation state. SetRotation(Rotation) + // GetSigningAlg returns the signing algorithm used by signing keys. + GetSigningAlg() string + // SetSigningAlg sets the signing algorithm used by signing keys. + SetSigningAlg(string) // Clone returns a copy of the cert authority object. Clone() CertAuthority } @@ -274,7 +299,14 @@ func TLSCerts(ca CertAuthority) [][]byte { } // NewCertAuthority returns new cert authority -func NewCertAuthority(caType CertAuthType, clusterName string, signingKeys, checkingKeys [][]byte, roles []string) CertAuthority { +func NewCertAuthority( + caType CertAuthType, + clusterName string, + signingKeys [][]byte, + checkingKeys [][]byte, + roles []string, + signingAlg CertAuthoritySpecV2_SigningAlgType, +) CertAuthority { return &CertAuthorityV2{ Kind: KindCertAuthority, Version: V2, @@ -289,6 +321,7 @@ func NewCertAuthority(caType CertAuthType, clusterName string, signingKeys, chec ClusterName: clusterName, CheckingKeys: checkingKeys, SigningKeys: signingKeys, + SigningAlg: signingAlg, }, } } @@ -547,7 +580,7 @@ func (ca *CertAuthorityV2) Checkers() ([]ssh.PublicKey, error) { return out, nil } -// Signers returns a list of signers that could be used to sign keys +// Signers returns a list of signers that could be used to sign keys. func (ca *CertAuthorityV2) Signers() ([]ssh.Signer, error) { out := make([]ssh.Signer, 0, len(ca.Spec.SigningKeys)) for _, keyBytes := range ca.Spec.SigningKeys { @@ -555,11 +588,32 @@ func (ca *CertAuthorityV2) Signers() ([]ssh.Signer, error) { if err != nil { return nil, trace.Wrap(err) } + signer = sshutils.AlgSigner(signer, ca.GetSigningAlg()) out = append(out, signer) } return out, nil } +func (ca *CertAuthorityV2) GetSigningAlg() string { + switch ca.Spec.SigningAlg { + // UNKNOWN algorithm can come from a cluster that existed before SigningAlg + // field was added. Default to RSA-SHA1 to match the implicit algorithm + // used in those clusters. + case CertAuthoritySpecV2_RSA_SHA1, CertAuthoritySpecV2_UNKNOWN: + return ssh.SigAlgoRSA + case CertAuthoritySpecV2_RSA_SHA2_256: + return ssh.SigAlgoRSASHA2256 + case CertAuthoritySpecV2_RSA_SHA2_512: + return ssh.SigAlgoRSASHA2512 + default: + return "" + } +} + +func (ca *CertAuthorityV2) SetSigningAlg(alg string) { + ca.Spec.SigningAlg = ParseSigningAlg(alg) +} + // Check checks if all passed parameters are valid func (ca *CertAuthorityV2) Check() error { err := ca.ID().Check() @@ -599,6 +653,24 @@ func (ca *CertAuthorityV2) CheckAndSetDefaults() error { return nil } +// ParseSigningAlg converts the SSH signature algorithm strings to the +// corresponding proto enum value. +// +// alg should be one of ssh.SigAlgo* constants. If it's not one of those +// constants, CertAuthoritySpecV2_UNKNOWN is returned. +func ParseSigningAlg(alg string) CertAuthoritySpecV2_SigningAlgType { + switch alg { + case ssh.SigAlgoRSA: + return CertAuthoritySpecV2_RSA_SHA1 + case ssh.SigAlgoRSASHA2256: + return CertAuthoritySpecV2_RSA_SHA2_256 + case ssh.SigAlgoRSASHA2512: + return CertAuthoritySpecV2_RSA_SHA2_512 + default: + return CertAuthoritySpecV2_UNKNOWN + } +} + // RemoveCASecrets removes secret values and keys // from the certificate authority func RemoveCASecrets(ca CertAuthority) { @@ -808,6 +880,7 @@ const CertAuthoritySpecV2Schema = `{ } } }, + "signing_alg": {"type": "integer"}, "rotation": %v, "role_map": %v } diff --git a/lib/services/types.pb.go b/lib/services/types.pb.go index e8522e0c83b40..da2fb37fe5f5b 100644 --- a/lib/services/types.pb.go +++ b/lib/services/types.pb.go @@ -64,7 +64,38 @@ func (x RequestState) String() string { return proto.EnumName(RequestState_name, int32(x)) } func (RequestState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{0} + return fileDescriptor_types_4c8f0d072f915196, []int{0} +} + +// SigningAlg is the algorithm used for signing new SSH certificates using +// SigningKeys. +type CertAuthoritySpecV2_SigningAlgType int32 + +const ( + CertAuthoritySpecV2_UNKNOWN CertAuthoritySpecV2_SigningAlgType = 0 + CertAuthoritySpecV2_RSA_SHA1 CertAuthoritySpecV2_SigningAlgType = 1 + CertAuthoritySpecV2_RSA_SHA2_256 CertAuthoritySpecV2_SigningAlgType = 2 + CertAuthoritySpecV2_RSA_SHA2_512 CertAuthoritySpecV2_SigningAlgType = 3 +) + +var CertAuthoritySpecV2_SigningAlgType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "RSA_SHA1", + 2: "RSA_SHA2_256", + 3: "RSA_SHA2_512", +} +var CertAuthoritySpecV2_SigningAlgType_value = map[string]int32{ + "UNKNOWN": 0, + "RSA_SHA1": 1, + "RSA_SHA2_256": 2, + "RSA_SHA2_512": 3, +} + +func (x CertAuthoritySpecV2_SigningAlgType) String() string { + return proto.EnumName(CertAuthoritySpecV2_SigningAlgType_name, int32(x)) +} +func (CertAuthoritySpecV2_SigningAlgType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_types_4c8f0d072f915196, []int{10, 0} } type KeepAlive struct { @@ -85,7 +116,7 @@ func (m *KeepAlive) Reset() { *m = KeepAlive{} } func (m *KeepAlive) String() string { return proto.CompactTextString(m) } func (*KeepAlive) ProtoMessage() {} func (*KeepAlive) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{0} + return fileDescriptor_types_4c8f0d072f915196, []int{0} } func (m *KeepAlive) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -139,7 +170,7 @@ func (m *Metadata) Reset() { *m = Metadata{} } func (m *Metadata) String() string { return proto.CompactTextString(m) } func (*Metadata) ProtoMessage() {} func (*Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{1} + return fileDescriptor_types_4c8f0d072f915196, []int{1} } func (m *Metadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -198,7 +229,7 @@ type Rotation struct { func (m *Rotation) Reset() { *m = Rotation{} } func (*Rotation) ProtoMessage() {} func (*Rotation) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{2} + return fileDescriptor_types_4c8f0d072f915196, []int{2} } func (m *Rotation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -245,7 +276,7 @@ func (m *RotationSchedule) Reset() { *m = RotationSchedule{} } func (m *RotationSchedule) String() string { return proto.CompactTextString(m) } func (*RotationSchedule) ProtoMessage() {} func (*RotationSchedule) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{3} + return fileDescriptor_types_4c8f0d072f915196, []int{3} } func (m *RotationSchedule) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -294,7 +325,7 @@ func (m *ResourceHeader) Reset() { *m = ResourceHeader{} } func (m *ResourceHeader) String() string { return proto.CompactTextString(m) } func (*ResourceHeader) ProtoMessage() {} func (*ResourceHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{4} + return fileDescriptor_types_4c8f0d072f915196, []int{4} } func (m *ResourceHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -343,7 +374,7 @@ type ServerV2 struct { func (m *ServerV2) Reset() { *m = ServerV2{} } func (*ServerV2) ProtoMessage() {} func (*ServerV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{5} + return fileDescriptor_types_4c8f0d072f915196, []int{5} } func (m *ServerV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -398,7 +429,7 @@ func (m *ServerSpecV2) Reset() { *m = ServerSpecV2{} } func (m *ServerSpecV2) String() string { return proto.CompactTextString(m) } func (*ServerSpecV2) ProtoMessage() {} func (*ServerSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{6} + return fileDescriptor_types_4c8f0d072f915196, []int{6} } func (m *ServerSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -445,7 +476,7 @@ func (m *CommandLabelV2) Reset() { *m = CommandLabelV2{} } func (m *CommandLabelV2) String() string { return proto.CompactTextString(m) } func (*CommandLabelV2) ProtoMessage() {} func (*CommandLabelV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{7} + return fileDescriptor_types_4c8f0d072f915196, []int{7} } func (m *CommandLabelV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -489,7 +520,7 @@ func (m *TLSKeyPair) Reset() { *m = TLSKeyPair{} } func (m *TLSKeyPair) String() string { return proto.CompactTextString(m) } func (*TLSKeyPair) ProtoMessage() {} func (*TLSKeyPair) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{8} + return fileDescriptor_types_4c8f0d072f915196, []int{8} } func (m *TLSKeyPair) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -538,7 +569,7 @@ type CertAuthorityV2 struct { func (m *CertAuthorityV2) Reset() { *m = CertAuthorityV2{} } func (*CertAuthorityV2) ProtoMessage() {} func (*CertAuthorityV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{9} + return fileDescriptor_types_4c8f0d072f915196, []int{9} } func (m *CertAuthorityV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -591,17 +622,18 @@ type CertAuthoritySpecV2 struct { // TLS is a list of TLS key pairs TLSKeyPairs []TLSKeyPair `protobuf:"bytes,7,rep,name=TLSKeyPairs" json:"tls_key_pairs,omitempty"` // Rotation is a status of the certificate authority rotation - Rotation *Rotation `protobuf:"bytes,8,opt,name=Rotation" json:"rotation,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Rotation *Rotation `protobuf:"bytes,8,opt,name=Rotation" json:"rotation,omitempty"` + SigningAlg CertAuthoritySpecV2_SigningAlgType `protobuf:"varint,9,opt,name=SigningAlg,proto3,enum=services.CertAuthoritySpecV2_SigningAlgType" json:"signing_alg,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *CertAuthoritySpecV2) Reset() { *m = CertAuthoritySpecV2{} } func (m *CertAuthoritySpecV2) String() string { return proto.CompactTextString(m) } func (*CertAuthoritySpecV2) ProtoMessage() {} func (*CertAuthoritySpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{10} + return fileDescriptor_types_4c8f0d072f915196, []int{10} } func (m *CertAuthoritySpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -646,7 +678,7 @@ func (m *RoleMapping) Reset() { *m = RoleMapping{} } func (m *RoleMapping) String() string { return proto.CompactTextString(m) } func (*RoleMapping) ProtoMessage() {} func (*RoleMapping) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{11} + return fileDescriptor_types_4c8f0d072f915196, []int{11} } func (m *RoleMapping) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -694,7 +726,7 @@ type ProvisionTokenV1 struct { func (m *ProvisionTokenV1) Reset() { *m = ProvisionTokenV1{} } func (*ProvisionTokenV1) ProtoMessage() {} func (*ProvisionTokenV1) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{12} + return fileDescriptor_types_4c8f0d072f915196, []int{12} } func (m *ProvisionTokenV1) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -743,7 +775,7 @@ type ProvisionTokenV2 struct { func (m *ProvisionTokenV2) Reset() { *m = ProvisionTokenV2{} } func (*ProvisionTokenV2) ProtoMessage() {} func (*ProvisionTokenV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{13} + return fileDescriptor_types_4c8f0d072f915196, []int{13} } func (m *ProvisionTokenV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -787,7 +819,7 @@ func (m *ProvisionTokenSpecV2) Reset() { *m = ProvisionTokenSpecV2{} } func (m *ProvisionTokenSpecV2) String() string { return proto.CompactTextString(m) } func (*ProvisionTokenSpecV2) ProtoMessage() {} func (*ProvisionTokenSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{14} + return fileDescriptor_types_4c8f0d072f915196, []int{14} } func (m *ProvisionTokenSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -836,7 +868,7 @@ type StaticTokensV2 struct { func (m *StaticTokensV2) Reset() { *m = StaticTokensV2{} } func (*StaticTokensV2) ProtoMessage() {} func (*StaticTokensV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{15} + return fileDescriptor_types_4c8f0d072f915196, []int{15} } func (m *StaticTokensV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -879,7 +911,7 @@ func (m *StaticTokensSpecV2) Reset() { *m = StaticTokensSpecV2{} } func (m *StaticTokensSpecV2) String() string { return proto.CompactTextString(m) } func (*StaticTokensSpecV2) ProtoMessage() {} func (*StaticTokensSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{16} + return fileDescriptor_types_4c8f0d072f915196, []int{16} } func (m *StaticTokensSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -928,7 +960,7 @@ type ClusterNameV2 struct { func (m *ClusterNameV2) Reset() { *m = ClusterNameV2{} } func (*ClusterNameV2) ProtoMessage() {} func (*ClusterNameV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{17} + return fileDescriptor_types_4c8f0d072f915196, []int{17} } func (m *ClusterNameV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -971,7 +1003,7 @@ func (m *ClusterNameSpecV2) Reset() { *m = ClusterNameSpecV2{} } func (m *ClusterNameSpecV2) String() string { return proto.CompactTextString(m) } func (*ClusterNameSpecV2) ProtoMessage() {} func (*ClusterNameSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{18} + return fileDescriptor_types_4c8f0d072f915196, []int{18} } func (m *ClusterNameSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1020,7 +1052,7 @@ type ClusterConfigV3 struct { func (m *ClusterConfigV3) Reset() { *m = ClusterConfigV3{} } func (*ClusterConfigV3) ProtoMessage() {} func (*ClusterConfigV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{19} + return fileDescriptor_types_4c8f0d072f915196, []int{19} } func (m *ClusterConfigV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1085,7 +1117,7 @@ func (m *ClusterConfigSpecV3) Reset() { *m = ClusterConfigSpecV3{} } func (m *ClusterConfigSpecV3) String() string { return proto.CompactTextString(m) } func (*ClusterConfigSpecV3) ProtoMessage() {} func (*ClusterConfigSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{20} + return fileDescriptor_types_4c8f0d072f915196, []int{20} } func (m *ClusterConfigSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1138,7 +1170,7 @@ func (m *AuditConfig) Reset() { *m = AuditConfig{} } func (m *AuditConfig) String() string { return proto.CompactTextString(m) } func (*AuditConfig) ProtoMessage() {} func (*AuditConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{21} + return fileDescriptor_types_4c8f0d072f915196, []int{21} } func (m *AuditConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1188,7 +1220,7 @@ func (m *Namespace) Reset() { *m = Namespace{} } func (m *Namespace) String() string { return proto.CompactTextString(m) } func (*Namespace) ProtoMessage() {} func (*Namespace) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{22} + return fileDescriptor_types_4c8f0d072f915196, []int{22} } func (m *Namespace) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1228,7 +1260,7 @@ func (m *NamespaceSpec) Reset() { *m = NamespaceSpec{} } func (m *NamespaceSpec) String() string { return proto.CompactTextString(m) } func (*NamespaceSpec) ProtoMessage() {} func (*NamespaceSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{23} + return fileDescriptor_types_4c8f0d072f915196, []int{23} } func (m *NamespaceSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1276,7 +1308,7 @@ type ResetPasswordTokenV3 struct { func (m *ResetPasswordTokenV3) Reset() { *m = ResetPasswordTokenV3{} } func (*ResetPasswordTokenV3) ProtoMessage() {} func (*ResetPasswordTokenV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{24} + return fileDescriptor_types_4c8f0d072f915196, []int{24} } func (m *ResetPasswordTokenV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1321,7 +1353,7 @@ func (m *ResetPasswordTokenSpecV3) Reset() { *m = ResetPasswordTokenSpec func (m *ResetPasswordTokenSpecV3) String() string { return proto.CompactTextString(m) } func (*ResetPasswordTokenSpecV3) ProtoMessage() {} func (*ResetPasswordTokenSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{25} + return fileDescriptor_types_4c8f0d072f915196, []int{25} } func (m *ResetPasswordTokenSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1369,7 +1401,7 @@ type ResetPasswordTokenSecretsV3 struct { func (m *ResetPasswordTokenSecretsV3) Reset() { *m = ResetPasswordTokenSecretsV3{} } func (*ResetPasswordTokenSecretsV3) ProtoMessage() {} func (*ResetPasswordTokenSecretsV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{26} + return fileDescriptor_types_4c8f0d072f915196, []int{26} } func (m *ResetPasswordTokenSecretsV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1414,7 +1446,7 @@ func (m *ResetPasswordTokenSecretsSpecV3) Reset() { *m = ResetPasswordTo func (m *ResetPasswordTokenSecretsSpecV3) String() string { return proto.CompactTextString(m) } func (*ResetPasswordTokenSecretsSpecV3) ProtoMessage() {} func (*ResetPasswordTokenSecretsSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{27} + return fileDescriptor_types_4c8f0d072f915196, []int{27} } func (m *ResetPasswordTokenSecretsSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1463,7 +1495,7 @@ type AccessRequestV3 struct { func (m *AccessRequestV3) Reset() { *m = AccessRequestV3{} } func (*AccessRequestV3) ProtoMessage() {} func (*AccessRequestV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{28} + return fileDescriptor_types_4c8f0d072f915196, []int{28} } func (m *AccessRequestV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1515,7 +1547,7 @@ func (m *AccessRequestSpecV3) Reset() { *m = AccessRequestSpecV3{} } func (m *AccessRequestSpecV3) String() string { return proto.CompactTextString(m) } func (*AccessRequestSpecV3) ProtoMessage() {} func (*AccessRequestSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{29} + return fileDescriptor_types_4c8f0d072f915196, []int{29} } func (m *AccessRequestSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1561,7 +1593,7 @@ func (m *AccessRequestFilter) Reset() { *m = AccessRequestFilter{} } func (m *AccessRequestFilter) String() string { return proto.CompactTextString(m) } func (*AccessRequestFilter) ProtoMessage() {} func (*AccessRequestFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{30} + return fileDescriptor_types_4c8f0d072f915196, []int{30} } func (m *AccessRequestFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1610,7 +1642,7 @@ type PluginDataV3 struct { func (m *PluginDataV3) Reset() { *m = PluginDataV3{} } func (*PluginDataV3) ProtoMessage() {} func (*PluginDataV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{31} + return fileDescriptor_types_4c8f0d072f915196, []int{31} } func (m *PluginDataV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1653,7 +1685,7 @@ func (m *PluginDataEntry) Reset() { *m = PluginDataEntry{} } func (m *PluginDataEntry) String() string { return proto.CompactTextString(m) } func (*PluginDataEntry) ProtoMessage() {} func (*PluginDataEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{32} + return fileDescriptor_types_4c8f0d072f915196, []int{32} } func (m *PluginDataEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1695,7 +1727,7 @@ func (m *PluginDataSpecV3) Reset() { *m = PluginDataSpecV3{} } func (m *PluginDataSpecV3) String() string { return proto.CompactTextString(m) } func (*PluginDataSpecV3) ProtoMessage() {} func (*PluginDataSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{33} + return fileDescriptor_types_4c8f0d072f915196, []int{33} } func (m *PluginDataSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1742,7 +1774,7 @@ func (m *PluginDataFilter) Reset() { *m = PluginDataFilter{} } func (m *PluginDataFilter) String() string { return proto.CompactTextString(m) } func (*PluginDataFilter) ProtoMessage() {} func (*PluginDataFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{34} + return fileDescriptor_types_4c8f0d072f915196, []int{34} } func (m *PluginDataFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1793,7 +1825,7 @@ func (m *PluginDataUpdateParams) Reset() { *m = PluginDataUpdateParams{} func (m *PluginDataUpdateParams) String() string { return proto.CompactTextString(m) } func (*PluginDataUpdateParams) ProtoMessage() {} func (*PluginDataUpdateParams) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{35} + return fileDescriptor_types_4c8f0d072f915196, []int{35} } func (m *PluginDataUpdateParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1842,7 +1874,7 @@ type RoleV3 struct { func (m *RoleV3) Reset() { *m = RoleV3{} } func (*RoleV3) ProtoMessage() {} func (*RoleV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{36} + return fileDescriptor_types_4c8f0d072f915196, []int{36} } func (m *RoleV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1889,7 +1921,7 @@ func (m *RoleSpecV3) Reset() { *m = RoleSpecV3{} } func (m *RoleSpecV3) String() string { return proto.CompactTextString(m) } func (*RoleSpecV3) ProtoMessage() {} func (*RoleSpecV3) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{37} + return fileDescriptor_types_4c8f0d072f915196, []int{37} } func (m *RoleSpecV3) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1951,7 +1983,7 @@ func (m *RoleOptions) Reset() { *m = RoleOptions{} } func (m *RoleOptions) String() string { return proto.CompactTextString(m) } func (*RoleOptions) ProtoMessage() {} func (*RoleOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{38} + return fileDescriptor_types_4c8f0d072f915196, []int{38} } func (m *RoleOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2008,7 +2040,7 @@ func (m *RoleConditions) Reset() { *m = RoleConditions{} } func (m *RoleConditions) String() string { return proto.CompactTextString(m) } func (*RoleConditions) ProtoMessage() {} func (*RoleConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{39} + return fileDescriptor_types_4c8f0d072f915196, []int{39} } func (m *RoleConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2051,7 +2083,7 @@ func (m *AccessRequestConditions) Reset() { *m = AccessRequestConditions func (m *AccessRequestConditions) String() string { return proto.CompactTextString(m) } func (*AccessRequestConditions) ProtoMessage() {} func (*AccessRequestConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{40} + return fileDescriptor_types_4c8f0d072f915196, []int{40} } func (m *AccessRequestConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2100,7 +2132,7 @@ func (m *Rule) Reset() { *m = Rule{} } func (m *Rule) String() string { return proto.CompactTextString(m) } func (*Rule) ProtoMessage() {} func (*Rule) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{41} + return fileDescriptor_types_4c8f0d072f915196, []int{41} } func (m *Rule) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2142,7 +2174,7 @@ func (m *BoolValue) Reset() { *m = BoolValue{} } func (m *BoolValue) String() string { return proto.CompactTextString(m) } func (*BoolValue) ProtoMessage() {} func (*BoolValue) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{42} + return fileDescriptor_types_4c8f0d072f915196, []int{42} } func (m *BoolValue) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2191,7 +2223,7 @@ type UserV2 struct { func (m *UserV2) Reset() { *m = UserV2{} } func (*UserV2) ProtoMessage() {} func (*UserV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{43} + return fileDescriptor_types_4c8f0d072f915196, []int{43} } func (m *UserV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2255,7 +2287,7 @@ func (m *UserSpecV2) Reset() { *m = UserSpecV2{} } func (m *UserSpecV2) String() string { return proto.CompactTextString(m) } func (*UserSpecV2) ProtoMessage() {} func (*UserSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{44} + return fileDescriptor_types_4c8f0d072f915196, []int{44} } func (m *UserSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2300,7 +2332,7 @@ type ExternalIdentity struct { func (m *ExternalIdentity) Reset() { *m = ExternalIdentity{} } func (*ExternalIdentity) ProtoMessage() {} func (*ExternalIdentity) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{45} + return fileDescriptor_types_4c8f0d072f915196, []int{45} } func (m *ExternalIdentity) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2348,7 +2380,7 @@ func (m *LoginStatus) Reset() { *m = LoginStatus{} } func (m *LoginStatus) String() string { return proto.CompactTextString(m) } func (*LoginStatus) ProtoMessage() {} func (*LoginStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{46} + return fileDescriptor_types_4c8f0d072f915196, []int{46} } func (m *LoginStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2393,7 +2425,7 @@ type CreatedBy struct { func (m *CreatedBy) Reset() { *m = CreatedBy{} } func (*CreatedBy) ProtoMessage() {} func (*CreatedBy) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{47} + return fileDescriptor_types_4c8f0d072f915196, []int{47} } func (m *CreatedBy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2439,7 +2471,7 @@ func (m *U2FRegistrationData) Reset() { *m = U2FRegistrationData{} } func (m *U2FRegistrationData) String() string { return proto.CompactTextString(m) } func (*U2FRegistrationData) ProtoMessage() {} func (*U2FRegistrationData) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{48} + return fileDescriptor_types_4c8f0d072f915196, []int{48} } func (m *U2FRegistrationData) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2488,7 +2520,7 @@ func (m *LocalAuthSecrets) Reset() { *m = LocalAuthSecrets{} } func (m *LocalAuthSecrets) String() string { return proto.CompactTextString(m) } func (*LocalAuthSecrets) ProtoMessage() {} func (*LocalAuthSecrets) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{49} + return fileDescriptor_types_4c8f0d072f915196, []int{49} } func (m *LocalAuthSecrets) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2534,7 +2566,7 @@ func (m *ConnectorRef) Reset() { *m = ConnectorRef{} } func (m *ConnectorRef) String() string { return proto.CompactTextString(m) } func (*ConnectorRef) ProtoMessage() {} func (*ConnectorRef) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{50} + return fileDescriptor_types_4c8f0d072f915196, []int{50} } func (m *ConnectorRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2576,7 +2608,7 @@ func (m *UserRef) Reset() { *m = UserRef{} } func (m *UserRef) String() string { return proto.CompactTextString(m) } func (*UserRef) ProtoMessage() {} func (*UserRef) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{51} + return fileDescriptor_types_4c8f0d072f915196, []int{51} } func (m *UserRef) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2626,7 +2658,7 @@ func (m *ReverseTunnelV2) Reset() { *m = ReverseTunnelV2{} } func (m *ReverseTunnelV2) String() string { return proto.CompactTextString(m) } func (*ReverseTunnelV2) ProtoMessage() {} func (*ReverseTunnelV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{52} + return fileDescriptor_types_4c8f0d072f915196, []int{52} } func (m *ReverseTunnelV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2673,7 +2705,7 @@ func (m *ReverseTunnelSpecV2) Reset() { *m = ReverseTunnelSpecV2{} } func (m *ReverseTunnelSpecV2) String() string { return proto.CompactTextString(m) } func (*ReverseTunnelSpecV2) ProtoMessage() {} func (*ReverseTunnelSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{53} + return fileDescriptor_types_4c8f0d072f915196, []int{53} } func (m *ReverseTunnelSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2722,7 +2754,7 @@ type TunnelConnectionV2 struct { func (m *TunnelConnectionV2) Reset() { *m = TunnelConnectionV2{} } func (*TunnelConnectionV2) ProtoMessage() {} func (*TunnelConnectionV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{54} + return fileDescriptor_types_4c8f0d072f915196, []int{54} } func (m *TunnelConnectionV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2770,7 +2802,7 @@ func (m *TunnelConnectionSpecV2) Reset() { *m = TunnelConnectionSpecV2{} func (m *TunnelConnectionSpecV2) String() string { return proto.CompactTextString(m) } func (*TunnelConnectionSpecV2) ProtoMessage() {} func (*TunnelConnectionSpecV2) Descriptor() ([]byte, []int) { - return fileDescriptor_types_c4d9386f51e6f4e8, []int{55} + return fileDescriptor_types_4c8f0d072f915196, []int{55} } func (m *TunnelConnectionSpecV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2863,6 +2895,7 @@ func init() { proto.RegisterType((*TunnelConnectionV2)(nil), "services.TunnelConnectionV2") proto.RegisterType((*TunnelConnectionSpecV2)(nil), "services.TunnelConnectionSpecV2") proto.RegisterEnum("services.RequestState", RequestState_name, RequestState_value) + proto.RegisterEnum("services.CertAuthoritySpecV2_SigningAlgType", CertAuthoritySpecV2_SigningAlgType_name, CertAuthoritySpecV2_SigningAlgType_value) } func (m *KeepAlive) Marshal() (dAtA []byte, err error) { size := m.Size() @@ -3518,6 +3551,11 @@ func (m *CertAuthoritySpecV2) MarshalTo(dAtA []byte) (int, error) { } i += n16 } + if m.SigningAlg != 0 { + dAtA[i] = 0x48 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.SigningAlg)) + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -6159,6 +6197,9 @@ func (m *CertAuthoritySpecV2) Size() (n int) { l = m.Rotation.Size() n += 1 + l + sovTypes(uint64(l)) } + if m.SigningAlg != 0 { + n += 1 + sovTypes(uint64(m.SigningAlg)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -9518,6 +9559,25 @@ func (m *CertAuthoritySpecV2) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SigningAlg", wireType) + } + m.SigningAlg = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SigningAlg |= (CertAuthoritySpecV2_SigningAlgType(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -17201,270 +17261,275 @@ var ( ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") ) -func init() { proto.RegisterFile("types.proto", fileDescriptor_types_c4d9386f51e6f4e8) } - -var fileDescriptor_types_c4d9386f51e6f4e8 = []byte{ - // 4179 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x3b, 0x5d, 0x6f, 0x1c, 0xc9, - 0x71, 0xda, 0x0f, 0x92, 0xbb, 0xc5, 0x0f, 0x51, 0x4d, 0x7d, 0xac, 0x28, 0x9d, 0x86, 0xb7, 0xca, - 0xdd, 0x49, 0x8e, 0x8e, 0x8c, 0xa8, 0x9c, 0x6c, 0x5d, 0x4e, 0xb9, 0xe3, 0x72, 0x29, 0x89, 0x26, - 0x25, 0xf1, 0x86, 0x14, 0x1d, 0xe7, 0x6b, 0x32, 0x9c, 0x69, 0x2d, 0x07, 0x9c, 0x9d, 0x59, 0xcf, - 0xf4, 0x50, 0xdc, 0x37, 0x23, 0x09, 0x10, 0x24, 0x06, 0xec, 0x04, 0x81, 0xe1, 0x03, 0x62, 0x20, - 0x01, 0xf2, 0x90, 0xe4, 0xc1, 0x79, 0x0d, 0xf2, 0x90, 0x87, 0x00, 0x79, 0x10, 0x02, 0x04, 0xc8, - 0xb3, 0xe1, 0x8c, 0x93, 0xcb, 0xc3, 0x01, 0xfb, 0x07, 0x02, 0xdc, 0x4b, 0x82, 0xae, 0xee, 0x99, - 0xe9, 0xd9, 0x5d, 0x8a, 0xab, 0xcb, 0xf9, 0x81, 0xf7, 0xc4, 0x61, 0x75, 0x55, 0x75, 0x55, 0x75, - 0x75, 0x75, 0x75, 0x75, 0x2d, 0x4c, 0xb2, 0x6e, 0x87, 0x86, 0x8b, 0x9d, 0xc0, 0x67, 0x3e, 0xa9, - 0x84, 0x34, 0x38, 0x74, 0x2c, 0x1a, 0xce, 0x9f, 0x6f, 0xf9, 0x2d, 0x1f, 0x81, 0x4b, 0xfc, 0x4b, - 0x8c, 0xcf, 0x6b, 0x2d, 0xdf, 0x6f, 0xb9, 0x74, 0x09, 0xff, 0xdb, 0x8b, 0x9e, 0x2f, 0x31, 0xa7, - 0x4d, 0x43, 0x66, 0xb6, 0x3b, 0x12, 0xe1, 0x7e, 0xcb, 0x61, 0xfb, 0xd1, 0xde, 0xa2, 0xe5, 0xb7, - 0x97, 0x5a, 0x81, 0x79, 0xe8, 0x30, 0x93, 0x39, 0xbe, 0x67, 0xba, 0x4b, 0x8c, 0xba, 0xb4, 0xe3, - 0x07, 0x6c, 0xc9, 0x75, 0xf6, 0x96, 0x5e, 0x04, 0x66, 0xa7, 0x43, 0x83, 0x30, 0xfd, 0x10, 0xe4, - 0xf5, 0x9f, 0x15, 0xa0, 0xba, 0x41, 0x69, 0x67, 0xc5, 0x75, 0x0e, 0x29, 0x59, 0x02, 0xd8, 0xa6, - 0xc1, 0x21, 0x0d, 0x9e, 0x98, 0x6d, 0x5a, 0x2b, 0x2c, 0x14, 0x6e, 0x54, 0x1b, 0x67, 0x7b, 0xb1, - 0x36, 0x19, 0x22, 0xd4, 0xf0, 0xcc, 0x36, 0xd5, 0x15, 0x14, 0xf2, 0xcb, 0x50, 0xe5, 0x7f, 0xc3, - 0x8e, 0x69, 0xd1, 0x5a, 0x11, 0xf1, 0xa7, 0x7b, 0xb1, 0x56, 0xf5, 0x12, 0xa0, 0x9e, 0x8d, 0x93, - 0xb7, 0x61, 0x62, 0x93, 0x9a, 0x21, 0x5d, 0x6f, 0xd6, 0x4a, 0x0b, 0x85, 0x1b, 0xa5, 0xc6, 0x54, - 0x2f, 0xd6, 0x2a, 0x2e, 0x07, 0x19, 0x8e, 0xad, 0x27, 0x83, 0x64, 0x1d, 0x26, 0xd6, 0x8e, 0x3a, - 0x4e, 0x40, 0xc3, 0x5a, 0x79, 0xa1, 0x70, 0x63, 0x72, 0x79, 0x7e, 0x51, 0x58, 0x61, 0x31, 0xb1, - 0xc2, 0xe2, 0x4e, 0x62, 0x85, 0xc6, 0xdc, 0xcb, 0x58, 0x3b, 0xd3, 0x8b, 0xb5, 0x09, 0x2a, 0x48, - 0xfe, 0xf4, 0xe7, 0x5a, 0x41, 0x4f, 0xe8, 0xeb, 0x7f, 0x52, 0x82, 0xca, 0x63, 0xca, 0x4c, 0xdb, - 0x64, 0x26, 0xb9, 0x0a, 0x65, 0x45, 0xaf, 0x4a, 0x2f, 0xd6, 0xca, 0xa8, 0x10, 0x42, 0xc9, 0xf5, - 0x41, 0x55, 0xc6, 0x7a, 0xb1, 0x56, 0x78, 0x57, 0x55, 0xe1, 0xd7, 0x60, 0xb2, 0x49, 0x43, 0x2b, - 0x70, 0x3a, 0xdc, 0xc8, 0xa8, 0x46, 0xb5, 0x71, 0xb9, 0x17, 0x6b, 0x17, 0xec, 0x0c, 0x7c, 0xcb, - 0x6f, 0x3b, 0x8c, 0xb6, 0x3b, 0xac, 0xab, 0xab, 0xd8, 0x64, 0x13, 0xc6, 0x37, 0xcd, 0x3d, 0xea, - 0x86, 0xb5, 0xb1, 0x85, 0xd2, 0x8d, 0xc9, 0xe5, 0x6b, 0x8b, 0xc9, 0xe2, 0x2f, 0x26, 0x32, 0x2e, - 0x0a, 0x84, 0x35, 0x8f, 0x05, 0xdd, 0xc6, 0xf9, 0x5e, 0xac, 0xcd, 0xba, 0x08, 0x50, 0x58, 0x4a, - 0x1e, 0x64, 0x3b, 0xb3, 0xd2, 0xf8, 0x89, 0x56, 0x7a, 0xe3, 0x65, 0xac, 0x15, 0x7a, 0xb1, 0x76, - 0x4e, 0x5a, 0x29, 0xe3, 0x97, 0xb3, 0x17, 0x59, 0x80, 0xe2, 0x7a, 0xb3, 0x36, 0x81, 0xab, 0x33, - 0xdb, 0x8b, 0xb5, 0x29, 0xc7, 0x56, 0xa6, 0x2e, 0xae, 0x37, 0xe7, 0xef, 0xc1, 0xa4, 0x22, 0x23, - 0x99, 0x85, 0xd2, 0x01, 0xed, 0x0a, 0x93, 0xea, 0xfc, 0x93, 0x9c, 0x87, 0xb1, 0x43, 0xd3, 0x8d, - 0xa4, 0x0d, 0x75, 0xf1, 0xcf, 0xfb, 0xc5, 0x6f, 0x14, 0xea, 0x3f, 0x2c, 0x43, 0x45, 0xf7, 0x85, - 0x7f, 0x92, 0x9b, 0x30, 0xb6, 0xcd, 0x4c, 0x96, 0xac, 0xc6, 0x5c, 0x2f, 0xd6, 0xce, 0x86, 0x1c, - 0xa0, 0xcc, 0x27, 0x30, 0x38, 0xea, 0xd6, 0xbe, 0x19, 0x26, 0xab, 0x82, 0xa8, 0x1d, 0x0e, 0x50, - 0x51, 0x11, 0x83, 0xbc, 0x0d, 0xe5, 0xc7, 0xbe, 0x4d, 0xe5, 0xc2, 0x90, 0x5e, 0xac, 0xcd, 0xb4, - 0x7d, 0x5b, 0x45, 0xc4, 0x71, 0x72, 0x0b, 0xaa, 0xab, 0x51, 0x10, 0x50, 0x8f, 0xad, 0x37, 0xd1, - 0xc9, 0xaa, 0x8d, 0x99, 0x5e, 0xac, 0x81, 0x25, 0x80, 0xdc, 0x1d, 0x33, 0x04, 0x6e, 0xea, 0x6d, - 0x66, 0x06, 0x8c, 0xda, 0xb5, 0xb1, 0x91, 0x4c, 0xcd, 0x1d, 0xf2, 0x5c, 0x28, 0x48, 0xfa, 0x4d, - 0x2d, 0x39, 0x91, 0x47, 0x30, 0xf9, 0x30, 0x30, 0x2d, 0xba, 0x45, 0x03, 0xc7, 0xb7, 0x71, 0x0d, - 0x4b, 0x8d, 0xb7, 0x7b, 0xb1, 0x76, 0xb1, 0xc5, 0xc1, 0x46, 0x07, 0xe1, 0x19, 0xf5, 0xe7, 0xb1, - 0x56, 0x69, 0x46, 0x01, 0x5a, 0x4f, 0x57, 0x49, 0xc9, 0xef, 0xf1, 0x25, 0x09, 0x19, 0x9a, 0x96, - 0xda, 0xb8, 0x7a, 0xaf, 0x16, 0xb1, 0x2e, 0x45, 0xbc, 0xe8, 0x9a, 0x21, 0x33, 0x02, 0x41, 0xd7, - 0x27, 0xa7, 0xca, 0x92, 0xe8, 0x50, 0xd9, 0xb6, 0xf6, 0xa9, 0x1d, 0xb9, 0xb4, 0x56, 0x91, 0xec, - 0x53, 0xdf, 0x4d, 0x96, 0x34, 0xc1, 0x68, 0xcc, 0x4b, 0xf6, 0x24, 0x94, 0x10, 0xc5, 0xfc, 0x29, - 0x9f, 0xf7, 0x2b, 0x9f, 0xfc, 0x95, 0x76, 0xe6, 0xbb, 0x3f, 0x5b, 0x38, 0x53, 0xff, 0x87, 0x22, - 0xcc, 0xf6, 0x33, 0x21, 0xcf, 0x61, 0xfa, 0x59, 0xc7, 0x36, 0x19, 0x5d, 0x75, 0x1d, 0xea, 0xb1, - 0x10, 0xfd, 0xe4, 0xd5, 0x6a, 0xfd, 0x92, 0x9c, 0xb7, 0x16, 0x21, 0xa1, 0x61, 0x09, 0xca, 0x3e, - 0xc5, 0xf2, 0x6c, 0xb3, 0x79, 0x44, 0x54, 0x0b, 0xd1, 0xc9, 0x5e, 0x6f, 0x1e, 0x11, 0x1c, 0x8f, - 0x99, 0x47, 0xb2, 0x95, 0x3e, 0xe4, 0xd9, 0x7b, 0x5d, 0x74, 0xce, 0xd1, 0x7d, 0x88, 0x93, 0x0c, - 0xf1, 0x21, 0x0e, 0xae, 0x7f, 0x56, 0x80, 0x19, 0x9d, 0x86, 0x7e, 0x14, 0x58, 0xf4, 0x11, 0x35, - 0x6d, 0x1a, 0xf0, 0x1d, 0xb0, 0xe1, 0x78, 0xb6, 0xdc, 0x56, 0xb8, 0x03, 0x0e, 0x1c, 0x4f, 0xdd, - 0xc5, 0x38, 0x4e, 0x7e, 0x05, 0x26, 0xb6, 0xa3, 0x3d, 0x44, 0x15, 0xdb, 0xea, 0x22, 0xae, 0x58, - 0xb4, 0x67, 0xf4, 0xa1, 0x27, 0x68, 0x64, 0x09, 0x26, 0x76, 0x69, 0x10, 0x66, 0x71, 0xef, 0x02, - 0x97, 0xf0, 0x50, 0x80, 0x54, 0x02, 0x89, 0x45, 0xbe, 0x99, 0xc5, 0x5e, 0x19, 0xc8, 0xc9, 0x60, - 0xc4, 0xcb, 0xbc, 0xa5, 0x2d, 0x21, 0xaa, 0xb7, 0x24, 0x58, 0xf5, 0x3f, 0x2a, 0x42, 0x45, 0x98, - 0x72, 0x77, 0x99, 0x07, 0x72, 0x45, 0x47, 0x0c, 0xe4, 0x5c, 0xe8, 0x2f, 0xac, 0xd9, 0x5b, 0xfd, - 0x9a, 0x4d, 0xf2, 0x03, 0x45, 0x6a, 0x96, 0xe9, 0xf3, 0xd1, 0x48, 0xfa, 0xcc, 0x4a, 0x7d, 0x2a, - 0x89, 0x3e, 0x99, 0x16, 0xe4, 0x1b, 0x50, 0xde, 0xee, 0x50, 0x4b, 0x46, 0x91, 0x8b, 0x19, 0xb5, - 0x50, 0x8d, 0x8f, 0xed, 0x2e, 0x37, 0xa6, 0x24, 0x87, 0x72, 0xd8, 0xa1, 0x96, 0x8e, 0x14, 0xca, - 0x6e, 0xf9, 0x9f, 0x12, 0x4c, 0xa9, 0xe8, 0xdc, 0x1a, 0x2b, 0xb6, 0x1d, 0xa8, 0xd6, 0x30, 0x6d, - 0x3b, 0xd0, 0x11, 0x4a, 0xee, 0x01, 0x6c, 0x45, 0x7b, 0xae, 0x63, 0x21, 0x4e, 0x31, 0x3b, 0xb0, - 0x3a, 0x08, 0x35, 0x38, 0xaa, 0x62, 0x13, 0x05, 0x99, 0xdc, 0x80, 0xca, 0x23, 0x3f, 0x64, 0xfc, - 0x8c, 0x94, 0x76, 0xc1, 0x03, 0x7b, 0x5f, 0xc2, 0xf4, 0x74, 0x94, 0x98, 0x50, 0x5d, 0x6d, 0xdb, - 0xf2, 0x70, 0x2b, 0xe3, 0xe1, 0xf6, 0xd6, 0x70, 0xe5, 0x16, 0x53, 0x3c, 0x71, 0xc6, 0x5d, 0x95, - 0xba, 0x9e, 0xb7, 0xda, 0xb6, 0x31, 0x70, 0xd6, 0x65, 0x5c, 0xb9, 0x33, 0x25, 0x31, 0x42, 0x9a, - 0x8f, 0x0c, 0x86, 0xa0, 0xcc, 0x99, 0x02, 0x09, 0x51, 0x9d, 0x29, 0x3d, 0x7b, 0xee, 0x42, 0xf5, - 0x59, 0x48, 0x77, 0x22, 0xcf, 0xa3, 0x2e, 0x06, 0xde, 0x4a, 0xa3, 0xc6, 0x65, 0x88, 0x42, 0x6a, - 0x30, 0x84, 0xaa, 0x32, 0xa4, 0xa8, 0xaa, 0x9f, 0x4c, 0x1c, 0xef, 0x27, 0xf3, 0xbb, 0x30, 0x93, - 0xd7, 0x72, 0xc8, 0x29, 0xb9, 0xa8, 0x9e, 0x92, 0x93, 0xcb, 0xb5, 0x4c, 0x97, 0x55, 0xbf, 0xdd, - 0x36, 0x3d, 0x41, 0xbe, 0xbb, 0xac, 0x9e, 0x9f, 0xdf, 0x2b, 0xc0, 0x4c, 0x7e, 0x94, 0x2c, 0xc2, - 0xb8, 0x3c, 0x3f, 0x0a, 0x78, 0x7e, 0x70, 0x57, 0x1f, 0x17, 0x27, 0x47, 0xee, 0xbc, 0x90, 0x58, - 0x5c, 0x03, 0xc9, 0xa1, 0x56, 0x5c, 0x28, 0x25, 0x1a, 0x58, 0x02, 0xa4, 0x27, 0x63, 0xa4, 0x0e, - 0xe3, 0x3a, 0x0d, 0x23, 0x97, 0xc9, 0x75, 0x07, 0xce, 0x36, 0x40, 0x88, 0x2e, 0x47, 0xea, 0xdf, - 0x06, 0xd8, 0xd9, 0xdc, 0xde, 0xa0, 0xdd, 0x2d, 0xd3, 0xc1, 0xb0, 0xb3, 0x4a, 0x03, 0x86, 0x62, - 0x4c, 0x89, 0xb0, 0x63, 0xd1, 0x80, 0xa9, 0x61, 0x87, 0x8f, 0x93, 0xeb, 0x50, 0xda, 0xa0, 0x5d, - 0xd4, 0x7a, 0xaa, 0x71, 0xae, 0x17, 0x6b, 0xd3, 0x07, 0x54, 0x09, 0x6f, 0x3a, 0x1f, 0xad, 0xff, - 0xb0, 0x08, 0x67, 0x39, 0xf6, 0x4a, 0xc4, 0xf6, 0xfd, 0xc0, 0x61, 0xdd, 0xd3, 0xbc, 0xe7, 0x3f, - 0xcc, 0xed, 0xf9, 0x37, 0x94, 0x85, 0x56, 0x35, 0x1c, 0x69, 0xeb, 0xff, 0x71, 0x19, 0xe6, 0x86, - 0x50, 0x91, 0x5b, 0x50, 0xde, 0xe9, 0x76, 0x92, 0x54, 0x8a, 0xbb, 0x72, 0x99, 0xdf, 0x31, 0x3e, - 0x8f, 0xb5, 0xa9, 0x04, 0x9d, 0x8f, 0xeb, 0x88, 0x45, 0x96, 0x61, 0x72, 0xd5, 0x8d, 0x42, 0x26, - 0xb3, 0x7c, 0x61, 0x2f, 0x4c, 0xf6, 0x2c, 0x01, 0x16, 0x69, 0xbe, 0x8a, 0x44, 0xde, 0x83, 0xa9, - 0xd5, 0x7d, 0x6a, 0x1d, 0x38, 0x5e, 0x6b, 0x83, 0x76, 0xc3, 0x5a, 0x69, 0xa1, 0x94, 0xac, 0x9f, - 0x25, 0xe1, 0xc6, 0x01, 0xed, 0x86, 0x7a, 0x0e, 0x8d, 0x7c, 0x00, 0x93, 0xdb, 0x4e, 0xcb, 0x4b, - 0xa8, 0xca, 0x48, 0x35, 0xcf, 0x33, 0x8f, 0x50, 0x80, 0x91, 0x48, 0xcd, 0x97, 0x15, 0x74, 0x9e, - 0xf7, 0xe9, 0xbe, 0x4b, 0x45, 0xba, 0x2c, 0xf3, 0xbe, 0x80, 0x03, 0xd4, 0xbc, 0x0f, 0x31, 0xc8, - 0x06, 0x4c, 0xf0, 0x8f, 0xc7, 0x66, 0xa7, 0x36, 0x8e, 0xe1, 0xe7, 0x82, 0x1a, 0x1c, 0x70, 0xa0, - 0xe3, 0x78, 0x2d, 0x35, 0x3e, 0xb8, 0xd4, 0x68, 0x9b, 0x1d, 0xd5, 0x35, 0x24, 0x22, 0xf9, 0x16, - 0x4c, 0x66, 0x9e, 0x1d, 0xd6, 0x26, 0x90, 0xe1, 0xf9, 0x8c, 0x61, 0x36, 0xd8, 0xd0, 0x24, 0xbf, - 0x4b, 0xcc, 0x0d, 0xb9, 0x2e, 0x46, 0x87, 0x93, 0xa8, 0x0a, 0x29, 0x9c, 0x72, 0x31, 0xac, 0xf2, - 0xca, 0x18, 0x56, 0x38, 0x29, 0x86, 0xd5, 0x75, 0x98, 0x54, 0x14, 0x13, 0x3b, 0xb6, 0xed, 0xa7, - 0xf9, 0xb4, 0xdc, 0xb1, 0x1c, 0xa2, 0xcb, 0x11, 0xa2, 0xc1, 0xd8, 0xa6, 0x6f, 0x99, 0xae, 0xdc, - 0xfa, 0xd5, 0x5e, 0xac, 0x8d, 0xb9, 0x1c, 0xa0, 0x0b, 0x78, 0xfd, 0x3f, 0x0a, 0x30, 0xbb, 0x15, - 0xf8, 0x87, 0x0e, 0x77, 0xfd, 0x1d, 0xff, 0x80, 0x7a, 0xbb, 0xb7, 0xc9, 0x7a, 0xb2, 0x0a, 0x05, - 0xa4, 0xba, 0xc3, 0xa9, 0x70, 0x15, 0x3e, 0x8f, 0xb5, 0xb7, 0x4f, 0xbc, 0x7c, 0xa2, 0xf5, 0x93, - 0x55, 0x52, 0xae, 0x2c, 0xc5, 0xd1, 0x73, 0xa0, 0x13, 0xae, 0x2c, 0x1a, 0x8c, 0xa1, 0xa8, 0x72, - 0x1b, 0xa3, 0x56, 0x8c, 0x03, 0x74, 0x01, 0x57, 0xf6, 0xcf, 0x8f, 0x8a, 0x03, 0xfa, 0x9d, 0xe2, - 0xc0, 0xf2, 0x51, 0x2e, 0xb0, 0x28, 0x97, 0xc9, 0xbc, 0x8a, 0x23, 0x45, 0x16, 0x13, 0xce, 0x0f, - 0xa3, 0xfa, 0x12, 0x17, 0xbf, 0xfe, 0xe7, 0x45, 0x98, 0xe1, 0xf7, 0x39, 0xc7, 0xc2, 0x09, 0xc2, - 0xd3, 0x6c, 0xfa, 0x5f, 0xcf, 0x99, 0xfe, 0xaa, 0x92, 0xea, 0x28, 0x0a, 0x8e, 0x64, 0xf8, 0x03, - 0x20, 0x83, 0x34, 0xe4, 0x19, 0x4c, 0xa9, 0x50, 0xb4, 0x7e, 0xee, 0xce, 0xd5, 0xbf, 0x4b, 0x1b, - 0x17, 0xe4, 0x2c, 0xd3, 0x21, 0xd2, 0x19, 0xb8, 0x03, 0x42, 0x3d, 0xc7, 0xa6, 0xfe, 0x67, 0x45, - 0x98, 0x56, 0xa2, 0xfa, 0x69, 0x5e, 0x81, 0xfb, 0xb9, 0x15, 0xb8, 0xa2, 0x9c, 0xaa, 0x99, 0x7e, - 0x23, 0x2d, 0xc0, 0x43, 0x38, 0x37, 0x40, 0xd2, 0x7f, 0x44, 0x16, 0x46, 0x38, 0x22, 0x45, 0xd2, - 0x22, 0xfe, 0x5f, 0xf5, 0xbd, 0xe7, 0x4e, 0x6b, 0xf7, 0xce, 0x57, 0x31, 0x69, 0x51, 0x35, 0x44, - 0x6b, 0xdd, 0x39, 0xc1, 0xc0, 0x3f, 0x18, 0x83, 0xb9, 0x21, 0x54, 0x64, 0x05, 0x66, 0xb7, 0x69, - 0x88, 0x82, 0x53, 0xcb, 0x0f, 0x6c, 0xc7, 0x6b, 0x49, 0x3b, 0xe1, 0xbd, 0x32, 0x14, 0x63, 0x46, - 0x90, 0x0c, 0xea, 0x03, 0xe8, 0x58, 0xc5, 0x11, 0x9c, 0xd7, 0x9b, 0xd2, 0x84, 0xa2, 0x8a, 0x23, - 0x17, 0x09, 0xab, 0x38, 0x09, 0x02, 0xd9, 0x84, 0xb9, 0xad, 0xc0, 0x3f, 0xea, 0x62, 0x86, 0x12, - 0xf2, 0xbb, 0x8b, 0x4c, 0x65, 0x38, 0x1d, 0x26, 0x25, 0x1d, 0x3e, 0x6c, 0x60, 0x42, 0x13, 0x1a, - 0xfc, 0x9a, 0x23, 0x72, 0x9a, 0x61, 0x64, 0xe4, 0x7d, 0x18, 0x5b, 0x89, 0x6c, 0x87, 0x49, 0x03, - 0x2b, 0xf9, 0x06, 0x82, 0x85, 0xaa, 0x8d, 0x69, 0x69, 0x9a, 0x31, 0x93, 0x03, 0x75, 0x41, 0x42, - 0x3e, 0xe6, 0x3e, 0xe7, 0x50, 0x8f, 0xad, 0xdb, 0x2e, 0xe5, 0x27, 0x9e, 0x1f, 0x31, 0x34, 0x75, - 0xa9, 0x71, 0xbd, 0x17, 0x6b, 0x73, 0xa2, 0x70, 0x61, 0x38, 0xb6, 0x4b, 0x0d, 0x26, 0x86, 0x73, - 0xd9, 0xfc, 0x20, 0x35, 0xf9, 0x36, 0x5c, 0x68, 0x3a, 0xa1, 0xe5, 0x7b, 0x1e, 0xb5, 0x98, 0x38, - 0x1a, 0x6d, 0x4c, 0xc8, 0xc5, 0xf5, 0x86, 0xb3, 0xbd, 0x64, 0xa7, 0x08, 0x86, 0x38, 0x53, 0x6d, - 0x83, 0xe7, 0xe8, 0x9f, 0xc7, 0x5a, 0xb9, 0xe1, 0xfb, 0xae, 0x3e, 0x9c, 0x03, 0x97, 0x36, 0xad, - 0x10, 0xaf, 0x7b, 0x8c, 0x06, 0x87, 0xa6, 0x2b, 0x4b, 0x84, 0x28, 0xed, 0x01, 0xa5, 0x1d, 0xc3, - 0xe4, 0xa3, 0x86, 0x23, 0x87, 0xf3, 0xd2, 0x0e, 0x50, 0x93, 0x07, 0x0a, 0xcb, 0x55, 0x3f, 0xf2, - 0xd8, 0x63, 0xf3, 0x08, 0x33, 0xa2, 0x92, 0xb8, 0x88, 0x29, 0x2c, 0x2d, 0x3e, 0x6c, 0xb4, 0xcd, - 0x23, 0x7d, 0x90, 0x84, 0xfc, 0x2a, 0x54, 0x31, 0x73, 0xe1, 0x19, 0x6e, 0xad, 0x8a, 0x9a, 0xf2, - 0x3d, 0x04, 0x98, 0xd5, 0x18, 0x66, 0xc4, 0xf6, 0x53, 0xe5, 0x32, 0xc4, 0xfa, 0x27, 0x25, 0x98, - 0x54, 0x16, 0x89, 0xdf, 0x5d, 0x94, 0xf4, 0x19, 0xef, 0x2e, 0x3c, 0x7d, 0x56, 0xef, 0x2e, 0x98, - 0x38, 0xdf, 0xe2, 0x39, 0x56, 0x8b, 0x6f, 0x3e, 0xe1, 0x6b, 0x58, 0x9f, 0x0d, 0x10, 0xa2, 0xd6, - 0x67, 0x05, 0x0e, 0xd9, 0x84, 0x59, 0x9c, 0x44, 0x7a, 0x6d, 0xf8, 0x4c, 0x5f, 0x97, 0xbe, 0xb6, - 0xd0, 0x8b, 0xb5, 0xab, 0xe8, 0x10, 0x86, 0xf4, 0xf2, 0xd0, 0x88, 0x02, 0x47, 0xe1, 0x31, 0x40, - 0x49, 0x7e, 0x5c, 0x80, 0x19, 0x04, 0xae, 0x1d, 0x52, 0x8f, 0x21, 0xb3, 0xb2, 0x2c, 0x22, 0xa4, - 0x15, 0xfd, 0x6d, 0x16, 0x38, 0x5e, 0x6b, 0x97, 0xdf, 0x17, 0xc3, 0xc6, 0x6f, 0x73, 0xcf, 0xfb, - 0x69, 0xac, 0xdd, 0x7d, 0xbd, 0xf7, 0x01, 0xc9, 0x24, 0xec, 0xc5, 0xda, 0xbc, 0x10, 0x91, 0xe2, - 0x84, 0x7d, 0x02, 0xf6, 0xc9, 0x42, 0x1e, 0x48, 0xe9, 0x76, 0xcc, 0x3d, 0x97, 0x62, 0xcc, 0x1c, - 0x43, 0x55, 0xaf, 0x65, 0x7c, 0x18, 0x1f, 0xc2, 0xb8, 0x39, 0xc0, 0x27, 0xa5, 0xaa, 0xff, 0x6f, - 0x41, 0xa9, 0xc2, 0x9f, 0xde, 0xf0, 0x79, 0x2f, 0x17, 0x3e, 0x2f, 0x65, 0xd4, 0xa9, 0x6e, 0x7c, - 0x78, 0x58, 0xe0, 0xac, 0x9f, 0x85, 0xe9, 0x1c, 0x52, 0xfd, 0x2f, 0x8b, 0x70, 0x5e, 0xa7, 0x21, - 0x65, 0x5b, 0x66, 0x18, 0xbe, 0xf0, 0x03, 0x5b, 0x1c, 0xf9, 0xa7, 0xf8, 0x70, 0x69, 0xe6, 0xac, - 0x53, 0x57, 0xae, 0x40, 0x03, 0x6a, 0x8e, 0x74, 0xc2, 0xfc, 0x6d, 0x01, 0x6a, 0xc7, 0x91, 0x72, - 0x2b, 0x3d, 0x0b, 0x69, 0xae, 0x3a, 0x16, 0x85, 0x34, 0xd0, 0x11, 0x4a, 0x2e, 0x43, 0xe9, 0x99, - 0xbe, 0x29, 0x2d, 0x34, 0xd1, 0x8b, 0xb5, 0x52, 0x14, 0xb8, 0x3a, 0x87, 0xf1, 0xcb, 0xca, 0x6a, - 0x40, 0xb1, 0xa2, 0x5e, 0x1e, 0xfd, 0xb2, 0x62, 0x09, 0x92, 0xfe, 0xcb, 0x8a, 0xe4, 0x54, 0xff, - 0x49, 0x11, 0xae, 0x0c, 0x11, 0x95, 0x5a, 0x01, 0x65, 0xe1, 0x69, 0x5e, 0xd3, 0x8d, 0xdc, 0x9a, - 0xde, 0x7c, 0xe5, 0x9a, 0x0a, 0x6d, 0x47, 0x5a, 0xda, 0x7f, 0x2d, 0x80, 0x76, 0x02, 0x07, 0x72, - 0x1d, 0xc6, 0x9f, 0xee, 0x6c, 0x6d, 0x24, 0xf5, 0x35, 0xa1, 0xa2, 0xdf, 0xc1, 0xc3, 0x5b, 0x97, - 0x43, 0xe4, 0x5d, 0x18, 0xff, 0x58, 0x5f, 0xf5, 0xed, 0xa4, 0xde, 0x81, 0x39, 0xc6, 0x77, 0x02, - 0xc3, 0xca, 0xbf, 0x0e, 0x49, 0x24, 0x75, 0xf1, 0x4b, 0x5f, 0xda, 0xe2, 0xf3, 0x0c, 0x71, 0xc5, - 0xb2, 0x68, 0x18, 0xea, 0xf4, 0x3b, 0x11, 0x0d, 0xd9, 0x57, 0x32, 0x43, 0xcc, 0x69, 0x38, 0xd2, - 0x22, 0xff, 0x73, 0x11, 0xe6, 0x86, 0x50, 0x9d, 0xb0, 0x75, 0xb5, 0xe4, 0x6a, 0xaa, 0x54, 0x33, - 0xf0, 0x6a, 0x9a, 0x54, 0x1b, 0x56, 0x92, 0x17, 0x46, 0x6e, 0x88, 0x19, 0xb5, 0xda, 0x9e, 0x4c, - 0xc3, 0x47, 0x5f, 0xf9, 0xf2, 0xf8, 0x8b, 0x88, 0x01, 0x6a, 0x15, 0x64, 0xec, 0xcb, 0xaa, 0x82, - 0xd4, 0xff, 0xb0, 0xd0, 0x67, 0xc3, 0x07, 0x8e, 0xcb, 0x68, 0x40, 0x2e, 0xe2, 0x83, 0xae, 0xb0, - 0xe0, 0x78, 0x2f, 0xd6, 0x8a, 0x8e, 0xad, 0x17, 0xd7, 0x9b, 0xa9, 0x6d, 0x8b, 0x43, 0x6d, 0xfb, - 0xf5, 0xd1, 0x4c, 0x87, 0x36, 0x47, 0xd3, 0x49, 0x83, 0xd5, 0x7f, 0x50, 0x84, 0xa9, 0x2d, 0x37, - 0x6a, 0x39, 0x5e, 0xd3, 0x64, 0xe6, 0x69, 0xf6, 0xef, 0x0f, 0x72, 0xfe, 0xad, 0x5e, 0xbd, 0x53, - 0xf5, 0x46, 0x72, 0xee, 0x1f, 0x15, 0xe0, 0x6c, 0x46, 0x22, 0x9e, 0x03, 0x36, 0xa0, 0xcc, 0xff, - 0x91, 0xd7, 0xfa, 0xeb, 0xc3, 0x78, 0x23, 0xe2, 0x62, 0xfa, 0x25, 0xb2, 0xd2, 0xbe, 0xd7, 0x31, - 0x64, 0x32, 0xff, 0x75, 0xa8, 0x66, 0x9c, 0x5f, 0xe7, 0x39, 0xfe, 0x1f, 0x0b, 0x30, 0xdb, 0xaf, - 0x0c, 0x79, 0x02, 0x13, 0x9c, 0x93, 0x43, 0x93, 0xa2, 0xc3, 0x3b, 0xc7, 0x6b, 0xbe, 0x28, 0x31, - 0x85, 0x84, 0xb8, 0x10, 0x54, 0x40, 0xf4, 0x84, 0xc9, 0xfc, 0x33, 0x98, 0x52, 0xb1, 0x86, 0x08, - 0xb8, 0x94, 0x7f, 0x09, 0xb9, 0x7c, 0xac, 0x35, 0x54, 0xd9, 0x7f, 0x9c, 0x93, 0x5d, 0xfa, 0xfa, - 0xa8, 0x4f, 0x9f, 0xcb, 0x50, 0x49, 0x1e, 0x4d, 0x55, 0xb7, 0x0b, 0x24, 0x2c, 0x57, 0x6e, 0x95, - 0x30, 0x9e, 0xfb, 0x8b, 0xf9, 0xa4, 0xdb, 0x61, 0xee, 0xdf, 0x41, 0x88, 0x7a, 0x7c, 0x08, 0x9c, - 0xfa, 0x5f, 0x97, 0xe0, 0x62, 0x26, 0x9e, 0x78, 0x08, 0xde, 0x32, 0x03, 0xb3, 0x1d, 0x9e, 0xb0, - 0x21, 0x6e, 0x0c, 0x88, 0x86, 0x4f, 0x6e, 0x89, 0x68, 0x8a, 0x40, 0xf5, 0x3e, 0x81, 0xb0, 0xe0, - 0x2b, 0x04, 0x4a, 0xc4, 0x20, 0x4f, 0xa0, 0xb4, 0x4d, 0x99, 0x7c, 0x90, 0xbb, 0x39, 0xcc, 0xb0, - 0xaa, 0x68, 0x8b, 0xdb, 0x94, 0x89, 0xa5, 0xc4, 0xba, 0x7e, 0x48, 0xd5, 0xd7, 0x1b, 0xce, 0x88, - 0xfc, 0x26, 0x8c, 0xaf, 0x1d, 0x75, 0xa8, 0xc5, 0x64, 0x03, 0xcb, 0xad, 0x13, 0x59, 0x0a, 0x74, - 0xa5, 0x9d, 0x85, 0x22, 0x40, 0x35, 0x99, 0x40, 0x99, 0xbf, 0x0b, 0x95, 0x64, 0xfe, 0xd7, 0xf1, - 0xe2, 0xf9, 0x7b, 0x30, 0xa9, 0x4c, 0xf2, 0x5a, 0x1b, 0xe0, 0x0f, 0x8a, 0x30, 0xce, 0x8f, 0x8a, - 0xd3, 0x1c, 0xa6, 0xee, 0xe6, 0xc2, 0xd4, 0xf9, 0xfc, 0xab, 0xc7, 0x48, 0x01, 0xea, 0xb3, 0x02, - 0x40, 0x86, 0x4c, 0xbe, 0x09, 0x13, 0x4f, 0xb1, 0x5d, 0x29, 0xe9, 0xb8, 0xe8, 0x7b, 0x49, 0x91, - 0x83, 0x8d, 0xcb, 0xc9, 0xc1, 0xe4, 0x0b, 0x80, 0x6a, 0x05, 0x89, 0x43, 0x1e, 0xc2, 0xd8, 0x8a, - 0xeb, 0xfa, 0x2f, 0x06, 0x1f, 0x39, 0x39, 0xa7, 0x55, 0xdf, 0xb3, 0x1d, 0xc1, 0xec, 0x92, 0x64, - 0x76, 0xd6, 0xe4, 0xe8, 0xea, 0x39, 0x8c, 0xf4, 0xfc, 0xc6, 0xd0, 0xa4, 0x5e, 0xd2, 0x39, 0x71, - 0x3c, 0x9f, 0x8b, 0x92, 0xcf, 0x8c, 0x4d, 0xbd, 0x6e, 0x2e, 0x52, 0x52, 0xaf, 0x5b, 0xff, 0x9b, - 0x31, 0xf1, 0x66, 0x92, 0x88, 0x77, 0x1f, 0xa6, 0x1e, 0xf8, 0xc1, 0x0b, 0x33, 0xb0, 0x57, 0x5a, - 0xd4, 0x13, 0x6f, 0x97, 0x15, 0x7c, 0x1c, 0x9f, 0x7e, 0x2e, 0xe0, 0x86, 0xc9, 0x07, 0xd2, 0x1a, - 0x42, 0x0e, 0x9d, 0x3c, 0x85, 0xe9, 0xc7, 0xe6, 0x91, 0xbc, 0xa4, 0xef, 0xec, 0x88, 0x5b, 0x44, - 0xa9, 0x71, 0xb3, 0x17, 0x6b, 0x97, 0xdb, 0xe6, 0x51, 0x72, 0xb7, 0x37, 0x18, 0x73, 0x8f, 0xe9, - 0xe2, 0xc9, 0xd3, 0x13, 0x17, 0x66, 0xb6, 0xfc, 0x80, 0xc9, 0x49, 0x1c, 0xaf, 0x25, 0xf5, 0x9d, - 0xcb, 0xf4, 0xe5, 0x62, 0xe0, 0x05, 0xbf, 0xb1, 0xf4, 0x32, 0xd6, 0x0a, 0x3f, 0x8d, 0x35, 0xe0, - 0x20, 0xa1, 0x11, 0x9f, 0x98, 0x5f, 0xe8, 0x8d, 0xe7, 0x29, 0x07, 0xf5, 0xaa, 0x9d, 0xe7, 0x4d, - 0xee, 0xc3, 0xb9, 0x55, 0x1a, 0x30, 0xe7, 0xb9, 0x63, 0x99, 0x8c, 0x3e, 0xf0, 0x83, 0xb6, 0xc9, - 0x64, 0x2b, 0x14, 0xb6, 0xfc, 0x59, 0x54, 0x70, 0x6a, 0x9b, 0x4c, 0x1f, 0xc4, 0x24, 0xbf, 0x75, - 0x7c, 0x0d, 0xeb, 0xdd, 0x5e, 0xac, 0xbd, 0x31, 0xa4, 0x86, 0x75, 0x8c, 0x15, 0x86, 0x54, 0xb3, - 0x5a, 0xaf, 0xae, 0x66, 0xdd, 0x96, 0x2f, 0x64, 0x6f, 0x1e, 0x53, 0xd1, 0xca, 0x4d, 0xf4, 0xca, - 0xda, 0xd6, 0x32, 0x94, 0x1a, 0x5b, 0x0f, 0xf0, 0x89, 0x4f, 0xd6, 0x65, 0xa8, 0xb7, 0x6f, 0x7a, - 0x16, 0xb5, 0xb3, 0xc2, 0xa3, 0x1a, 0x05, 0x1b, 0x5b, 0x0f, 0x88, 0x09, 0x73, 0x5b, 0x34, 0x68, - 0x3b, 0xec, 0x37, 0x6e, 0xdf, 0x56, 0xd6, 0xaa, 0x82, 0xa2, 0x2d, 0x49, 0xd1, 0xb4, 0x0e, 0xa2, - 0x18, 0x47, 0xb7, 0x6f, 0x0f, 0x5d, 0x8e, 0x54, 0xb0, 0x61, 0xbc, 0xea, 0xff, 0x56, 0x82, 0x99, - 0xbc, 0x6b, 0xf3, 0x78, 0xbf, 0xe9, 0xb7, 0x1c, 0x2f, 0x79, 0x8a, 0xc1, 0x78, 0xef, 0x22, 0x44, - 0x97, 0x23, 0xe4, 0x2d, 0x80, 0xb4, 0x76, 0x90, 0xe4, 0xc5, 0xb2, 0x87, 0x51, 0x19, 0x20, 0xbf, - 0x0b, 0xf0, 0xc4, 0xb7, 0xa9, 0x6c, 0xd7, 0x28, 0xc9, 0x5d, 0x9e, 0x56, 0x80, 0x44, 0x6f, 0x81, - 0xa8, 0x22, 0xbd, 0x23, 0xab, 0x48, 0xb2, 0xe9, 0xb0, 0x17, 0x6b, 0x17, 0x3c, 0xdf, 0xa6, 0x83, - 0x9d, 0x1a, 0x0a, 0x47, 0x72, 0x1f, 0xc6, 0xf4, 0xc8, 0xa5, 0x49, 0x27, 0xc8, 0x8c, 0xb2, 0x5d, - 0x23, 0x97, 0x66, 0x9b, 0x3d, 0x88, 0xfa, 0xdf, 0x72, 0x39, 0x80, 0x7c, 0x08, 0xb0, 0x11, 0xed, - 0xd1, 0x87, 0x81, 0x1f, 0x75, 0x92, 0xb7, 0x5f, 0xad, 0x17, 0x6b, 0x57, 0x0e, 0xa2, 0x3d, 0x1a, - 0x78, 0x94, 0xd1, 0xd0, 0x68, 0xe1, 0xa0, 0x3a, 0x7f, 0x46, 0x42, 0x74, 0x98, 0x90, 0x69, 0xaa, - 0xec, 0x8c, 0x7c, 0xf3, 0x98, 0xdb, 0x89, 0x12, 0x39, 0xf0, 0x3e, 0x18, 0x08, 0x70, 0xee, 0x4d, - 0x58, 0x80, 0xc8, 0x07, 0x50, 0xe5, 0x33, 0xf0, 0xec, 0x38, 0x94, 0xee, 0x82, 0xb5, 0x2d, 0x45, - 0x26, 0x9e, 0x3f, 0xe7, 0x9a, 0x57, 0x52, 0x82, 0x7a, 0x13, 0x2e, 0x1d, 0x33, 0x71, 0xf6, 0xc8, - 0x5d, 0x38, 0xe9, 0x91, 0xbb, 0xfe, 0x2f, 0x05, 0x28, 0x73, 0x13, 0x91, 0xf7, 0xa0, 0x9a, 0xe4, - 0x01, 0x09, 0xdd, 0xa5, 0x5e, 0xac, 0xcd, 0x25, 0x69, 0x42, 0x4e, 0x8a, 0x14, 0x93, 0x4f, 0xb5, - 0x4b, 0x83, 0xbd, 0xc4, 0x33, 0x70, 0xaa, 0x43, 0x0e, 0x50, 0xa7, 0x42, 0x0c, 0x8e, 0xfa, 0xad, - 0x7d, 0x1a, 0x24, 0x7d, 0x3f, 0x88, 0xfa, 0x82, 0x03, 0x54, 0x54, 0xc4, 0x20, 0x4b, 0x30, 0xb1, - 0x62, 0x89, 0x03, 0xa3, 0x8c, 0x7c, 0xd1, 0x94, 0xa6, 0x35, 0x70, 0x2a, 0x48, 0xac, 0xfa, 0x9b, - 0x50, 0x4d, 0xc3, 0x18, 0x3f, 0x9d, 0xf1, 0x43, 0x04, 0x5f, 0x5d, 0xfc, 0x83, 0x27, 0x33, 0xb7, - 0xdc, 0x69, 0x7e, 0xa1, 0x3a, 0xf6, 0x64, 0xe6, 0x8a, 0x8d, 0xf4, 0x34, 0xf5, 0xf7, 0xe3, 0x00, - 0x19, 0x32, 0xa1, 0x30, 0xf3, 0x74, 0xbd, 0xb9, 0xba, 0x6e, 0x53, 0x8f, 0x39, 0x2c, 0xcb, 0xd0, - 0x95, 0xbb, 0xc9, 0xda, 0x11, 0xa3, 0x81, 0x67, 0xba, 0x12, 0xa7, 0xdb, 0x78, 0x53, 0x4e, 0x70, - 0xd9, 0x77, 0x6c, 0xcb, 0x70, 0x52, 0x52, 0xf5, 0x5c, 0xc8, 0x33, 0xe5, 0xd3, 0x6c, 0xaf, 0x3c, - 0xde, 0x54, 0xa6, 0x29, 0x8e, 0x3e, 0x4d, 0x68, 0xb6, 0xdd, 0x63, 0xa6, 0xc9, 0x33, 0x25, 0x07, - 0x30, 0xfb, 0x10, 0x2b, 0xd3, 0xca, 0x44, 0xa5, 0x13, 0x27, 0xba, 0x2e, 0x27, 0xba, 0x22, 0xaa, - 0xda, 0xc3, 0xa7, 0x1a, 0x60, 0x9c, 0x6d, 0xb2, 0xf2, 0x89, 0x9d, 0x24, 0xdf, 0x2d, 0xc0, 0xf8, - 0x4e, 0x60, 0x3a, 0x2c, 0xb9, 0x9d, 0x1f, 0x13, 0x19, 0x3f, 0x96, 0x91, 0xf1, 0xbd, 0xd7, 0xac, - 0xaf, 0x0b, 0xde, 0x3c, 0x15, 0x66, 0xf8, 0xa5, 0xa6, 0xc2, 0x62, 0x8c, 0x3c, 0x84, 0x71, 0x7e, - 0x9b, 0x8e, 0x92, 0xc6, 0x6e, 0x25, 0x03, 0xc3, 0x40, 0x2f, 0x06, 0x1b, 0x35, 0x69, 0x8b, 0xd9, - 0x10, 0xff, 0x57, 0x19, 0x09, 0x0c, 0xb5, 0x91, 0x7e, 0xe2, 0xff, 0xd7, 0x48, 0x4f, 0x9e, 0x42, - 0x55, 0xd6, 0x2f, 0x1a, 0x5d, 0xd9, 0xbb, 0xa2, 0xa4, 0x25, 0xe9, 0x90, 0xd2, 0xcf, 0x27, 0x40, - 0x86, 0xda, 0xbc, 0xaa, 0x67, 0x3c, 0x88, 0xde, 0xff, 0x74, 0x93, 0x5b, 0xf8, 0x74, 0x48, 0x96, - 0xfa, 0xc4, 0xb3, 0x50, 0xf6, 0xac, 0xa3, 0xf2, 0xcc, 0x1e, 0x76, 0xbe, 0x5f, 0x80, 0xd9, 0x7e, - 0x97, 0x21, 0x1f, 0xc0, 0xe4, 0xaa, 0x38, 0xf8, 0xfd, 0x20, 0x2d, 0x85, 0xe0, 0x73, 0x9f, 0x95, - 0x80, 0x8d, 0x5c, 0x97, 0xbb, 0x8a, 0xce, 0xef, 0x8a, 0x7c, 0x0b, 0x7a, 0x59, 0xa7, 0x14, 0x46, - 0x98, 0x48, 0xc2, 0xd4, 0xbb, 0x62, 0x82, 0xa7, 0xec, 0xe0, 0x7f, 0x2a, 0xc2, 0xa4, 0xb2, 0x64, - 0xe4, 0x26, 0x54, 0xd6, 0xc3, 0x4d, 0xdf, 0x3a, 0xa0, 0xb6, 0xcc, 0x36, 0xf1, 0xd7, 0x12, 0x4e, - 0x68, 0xb8, 0x08, 0xd4, 0xd3, 0x61, 0xd2, 0x80, 0x69, 0xf1, 0xf5, 0x98, 0x86, 0xa1, 0xd9, 0x4a, - 0x66, 0xbf, 0xda, 0x8b, 0xb5, 0x9a, 0x40, 0x36, 0xda, 0x62, 0x44, 0x91, 0x21, 0x4f, 0x42, 0x7e, - 0x07, 0x40, 0x00, 0xf8, 0x2a, 0x8f, 0x50, 0xc8, 0x4c, 0xb6, 0xf1, 0x05, 0x39, 0x01, 0xcf, 0xdb, - 0xfa, 0x0a, 0x4e, 0x0a, 0x43, 0xec, 0x3b, 0xf7, 0xad, 0x83, 0xd1, 0x7f, 0xab, 0x91, 0xf5, 0x9d, - 0xfb, 0xd6, 0x81, 0x31, 0xbc, 0xa2, 0xa5, 0xb2, 0xac, 0xff, 0xbc, 0xa0, 0xb8, 0x1d, 0xf9, 0x18, - 0xaa, 0xe9, 0xd2, 0xc8, 0xcb, 0xc9, 0x45, 0xb5, 0x6f, 0x52, 0x0e, 0xe9, 0xf4, 0x79, 0xe3, 0x8a, - 0x4c, 0xc3, 0xe6, 0xd2, 0x35, 0xce, 0x79, 0x61, 0x02, 0x24, 0x1f, 0x41, 0x19, 0x6d, 0x73, 0x72, - 0x3b, 0x52, 0x12, 0xea, 0xcb, 0xdc, 0x28, 0x28, 0x29, 0x52, 0x92, 0x3b, 0xb2, 0x90, 0x26, 0xac, - 0x7b, 0x2e, 0x1f, 0xe6, 0xb9, 0x28, 0x69, 0x8c, 0xcf, 0xea, 0x6b, 0x8a, 0x87, 0xfc, 0x7e, 0x01, - 0xe6, 0x9e, 0x2d, 0x3f, 0xd0, 0x69, 0xcb, 0x09, 0x99, 0x48, 0x88, 0xf9, 0x25, 0x9a, 0x5c, 0x86, - 0x92, 0x6e, 0xbe, 0x90, 0xed, 0x94, 0xf8, 0x30, 0x11, 0x98, 0x2f, 0x74, 0x0e, 0x23, 0xb7, 0xa0, - 0xba, 0x41, 0xbb, 0x8f, 0x4c, 0xcf, 0x76, 0xa9, 0x6c, 0xa4, 0xc4, 0x57, 0xef, 0x03, 0xda, 0x35, - 0xf6, 0x11, 0xaa, 0x67, 0x08, 0x58, 0x27, 0x88, 0xf6, 0x36, 0xa8, 0xb8, 0x3c, 0x4d, 0xc9, 0x3a, - 0x41, 0xb4, 0x87, 0xc5, 0x71, 0x31, 0x52, 0xff, 0xbb, 0x22, 0xcc, 0xf6, 0xef, 0x38, 0xf2, 0x21, - 0x4c, 0x25, 0x45, 0xf7, 0x47, 0x66, 0xb8, 0x2f, 0x45, 0xb9, 0xd2, 0x8b, 0xb5, 0x4b, 0x1d, 0x09, - 0x37, 0xf6, 0xcd, 0x50, 0xdd, 0x8a, 0x39, 0x02, 0x7e, 0x36, 0xef, 0xc8, 0xc2, 0xbc, 0xb2, 0x73, - 0x98, 0xcf, 0x3a, 0x46, 0xbe, 0xe7, 0x33, 0x41, 0x23, 0x2d, 0x38, 0xdb, 0x67, 0x0b, 0x69, 0x56, - 0xa5, 0xbc, 0x3c, 0xc4, 0x58, 0x22, 0x13, 0x8b, 0x96, 0x9f, 0x1b, 0x81, 0x32, 0xa2, 0x4c, 0xd0, - 0xcf, 0x95, 0xdc, 0x03, 0x78, 0xb6, 0xfc, 0x00, 0x9f, 0x91, 0x69, 0x80, 0x8e, 0x3b, 0x2d, 0x9a, - 0xa2, 0x39, 0x13, 0x4b, 0x80, 0xd5, 0xe4, 0x32, 0x43, 0xae, 0x7b, 0x30, 0xa5, 0x7a, 0x1a, 0xcf, - 0x4f, 0x94, 0xc7, 0xe3, 0x4a, 0xd2, 0x7b, 0x29, 0x9f, 0x8c, 0x45, 0xf9, 0xb5, 0x38, 0x50, 0x7e, - 0xbd, 0x01, 0x95, 0x24, 0x40, 0xa9, 0xad, 0xd5, 0xf2, 0x38, 0xeb, 0xea, 0xe9, 0x68, 0xfd, 0x1d, - 0x98, 0x90, 0x9e, 0xf4, 0xea, 0xdf, 0x2f, 0xd5, 0xbf, 0x57, 0x84, 0xb3, 0x3a, 0xe5, 0x89, 0x8c, - 0x6c, 0x57, 0xfe, 0x4a, 0x36, 0xcd, 0xe6, 0x34, 0x3c, 0x3e, 0x8b, 0xaa, 0xff, 0xa4, 0x00, 0x73, - 0x43, 0x70, 0xbf, 0x48, 0x67, 0x0f, 0xb9, 0x0b, 0xd5, 0xa6, 0x63, 0xba, 0x2b, 0xb6, 0x1d, 0x24, - 0xb9, 0x33, 0x1e, 0x47, 0xb6, 0xc3, 0x4f, 0x23, 0x0e, 0x55, 0x83, 0x4b, 0x8a, 0x4a, 0xbe, 0x26, - 0x5d, 0xa3, 0x94, 0x1a, 0x37, 0x69, 0xcb, 0x05, 0x21, 0x53, 0xd6, 0x94, 0x5b, 0xff, 0x8b, 0x22, - 0x10, 0x01, 0x94, 0xde, 0xe5, 0xf8, 0xa7, 0xba, 0x39, 0xb1, 0x91, 0x5b, 0xc0, 0x05, 0xa5, 0x79, - 0xb6, 0x4f, 0xc9, 0x91, 0x32, 0xe1, 0xef, 0x17, 0xe1, 0xe2, 0x70, 0xc2, 0x2f, 0xb4, 0xa0, 0xb7, - 0xa0, 0x8a, 0x2d, 0x3d, 0x4a, 0xff, 0x33, 0x46, 0x50, 0xd1, 0xff, 0x83, 0xf8, 0x19, 0x02, 0x79, - 0x0e, 0xd3, 0x9b, 0x66, 0xc8, 0x1e, 0x51, 0x33, 0x60, 0x7b, 0xd4, 0x64, 0x23, 0x1c, 0xa4, 0xe9, - 0x2f, 0x84, 0xf0, 0x07, 0x56, 0xfb, 0x09, 0x65, 0xff, 0x2f, 0x84, 0x72, 0x6c, 0x53, 0x77, 0x29, - 0x9f, 0xec, 0x2e, 0x5f, 0xfb, 0x10, 0xa6, 0xd4, 0x97, 0x18, 0x52, 0x81, 0xf2, 0x93, 0xa7, 0x4f, - 0xd6, 0x66, 0xcf, 0x90, 0x49, 0x98, 0xd8, 0x5a, 0x7b, 0xd2, 0x5c, 0x7f, 0xf2, 0x70, 0xb6, 0x40, - 0xa6, 0xa0, 0xb2, 0xb2, 0xb5, 0xa5, 0x3f, 0xdd, 0x5d, 0x6b, 0xce, 0x16, 0x09, 0xc0, 0x78, 0x73, - 0xed, 0xc9, 0xfa, 0x5a, 0x73, 0xb6, 0xd4, 0x38, 0xff, 0xf2, 0xbf, 0xae, 0x9d, 0x79, 0xf9, 0xe9, - 0xb5, 0xc2, 0xbf, 0x7f, 0x7a, 0xad, 0xf0, 0x9f, 0x9f, 0x5e, 0x2b, 0x7c, 0xf2, 0xdf, 0xd7, 0xce, - 0xec, 0x8d, 0xa3, 0x2e, 0x77, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x23, 0x35, 0x4d, 0xa3, - 0x3a, 0x00, 0x00, +func init() { proto.RegisterFile("types.proto", fileDescriptor_types_4c8f0d072f915196) } + +var fileDescriptor_types_4c8f0d072f915196 = []byte{ + // 4264 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x3b, 0x5d, 0x6f, 0x1b, 0x49, + 0x72, 0x1e, 0x92, 0x92, 0xc8, 0x22, 0x25, 0xd3, 0x2d, 0x5b, 0xa6, 0xe5, 0x5d, 0x8f, 0x96, 0xce, + 0xee, 0xda, 0x17, 0xaf, 0x14, 0xcb, 0xb1, 0xef, 0xbc, 0x59, 0x67, 0x57, 0x14, 0x65, 0x5b, 0x27, + 0x59, 0xd6, 0x8e, 0x3e, 0x36, 0x97, 0xaf, 0xc9, 0x68, 0xa6, 0x4d, 0x0d, 0x34, 0x9c, 0xe1, 0xcd, + 0x0c, 0x65, 0xf3, 0xed, 0x90, 0x04, 0x08, 0x90, 0x03, 0xee, 0x12, 0x04, 0x87, 0x5b, 0x20, 0x07, + 0x24, 0x40, 0x1e, 0x92, 0x3c, 0x5c, 0x5e, 0x83, 0x3c, 0xe4, 0x21, 0x48, 0x1e, 0x8c, 0x00, 0x01, + 0xf2, 0x7c, 0xb8, 0xcc, 0x25, 0x9b, 0x87, 0x03, 0xf8, 0x07, 0x02, 0xec, 0x4b, 0x82, 0xae, 0xee, + 0x99, 0xe9, 0x21, 0x29, 0x8b, 0xde, 0xec, 0x3d, 0x68, 0x9f, 0x44, 0x55, 0x57, 0x55, 0x77, 0x55, + 0x57, 0x57, 0x57, 0x57, 0xd5, 0x40, 0x39, 0xec, 0x75, 0x68, 0xb0, 0xd8, 0xf1, 0xbd, 0xd0, 0x23, + 0xc5, 0x80, 0xfa, 0xc7, 0xb6, 0x49, 0x83, 0xf9, 0x8b, 0x2d, 0xaf, 0xe5, 0x21, 0x70, 0x89, 0xfd, + 0xe2, 0xe3, 0xf3, 0x6a, 0xcb, 0xf3, 0x5a, 0x0e, 0x5d, 0xc2, 0xff, 0x0e, 0xba, 0xcf, 0x96, 0x42, + 0xbb, 0x4d, 0x83, 0xd0, 0x68, 0x77, 0x04, 0xc2, 0x83, 0x96, 0x1d, 0x1e, 0x76, 0x0f, 0x16, 0x4d, + 0xaf, 0xbd, 0xd4, 0xf2, 0x8d, 0x63, 0x3b, 0x34, 0x42, 0xdb, 0x73, 0x0d, 0x67, 0x29, 0xa4, 0x0e, + 0xed, 0x78, 0x7e, 0xb8, 0xe4, 0xd8, 0x07, 0x4b, 0xcf, 0x7d, 0xa3, 0xd3, 0xa1, 0x7e, 0x90, 0xfc, + 0xe0, 0xe4, 0xf5, 0x9f, 0x2a, 0x50, 0xda, 0xa0, 0xb4, 0xb3, 0xe2, 0xd8, 0xc7, 0x94, 0x2c, 0x01, + 0xec, 0x50, 0xff, 0x98, 0xfa, 0x5b, 0x46, 0x9b, 0xd6, 0x94, 0x05, 0xe5, 0x46, 0xa9, 0x71, 0xbe, + 0x1f, 0xa9, 0xe5, 0x00, 0xa1, 0xba, 0x6b, 0xb4, 0xa9, 0x26, 0xa1, 0x90, 0x5f, 0x86, 0x12, 0xfb, + 0x1b, 0x74, 0x0c, 0x93, 0xd6, 0x72, 0x88, 0x3f, 0xdd, 0x8f, 0xd4, 0x92, 0x1b, 0x03, 0xb5, 0x74, + 0x9c, 0xbc, 0x03, 0x53, 0x9b, 0xd4, 0x08, 0xe8, 0x7a, 0xb3, 0x96, 0x5f, 0x50, 0x6e, 0xe4, 0x1b, + 0x95, 0x7e, 0xa4, 0x16, 0x1d, 0x06, 0xd2, 0x6d, 0x4b, 0x8b, 0x07, 0xc9, 0x3a, 0x4c, 0xad, 0xbd, + 0xe8, 0xd8, 0x3e, 0x0d, 0x6a, 0x85, 0x05, 0xe5, 0x46, 0x79, 0x79, 0x7e, 0x91, 0x6b, 0x61, 0x31, + 0xd6, 0xc2, 0xe2, 0x6e, 0xac, 0x85, 0xc6, 0xec, 0xcb, 0x48, 0x3d, 0xd7, 0x8f, 0xd4, 0x29, 0xca, + 0x49, 0xfe, 0xe4, 0x67, 0xaa, 0xa2, 0xc5, 0xf4, 0xf5, 0x3f, 0xce, 0x43, 0xf1, 0x09, 0x0d, 0x0d, + 0xcb, 0x08, 0x0d, 0xf2, 0x06, 0x14, 0x24, 0xb9, 0x8a, 0xfd, 0x48, 0x2d, 0xa0, 0x40, 0x08, 0x25, + 0xd7, 0x87, 0x45, 0x99, 0xe8, 0x47, 0xaa, 0xf2, 0x9e, 0x2c, 0xc2, 0xaf, 0x41, 0xb9, 0x49, 0x03, + 0xd3, 0xb7, 0x3b, 0x4c, 0xc9, 0x28, 0x46, 0xa9, 0x71, 0xa5, 0x1f, 0xa9, 0x97, 0xac, 0x14, 0x7c, + 0xcb, 0x6b, 0xdb, 0x21, 0x6d, 0x77, 0xc2, 0x9e, 0x26, 0x63, 0x93, 0x4d, 0x98, 0xdc, 0x34, 0x0e, + 0xa8, 0x13, 0xd4, 0x26, 0x16, 0xf2, 0x37, 0xca, 0xcb, 0xd7, 0x16, 0xe3, 0xcd, 0x5f, 0x8c, 0xd7, + 0xb8, 0xc8, 0x11, 0xd6, 0xdc, 0xd0, 0xef, 0x35, 0x2e, 0xf6, 0x23, 0xb5, 0xea, 0x20, 0x40, 0x62, + 0x29, 0x78, 0x90, 0x9d, 0x54, 0x4b, 0x93, 0xa7, 0x6a, 0xe9, 0xcd, 0x97, 0x91, 0xaa, 0xf4, 0x23, + 0xf5, 0x82, 0xd0, 0x52, 0xca, 0x2f, 0xa3, 0x2f, 0xb2, 0x00, 0xb9, 0xf5, 0x66, 0x6d, 0x0a, 0x77, + 0xa7, 0xda, 0x8f, 0xd4, 0x8a, 0x6d, 0x49, 0x53, 0xe7, 0xd6, 0x9b, 0xf3, 0xf7, 0xa1, 0x2c, 0xad, + 0x91, 0x54, 0x21, 0x7f, 0x44, 0x7b, 0x5c, 0xa5, 0x1a, 0xfb, 0x49, 0x2e, 0xc2, 0xc4, 0xb1, 0xe1, + 0x74, 0x85, 0x0e, 0x35, 0xfe, 0xcf, 0xfb, 0xb9, 0x6f, 0x28, 0xf5, 0x1f, 0x14, 0xa0, 0xa8, 0x79, + 0xdc, 0x3e, 0xc9, 0x4d, 0x98, 0xd8, 0x09, 0x8d, 0x30, 0xde, 0x8d, 0xd9, 0x7e, 0xa4, 0x9e, 0x0f, + 0x18, 0x40, 0x9a, 0x8f, 0x63, 0x30, 0xd4, 0xed, 0x43, 0x23, 0x88, 0x77, 0x05, 0x51, 0x3b, 0x0c, + 0x20, 0xa3, 0x22, 0x06, 0x79, 0x07, 0x0a, 0x4f, 0x3c, 0x8b, 0x8a, 0x8d, 0x21, 0xfd, 0x48, 0x9d, + 0x69, 0x7b, 0x96, 0x8c, 0x88, 0xe3, 0xe4, 0x16, 0x94, 0x56, 0xbb, 0xbe, 0x4f, 0xdd, 0x70, 0xbd, + 0x89, 0x46, 0x56, 0x6a, 0xcc, 0xf4, 0x23, 0x15, 0x4c, 0x0e, 0x64, 0xe6, 0x98, 0x22, 0x30, 0x55, + 0xef, 0x84, 0x86, 0x1f, 0x52, 0xab, 0x36, 0x31, 0x96, 0xaa, 0x99, 0x41, 0x5e, 0x08, 0x38, 0xc9, + 0xa0, 0xaa, 0x05, 0x27, 0xf2, 0x18, 0xca, 0x8f, 0x7c, 0xc3, 0xa4, 0xdb, 0xd4, 0xb7, 0x3d, 0x0b, + 0xf7, 0x30, 0xdf, 0x78, 0xa7, 0x1f, 0xa9, 0x73, 0x2d, 0x06, 0xd6, 0x3b, 0x08, 0x4f, 0xa9, 0x3f, + 0x8f, 0xd4, 0x62, 0xb3, 0xeb, 0xa3, 0xf6, 0x34, 0x99, 0x94, 0xfc, 0x1e, 0xdb, 0x92, 0x20, 0x44, + 0xd5, 0x52, 0x0b, 0x77, 0xef, 0xd5, 0x4b, 0xac, 0x8b, 0x25, 0xce, 0x39, 0x46, 0x10, 0xea, 0x3e, + 0xa7, 0x1b, 0x58, 0xa7, 0xcc, 0x92, 0x68, 0x50, 0xdc, 0x31, 0x0f, 0xa9, 0xd5, 0x75, 0x68, 0xad, + 0x28, 0xd8, 0x27, 0xb6, 0x1b, 0x6f, 0x69, 0x8c, 0xd1, 0x98, 0x17, 0xec, 0x49, 0x20, 0x20, 0x92, + 0xfa, 0x13, 0x3e, 0xef, 0x17, 0x3f, 0xfd, 0x4b, 0xf5, 0xdc, 0x77, 0x7e, 0xba, 0x70, 0xae, 0xfe, + 0xf7, 0x39, 0xa8, 0x0e, 0x32, 0x21, 0xcf, 0x60, 0x7a, 0xaf, 0x63, 0x19, 0x21, 0x5d, 0x75, 0x6c, + 0xea, 0x86, 0x01, 0xda, 0xc9, 0xab, 0xc5, 0xfa, 0x25, 0x31, 0x6f, 0xad, 0x8b, 0x84, 0xba, 0xc9, + 0x29, 0x07, 0x04, 0xcb, 0xb2, 0x4d, 0xe7, 0xe1, 0x5e, 0x2d, 0x40, 0x23, 0x7b, 0xbd, 0x79, 0xb8, + 0x73, 0x3c, 0x61, 0x1e, 0xc1, 0x56, 0xd8, 0x90, 0x6b, 0x1d, 0xf4, 0xd0, 0x38, 0xc7, 0xb7, 0x21, + 0x46, 0x32, 0xc2, 0x86, 0x18, 0xb8, 0xfe, 0x73, 0x05, 0x66, 0x34, 0x1a, 0x78, 0x5d, 0xdf, 0xa4, + 0x8f, 0xa9, 0x61, 0x51, 0x9f, 0x9d, 0x80, 0x0d, 0xdb, 0xb5, 0xc4, 0xb1, 0xc2, 0x13, 0x70, 0x64, + 0xbb, 0xf2, 0x29, 0xc6, 0x71, 0xf2, 0x2b, 0x30, 0xb5, 0xd3, 0x3d, 0x40, 0x54, 0x7e, 0xac, 0xe6, + 0x70, 0xc7, 0xba, 0x07, 0xfa, 0x00, 0x7a, 0x8c, 0x46, 0x96, 0x60, 0x6a, 0x9f, 0xfa, 0x41, 0xea, + 0xf7, 0x2e, 0xb1, 0x15, 0x1e, 0x73, 0x90, 0x4c, 0x20, 0xb0, 0xc8, 0x37, 0x53, 0xdf, 0x2b, 0x1c, + 0x39, 0x19, 0xf6, 0x78, 0xa9, 0xb5, 0xb4, 0x05, 0x44, 0xb6, 0x96, 0x18, 0xab, 0xfe, 0x47, 0x39, + 0x28, 0x72, 0x55, 0xee, 0x2f, 0x33, 0x47, 0x2e, 0xc9, 0x88, 0x8e, 0x9c, 0x2d, 0xfa, 0x0b, 0x4b, + 0xf6, 0xf6, 0xa0, 0x64, 0x65, 0x76, 0xa1, 0x08, 0xc9, 0x52, 0x79, 0x3e, 0x1a, 0x4b, 0x9e, 0xaa, + 0x90, 0xa7, 0x18, 0xcb, 0x93, 0x4a, 0x41, 0xbe, 0x01, 0x85, 0x9d, 0x0e, 0x35, 0x85, 0x17, 0x99, + 0x4b, 0xa9, 0xb9, 0x68, 0x6c, 0x6c, 0x7f, 0xb9, 0x51, 0x11, 0x1c, 0x0a, 0x41, 0x87, 0x9a, 0x1a, + 0x52, 0x48, 0xa7, 0xe5, 0x7f, 0xf2, 0x50, 0x91, 0xd1, 0x99, 0x36, 0x56, 0x2c, 0xcb, 0x97, 0xb5, + 0x61, 0x58, 0x96, 0xaf, 0x21, 0x94, 0xdc, 0x07, 0xd8, 0xee, 0x1e, 0x38, 0xb6, 0x89, 0x38, 0xb9, + 0xf4, 0xc2, 0xea, 0x20, 0x54, 0x67, 0xa8, 0x92, 0x4e, 0x24, 0x64, 0x72, 0x03, 0x8a, 0x8f, 0xbd, + 0x20, 0x64, 0x77, 0xa4, 0xd0, 0x0b, 0x5e, 0xd8, 0x87, 0x02, 0xa6, 0x25, 0xa3, 0xc4, 0x80, 0xd2, + 0x6a, 0xdb, 0x12, 0x97, 0x5b, 0x01, 0x2f, 0xb7, 0xb7, 0x47, 0x0b, 0xb7, 0x98, 0xe0, 0xf1, 0x3b, + 0xee, 0x0d, 0x21, 0xeb, 0x45, 0xb3, 0x6d, 0xe9, 0x43, 0x77, 0x5d, 0xca, 0x95, 0x19, 0x53, 0xec, + 0x23, 0x84, 0xfa, 0xc8, 0xb0, 0x0b, 0x4a, 0x8d, 0xc9, 0x17, 0x10, 0xd9, 0x98, 0x92, 0xbb, 0xe7, + 0x1e, 0x94, 0xf6, 0x02, 0xba, 0xdb, 0x75, 0x5d, 0xea, 0xa0, 0xe3, 0x2d, 0x36, 0x6a, 0x6c, 0x0d, + 0xdd, 0x80, 0xea, 0x21, 0x42, 0xe5, 0x35, 0x24, 0xa8, 0xb2, 0x9d, 0x4c, 0x9d, 0x6c, 0x27, 0xf3, + 0xfb, 0x30, 0x93, 0x95, 0x72, 0xc4, 0x2d, 0xb9, 0x28, 0xdf, 0x92, 0xe5, 0xe5, 0x5a, 0x2a, 0xcb, + 0xaa, 0xd7, 0x6e, 0x1b, 0x2e, 0x27, 0xdf, 0x5f, 0x96, 0xef, 0xcf, 0xef, 0x2a, 0x30, 0x93, 0x1d, + 0x25, 0x8b, 0x30, 0x29, 0xee, 0x0f, 0x05, 0xef, 0x0f, 0x66, 0xea, 0x93, 0xfc, 0xe6, 0xc8, 0xdc, + 0x17, 0x02, 0x8b, 0x49, 0x20, 0x38, 0xd4, 0x72, 0x0b, 0xf9, 0x58, 0x02, 0x93, 0x83, 0xb4, 0x78, + 0x8c, 0xd4, 0x61, 0x52, 0xa3, 0x41, 0xd7, 0x09, 0xc5, 0xbe, 0x03, 0x63, 0xeb, 0x23, 0x44, 0x13, + 0x23, 0xf5, 0x6f, 0x01, 0xec, 0x6e, 0xee, 0x6c, 0xd0, 0xde, 0xb6, 0x61, 0xa3, 0xdb, 0x59, 0xa5, + 0x7e, 0x88, 0xcb, 0xa8, 0x70, 0xb7, 0x63, 0x52, 0x3f, 0x94, 0xdd, 0x0e, 0x1b, 0x27, 0xd7, 0x21, + 0xbf, 0x41, 0x7b, 0x28, 0x75, 0xa5, 0x71, 0xa1, 0x1f, 0xa9, 0xd3, 0x47, 0x54, 0x72, 0x6f, 0x1a, + 0x1b, 0xad, 0xff, 0x20, 0x07, 0xe7, 0x19, 0xf6, 0x4a, 0x37, 0x3c, 0xf4, 0x7c, 0x3b, 0xec, 0x9d, + 0xe5, 0x33, 0xff, 0x61, 0xe6, 0xcc, 0xbf, 0x29, 0x6d, 0xb4, 0x2c, 0xe1, 0x58, 0x47, 0xff, 0x9f, + 0x27, 0x60, 0x76, 0x04, 0x15, 0xb9, 0x05, 0x85, 0xdd, 0x5e, 0x27, 0x0e, 0xa5, 0x98, 0x29, 0x17, + 0xd8, 0x1b, 0xe3, 0xf3, 0x48, 0xad, 0xc4, 0xe8, 0x6c, 0x5c, 0x43, 0x2c, 0xb2, 0x0c, 0xe5, 0x55, + 0xa7, 0x1b, 0x84, 0x22, 0xca, 0xe7, 0xfa, 0xc2, 0x60, 0xcf, 0xe4, 0x60, 0x1e, 0xe6, 0xcb, 0x48, + 0xe4, 0x2e, 0x54, 0x56, 0x0f, 0xa9, 0x79, 0x64, 0xbb, 0xad, 0x0d, 0xda, 0x0b, 0x6a, 0xf9, 0x85, + 0x7c, 0xbc, 0x7f, 0xa6, 0x80, 0xeb, 0x47, 0xb4, 0x17, 0x68, 0x19, 0x34, 0xf2, 0x01, 0x94, 0x77, + 0xec, 0x96, 0x1b, 0x53, 0x15, 0x90, 0x6a, 0x9e, 0x45, 0x1e, 0x01, 0x07, 0x23, 0x91, 0x1c, 0x2f, + 0x4b, 0xe8, 0x2c, 0xee, 0xd3, 0x3c, 0x87, 0xf2, 0x70, 0x59, 0xc4, 0x7d, 0x3e, 0x03, 0xc8, 0x71, + 0x1f, 0x62, 0x90, 0x0d, 0x98, 0x62, 0x3f, 0x9e, 0x18, 0x9d, 0xda, 0x24, 0xba, 0x9f, 0x4b, 0xb2, + 0x73, 0xc0, 0x81, 0x8e, 0xed, 0xb6, 0x64, 0xff, 0xe0, 0x50, 0xbd, 0x6d, 0x74, 0x64, 0xd3, 0x10, + 0x88, 0xe4, 0x13, 0x28, 0xa7, 0x96, 0x1d, 0xd4, 0xa6, 0x90, 0xe1, 0xc5, 0x94, 0x61, 0x3a, 0xd8, + 0x50, 0x05, 0xbf, 0xcb, 0xa1, 0x13, 0x30, 0x59, 0xf4, 0x0e, 0x23, 0x91, 0x05, 0x92, 0x38, 0x65, + 0x7c, 0x58, 0xf1, 0x95, 0x3e, 0x4c, 0x39, 0xd5, 0x87, 0xb5, 0x00, 0x84, 0xae, 0x56, 0x9c, 0x56, + 0xad, 0xb4, 0xa0, 0xdc, 0x98, 0x59, 0xbe, 0xf5, 0x4a, 0xe3, 0x5a, 0x4c, 0xf1, 0x99, 0x1d, 0xf0, + 0x5b, 0x20, 0xde, 0x07, 0xc3, 0x69, 0xc9, 0xb7, 0x40, 0x8a, 0x5a, 0x7f, 0x0a, 0x33, 0x59, 0x42, + 0x52, 0x86, 0xa9, 0xbd, 0xad, 0x8d, 0xad, 0xa7, 0x9f, 0x6c, 0x55, 0xcf, 0x91, 0x0a, 0x14, 0xb5, + 0x9d, 0x15, 0x7d, 0xe7, 0xf1, 0xca, 0xed, 0xaa, 0x42, 0xaa, 0x50, 0x11, 0xff, 0x2d, 0xeb, 0xcb, + 0x77, 0xef, 0x55, 0x73, 0x19, 0xc8, 0xdd, 0xdb, 0xcb, 0xd5, 0x7c, 0x5d, 0x83, 0xb2, 0xb4, 0x25, + 0xdc, 0xd7, 0xb4, 0xbd, 0xe4, 0x25, 0x20, 0x7c, 0x0d, 0x83, 0x68, 0x62, 0x84, 0xa8, 0x30, 0xb1, + 0xe9, 0x99, 0x86, 0x23, 0x9c, 0x56, 0xa9, 0x1f, 0xa9, 0x13, 0x0e, 0x03, 0x68, 0x1c, 0x5e, 0xff, + 0x0f, 0x05, 0xaa, 0xdb, 0xbe, 0x77, 0x6c, 0xb3, 0x43, 0xbb, 0xeb, 0x1d, 0x51, 0x77, 0xff, 0x36, + 0x59, 0x8f, 0xed, 0x47, 0x41, 0xaa, 0x3b, 0x8c, 0x0a, 0xed, 0xe7, 0xf3, 0x48, 0x7d, 0xe7, 0xd4, + 0x67, 0x33, 0xda, 0x4d, 0x6c, 0x5f, 0xd2, 0x63, 0x2b, 0x37, 0x7e, 0xf4, 0x76, 0xca, 0x63, 0x4b, + 0x85, 0x09, 0x5c, 0xaa, 0x70, 0x40, 0x28, 0x55, 0xc8, 0x00, 0x1a, 0x87, 0x4b, 0x27, 0xff, 0x87, + 0xb9, 0x21, 0xf9, 0xce, 0xb0, 0x4b, 0xfc, 0x28, 0xe3, 0x12, 0xa5, 0x67, 0x70, 0x56, 0xc4, 0xb1, + 0x7c, 0xa2, 0x01, 0x17, 0x47, 0x51, 0x7d, 0x89, 0x9b, 0x5f, 0xff, 0xb3, 0x1c, 0xcc, 0xb0, 0x97, + 0xa8, 0x6d, 0xe2, 0x04, 0xc1, 0x59, 0x56, 0xfd, 0xaf, 0x67, 0x54, 0xff, 0x86, 0x14, 0xa4, 0x49, + 0x02, 0x8e, 0xa5, 0xf8, 0x23, 0x20, 0xc3, 0x34, 0x64, 0x0f, 0x2a, 0x32, 0x14, 0xb5, 0x9f, 0x79, + 0x2d, 0x0e, 0x9e, 0xd2, 0xc6, 0x25, 0x31, 0xcb, 0x74, 0x80, 0x74, 0x3a, 0x9e, 0x80, 0x40, 0xcb, + 0xb0, 0xa9, 0xff, 0x69, 0x0e, 0xa6, 0xa5, 0xfb, 0xe8, 0x2c, 0xef, 0xc0, 0x83, 0xcc, 0x0e, 0x5c, + 0x95, 0x5c, 0x76, 0x2a, 0xdf, 0x58, 0x1b, 0xf0, 0x08, 0x2e, 0x0c, 0x91, 0x0c, 0x5e, 0xee, 0xca, + 0x18, 0x97, 0x3b, 0x0f, 0xb7, 0xf8, 0xff, 0xab, 0x9e, 0xfb, 0xcc, 0x6e, 0xed, 0xdf, 0xf9, 0x2a, + 0x86, 0x5b, 0xb2, 0x84, 0xa8, 0xad, 0x3b, 0xa7, 0x28, 0xf8, 0xfb, 0x2c, 0xdc, 0x1a, 0xa6, 0x22, + 0x2b, 0x50, 0xdd, 0xa1, 0x01, 0x2e, 0x9c, 0x9a, 0x9e, 0x6f, 0xd9, 0x6e, 0x4b, 0xe8, 0x09, 0x5f, + 0xc4, 0x01, 0x1f, 0xd3, 0xfd, 0x78, 0x50, 0x1b, 0x42, 0xc7, 0xfc, 0x13, 0xe7, 0xbc, 0xde, 0x14, + 0x2a, 0xe4, 0xf9, 0x27, 0xb1, 0x49, 0x98, 0x7f, 0x8a, 0x11, 0xc8, 0x26, 0xcc, 0x6e, 0xfb, 0xde, + 0x8b, 0x1e, 0xc6, 0x56, 0x01, 0x7b, 0x75, 0x89, 0x20, 0x8c, 0xd1, 0x61, 0x38, 0xd5, 0x61, 0xc3, + 0x3a, 0x86, 0x62, 0x81, 0xce, 0x1e, 0x68, 0x3c, 0x1a, 0x1b, 0x45, 0x46, 0xde, 0x87, 0x89, 0x95, + 0xae, 0x65, 0x87, 0x42, 0xc1, 0x52, 0xa4, 0x84, 0x60, 0x2e, 0x6a, 0x63, 0x5a, 0xa8, 0x66, 0xc2, + 0x60, 0x40, 0x8d, 0x93, 0x90, 0x8f, 0x99, 0xcd, 0xd9, 0xd4, 0x0d, 0xd7, 0x2d, 0x87, 0xb2, 0x1b, + 0xcf, 0xeb, 0x86, 0xa8, 0xea, 0x7c, 0xe3, 0x7a, 0x3f, 0x52, 0x67, 0x79, 0xca, 0x45, 0xb7, 0x2d, + 0x87, 0xea, 0x21, 0x1f, 0xce, 0xbc, 0x43, 0x86, 0xa9, 0xc9, 0xb7, 0xe0, 0x52, 0xd3, 0x0e, 0x4c, + 0xcf, 0x75, 0xa9, 0x19, 0xf2, 0xab, 0xd1, 0xc2, 0xa7, 0x04, 0x7f, 0x98, 0x31, 0xb6, 0x97, 0xad, + 0x04, 0x41, 0xe7, 0x77, 0xaa, 0xa5, 0xb3, 0xd7, 0xc5, 0xe7, 0x91, 0x5a, 0x68, 0x78, 0x9e, 0xa3, + 0x8d, 0xe6, 0xc0, 0x56, 0x9b, 0xe4, 0xb6, 0xd7, 0xdd, 0x90, 0xfa, 0xc7, 0x86, 0x23, 0x92, 0x9b, + 0xb8, 0xda, 0x23, 0x4a, 0x3b, 0xba, 0xc1, 0x46, 0x75, 0x5b, 0x0c, 0x67, 0x57, 0x3b, 0x44, 0x4d, + 0x1e, 0x4a, 0x2c, 0x57, 0xbd, 0xae, 0x1b, 0x3e, 0x31, 0x5e, 0x60, 0x2c, 0x97, 0xe7, 0x4f, 0x48, + 0x89, 0xa5, 0xc9, 0x86, 0xf5, 0xb6, 0xf1, 0x42, 0x1b, 0x26, 0x21, 0xbf, 0x0a, 0x25, 0x8c, 0x5c, + 0x58, 0x8c, 0x86, 0xd1, 0x5b, 0x11, 0xcf, 0x10, 0x60, 0x54, 0xa3, 0x1b, 0xdd, 0xf0, 0x30, 0x11, + 0x2e, 0x45, 0xac, 0x7f, 0x9a, 0x87, 0xb2, 0xb4, 0x49, 0xec, 0xd5, 0x25, 0x05, 0xfe, 0xf8, 0xea, + 0x62, 0x81, 0xbf, 0xfc, 0xea, 0xc2, 0x88, 0xed, 0x16, 0x8b, 0xb1, 0x5a, 0xec, 0xf0, 0x71, 0x5b, + 0xc3, 0xcc, 0xb2, 0x8f, 0x10, 0x39, 0xb3, 0xcc, 0x71, 0xc8, 0x26, 0x54, 0x71, 0x12, 0x61, 0xb5, + 0xc1, 0x9e, 0xb6, 0x2e, 0x6c, 0x6d, 0xa1, 0x1f, 0xa9, 0x6f, 0xa0, 0x41, 0xe8, 0xc2, 0xca, 0x03, + 0xbd, 0xeb, 0xdb, 0x12, 0x8f, 0x21, 0x4a, 0xf2, 0x23, 0x05, 0x66, 0x10, 0xb8, 0x76, 0x4c, 0xdd, + 0x10, 0x99, 0x15, 0x44, 0xfa, 0x23, 0xa9, 0x45, 0xec, 0x84, 0xbe, 0xed, 0xb6, 0xf6, 0xd9, 0x4b, + 0x37, 0x68, 0xfc, 0x36, 0xb3, 0xbc, 0x9f, 0x44, 0xea, 0xbd, 0xd7, 0xab, 0x6c, 0x08, 0x26, 0x41, + 0x3f, 0x52, 0xe7, 0xf9, 0x12, 0x29, 0x4e, 0x38, 0xb0, 0xc0, 0x81, 0xb5, 0x90, 0x87, 0x62, 0x75, + 0xbb, 0xc6, 0x81, 0x43, 0xd1, 0x67, 0x4e, 0xa0, 0xa8, 0xd7, 0x52, 0x3e, 0x21, 0x1b, 0x42, 0xbf, + 0x39, 0xc4, 0x27, 0xa1, 0xaa, 0xff, 0xaf, 0x22, 0xd5, 0x0f, 0xce, 0xae, 0xfb, 0xbc, 0x9f, 0x71, + 0x9f, 0x97, 0x53, 0xea, 0x44, 0x36, 0x36, 0x3c, 0xca, 0x71, 0xd6, 0xcf, 0xc3, 0x74, 0x06, 0xa9, + 0xfe, 0x17, 0x39, 0xb8, 0xa8, 0xd1, 0x80, 0x86, 0xdb, 0x46, 0x10, 0x3c, 0xf7, 0x7c, 0x8b, 0x5f, + 0xf9, 0x67, 0xf8, 0x72, 0x69, 0x66, 0xb4, 0x53, 0x97, 0x1e, 0x6f, 0x43, 0x62, 0x8e, 0x75, 0xc3, + 0xfc, 0x8d, 0x02, 0xb5, 0x93, 0x48, 0x99, 0x96, 0xf6, 0x02, 0x9a, 0xc9, 0xeb, 0x75, 0x03, 0xea, + 0x6b, 0x08, 0x25, 0x57, 0x20, 0xbf, 0xa7, 0x6d, 0x0a, 0x0d, 0x4d, 0xf5, 0x23, 0x35, 0xdf, 0xf5, + 0x1d, 0x8d, 0xc1, 0xd8, 0x63, 0x65, 0xd5, 0xa7, 0x58, 0x0b, 0x28, 0x8c, 0xff, 0x58, 0x31, 0x39, + 0xc9, 0xe0, 0x63, 0x45, 0x70, 0xaa, 0xff, 0x38, 0x07, 0x57, 0x47, 0x2c, 0x95, 0x9a, 0x3e, 0x0d, + 0x83, 0xb3, 0xbc, 0xa7, 0x1b, 0x99, 0x3d, 0xbd, 0xf9, 0xca, 0x3d, 0xe5, 0xd2, 0x8e, 0xb5, 0xb5, + 0xff, 0xaa, 0x80, 0x7a, 0x0a, 0x07, 0x72, 0x1d, 0x26, 0x9f, 0xee, 0x6e, 0x6f, 0xc4, 0x99, 0x41, + 0x2e, 0xa2, 0xd7, 0xc1, 0xcb, 0x5b, 0x13, 0x43, 0xe4, 0x3d, 0x98, 0xfc, 0x58, 0x5b, 0xf5, 0xac, + 0x38, 0x53, 0x83, 0x31, 0xc6, 0xb7, 0x7d, 0xdd, 0xcc, 0xd6, 0xb5, 0x04, 0x92, 0xbc, 0xf9, 0xf9, + 0x2f, 0x6d, 0xf3, 0x59, 0x84, 0xb8, 0x62, 0x9a, 0x34, 0x08, 0x34, 0xfa, 0xed, 0x2e, 0x0d, 0xc2, + 0xaf, 0x64, 0x84, 0x98, 0x91, 0x70, 0xac, 0x4d, 0xfe, 0xa7, 0x1c, 0xcc, 0x8e, 0xa0, 0x3a, 0xe5, + 0xe8, 0xaa, 0xf1, 0xd3, 0x54, 0xca, 0x66, 0xe0, 0xd3, 0x34, 0xce, 0x36, 0xac, 0xc4, 0xb5, 0xd1, + 0x3c, 0xa6, 0x75, 0xe6, 0x64, 0x9b, 0xe4, 0xd3, 0xb0, 0xd1, 0x57, 0xd6, 0x4c, 0x7f, 0x11, 0x3e, + 0x40, 0xce, 0x82, 0x4c, 0x7c, 0x59, 0x59, 0x90, 0xfa, 0x1f, 0x2a, 0x03, 0x3a, 0x7c, 0x68, 0x3b, + 0x21, 0xf5, 0xc9, 0x1c, 0x96, 0xa2, 0xb9, 0x06, 0x27, 0xfb, 0x91, 0x9a, 0xb3, 0x2d, 0x2d, 0xb7, + 0xde, 0x4c, 0x74, 0x9b, 0x1b, 0xa9, 0xdb, 0xaf, 0x8f, 0xa7, 0x3a, 0xd4, 0x39, 0xaa, 0x4e, 0x28, + 0xac, 0xfe, 0xfd, 0x1c, 0x54, 0xb6, 0x9d, 0x6e, 0xcb, 0x76, 0x9b, 0x46, 0x68, 0x9c, 0x65, 0xfb, + 0xfe, 0x20, 0x63, 0xdf, 0xf2, 0xd3, 0x3b, 0x11, 0x6f, 0x2c, 0xe3, 0xfe, 0xa1, 0x02, 0xe7, 0x53, + 0x12, 0x5e, 0xc8, 0xd8, 0x80, 0x02, 0xfb, 0x47, 0x3c, 0xeb, 0xaf, 0x8f, 0xe2, 0x8d, 0x88, 0x8b, + 0xc9, 0x2f, 0x1e, 0x95, 0x0e, 0xd4, 0xf5, 0x90, 0xc9, 0xfc, 0xd7, 0xa1, 0x94, 0x72, 0x7e, 0x9d, + 0x46, 0x82, 0x7f, 0x50, 0xa0, 0x3a, 0x28, 0x0c, 0xd9, 0x82, 0x29, 0xc6, 0xc9, 0xa6, 0x71, 0xd2, + 0xe1, 0xdd, 0x93, 0x25, 0x5f, 0x14, 0x98, 0x7c, 0x85, 0xb8, 0x11, 0x94, 0x43, 0xb4, 0x98, 0xc9, + 0xfc, 0x1e, 0x54, 0x64, 0xac, 0x11, 0x0b, 0x5c, 0xca, 0xd6, 0x70, 0xae, 0x9c, 0xa8, 0x0d, 0x79, + 0xed, 0x3f, 0xca, 0xac, 0x5d, 0xd8, 0xfa, 0xb8, 0x45, 0xdb, 0x65, 0x28, 0xc6, 0xe5, 0x5e, 0xd9, + 0xec, 0x7c, 0x01, 0xcb, 0x24, 0x8a, 0x05, 0x8c, 0xc5, 0xfe, 0x7c, 0x3e, 0x61, 0x76, 0x18, 0xfb, + 0x77, 0x10, 0x22, 0x5f, 0x1f, 0x1c, 0xa7, 0xfe, 0x57, 0x79, 0x98, 0x4b, 0x97, 0xc7, 0x4b, 0xd8, + 0xdb, 0x86, 0x6f, 0xb4, 0x83, 0x53, 0x0e, 0xc4, 0x8d, 0xa1, 0xa5, 0x61, 0xb1, 0x30, 0x5e, 0x9a, + 0xb4, 0xa0, 0xfa, 0xc0, 0x82, 0x30, 0xe1, 0xcb, 0x17, 0x14, 0x2f, 0x83, 0x6c, 0x41, 0x7e, 0x87, + 0x86, 0xa2, 0x94, 0x78, 0x73, 0x94, 0x62, 0xe5, 0xa5, 0x2d, 0xee, 0xd0, 0x90, 0x6f, 0x25, 0x56, + 0x24, 0x02, 0x2a, 0xd7, 0x9d, 0x18, 0x23, 0xf2, 0x9b, 0x30, 0xb9, 0xf6, 0xa2, 0x43, 0xcd, 0x50, + 0xb4, 0xde, 0xdc, 0x3a, 0x95, 0x25, 0x47, 0x97, 0x1a, 0x71, 0x28, 0x02, 0x64, 0x95, 0x71, 0x94, + 0xf9, 0x7b, 0x50, 0x8c, 0xe7, 0x7f, 0x1d, 0x2b, 0x9e, 0xbf, 0x0f, 0x65, 0x69, 0x92, 0xd7, 0x3a, + 0x00, 0x7f, 0x90, 0x83, 0x49, 0x76, 0x55, 0x9c, 0x65, 0x37, 0x75, 0x2f, 0xe3, 0xa6, 0x2e, 0x66, + 0xeb, 0x35, 0x63, 0x39, 0xa8, 0x9f, 0x2b, 0x00, 0x29, 0x32, 0xf9, 0x26, 0x4c, 0x3d, 0xc5, 0x46, + 0xab, 0xb8, 0x57, 0x64, 0xa0, 0x06, 0x24, 0x06, 0x1b, 0x57, 0xe2, 0x8b, 0xc9, 0xe3, 0x00, 0x59, + 0x0b, 0x02, 0x87, 0x3c, 0x82, 0x89, 0x15, 0xc7, 0xf1, 0x9e, 0x0f, 0x97, 0x67, 0x19, 0xa7, 0x55, + 0xcf, 0xb5, 0x6c, 0xce, 0xec, 0xb2, 0x60, 0x76, 0xde, 0x60, 0xe8, 0xf2, 0x3d, 0x8c, 0xf4, 0xec, + 0xc5, 0xd0, 0xa4, 0x6e, 0xdc, 0xf3, 0x71, 0x32, 0x9f, 0x39, 0xc1, 0x67, 0xc6, 0xa2, 0x6e, 0x2f, + 0xe3, 0x29, 0xa9, 0xdb, 0xab, 0xff, 0xf5, 0x04, 0xaf, 0x99, 0xc4, 0xcb, 0x7b, 0x00, 0x95, 0x87, + 0x9e, 0xff, 0xdc, 0xf0, 0xad, 0x95, 0x16, 0x75, 0x79, 0xd5, 0xb5, 0x88, 0x05, 0x9d, 0xe9, 0x67, + 0x1c, 0xae, 0x1b, 0x6c, 0x20, 0xc9, 0x21, 0x64, 0xd0, 0xc9, 0x53, 0x98, 0x7e, 0x62, 0xbc, 0x10, + 0x8f, 0xf4, 0xdd, 0x5d, 0xfe, 0x8a, 0xc8, 0x37, 0x6e, 0xf6, 0x23, 0xf5, 0x4a, 0xdb, 0x78, 0x11, + 0xbf, 0xed, 0xf5, 0x30, 0x74, 0x4e, 0xe8, 0x3f, 0xca, 0xd2, 0x13, 0x07, 0x66, 0xb6, 0x3d, 0x3f, + 0x14, 0x93, 0xd8, 0x6e, 0x4b, 0xc8, 0x3b, 0x9b, 0xca, 0xcb, 0x96, 0x81, 0x0f, 0xfc, 0xc6, 0xd2, + 0xcb, 0x48, 0x55, 0x7e, 0x12, 0xa9, 0xc0, 0x40, 0x5c, 0x22, 0x36, 0x31, 0x7b, 0xd0, 0xeb, 0xcf, + 0x12, 0x0e, 0xf2, 0x53, 0x3b, 0xcb, 0x9b, 0x3c, 0x80, 0x0b, 0xab, 0xd4, 0x0f, 0xed, 0x67, 0xb6, + 0x69, 0x84, 0xf4, 0xa1, 0xe7, 0xb7, 0x8d, 0x50, 0x34, 0x71, 0x61, 0xb3, 0xa2, 0x49, 0x39, 0xa7, + 0xb6, 0x11, 0x6a, 0xc3, 0x98, 0xe4, 0xb7, 0x4e, 0xce, 0x61, 0xbd, 0xd7, 0x8f, 0xd4, 0x37, 0x47, + 0xe4, 0xb0, 0x4e, 0xd0, 0xc2, 0x88, 0x6c, 0x56, 0xeb, 0xd5, 0xd9, 0xac, 0xdb, 0xa2, 0xb6, 0xf7, + 0xd6, 0x09, 0x19, 0xad, 0xcc, 0x44, 0xaf, 0xcc, 0x6d, 0x2d, 0x43, 0xbe, 0xb1, 0xfd, 0x10, 0x8b, + 0x93, 0x22, 0x2f, 0x43, 0xdd, 0x43, 0xc3, 0x35, 0xa9, 0x95, 0x26, 0x1e, 0x65, 0x2f, 0xd8, 0xd8, + 0x7e, 0x48, 0x0c, 0x98, 0xdd, 0xa6, 0x7e, 0xdb, 0x0e, 0x7f, 0xe3, 0xf6, 0x6d, 0x69, 0xaf, 0x8a, + 0xb8, 0xb4, 0x25, 0xb1, 0x34, 0xb5, 0x83, 0x28, 0xfa, 0x8b, 0xdb, 0xb7, 0x47, 0x6e, 0x47, 0xb2, + 0xb0, 0x51, 0xbc, 0xea, 0xff, 0x96, 0x87, 0x99, 0xac, 0x69, 0x33, 0x7f, 0xbf, 0xe9, 0xb5, 0x6c, + 0x37, 0x2e, 0xc5, 0xa0, 0xbf, 0x77, 0x10, 0xa2, 0x89, 0x11, 0xf2, 0x36, 0x40, 0x92, 0x3b, 0x88, + 0xe3, 0x62, 0xd1, 0x7d, 0x29, 0x0d, 0x90, 0xdf, 0x05, 0xd8, 0xf2, 0x2c, 0x2a, 0x1a, 0x4d, 0xf2, + 0xe2, 0x94, 0x27, 0x19, 0x20, 0xde, 0x15, 0xc1, 0xb3, 0x48, 0xef, 0x8a, 0x2c, 0x92, 0x68, 0x97, + 0xec, 0x47, 0xea, 0x25, 0xd7, 0xb3, 0xe8, 0x70, 0x8f, 0x89, 0xc4, 0x91, 0x3c, 0x80, 0x09, 0xad, + 0xeb, 0xd0, 0xb8, 0x87, 0x65, 0x46, 0x3a, 0xae, 0x5d, 0x87, 0xa6, 0x87, 0xdd, 0xef, 0x0e, 0x56, + 0xa1, 0x19, 0x80, 0x7c, 0x08, 0xb0, 0xd1, 0x3d, 0xa0, 0x8f, 0x7c, 0xaf, 0xdb, 0x89, 0xab, 0xd6, + 0x6a, 0x3f, 0x52, 0xaf, 0x1e, 0x75, 0x0f, 0xa8, 0xef, 0xd2, 0x90, 0x06, 0x7a, 0x0b, 0x07, 0xe5, + 0xf9, 0x53, 0x12, 0xa2, 0xc1, 0x94, 0x08, 0x53, 0x45, 0x4f, 0xe7, 0x5b, 0x27, 0xbc, 0x4e, 0x24, + 0xcf, 0x81, 0xef, 0x41, 0x9f, 0x83, 0x33, 0xd5, 0x6c, 0x0e, 0x22, 0x1f, 0x40, 0x89, 0xcd, 0xc0, + 0xa2, 0xe3, 0x40, 0x98, 0x0b, 0xe6, 0xb6, 0xa4, 0x35, 0xb1, 0xf8, 0x39, 0xd3, 0x76, 0x93, 0x10, + 0xd4, 0x9b, 0x70, 0xf9, 0x84, 0x89, 0xd3, 0xf2, 0xbc, 0x72, 0x5a, 0x79, 0xbe, 0xfe, 0x2f, 0x0a, + 0x14, 0x98, 0x8a, 0xc8, 0x5d, 0x28, 0xc5, 0x71, 0x40, 0x4c, 0x77, 0xb9, 0x1f, 0xa9, 0xb3, 0x71, + 0x98, 0x90, 0x59, 0x45, 0x82, 0xc9, 0xa6, 0xda, 0xa7, 0xfe, 0x41, 0x6c, 0x19, 0x38, 0xd5, 0x31, + 0x03, 0xc8, 0x53, 0x21, 0x06, 0x43, 0xfd, 0xe4, 0x90, 0xfa, 0x71, 0xc7, 0x12, 0xa2, 0x3e, 0x67, + 0x00, 0x19, 0x15, 0x31, 0xc8, 0x12, 0x4c, 0xad, 0x98, 0xfc, 0xc2, 0x28, 0x20, 0x5f, 0x54, 0xa5, + 0x61, 0x0e, 0xdd, 0x0a, 0x02, 0xab, 0xfe, 0x16, 0x94, 0x12, 0x37, 0xc6, 0x6e, 0x67, 0xfc, 0xc1, + 0x9d, 0xaf, 0xc6, 0xff, 0xc1, 0x9b, 0x99, 0x69, 0xee, 0x2c, 0x57, 0xa8, 0x4e, 0xbc, 0x99, 0x99, + 0x60, 0x63, 0x95, 0xa6, 0xfe, 0x6e, 0x12, 0x20, 0x45, 0x26, 0x14, 0x66, 0x9e, 0xae, 0x37, 0x57, + 0xd7, 0x2d, 0xea, 0x86, 0x76, 0x98, 0x46, 0xe8, 0xd2, 0xdb, 0x64, 0xed, 0x45, 0x48, 0x7d, 0xd7, + 0x70, 0x04, 0x4e, 0xaf, 0xf1, 0x96, 0x98, 0xe0, 0x8a, 0x67, 0x5b, 0xa6, 0x6e, 0x27, 0xa4, 0xf2, + 0xbd, 0x90, 0x65, 0xca, 0xa6, 0xd9, 0x59, 0x79, 0xb2, 0x29, 0x4d, 0x93, 0x1b, 0x7f, 0x9a, 0xc0, + 0x68, 0x3b, 0x27, 0x4c, 0x93, 0x65, 0x4a, 0x8e, 0xa0, 0xfa, 0x08, 0x33, 0xd3, 0xd2, 0x44, 0xf9, + 0x53, 0x27, 0xba, 0x2e, 0x26, 0xba, 0xca, 0xb3, 0xda, 0xa3, 0xa7, 0x1a, 0x62, 0x9c, 0x1e, 0xb2, + 0xc2, 0xa9, 0x3d, 0x30, 0xdf, 0x51, 0x60, 0x72, 0xd7, 0x37, 0xec, 0x30, 0x7e, 0x9d, 0x9f, 0xe0, + 0x19, 0x3f, 0x16, 0x9e, 0xf1, 0xee, 0x6b, 0xe6, 0xd7, 0x39, 0x6f, 0x16, 0x0a, 0x87, 0xf8, 0x4b, + 0x0e, 0x85, 0xf9, 0x18, 0x79, 0x04, 0x93, 0xec, 0x35, 0xdd, 0x8d, 0x5b, 0xd2, 0xa5, 0x08, 0x0c, + 0x1d, 0x3d, 0x1f, 0x6c, 0xd4, 0x84, 0x2e, 0xaa, 0x01, 0xfe, 0x2f, 0x33, 0xe2, 0x18, 0xf2, 0x27, + 0x00, 0x53, 0xff, 0xbf, 0x4f, 0x00, 0xc8, 0x53, 0x28, 0x89, 0xfc, 0x45, 0xa3, 0x27, 0xba, 0x6e, + 0xa4, 0xb0, 0x24, 0x19, 0x92, 0x3a, 0x11, 0x39, 0x48, 0x97, 0xdb, 0x6e, 0xb5, 0x94, 0x07, 0xd1, + 0x06, 0x4b, 0x37, 0x99, 0x8d, 0x4f, 0x86, 0x44, 0xaa, 0x8f, 0x97, 0x85, 0xd2, 0xb2, 0x8e, 0xcc, + 0x33, 0x2d, 0xec, 0x7c, 0x4f, 0x81, 0xea, 0xa0, 0xc9, 0x90, 0x0f, 0xa0, 0xbc, 0xca, 0x2f, 0x7e, + 0xcf, 0x4f, 0x52, 0x21, 0x58, 0xee, 0x33, 0x63, 0xb0, 0x9e, 0xe9, 0xcf, 0x97, 0xd1, 0xd9, 0x5b, + 0x91, 0x1d, 0x41, 0x37, 0xed, 0xf1, 0x42, 0x0f, 0xd3, 0x15, 0x30, 0xf9, 0xad, 0x18, 0xe3, 0x49, + 0x27, 0xf8, 0x1f, 0x73, 0x50, 0x96, 0xb6, 0x8c, 0xdc, 0x84, 0xe2, 0x7a, 0xb0, 0xe9, 0x99, 0x47, + 0xd4, 0x12, 0xd1, 0x26, 0x7e, 0xe7, 0x61, 0x07, 0xba, 0x83, 0x40, 0x2d, 0x19, 0x26, 0x0d, 0x98, + 0xe6, 0xbf, 0x9e, 0xd0, 0x20, 0x30, 0x5a, 0xf1, 0xec, 0x6f, 0xf4, 0x23, 0xb5, 0xc6, 0x91, 0xf5, + 0x36, 0x1f, 0x91, 0xd6, 0x90, 0x25, 0x21, 0xbf, 0x03, 0xc0, 0x01, 0x6c, 0x97, 0xc7, 0x48, 0x64, + 0xc6, 0xc7, 0xf8, 0x92, 0x98, 0x80, 0xc5, 0x6d, 0x03, 0x09, 0x27, 0x89, 0x21, 0x76, 0xcc, 0x7b, + 0xe6, 0xd1, 0xf8, 0x5f, 0x99, 0xa4, 0x1d, 0xf3, 0x9e, 0x79, 0xa4, 0x8f, 0xce, 0x68, 0xc9, 0x2c, + 0xeb, 0x3f, 0x53, 0x24, 0xb3, 0x23, 0x1f, 0x43, 0x29, 0xd9, 0x1a, 0xf1, 0x38, 0x99, 0x93, 0x3b, + 0x3e, 0xc5, 0x90, 0x46, 0x9f, 0x35, 0xae, 0x8a, 0x30, 0x6c, 0x36, 0xd9, 0xe3, 0x8c, 0x15, 0xc6, + 0x40, 0xf2, 0x11, 0x14, 0x50, 0x37, 0xa7, 0xb7, 0x23, 0xc5, 0xae, 0xbe, 0xc0, 0x94, 0x82, 0x2b, + 0x45, 0x4a, 0x72, 0x47, 0x24, 0xd2, 0xb8, 0x76, 0x2f, 0x64, 0xdd, 0x3c, 0x5b, 0x4a, 0xe2, 0xe3, + 0xd3, 0xfc, 0x9a, 0x64, 0x21, 0xbf, 0xaf, 0xc0, 0xec, 0xde, 0xf2, 0x43, 0x8d, 0xb6, 0xec, 0x20, + 0xe4, 0x01, 0x31, 0x7b, 0x44, 0x93, 0x2b, 0x90, 0xd7, 0x8c, 0xe7, 0xa2, 0x11, 0x14, 0x0b, 0x13, + 0xbe, 0xf1, 0x5c, 0x63, 0x30, 0x72, 0x0b, 0x4a, 0x1b, 0xb4, 0xf7, 0xd8, 0x70, 0x2d, 0x87, 0x8a, + 0x16, 0x50, 0xac, 0x7a, 0x1f, 0xd1, 0x9e, 0x7e, 0x88, 0x50, 0x2d, 0x45, 0xc0, 0x3c, 0x41, 0xf7, + 0x60, 0x83, 0xf2, 0xc7, 0x53, 0x45, 0xe4, 0x09, 0xba, 0x07, 0x98, 0x1c, 0xe7, 0x23, 0xf5, 0xbf, + 0xcd, 0x41, 0x75, 0xf0, 0xc4, 0x91, 0x0f, 0xa1, 0x12, 0x27, 0xdd, 0x1f, 0x1b, 0xc1, 0xa1, 0x58, + 0xca, 0xd5, 0x7e, 0xa4, 0x5e, 0xee, 0x08, 0xb8, 0x7e, 0x68, 0x04, 0xf2, 0x51, 0xcc, 0x10, 0xb0, + 0xbb, 0x79, 0x57, 0x24, 0xe6, 0xa5, 0x93, 0x13, 0x7a, 0x61, 0x47, 0xcf, 0x76, 0xab, 0xc6, 0x68, + 0xa4, 0x05, 0xe7, 0x07, 0x74, 0x21, 0xd4, 0x2a, 0xa5, 0x97, 0x47, 0x28, 0x8b, 0x47, 0x62, 0xdd, + 0xe5, 0x67, 0xba, 0x2f, 0x8d, 0x48, 0x13, 0x0c, 0x72, 0x25, 0xf7, 0x01, 0xf6, 0x96, 0x1f, 0x62, + 0x19, 0x99, 0xfa, 0x68, 0xb8, 0xd3, 0xbc, 0x91, 0x8f, 0x31, 0x31, 0x39, 0x58, 0x0e, 0x2e, 0x53, + 0xe4, 0xba, 0x0b, 0x15, 0xd9, 0xd2, 0x58, 0x7c, 0x22, 0x15, 0x8f, 0x8b, 0x71, 0xd7, 0xa8, 0x28, + 0x19, 0xf3, 0xf4, 0x6b, 0x6e, 0x28, 0xfd, 0x7a, 0x03, 0x8a, 0xb1, 0x83, 0x92, 0x9b, 0xc2, 0xc5, + 0x75, 0xd6, 0xd3, 0x92, 0xd1, 0xfa, 0xbb, 0x30, 0x25, 0x2c, 0xe9, 0xd5, 0x5f, 0x5e, 0xd5, 0xbf, + 0x9b, 0x83, 0xf3, 0x1a, 0x65, 0x81, 0x8c, 0x68, 0xb4, 0xfe, 0x4a, 0xb6, 0xfb, 0x66, 0x24, 0x3c, + 0x39, 0x8a, 0xaa, 0xff, 0x58, 0x81, 0xd9, 0x11, 0xb8, 0x5f, 0xa4, 0xb3, 0x87, 0xdc, 0x83, 0x52, + 0xd3, 0x36, 0x9c, 0x15, 0xcb, 0xf2, 0xe3, 0xd8, 0x19, 0xaf, 0x23, 0xcb, 0x66, 0xb7, 0x11, 0x83, + 0xca, 0xce, 0x25, 0x41, 0x25, 0x5f, 0x13, 0xa6, 0x91, 0x4f, 0x94, 0x1b, 0x37, 0x14, 0x03, 0x5f, + 0x53, 0xda, 0x4e, 0x5c, 0xff, 0xf3, 0x1c, 0x10, 0x0e, 0x14, 0xd6, 0x65, 0x7b, 0x67, 0xba, 0x39, + 0xb1, 0x91, 0xd9, 0xc0, 0x05, 0xa9, 0xed, 0x77, 0x40, 0xc8, 0xb1, 0x22, 0xe1, 0xef, 0xe5, 0x60, + 0x6e, 0x34, 0xe1, 0x17, 0xda, 0xd0, 0x5b, 0x50, 0xc2, 0x96, 0x1e, 0xa9, 0x73, 0x1b, 0x3d, 0x28, + 0xef, 0xff, 0x41, 0xfc, 0x14, 0x81, 0x3c, 0x83, 0xe9, 0x4d, 0x23, 0x08, 0x1f, 0x53, 0xc3, 0x0f, + 0x0f, 0xa8, 0x11, 0x8e, 0x71, 0x91, 0x26, 0xdf, 0x36, 0xe1, 0xa7, 0x61, 0x87, 0x31, 0xe5, 0xe0, + 0xb7, 0x4d, 0x19, 0xb6, 0x89, 0xb9, 0x14, 0x4e, 0x37, 0x97, 0xaf, 0x7d, 0x08, 0x15, 0xb9, 0x12, + 0x43, 0x8a, 0x50, 0xd8, 0x7a, 0xba, 0xb5, 0x56, 0x3d, 0x47, 0xca, 0x30, 0xb5, 0xbd, 0xb6, 0xd5, + 0x5c, 0xdf, 0x7a, 0x54, 0x55, 0x48, 0x05, 0x8a, 0x2b, 0xdb, 0xdb, 0xda, 0xd3, 0xfd, 0xb5, 0x66, + 0x35, 0x47, 0x00, 0x26, 0x9b, 0x6b, 0x5b, 0xeb, 0x6b, 0xcd, 0x6a, 0xbe, 0x71, 0xf1, 0xe5, 0x7f, + 0x5d, 0x3b, 0xf7, 0xf2, 0xb3, 0x6b, 0xca, 0xbf, 0x7f, 0x76, 0x4d, 0xf9, 0xcf, 0xcf, 0xae, 0x29, + 0x9f, 0xfe, 0xf7, 0xb5, 0x73, 0x07, 0x93, 0x28, 0xcb, 0x9d, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, + 0xa5, 0x50, 0xe0, 0x04, 0x5d, 0x3b, 0x00, 0x00, } diff --git a/lib/services/types.proto b/lib/services/types.proto index 123214e25cca0..c341a48a7f385 100644 --- a/lib/services/types.proto +++ b/lib/services/types.proto @@ -221,6 +221,15 @@ message CertAuthoritySpecV2 { // Rotation is a status of the certificate authority rotation Rotation Rotation = 8 [ (gogoproto.nullable) = true, (gogoproto.jsontag) = "rotation,omitempty" ]; + // SigningAlg is the algorithm used for signing new SSH certificates using + // SigningKeys. + enum SigningAlgType { + UNKNOWN = 0; + RSA_SHA1 = 1; + RSA_SHA2_256 = 2; + RSA_SHA2_512 = 3; + } + SigningAlgType SigningAlg = 9 [ (gogoproto.jsontag) = "signing_alg,omitempty" ]; } // RoleMappping provides mapping of remote roles to local roles diff --git a/lib/sshutils/signer.go b/lib/sshutils/signer.go index 1746cd4df766d..ed8228ee20032 100644 --- a/lib/sshutils/signer.go +++ b/lib/sshutils/signer.go @@ -18,6 +18,7 @@ package sshutils import ( "crypto" + "io" "golang.org/x/crypto/ssh" @@ -59,3 +60,48 @@ func CryptoPublicKey(publicKey []byte) (crypto.PublicKey, error) { } return cryptoPubKey.CryptoPublicKey(), nil } + +// AlgSigner wraps a provided ssh.Signer to ensure signature algorithm +// compatibility with OpenSSH. +// +// Right now it allows forcing SHA-2 signatures with RSA keys, instead of the +// default SHA-1 used by x/crypto/ssh. See +// https://www.openssh.com/txt/release-8.2 for context. +// +// If the provided Signer is not an RSA key or does not implement +// ssh.AlgorithmSigner, it's returned as is. +// +// DELETE IN 5.0: assuming https://github.com/golang/go/issues/37278 is fixed +// by then and we pull in the fix. Also delete all call sites. +func AlgSigner(s ssh.Signer, alg string) ssh.Signer { + if alg == "" { + return s + } + if s.PublicKey().Type() != ssh.KeyAlgoRSA && s.PublicKey().Type() != ssh.CertAlgoRSAv01 { + return s + } + as, ok := s.(ssh.AlgorithmSigner) + if !ok { + return s + } + return fixedAlgorithmSigner{ + AlgorithmSigner: as, + alg: alg, + } +} + +type fixedAlgorithmSigner struct { + ssh.AlgorithmSigner + alg string +} + +func (s fixedAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, alg string) (*ssh.Signature, error) { + if alg == "" { + alg = s.alg + } + return s.AlgorithmSigner.SignWithAlgorithm(rand, data, alg) +} + +func (s fixedAlgorithmSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { + return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.alg) +} diff --git a/lib/sshutils/signer_test.go b/lib/sshutils/signer_test.go new file mode 100644 index 0000000000000..ea490f54132b4 --- /dev/null +++ b/lib/sshutils/signer_test.go @@ -0,0 +1,76 @@ +package sshutils + +import ( + "io" + + "github.com/gravitational/teleport/lib/defaults" + "golang.org/x/crypto/ssh" + "gopkg.in/check.v1" +) + +type AlgSignerSuite struct{} + +var _ = check.Suite(&AlgSignerSuite{}) + +func (s *AlgSignerSuite) TestAlgSignerNoop(c *check.C) { + sig := newMockSigner(ssh.KeyAlgoECDSA521) + + // ECDSA key should be returned as-is, not wrapped. + c.Assert(AlgSigner(sig, defaults.CASignatureAlgorithm), check.Equals, sig) +} + +func (s *AlgSignerSuite) TestAlgSigner(c *check.C) { + for _, pubType := range []string{ssh.KeyAlgoRSA, ssh.CertAlgoRSAv01} { + c.Logf("signer public key type: %q", pubType) + rsaSigner := newMockSigner(pubType) + + wrapped := AlgSigner(rsaSigner, defaults.CASignatureAlgorithm) + // RSA key or cert should get wrapped. + c.Assert(wrapped, check.Not(check.Equals), rsaSigner) + wrappedAS := wrapped.(ssh.AlgorithmSigner) + + // Simple Sign call should use the enforced SHA-2 algorithm. + wrapped.Sign(nil, nil) + c.Assert(rsaSigner.lastAlg, check.Equals, defaults.CASignatureAlgorithm) + rsaSigner.lastAlg = "" + + // SignWithAlgorithm without specifying an algorithm should use the + // enforced SHA-2 algorithm. + wrappedAS.SignWithAlgorithm(nil, nil, "") + c.Assert(rsaSigner.lastAlg, check.Equals, defaults.CASignatureAlgorithm) + rsaSigner.lastAlg = "" + + // SignWithAlgorithm *with* an algorithm should respect the provided + // algorithm. + wrappedAS.SignWithAlgorithm(nil, nil, "foo") + c.Assert(rsaSigner.lastAlg, check.Equals, "foo") + } +} + +type mockSigner struct { + ssh.Signer + lastAlg string + pubType string +} + +func newMockSigner(pubType string) *mockSigner { + return &mockSigner{pubType: pubType} +} + +func (s *mockSigner) PublicKey() ssh.PublicKey { + return mockPublicKey{pubType: s.pubType} +} + +func (s *mockSigner) SignWithAlgorithm(rand io.Reader, data []byte, alg string) (*ssh.Signature, error) { + s.lastAlg = alg + return nil, nil +} + +type mockPublicKey struct { + ssh.PublicKey + pubType string +} + +func (p mockPublicKey) Type() string { + return p.pubType +}