diff --git a/api/client/client.go b/api/client/client.go index f69903807b00d..aecdd1922b5e0 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -479,7 +479,7 @@ func (c *Client) dialGRPC(ctx context.Context, addr string) error { otelUnaryClientInterceptor(), metadata.UnaryClientInterceptor, interceptors.GRPCClientUnaryErrorInterceptor, - interceptors.WithMFAUnaryInterceptor(c.performMFACeremony), + interceptors.WithMFAUnaryInterceptor(c.performAdminActionMFACeremony), breaker.UnaryClientInterceptor(cb), ), grpc.WithChainStreamInterceptor( diff --git a/api/client/mfa.go b/api/client/mfa.go index cc81ca66405d6..a4538f2913c77 100644 --- a/api/client/mfa.go +++ b/api/client/mfa.go @@ -23,17 +23,19 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/mfa" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" ) -// performMFACeremony retrieves an MFA challenge from the server, prompts the -// user to answer the challenge, and returns the resulting MFA response. -func (c *Client) performMFACeremony(ctx context.Context, promptOpts ...mfa.PromptOpt) (*proto.MFAAuthenticateResponse, error) { +// performAdminActionMFACeremony retrieves an MFA challenge from the server, +// prompts the user to answer the challenge, and returns the resulting MFA response. +func (c *Client) performAdminActionMFACeremony(ctx context.Context, promptOpts ...mfa.PromptOpt) (*proto.MFAAuthenticateResponse, error) { if c.c.MFAPromptConstructor == nil { return nil, trace.BadParameter("missing PromptAdminRequestMFA field, client cannot perform MFA ceremony") } chal, err := c.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{}, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, }) if err != nil { return nil, trace.Wrap(err) diff --git a/api/client/mfa_test.go b/api/client/mfa_test.go index 22ae22d69cd40..9550c4f4b2d2c 100644 --- a/api/client/mfa_test.go +++ b/api/client/mfa_test.go @@ -70,7 +70,7 @@ func TestPerformMFACeremony(t *testing.T) { clt, err := New(ctx, cfg) require.NoError(t, err) - resp, err := clt.performMFACeremony(ctx) + resp, err := clt.performAdminActionMFACeremony(ctx) require.NoError(t, err) require.Equal(t, mfaTestResp.Response, resp.Response) } diff --git a/api/client/proto/authservice.pb.go b/api/client/proto/authservice.pb.go index 630a9f5ce21f1..625dd6b439604 100644 --- a/api/client/proto/authservice.pb.go +++ b/api/client/proto/authservice.pb.go @@ -6042,10 +6042,19 @@ type MFAAuthenticateChallenge struct { // If `MFA_REQUIRED_NO` is returned then the server may opt to end ongoing // communications, in case of streaming RPCs. It may also return empty // challenges for all other fields. - MFARequired MFARequired `protobuf:"varint,4,opt,name=MFARequired,proto3,enum=proto.MFARequired" json:"MFARequired,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + MFARequired MFARequired `protobuf:"varint,4,opt,name=MFARequired,proto3,enum=proto.MFARequired" json:"MFARequired,omitempty"` + // Scope is an authorization scope for this MFA challenge. + // Required. Only applies to webauthn challenges. + Scope webauthn.ChallengeScope `protobuf:"varint,5,opt,name=Scope,proto3,enum=webauthn.ChallengeScope" json:"scope,omitempty"` + // AllowReuse means webauthn credentials resolved from this challenge can be + // reused for a short span of time before the challenge expires. + // + // Reuse is only permitted for specific actions by the discretion of the server. + // See the server implementation for details. + AllowReuse bool `protobuf:"varint,6,opt,name=AllowReuse,proto3" json:"allow_reuse,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *MFAAuthenticateChallenge) Reset() { *m = MFAAuthenticateChallenge{} } @@ -6102,6 +6111,20 @@ func (m *MFAAuthenticateChallenge) GetMFARequired() MFARequired { return MFARequired_MFA_REQUIRED_UNSPECIFIED } +func (m *MFAAuthenticateChallenge) GetScope() webauthn.ChallengeScope { + if m != nil { + return m.Scope + } + return webauthn.ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED +} + +func (m *MFAAuthenticateChallenge) GetAllowReuse() bool { + if m != nil { + return m.AllowReuse + } + return false +} + // MFAAuthenticateResponse is a response to MFAAuthenticateChallenge using one // of the MFA devices registered for a user. type MFAAuthenticateResponse struct { @@ -10433,10 +10456,19 @@ type CreateAuthenticateChallengeRequest struct { // MFA verification should run in the cluster that holds the target resource. // If you are issuing challenges from the root cluster, but accessing a leaf, // call [AuthService.IsMFARequired] in the leaf instead of setting this field. - MFARequiredCheck *IsMFARequiredRequest `protobuf:"bytes,5,opt,name=MFARequiredCheck,proto3" json:"mfa_required_check,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + MFARequiredCheck *IsMFARequiredRequest `protobuf:"bytes,5,opt,name=MFARequiredCheck,proto3" json:"mfa_required_check,omitempty"` + // Scope is an authorization scope for this MFA challenge. + // Required. Only applies to webauthn challenges. + Scope webauthn.ChallengeScope `protobuf:"varint,6,opt,name=Scope,proto3,enum=webauthn.ChallengeScope" json:"scope,omitempty"` + // AllowReuse means webauthn credentials resolved from this challenge can be + // reused for a short span of time before the challenge expires. + // + // Reuse is only permitted for specific actions by the discretion of the server. + // See the server implementation for details. + AllowReuse bool `protobuf:"varint,7,opt,name=AllowReuse,proto3" json:"allow_reuse,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *CreateAuthenticateChallengeRequest) Reset() { *m = CreateAuthenticateChallengeRequest{} } @@ -10542,6 +10574,20 @@ func (m *CreateAuthenticateChallengeRequest) GetMFARequiredCheck() *IsMFARequire return nil } +func (m *CreateAuthenticateChallengeRequest) GetScope() webauthn.ChallengeScope { + if m != nil { + return m.Scope + } + return webauthn.ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED +} + +func (m *CreateAuthenticateChallengeRequest) GetAllowReuse() bool { + if m != nil { + return m.AllowReuse + } + return false +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*CreateAuthenticateChallengeRequest) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -15217,867 +15263,870 @@ func init() { } var fileDescriptor_0ffcffcda38ae159 = []byte{ - // 13749 bytes of a gzipped FileDescriptorProto + // 13806 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x5b, 0x6c, 0x5c, 0x49, - 0x7a, 0x18, 0xcc, 0x6e, 0x92, 0x22, 0xf9, 0xf1, 0xd6, 0x2a, 0x92, 0x22, 0xd5, 0xa2, 0xd4, 0xd2, - 0xd1, 0x48, 0xa3, 0xd1, 0xee, 0xea, 0x42, 0xcd, 0xcc, 0xce, 0x7d, 0xb6, 0xbb, 0x49, 0x91, 0x94, - 0x78, 0xe9, 0x39, 0xcd, 0xcb, 0xcc, 0xee, 0x78, 0x7b, 0x0f, 0xbb, 0x4b, 0xe4, 0xf9, 0xd5, 0x3c, - 0xa7, 0xf7, 0x9c, 0xd3, 0xba, 0xac, 0x7f, 0xfb, 0xff, 0x6d, 0x27, 0x46, 0x5e, 0xe2, 0x38, 0x80, - 0x1d, 0xd8, 0x88, 0x01, 0x27, 0x48, 0x02, 0x24, 0x01, 0x02, 0xf8, 0x25, 0xf0, 0x43, 0x9e, 0x82, - 0x04, 0xc8, 0x26, 0x80, 0x81, 0x00, 0x76, 0x5e, 0xf2, 0x40, 0xc7, 0x0b, 0xe4, 0x85, 0x70, 0x1e, - 0x82, 0x20, 0x09, 0xb2, 0x48, 0x80, 0xa0, 0xae, 0xa7, 0xea, 0xdc, 0xba, 0x29, 0x69, 0x36, 0x79, - 0x91, 0xd8, 0x55, 0xdf, 0xf7, 0x55, 0xd5, 0x57, 0x75, 0xaa, 0xbe, 0xfa, 0xea, 0xbb, 0xc0, 0x9d, - 0x00, 0xb7, 0x71, 0xc7, 0xf5, 0x82, 0xbb, 0x6d, 0x7c, 0x68, 0x35, 0x5f, 0xde, 0x6d, 0xb6, 0x6d, - 0xec, 0x04, 0x77, 0x3b, 0x9e, 0x1b, 0xb8, 0x77, 0xad, 0x6e, 0x70, 0xe4, 0x63, 0xef, 0x99, 0xdd, - 0xc4, 0x77, 0x68, 0x09, 0x1a, 0xa6, 0xff, 0x15, 0x67, 0x0f, 0xdd, 0x43, 0x97, 0xc1, 0x90, 0xbf, - 0x58, 0x65, 0xf1, 0xd2, 0xa1, 0xeb, 0x1e, 0xb6, 0x31, 0x43, 0x3e, 0xe8, 0x3e, 0xb9, 0x8b, 0x8f, - 0x3b, 0xc1, 0x4b, 0x5e, 0x59, 0x8a, 0x56, 0x06, 0xf6, 0x31, 0xf6, 0x03, 0xeb, 0xb8, 0xc3, 0x01, - 0xde, 0x91, 0x5d, 0xb1, 0x82, 0x80, 0xd4, 0x04, 0xb6, 0xeb, 0xdc, 0x7d, 0x76, 0x5f, 0xfd, 0xc9, - 0x41, 0x6f, 0x65, 0xf6, 0xba, 0x89, 0xbd, 0xc0, 0xef, 0x0b, 0x12, 0x3f, 0xc3, 0x4e, 0x10, 0x6b, - 0x9e, 0x43, 0x06, 0x2f, 0x3b, 0xd8, 0x67, 0x20, 0xe2, 0x3f, 0x0e, 0x7a, 0x2d, 0x19, 0x94, 0xfe, - 0xcb, 0x41, 0xbe, 0x93, 0x0c, 0xf2, 0x1c, 0x1f, 0x10, 0x9e, 0x3a, 0xf2, 0x8f, 0x1e, 0xe0, 0x9e, - 0xd5, 0xe9, 0x60, 0x2f, 0xfc, 0x23, 0xd6, 0xd7, 0xae, 0x6f, 0x1d, 0x62, 0xde, 0xc7, 0x67, 0xf7, - 0xd5, 0x9f, 0x0c, 0xd4, 0xf8, 0xc3, 0x1c, 0x0c, 0xef, 0x5b, 0x41, 0xf3, 0x08, 0x7d, 0x0e, 0xc3, - 0x8f, 0x6d, 0xa7, 0xe5, 0x2f, 0xe4, 0xae, 0x0e, 0xde, 0x1a, 0x5f, 0x2a, 0xdc, 0x61, 0xfd, 0xa5, - 0x95, 0xa4, 0xa2, 0x32, 0xff, 0xd3, 0x93, 0xd2, 0xc0, 0xe9, 0x49, 0x69, 0xfa, 0x29, 0x01, 0xfb, - 0xb6, 0x7b, 0x6c, 0x07, 0x74, 0x02, 0x4d, 0x86, 0x87, 0x76, 0x61, 0xa6, 0xdc, 0x6e, 0xbb, 0xcf, - 0x6b, 0x96, 0x17, 0xd8, 0x56, 0xbb, 0xde, 0x6d, 0x36, 0xb1, 0xef, 0x2f, 0xe4, 0xaf, 0xe6, 0x6e, - 0x8d, 0x56, 0xae, 0x9f, 0x9e, 0x94, 0x4a, 0x16, 0xa9, 0x6e, 0x74, 0x58, 0x7d, 0xc3, 0x67, 0x00, - 0x0a, 0xa1, 0x24, 0x7c, 0xe3, 0x2f, 0x87, 0xa1, 0xb0, 0xe6, 0xfa, 0x41, 0x95, 0x4c, 0x9b, 0x89, - 0x7f, 0xdc, 0xc5, 0x7e, 0x80, 0xae, 0xc3, 0x39, 0x52, 0xb6, 0xbe, 0xbc, 0x90, 0xbb, 0x9a, 0xbb, - 0x35, 0x56, 0x19, 0x3f, 0x3d, 0x29, 0x8d, 0x1c, 0xb9, 0x7e, 0xd0, 0xb0, 0x5b, 0x26, 0xaf, 0x42, - 0xef, 0xc0, 0xe8, 0x96, 0xdb, 0xc2, 0x5b, 0xd6, 0x31, 0xa6, 0xbd, 0x18, 0xab, 0x4c, 0x9e, 0x9e, - 0x94, 0xc6, 0x1c, 0xb7, 0x85, 0x1b, 0x8e, 0x75, 0x8c, 0x4d, 0x59, 0x8d, 0xf6, 0x60, 0xc8, 0x74, - 0xdb, 0x78, 0x61, 0x90, 0x82, 0x55, 0x4e, 0x4f, 0x4a, 0x43, 0x9e, 0xdb, 0xc6, 0x3f, 0x3f, 0x29, - 0xbd, 0x7f, 0x68, 0x07, 0x47, 0xdd, 0x83, 0x3b, 0x4d, 0xf7, 0xf8, 0xee, 0xa1, 0x67, 0x3d, 0xb3, - 0xd9, 0x4a, 0xb3, 0xda, 0x77, 0xc3, 0xf5, 0xd8, 0xb1, 0xf9, 0xe4, 0xd6, 0x5f, 0xfa, 0x01, 0x3e, - 0x26, 0x94, 0x4c, 0x4a, 0x0f, 0xed, 0xc3, 0x6c, 0xb9, 0xd5, 0xb2, 0x19, 0x46, 0xcd, 0xb3, 0x9d, - 0xa6, 0xdd, 0xb1, 0xda, 0xfe, 0xc2, 0xd0, 0xd5, 0xc1, 0x5b, 0x63, 0x9c, 0x29, 0xb2, 0xbe, 0xd1, - 0x91, 0x00, 0x0a, 0x53, 0x12, 0x09, 0xa0, 0x07, 0x30, 0xba, 0xbc, 0x55, 0x27, 0x7d, 0xf7, 0x17, - 0x86, 0x29, 0xb1, 0xf9, 0xd3, 0x93, 0xd2, 0x4c, 0xcb, 0xf1, 0xe9, 0xd0, 0x54, 0x02, 0x12, 0x10, - 0xbd, 0x0f, 0x13, 0xb5, 0xee, 0x41, 0xdb, 0x6e, 0xee, 0x6c, 0xd4, 0x1f, 0xe3, 0x97, 0x0b, 0xe7, - 0xae, 0xe6, 0x6e, 0x4d, 0x54, 0xd0, 0xe9, 0x49, 0x69, 0xaa, 0x43, 0xcb, 0x1b, 0x41, 0xdb, 0x6f, - 0x3c, 0xc5, 0x2f, 0x4d, 0x0d, 0x2e, 0xc4, 0xab, 0xd7, 0xd7, 0x08, 0xde, 0x48, 0x0c, 0xcf, 0xf7, - 0x8f, 0x54, 0x3c, 0x06, 0x87, 0xee, 0x02, 0x98, 0xf8, 0xd8, 0x0d, 0x70, 0xb9, 0xd5, 0xf2, 0x16, - 0x46, 0x29, 0x6f, 0xa7, 0x4f, 0x4f, 0x4a, 0xe3, 0x1e, 0x2d, 0x6d, 0x58, 0xad, 0x96, 0x67, 0x2a, - 0x20, 0xa8, 0x0a, 0xa3, 0xa6, 0xcb, 0x18, 0xbc, 0x30, 0x76, 0x35, 0x77, 0x6b, 0x7c, 0x69, 0x9a, - 0x2f, 0x43, 0x51, 0x5c, 0xb9, 0x70, 0x7a, 0x52, 0x42, 0x1e, 0xff, 0xa5, 0x8e, 0x52, 0x40, 0xa0, - 0x12, 0x8c, 0x6c, 0xb9, 0x55, 0xab, 0x79, 0x84, 0x17, 0x80, 0xae, 0xbd, 0xe1, 0xd3, 0x93, 0x52, - 0xee, 0x3b, 0xa6, 0x28, 0x45, 0xcf, 0x60, 0x3c, 0x9c, 0x28, 0x7f, 0x61, 0x9c, 0xb2, 0x6f, 0xe7, - 0xf4, 0xa4, 0x74, 0xc1, 0xa7, 0xc5, 0x0d, 0x32, 0xf5, 0x0a, 0x07, 0x5f, 0x63, 0x15, 0xa8, 0x0d, - 0x3d, 0x1a, 0x1a, 0x9d, 0x28, 0x4c, 0x9a, 0x97, 0x77, 0x1d, 0x3f, 0xb0, 0x0e, 0xda, 0x38, 0xac, - 0x2a, 0xfb, 0x3e, 0xf6, 0x08, 0xbd, 0xf5, 0x65, 0xe3, 0x7f, 0xe5, 0x00, 0x6d, 0x77, 0xb0, 0x53, - 0xaf, 0xaf, 0x91, 0x15, 0x2f, 0x16, 0xfc, 0xb7, 0x61, 0x8c, 0xb1, 0x96, 0xf0, 0x3f, 0x4f, 0xf9, - 0x3f, 0x75, 0x7a, 0x52, 0x02, 0xce, 0x7f, 0xc2, 0xfb, 0x10, 0x00, 0xdd, 0x80, 0xc1, 0x9d, 0x9d, - 0x0d, 0xba, 0x9a, 0x07, 0x2b, 0x33, 0xa7, 0x27, 0xa5, 0xc1, 0x20, 0x68, 0xff, 0xfc, 0xa4, 0x34, - 0xba, 0xdc, 0xf5, 0x68, 0xc7, 0x4d, 0x52, 0x8f, 0x6e, 0xc0, 0x48, 0xb5, 0xdd, 0xf5, 0x03, 0xec, - 0x2d, 0x0c, 0x85, 0x9f, 0x51, 0x93, 0x15, 0x99, 0xa2, 0x0e, 0x7d, 0x0b, 0x86, 0x76, 0x7d, 0xec, - 0x2d, 0x0c, 0xd3, 0x19, 0x99, 0xe4, 0x33, 0x42, 0x8a, 0xf6, 0x96, 0x2a, 0xa3, 0xe4, 0x5b, 0xe9, - 0xfa, 0xd8, 0x33, 0x29, 0x10, 0xba, 0x03, 0xc3, 0x8c, 0xad, 0xe7, 0xe8, 0x36, 0x32, 0x29, 0xe7, - 0xaf, 0x8d, 0xf7, 0xde, 0xaf, 0x8c, 0x9d, 0x9e, 0x94, 0x86, 0x29, 0x7b, 0xcd, 0x61, 0xc1, 0x94, - 0x5c, 0x21, 0x6f, 0x8e, 0x12, 0x5c, 0xb2, 0x70, 0x8d, 0x6f, 0xc1, 0xb8, 0x32, 0x7c, 0xb4, 0x08, - 0x43, 0xe4, 0x7f, 0xfa, 0x99, 0x4f, 0xb0, 0xc6, 0xc8, 0xfe, 0x6d, 0xd2, 0x52, 0xe3, 0x0f, 0xa6, - 0xa1, 0x40, 0x30, 0xb5, 0xbd, 0x41, 0x63, 0x55, 0xae, 0x17, 0xab, 0x6e, 0x81, 0x6c, 0x9b, 0x6f, - 0x12, 0x13, 0xa7, 0x27, 0xa5, 0xd1, 0x2e, 0x2f, 0x0b, 0x7b, 0x86, 0xea, 0x30, 0xb2, 0xf2, 0xa2, - 0x63, 0x7b, 0xd8, 0xa7, 0x8c, 0x1d, 0x5f, 0x2a, 0xde, 0x61, 0x67, 0xd6, 0x1d, 0x71, 0x66, 0xdd, - 0xd9, 0x11, 0x67, 0x56, 0xe5, 0x32, 0xdf, 0x2c, 0xcf, 0x63, 0x86, 0x12, 0xae, 0xa6, 0xdf, 0xfe, - 0xf3, 0x52, 0xce, 0x14, 0x94, 0xd0, 0xb7, 0xe1, 0xdc, 0x43, 0xd7, 0x3b, 0xb6, 0x02, 0x3e, 0x03, - 0xb3, 0xa7, 0x27, 0xa5, 0xc2, 0x13, 0x5a, 0xa2, 0x2c, 0x6e, 0x0e, 0x83, 0x1e, 0xc2, 0x94, 0xe9, - 0x76, 0x03, 0xbc, 0xe3, 0x8a, 0x79, 0x1b, 0xa6, 0x58, 0x57, 0x4e, 0x4f, 0x4a, 0x45, 0x8f, 0xd4, - 0x34, 0x02, 0xb7, 0xc1, 0x27, 0x50, 0xc1, 0x8f, 0x60, 0xa1, 0x15, 0x98, 0x2a, 0xd3, 0xdd, 0x95, - 0xf3, 0x8c, 0xcd, 0xd6, 0x58, 0xe5, 0xf2, 0xe9, 0x49, 0xe9, 0xa2, 0x45, 0x6b, 0x1a, 0x1e, 0xaf, - 0x52, 0xc9, 0xe8, 0x48, 0x68, 0x0b, 0xce, 0x3f, 0xee, 0x1e, 0x60, 0xcf, 0xc1, 0x01, 0xf6, 0x45, - 0x8f, 0x46, 0x68, 0x8f, 0xae, 0x9e, 0x9e, 0x94, 0x16, 0x9f, 0xca, 0xca, 0x84, 0x3e, 0xc5, 0x51, - 0x11, 0x86, 0x69, 0xde, 0xd1, 0x65, 0x2b, 0xb0, 0x0e, 0x2c, 0x1f, 0xd3, 0x4d, 0x63, 0x7c, 0xe9, - 0x02, 0x63, 0xf1, 0x9d, 0x48, 0x6d, 0xe5, 0x3a, 0xe7, 0xf2, 0x25, 0x39, 0xf6, 0x16, 0xaf, 0x52, - 0x1a, 0x8a, 0xd2, 0x24, 0x7b, 0xa7, 0x3c, 0x17, 0xc6, 0x68, 0x6f, 0xe9, 0xde, 0x29, 0xcf, 0x05, - 0x75, 0x57, 0x91, 0x27, 0xc4, 0x06, 0x0c, 0xef, 0x92, 0xd3, 0x93, 0xee, 0x29, 0x53, 0x4b, 0xd7, - 0x78, 0x8f, 0xa2, 0xab, 0xef, 0x0e, 0xf9, 0x41, 0x01, 0xe9, 0x77, 0x37, 0x4d, 0x4f, 0x5c, 0xf5, - 0xac, 0xa4, 0x75, 0xe8, 0x0b, 0x00, 0xde, 0xab, 0x72, 0xa7, 0xb3, 0x30, 0x4e, 0x07, 0x79, 0x5e, - 0x1f, 0x64, 0xb9, 0xd3, 0xa9, 0x5c, 0xe1, 0xe3, 0xbb, 0x20, 0xc7, 0x67, 0x75, 0x3a, 0x0a, 0x35, - 0x85, 0x08, 0xfa, 0x1c, 0x26, 0xe8, 0x96, 0x23, 0x66, 0x74, 0x82, 0xce, 0xe8, 0xa5, 0xd3, 0x93, - 0xd2, 0x3c, 0xf9, 0xe0, 0x92, 0xe6, 0x53, 0x43, 0x40, 0xbf, 0x0a, 0x73, 0x9c, 0xdc, 0xbe, 0xed, - 0xb4, 0xdc, 0xe7, 0xfe, 0x32, 0xf6, 0x9f, 0x06, 0x6e, 0x67, 0x61, 0x92, 0x76, 0x6f, 0x51, 0xef, - 0x9e, 0x0e, 0x53, 0xb9, 0xcd, 0x7b, 0x6a, 0xc8, 0x9e, 0x3e, 0x67, 0x00, 0x8d, 0x16, 0x83, 0x50, - 0x9a, 0x4d, 0x6e, 0x06, 0xad, 0xc3, 0xf4, 0xae, 0x8f, 0xb5, 0x31, 0x4c, 0xd1, 0xfd, 0xbb, 0x44, - 0x66, 0xb8, 0xeb, 0xe3, 0x46, 0xda, 0x38, 0xa2, 0x78, 0xc8, 0x04, 0xb4, 0xec, 0xb9, 0x9d, 0xc8, - 0x1a, 0x9f, 0xa6, 0x1c, 0x31, 0x4e, 0x4f, 0x4a, 0x57, 0x5a, 0x9e, 0xdb, 0x69, 0xa4, 0x2f, 0xf4, - 0x04, 0x6c, 0xf4, 0x43, 0xb8, 0x50, 0x75, 0x1d, 0x07, 0x37, 0xc9, 0xfe, 0xb9, 0x6c, 0x5b, 0x87, - 0x8e, 0xeb, 0x07, 0x76, 0x73, 0x7d, 0x79, 0xa1, 0x40, 0xd7, 0xd0, 0x4d, 0x32, 0xfa, 0xa6, 0x84, - 0x68, 0xb4, 0x24, 0x48, 0xc3, 0x6e, 0x29, 0xb4, 0x53, 0xa8, 0xa0, 0x1f, 0xc0, 0x24, 0x6f, 0x0b, - 0x7b, 0x74, 0x69, 0x9e, 0xcf, 0x5e, 0x68, 0x12, 0x98, 0x1d, 0xc4, 0x9e, 0xf8, 0xc9, 0x44, 0x1b, - 0x9d, 0x16, 0xfa, 0x1a, 0xc6, 0x37, 0x1f, 0x96, 0x4d, 0xec, 0x77, 0x5c, 0xc7, 0xc7, 0x0b, 0x88, - 0xce, 0xe8, 0x15, 0x4e, 0x7a, 0xf3, 0x61, 0xb9, 0xdc, 0x0d, 0x8e, 0xb0, 0x13, 0xd8, 0x4d, 0x2b, - 0xc0, 0x02, 0xaa, 0x52, 0x24, 0x2b, 0xef, 0xf8, 0x89, 0xd5, 0xf0, 0x78, 0x89, 0x32, 0x0a, 0x95, - 0x1c, 0x2a, 0xc2, 0x68, 0xbd, 0xbe, 0xb6, 0xe1, 0x1e, 0xda, 0xce, 0xc2, 0x0c, 0x61, 0x86, 0x29, - 0x7f, 0xa3, 0x03, 0x98, 0x53, 0x04, 0xf4, 0x06, 0xf9, 0x1f, 0x1f, 0x63, 0x27, 0x58, 0x98, 0xa5, - 0x7d, 0xf8, 0x8e, 0xbc, 0x61, 0xdc, 0x51, 0xe5, 0xf8, 0x67, 0xf7, 0xef, 0x94, 0xc3, 0x9f, 0x75, - 0x81, 0x64, 0xce, 0x5a, 0x09, 0xa5, 0x68, 0x07, 0x46, 0x6a, 0x5d, 0xaf, 0xe3, 0xfa, 0x78, 0x61, - 0x8e, 0x32, 0xed, 0x7a, 0xd6, 0xd7, 0xc9, 0x41, 0x2b, 0x73, 0x64, 0x7b, 0xee, 0xb0, 0x1f, 0xca, - 0xc8, 0x04, 0x29, 0xe3, 0x4b, 0x18, 0x93, 0x1f, 0x33, 0x1a, 0x81, 0xc1, 0x72, 0xbb, 0x5d, 0x18, - 0x20, 0x7f, 0xd4, 0xeb, 0x6b, 0x85, 0x1c, 0x9a, 0x02, 0x08, 0x77, 0xb0, 0x42, 0x1e, 0x4d, 0xc0, - 0xa8, 0xd8, 0x61, 0x0a, 0x83, 0x14, 0xbe, 0xd3, 0x29, 0x0c, 0x21, 0x04, 0x53, 0xfa, 0x3a, 0x2f, - 0x0c, 0x1b, 0x2f, 0x60, 0x4c, 0x4e, 0x0f, 0x9a, 0x86, 0xf1, 0xdd, 0xad, 0x7a, 0x6d, 0xa5, 0xba, - 0xfe, 0x70, 0x7d, 0x65, 0xb9, 0x30, 0x80, 0x2e, 0xc3, 0xc5, 0x9d, 0xfa, 0x5a, 0x63, 0xb9, 0xd2, - 0xd8, 0xd8, 0xae, 0x96, 0x37, 0x1a, 0x35, 0x73, 0xfb, 0xcb, 0xaf, 0x1a, 0x3b, 0xbb, 0x5b, 0x5b, - 0x2b, 0x1b, 0x85, 0x1c, 0x5a, 0x80, 0x59, 0x52, 0xfd, 0x78, 0xb7, 0xb2, 0xa2, 0x02, 0x14, 0xf2, - 0xe8, 0x1a, 0x5c, 0x4e, 0xaa, 0x69, 0xac, 0xad, 0x94, 0x97, 0x37, 0x56, 0xea, 0xf5, 0xc2, 0xa0, - 0xd1, 0x86, 0x71, 0x85, 0x05, 0x68, 0x11, 0x16, 0xaa, 0x2b, 0xe6, 0x4e, 0xa3, 0xb6, 0x6b, 0xd6, - 0xb6, 0xeb, 0x2b, 0x0d, 0xbd, 0x23, 0xd1, 0xda, 0x8d, 0xed, 0xd5, 0xf5, 0xad, 0x06, 0x29, 0xaa, - 0x17, 0x72, 0xa4, 0x35, 0xad, 0xb6, 0xbe, 0xbe, 0xb5, 0xba, 0xb1, 0xd2, 0xd8, 0xad, 0xaf, 0x70, - 0x90, 0xbc, 0xf1, 0xeb, 0xf9, 0xd8, 0x86, 0x8e, 0x96, 0x60, 0xbc, 0xce, 0xae, 0x8c, 0x74, 0x91, - 0x33, 0xf1, 0xbd, 0x70, 0x7a, 0x52, 0x9a, 0xe0, 0x37, 0x49, 0xb6, 0x7e, 0x55, 0x20, 0x72, 0x46, - 0xd7, 0xc8, 0x7c, 0x36, 0xdd, 0xb6, 0x7a, 0x46, 0x77, 0x78, 0x99, 0x29, 0x6b, 0xd1, 0x92, 0x72, - 0x9a, 0x33, 0x59, 0x9e, 0xca, 0x8b, 0xe2, 0x34, 0x57, 0x77, 0x76, 0x79, 0xae, 0x2f, 0x85, 0x13, - 0xc7, 0x0f, 0x61, 0x8a, 0x93, 0x70, 0x92, 0x48, 0x38, 0xf4, 0x8e, 0x90, 0x72, 0x98, 0xec, 0x4d, - 0xb7, 0xfa, 0x88, 0xd4, 0xc8, 0x05, 0x1c, 0xa3, 0x9b, 0xb2, 0xad, 0xa2, 0x8f, 0xa3, 0x2b, 0x83, - 0x33, 0x83, 0x12, 0x8b, 0xec, 0x9e, 0x66, 0x04, 0x14, 0x95, 0x60, 0x98, 0x7d, 0x6f, 0x8c, 0x1f, - 0x54, 0xae, 0x6a, 0x93, 0x02, 0x93, 0x95, 0x1b, 0xbf, 0x35, 0xa8, 0x1e, 0x31, 0x44, 0x8e, 0x52, - 0xf8, 0x4d, 0xe5, 0x28, 0xca, 0x67, 0x5a, 0x4a, 0x44, 0xa6, 0x3a, 0xf6, 0x7d, 0x2a, 0x81, 0x72, - 0x8a, 0x54, 0x64, 0xf2, 0x59, 0x21, 0xb9, 0x54, 0x85, 0x00, 0x44, 0xac, 0x67, 0xf2, 0x13, 0x15, - 0xeb, 0x07, 0x43, 0xb1, 0x9e, 0x4b, 0x58, 0x4c, 0xac, 0x0f, 0x41, 0xc8, 0x9c, 0xf3, 0x23, 0x9e, - 0xf6, 0x61, 0x28, 0x9c, 0x73, 0x2e, 0x16, 0xf0, 0x39, 0x57, 0x80, 0xd0, 0x47, 0x00, 0xe5, 0xfd, - 0x3a, 0x95, 0x8e, 0xcd, 0x2d, 0x2e, 0xe6, 0xd0, 0x0d, 0xc9, 0x7a, 0xee, 0xb3, 0x83, 0xc0, 0xf2, - 0x54, 0xf9, 0x5f, 0x81, 0x46, 0x15, 0x98, 0x2c, 0xff, 0xa4, 0xeb, 0xe1, 0xf5, 0x16, 0xd9, 0xd3, - 0x02, 0x76, 0xd1, 0x19, 0xab, 0x2c, 0x9e, 0x9e, 0x94, 0x16, 0x2c, 0x52, 0xd1, 0xb0, 0x79, 0x8d, - 0x42, 0x40, 0x47, 0x41, 0xdb, 0x70, 0x7e, 0xb5, 0x5a, 0xe3, 0xab, 0xb0, 0xdc, 0x6c, 0xba, 0x5d, - 0x27, 0xe0, 0xb2, 0xcd, 0xb5, 0xd3, 0x93, 0xd2, 0xe5, 0xc3, 0x66, 0xa7, 0x21, 0x56, 0xac, 0xc5, - 0xaa, 0x55, 0xe1, 0x26, 0x86, 0x6b, 0xb4, 0x61, 0x6a, 0x15, 0x07, 0x64, 0xd5, 0x09, 0x41, 0x35, - 0x7b, 0x4e, 0x3e, 0x81, 0xf1, 0x7d, 0x3b, 0x38, 0xaa, 0xe3, 0xa6, 0x87, 0x03, 0x71, 0x8d, 0xa6, - 0x1c, 0x78, 0x6e, 0x07, 0x47, 0x0d, 0x9f, 0x95, 0xab, 0x5b, 0xb2, 0x02, 0x6e, 0xac, 0xc0, 0x34, - 0x6f, 0x4d, 0xca, 0xc5, 0x4b, 0x3a, 0xc1, 0x1c, 0x25, 0x48, 0x67, 0x41, 0x25, 0xa8, 0x93, 0xf9, - 0xa7, 0x79, 0x98, 0xab, 0x1e, 0x59, 0xce, 0x21, 0xae, 0x59, 0xbe, 0xff, 0xdc, 0xf5, 0x5a, 0x4a, - 0xe7, 0xe9, 0xa5, 0x20, 0xd6, 0x79, 0x7a, 0x0b, 0x58, 0x82, 0xf1, 0xed, 0x76, 0x4b, 0xe0, 0xf0, - 0x0b, 0x0b, 0x6d, 0xcb, 0x6d, 0xb7, 0x1a, 0x1d, 0x41, 0x4b, 0x05, 0x22, 0x38, 0x5b, 0xf8, 0xb9, - 0xc4, 0x19, 0x0c, 0x71, 0x1c, 0xfc, 0x5c, 0xc1, 0x51, 0x80, 0xd0, 0x0a, 0x9c, 0xaf, 0xe3, 0xa6, - 0xeb, 0xb4, 0x1e, 0x5a, 0xcd, 0xc0, 0xf5, 0x76, 0xdc, 0xa7, 0xd8, 0xe1, 0xeb, 0x8b, 0xca, 0x74, - 0x3e, 0xad, 0x6c, 0x3c, 0xa1, 0xb5, 0x8d, 0x80, 0x54, 0x9b, 0x71, 0x0c, 0xb4, 0x0d, 0xa3, 0xfb, - 0x5c, 0xe3, 0xc2, 0x6f, 0x39, 0x37, 0xee, 0x48, 0x15, 0x4c, 0xd5, 0xc3, 0x74, 0x51, 0x58, 0x6d, - 0x79, 0x4f, 0x93, 0x47, 0x24, 0xdd, 0x87, 0x04, 0xa4, 0x29, 0x89, 0x18, 0xbb, 0x30, 0x59, 0x6b, - 0x77, 0x0f, 0x6d, 0x87, 0xec, 0x18, 0x75, 0xfc, 0x63, 0xb4, 0x0c, 0x10, 0x16, 0x70, 0x15, 0xcb, - 0x0c, 0xbf, 0x1b, 0x85, 0x15, 0x7b, 0x0f, 0xf8, 0x87, 0x44, 0x4b, 0xa8, 0x30, 0x6b, 0x2a, 0x78, - 0xc6, 0xff, 0x18, 0x04, 0xc4, 0x27, 0x80, 0x9e, 0x7e, 0x75, 0x1c, 0x90, 0x23, 0xe4, 0x02, 0xe4, - 0xa5, 0x26, 0xe4, 0xdc, 0xe9, 0x49, 0x29, 0x6f, 0xb7, 0xcc, 0xfc, 0xfa, 0x32, 0x7a, 0x17, 0x86, - 0x29, 0x18, 0xe5, 0xff, 0x94, 0x6c, 0x4f, 0xa5, 0xc0, 0x76, 0x0e, 0x7a, 0x2a, 0x9b, 0x0c, 0x18, - 0xbd, 0x07, 0x63, 0xcb, 0xb8, 0x8d, 0x0f, 0xad, 0xc0, 0x15, 0x5f, 0x37, 0xd3, 0x2d, 0x88, 0x42, - 0x65, 0xcd, 0x85, 0x90, 0xe4, 0x26, 0x63, 0x62, 0xcb, 0x77, 0x1d, 0xf5, 0x26, 0xe3, 0xd1, 0x12, - 0xf5, 0x26, 0xc3, 0x60, 0xd0, 0xef, 0xe6, 0x60, 0xbc, 0xec, 0x38, 0xfc, 0xce, 0xee, 0x73, 0xae, - 0xcf, 0xdd, 0x91, 0x9a, 0xac, 0x0d, 0xeb, 0x00, 0xb7, 0xf7, 0xac, 0x76, 0x17, 0xfb, 0x95, 0xaf, - 0x89, 0x70, 0xf9, 0xef, 0x4f, 0x4a, 0x1f, 0x9f, 0xe1, 0x16, 0x1e, 0xea, 0xc4, 0x76, 0x3c, 0xcb, - 0x0e, 0xfc, 0xd3, 0x93, 0xd2, 0x9c, 0x15, 0x36, 0xa8, 0x7e, 0x37, 0x4a, 0x3f, 0xc2, 0x8d, 0xfd, - 0x5c, 0xaf, 0x8d, 0x1d, 0x1d, 0xc3, 0x74, 0xd9, 0xf7, 0xbb, 0xc7, 0xb8, 0x1e, 0x58, 0x5e, 0x40, - 0xae, 0x7e, 0x74, 0x7f, 0xc8, 0xbe, 0x17, 0xbe, 0xfd, 0xd3, 0x93, 0x52, 0x8e, 0xc8, 0xb3, 0x16, - 0x45, 0x25, 0xf2, 0x90, 0x17, 0x34, 0x02, 0x5b, 0x3d, 0x9b, 0xe8, 0x0d, 0x31, 0x4a, 0xdb, 0xb8, - 0x2e, 0x85, 0x86, 0xf5, 0xe5, 0xb4, 0x19, 0x37, 0xaa, 0xb0, 0xb8, 0x8a, 0x03, 0x13, 0xfb, 0x38, - 0x10, 0xdf, 0x08, 0x5d, 0xe1, 0xa1, 0xde, 0x6c, 0x84, 0xfe, 0x96, 0xc8, 0x74, 0xfa, 0xd9, 0x77, - 0x21, 0x6a, 0x8c, 0xbf, 0x92, 0x83, 0x52, 0xd5, 0xc3, 0x4c, 0x14, 0x4c, 0x21, 0x94, 0xbd, 0x77, - 0x2d, 0xc2, 0xd0, 0xce, 0xcb, 0x8e, 0xb8, 0x50, 0xd3, 0x5a, 0x32, 0x29, 0x26, 0x2d, 0xed, 0x53, - 0x3b, 0x61, 0x3c, 0x81, 0x39, 0x13, 0x3b, 0xf8, 0xb9, 0x75, 0xd0, 0xc6, 0xda, 0x05, 0xbf, 0x04, - 0xc3, 0xec, 0x43, 0x8f, 0x0d, 0x81, 0x95, 0x9f, 0x4d, 0x59, 0x62, 0xfc, 0xa3, 0x3c, 0x14, 0xd8, - 0x70, 0x2b, 0x6e, 0xd0, 0xdf, 0xf8, 0xf8, 0x08, 0xf2, 0x3d, 0xf4, 0x2b, 0x37, 0x43, 0x6e, 0x0f, - 0x86, 0x62, 0x0b, 0xed, 0x2a, 0x39, 0x52, 0x45, 0x25, 0x19, 0x10, 0x5b, 0x74, 0x4c, 0x2d, 0x18, - 0x53, 0x92, 0xa0, 0xdf, 0xcc, 0xc1, 0x39, 0xb6, 0x8c, 0xb3, 0x3f, 0x94, 0xfd, 0x37, 0xf3, 0xa1, - 0x14, 0x02, 0xfa, 0x97, 0xfa, 0xd9, 0xb2, 0x3a, 0xe3, 0x9f, 0xe4, 0xe1, 0xbc, 0xc2, 0x2b, 0x2e, - 0xff, 0xbf, 0xc3, 0xa4, 0x2e, 0x85, 0x61, 0x54, 0xd1, 0x4a, 0xa4, 0xae, 0x46, 0xa8, 0x44, 0xa1, - 0x9c, 0x7b, 0x07, 0x46, 0xc9, 0x90, 0xa2, 0x3a, 0x59, 0x7a, 0xa0, 0x33, 0x50, 0x51, 0xdd, 0x37, - 0xf7, 0xee, 0xc2, 0x28, 0xfd, 0x93, 0xcc, 0xc8, 0x50, 0xfa, 0x8c, 0x48, 0x20, 0x64, 0x03, 0x3c, - 0x72, 0x6d, 0x67, 0x13, 0x07, 0x47, 0x6e, 0x8b, 0x8b, 0x16, 0xeb, 0x64, 0xdb, 0xfd, 0x7f, 0x5c, - 0xdb, 0x69, 0x1c, 0xd3, 0xe2, 0xb3, 0xea, 0xfc, 0x42, 0x82, 0xa6, 0x42, 0xdc, 0xb8, 0x07, 0x05, - 0xb2, 0x43, 0xf6, 0xbf, 0xb4, 0x8c, 0x59, 0x40, 0xab, 0x38, 0xa8, 0xb8, 0xda, 0xd9, 0x6d, 0x4c, - 0xc2, 0x78, 0xcd, 0x76, 0x0e, 0xc5, 0xcf, 0x3f, 0x1a, 0x84, 0x09, 0xf6, 0x9b, 0xcf, 0x40, 0x44, - 0xc2, 0xca, 0xf5, 0x23, 0x61, 0x7d, 0x00, 0x93, 0x44, 0x44, 0xc1, 0xde, 0x1e, 0xf6, 0x88, 0x64, - 0xc7, 0xe7, 0x83, 0xde, 0x26, 0x7d, 0x5a, 0xd1, 0x78, 0xc6, 0x6a, 0x4c, 0x1d, 0x10, 0x6d, 0xc0, - 0x14, 0x2b, 0x78, 0x88, 0xad, 0xa0, 0x1b, 0x2a, 0xc4, 0xa6, 0xf9, 0xb5, 0x4b, 0x14, 0xb3, 0xed, - 0x93, 0xd3, 0x7a, 0xc2, 0x0b, 0xcd, 0x08, 0x2e, 0xfa, 0x1c, 0xa6, 0x6b, 0x9e, 0xfb, 0xe2, 0xa5, - 0x22, 0x53, 0xb2, 0x13, 0x84, 0x5d, 0xd0, 0x48, 0x55, 0x43, 0x95, 0x2c, 0xa3, 0xd0, 0x64, 0x4d, - 0xad, 0xfb, 0x15, 0xd7, 0xb3, 0x9d, 0x43, 0x3a, 0x9b, 0xa3, 0x6c, 0x4d, 0xd9, 0x7e, 0xe3, 0x80, - 0x16, 0x9a, 0xb2, 0x3a, 0xa2, 0x91, 0x1e, 0xe9, 0xad, 0x91, 0xbe, 0x07, 0xb0, 0xe1, 0x5a, 0xad, - 0x72, 0xbb, 0x5d, 0x2d, 0xfb, 0x54, 0x1b, 0xc5, 0x65, 0xa6, 0xb6, 0x6b, 0xb5, 0x1a, 0x56, 0xbb, - 0xdd, 0x68, 0x5a, 0xbe, 0xa9, 0xc0, 0x3c, 0x1a, 0x1a, 0x3d, 0x57, 0x18, 0x31, 0xa7, 0x37, 0xec, - 0x26, 0x76, 0x7c, 0xbc, 0x6f, 0x79, 0x8e, 0xed, 0x1c, 0xfa, 0xc6, 0x1f, 0x8c, 0xc3, 0xa8, 0x1c, - 0xf2, 0x1d, 0xf5, 0xee, 0xc8, 0x25, 0x31, 0xba, 0x43, 0x85, 0x1a, 0x33, 0x53, 0x81, 0x40, 0x17, - 0xe9, 0x6d, 0x92, 0xcb, 0x80, 0x23, 0x64, 0x75, 0x5b, 0x9d, 0x8e, 0x49, 0xca, 0xc8, 0x49, 0xb0, - 0x5c, 0xa1, 0xfc, 0x1f, 0x65, 0x27, 0x41, 0xeb, 0xc0, 0xcc, 0x2f, 0x57, 0xc8, 0x2a, 0xdb, 0x5e, - 0x5f, 0xae, 0x52, 0x56, 0x8e, 0xb2, 0x55, 0xe6, 0xda, 0xad, 0xa6, 0x49, 0x4b, 0x49, 0x6d, 0xbd, - 0xbc, 0xb9, 0xc1, 0xd9, 0x45, 0x6b, 0x7d, 0xeb, 0xb8, 0x6d, 0xd2, 0x52, 0x72, 0x33, 0x61, 0xca, - 0x8f, 0xaa, 0xeb, 0x04, 0x9e, 0xdb, 0xf6, 0xa9, 0x00, 0x3d, 0xca, 0xa6, 0x93, 0x6b, 0x4d, 0x9a, - 0xbc, 0xca, 0x8c, 0x80, 0xa2, 0x7d, 0x98, 0x2f, 0xb7, 0x9e, 0x59, 0x4e, 0x13, 0xb7, 0x58, 0xcd, - 0xbe, 0xeb, 0x3d, 0x7d, 0xd2, 0x76, 0x9f, 0xfb, 0x94, 0xdf, 0xa3, 0x5c, 0xc9, 0xc8, 0x41, 0x84, - 0x12, 0xe6, 0xb9, 0x00, 0x32, 0xd3, 0xb0, 0xc9, 0x2e, 0x59, 0x6d, 0xbb, 0xdd, 0x16, 0x9f, 0x05, - 0xba, 0x4b, 0x36, 0x49, 0x81, 0xc9, 0xca, 0x09, 0x97, 0xd6, 0xea, 0x9b, 0x54, 0xa5, 0xc7, 0xb9, - 0x74, 0xe4, 0x1f, 0x9b, 0xa4, 0x0c, 0xdd, 0x80, 0x11, 0x71, 0xc9, 0x62, 0x6f, 0x02, 0x54, 0xd3, - 0x2d, 0x2e, 0x57, 0xa2, 0x8e, 0x7c, 0x12, 0x26, 0x6e, 0xba, 0xcf, 0xb0, 0xf7, 0xb2, 0xea, 0xb6, - 0xb0, 0x50, 0x40, 0x71, 0x05, 0x0b, 0xab, 0x68, 0x34, 0x49, 0x8d, 0xa9, 0x03, 0x92, 0x06, 0x98, - 0x9c, 0xe6, 0x2f, 0x4c, 0x87, 0x0d, 0x30, 0x39, 0xce, 0x37, 0x45, 0x1d, 0x5a, 0x86, 0xf3, 0xe5, - 0x6e, 0xe0, 0x1e, 0x5b, 0x81, 0xdd, 0xdc, 0xed, 0x1c, 0x7a, 0x16, 0x69, 0xa4, 0x40, 0x11, 0xe8, - 0xa5, 0xd3, 0x12, 0x95, 0x8d, 0x2e, 0xaf, 0x35, 0xe3, 0x08, 0xe8, 0x7d, 0x98, 0x58, 0xf7, 0x99, - 0x92, 0xd1, 0xf2, 0x71, 0x8b, 0x6a, 0x8a, 0x78, 0x2f, 0x6d, 0xbf, 0x41, 0x55, 0x8e, 0x0d, 0x72, - 0x4d, 0x6d, 0x99, 0x1a, 0x1c, 0x32, 0xe0, 0x5c, 0xd9, 0xf7, 0x6d, 0x3f, 0xa0, 0x0a, 0xa0, 0xd1, - 0x0a, 0x9c, 0x9e, 0x94, 0xce, 0x59, 0xb4, 0xc4, 0xe4, 0x35, 0x68, 0x1f, 0xc6, 0x97, 0x31, 0xb9, - 0xb7, 0xec, 0x78, 0x5d, 0x3f, 0xa0, 0xea, 0x9c, 0xf1, 0xa5, 0x8b, 0xfc, 0xc3, 0x56, 0x6a, 0xf8, - 0x5a, 0x66, 0x37, 0x92, 0x16, 0x2d, 0x6f, 0x04, 0xa4, 0x42, 0x95, 0xac, 0x14, 0x78, 0x72, 0x29, - 0xe3, 0x38, 0x6b, 0x76, 0x8b, 0x7c, 0xaa, 0xb3, 0xb4, 0x0f, 0xf4, 0x52, 0xc6, 0xf7, 0x86, 0xc6, - 0x11, 0xad, 0x51, 0x2f, 0x65, 0x1a, 0x0a, 0x6a, 0xc6, 0xf4, 0xd6, 0x73, 0x9a, 0x6e, 0x52, 0xaf, - 0x14, 0x5d, 0x3c, 0xa3, 0x56, 0xfb, 0x13, 0x18, 0xaf, 0x76, 0xfd, 0xc0, 0x3d, 0xde, 0x39, 0xc2, - 0xc7, 0x78, 0xe1, 0x42, 0x78, 0xf5, 0x6c, 0xd2, 0xe2, 0x46, 0x40, 0xca, 0xd5, 0x61, 0x2a, 0xe0, - 0xe8, 0x0b, 0x40, 0xe2, 0x0e, 0xb9, 0x4a, 0xd6, 0x87, 0x43, 0xd6, 0xf2, 0xc2, 0x3c, 0x1d, 0x2b, - 0xbd, 0x38, 0x8a, 0xab, 0x67, 0xe3, 0x50, 0x56, 0xab, 0x9a, 0xc7, 0x38, 0x32, 0xe9, 0x10, 0xeb, - 0xe2, 0xaa, 0x67, 0x75, 0x8e, 0x16, 0x16, 0xc2, 0x9b, 0x20, 0x1f, 0xd4, 0x21, 0x29, 0xd7, 0x24, - 0xda, 0x10, 0x1c, 0xd5, 0x01, 0xd8, 0xcf, 0x0d, 0x32, 0xf1, 0x17, 0x29, 0xbf, 0x16, 0x34, 0x7e, - 0x91, 0x0a, 0xc1, 0xab, 0x8b, 0x54, 0x4e, 0x66, 0x64, 0xdb, 0xb6, 0x36, 0x9b, 0x0a, 0x19, 0xf4, - 0x14, 0x0a, 0xec, 0xd7, 0xa6, 0xeb, 0xd8, 0x01, 0xdb, 0x7a, 0x8b, 0x9a, 0x52, 0x31, 0x5a, 0x2d, - 0x1a, 0xa0, 0xca, 0x5c, 0xde, 0xc0, 0xb1, 0xac, 0x55, 0x9a, 0x89, 0x11, 0x46, 0x35, 0x18, 0xaf, - 0x79, 0x6e, 0xab, 0xdb, 0x0c, 0xa8, 0x50, 0x79, 0x89, 0x5e, 0x66, 0x10, 0x6f, 0x47, 0xa9, 0x61, - 0x3c, 0xe9, 0xb0, 0x82, 0x06, 0x39, 0x97, 0x55, 0x9e, 0x28, 0x80, 0x8f, 0x86, 0x46, 0xc7, 0x0b, - 0x13, 0xec, 0x3d, 0xee, 0xd1, 0xd0, 0xe8, 0x64, 0x61, 0xca, 0xf8, 0xbd, 0x1c, 0xa0, 0xf8, 0xea, - 0x46, 0x77, 0x61, 0x04, 0x3b, 0x44, 0x00, 0x6d, 0xf1, 0x5d, 0x9a, 0x9e, 0x49, 0xbc, 0x48, 0x55, - 0x1a, 0xf2, 0x22, 0xf4, 0x05, 0xcc, 0xb0, 0x8f, 0x41, 0x7c, 0x87, 0x6d, 0xfb, 0xd8, 0x0e, 0xe8, - 0xce, 0x3d, 0xcc, 0xe6, 0x3f, 0xa1, 0x5a, 0x55, 0x1c, 0xf0, 0x6a, 0xfa, 0xd5, 0x6e, 0x90, 0x4a, - 0xa3, 0x0b, 0x73, 0x89, 0xeb, 0x1a, 0x6d, 0xc2, 0xdc, 0xb1, 0xeb, 0x04, 0x47, 0xed, 0x97, 0x62, - 0x59, 0xf3, 0xd6, 0x72, 0xb4, 0x35, 0x3a, 0x95, 0x89, 0x00, 0xe6, 0x0c, 0x2f, 0xe6, 0x14, 0x69, - 0x3b, 0x8f, 0x86, 0x46, 0xf3, 0x85, 0x41, 0x39, 0x12, 0xc3, 0x84, 0xf3, 0xb1, 0xe5, 0x81, 0x3e, - 0x85, 0x89, 0x26, 0x15, 0xff, 0xb4, 0x96, 0xd8, 0xc7, 0xa1, 0x94, 0xab, 0x7c, 0x67, 0xe5, 0x6c, - 0x28, 0xff, 0x20, 0x07, 0xf3, 0x29, 0x0b, 0xe3, 0xec, 0xac, 0xfe, 0x0a, 0x2e, 0x1c, 0x5b, 0x2f, - 0x1a, 0x1e, 0x15, 0xc5, 0x1a, 0x9e, 0xe5, 0x44, 0xb8, 0xfd, 0xd6, 0xe9, 0x49, 0xe9, 0x6a, 0x32, - 0x84, 0x6a, 0x73, 0x70, 0x6c, 0xbd, 0x30, 0x29, 0x80, 0x49, 0xea, 0x59, 0x3f, 0xef, 0xc3, 0x79, - 0x26, 0xb6, 0xf5, 0xad, 0xae, 0x31, 0x6a, 0x00, 0x75, 0x7c, 0x6c, 0x75, 0x8e, 0x5c, 0x72, 0xc0, - 0x57, 0xd4, 0x5f, 0xfc, 0xba, 0x8f, 0xf8, 0xf5, 0x5b, 0x56, 0xec, 0x3d, 0x10, 0x5a, 0x36, 0x01, + 0x7a, 0x18, 0xcc, 0x6e, 0xde, 0x3f, 0xde, 0x5a, 0x45, 0x52, 0xa4, 0x5a, 0x94, 0x5a, 0x3a, 0x1a, + 0x69, 0x34, 0xda, 0x5d, 0x5d, 0xa8, 0x99, 0xd9, 0xb9, 0xcf, 0x76, 0x37, 0x29, 0x92, 0x12, 0x45, + 0xf6, 0x9c, 0x26, 0xa9, 0x99, 0xdd, 0xf1, 0xf6, 0x1e, 0x76, 0x97, 0xc8, 0xf3, 0xab, 0x79, 0x4e, + 0xef, 0x39, 0xa7, 0x75, 0x59, 0xff, 0xf6, 0xff, 0xdb, 0x4e, 0x8c, 0xbc, 0xc4, 0x71, 0x00, 0x3b, + 0xb0, 0x11, 0x03, 0x4e, 0x90, 0x04, 0x48, 0x02, 0x04, 0xf0, 0x4b, 0xe0, 0x87, 0x3c, 0x05, 0x09, + 0x90, 0x4d, 0x00, 0x03, 0x01, 0xec, 0xbc, 0xe4, 0x81, 0x8e, 0x17, 0xc8, 0x0b, 0xe1, 0x3c, 0x04, + 0x41, 0x12, 0x64, 0x91, 0x00, 0x41, 0x5d, 0x4f, 0xd5, 0xb9, 0x75, 0x53, 0xe2, 0x6c, 0xf2, 0x22, + 0xb1, 0xab, 0xbe, 0xef, 0xab, 0xaa, 0xaf, 0xea, 0x54, 0x7d, 0xf5, 0xd5, 0x77, 0x81, 0xdb, 0x01, + 0x6e, 0xe3, 0x8e, 0xeb, 0x05, 0x77, 0xda, 0xf8, 0xc0, 0x6a, 0xbe, 0xba, 0xd3, 0x6c, 0xdb, 0xd8, + 0x09, 0xee, 0x74, 0x3c, 0x37, 0x70, 0xef, 0x58, 0xdd, 0xe0, 0xd0, 0xc7, 0xde, 0x73, 0xbb, 0x89, + 0x6f, 0xd3, 0x12, 0x34, 0x4c, 0xff, 0x2b, 0xce, 0x1d, 0xb8, 0x07, 0x2e, 0x83, 0x21, 0x7f, 0xb1, + 0xca, 0xe2, 0xc5, 0x03, 0xd7, 0x3d, 0x68, 0x63, 0x86, 0xbc, 0xdf, 0x7d, 0x7a, 0x07, 0x1f, 0x75, + 0x82, 0x57, 0xbc, 0xb2, 0x14, 0xad, 0x0c, 0xec, 0x23, 0xec, 0x07, 0xd6, 0x51, 0x87, 0x03, 0xbc, + 0x23, 0xbb, 0x62, 0x05, 0x01, 0xa9, 0x09, 0x6c, 0xd7, 0xb9, 0xf3, 0xfc, 0x9e, 0xfa, 0x93, 0x83, + 0xde, 0xcc, 0xec, 0x75, 0x13, 0x7b, 0x81, 0xdf, 0x17, 0x24, 0x7e, 0x8e, 0x9d, 0x20, 0xd6, 0x3c, + 0x87, 0x0c, 0x5e, 0x75, 0xb0, 0xcf, 0x40, 0xc4, 0x7f, 0x1c, 0xf4, 0x6a, 0x32, 0x28, 0xfd, 0x97, + 0x83, 0x7c, 0x27, 0x19, 0xe4, 0x05, 0xde, 0x27, 0x3c, 0x75, 0xe4, 0x1f, 0x3d, 0xc0, 0x3d, 0xab, + 0xd3, 0xc1, 0x5e, 0xf8, 0x47, 0xac, 0xaf, 0x5d, 0xdf, 0x3a, 0xc0, 0xbc, 0x8f, 0xcf, 0xef, 0xa9, + 0x3f, 0x19, 0xa8, 0xf1, 0x87, 0x39, 0x18, 0x7e, 0x62, 0x05, 0xcd, 0x43, 0xf4, 0x39, 0x0c, 0x3f, + 0xb2, 0x9d, 0x96, 0xbf, 0x98, 0xbb, 0x32, 0x78, 0x73, 0x62, 0xb9, 0x70, 0x9b, 0xf5, 0x97, 0x56, + 0x92, 0x8a, 0xca, 0xc2, 0x4f, 0x8f, 0x4b, 0x03, 0x27, 0xc7, 0xa5, 0x99, 0x67, 0x04, 0xec, 0xdb, + 0xee, 0x91, 0x1d, 0xd0, 0x09, 0x34, 0x19, 0x1e, 0xda, 0x85, 0xd9, 0x72, 0xbb, 0xed, 0xbe, 0xa8, + 0x59, 0x5e, 0x60, 0x5b, 0xed, 0x7a, 0xb7, 0xd9, 0xc4, 0xbe, 0xbf, 0x98, 0xbf, 0x92, 0xbb, 0x39, + 0x56, 0xb9, 0x76, 0x72, 0x5c, 0x2a, 0x59, 0xa4, 0xba, 0xd1, 0x61, 0xf5, 0x0d, 0x9f, 0x01, 0x28, + 0x84, 0x92, 0xf0, 0x8d, 0xbf, 0x1c, 0x86, 0xc2, 0xba, 0xeb, 0x07, 0x55, 0x32, 0x6d, 0x26, 0xfe, + 0x71, 0x17, 0xfb, 0x01, 0xba, 0x06, 0x23, 0xa4, 0x6c, 0x63, 0x65, 0x31, 0x77, 0x25, 0x77, 0x73, + 0xbc, 0x32, 0x71, 0x72, 0x5c, 0x1a, 0x3d, 0x74, 0xfd, 0xa0, 0x61, 0xb7, 0x4c, 0x5e, 0x85, 0xde, + 0x81, 0xb1, 0x2d, 0xb7, 0x85, 0xb7, 0xac, 0x23, 0x4c, 0x7b, 0x31, 0x5e, 0x99, 0x3a, 0x39, 0x2e, + 0x8d, 0x3b, 0x6e, 0x0b, 0x37, 0x1c, 0xeb, 0x08, 0x9b, 0xb2, 0x1a, 0xed, 0xc1, 0x90, 0xe9, 0xb6, + 0xf1, 0xe2, 0x20, 0x05, 0xab, 0x9c, 0x1c, 0x97, 0x86, 0x3c, 0xb7, 0x8d, 0x7f, 0x7e, 0x5c, 0x7a, + 0xff, 0xc0, 0x0e, 0x0e, 0xbb, 0xfb, 0xb7, 0x9b, 0xee, 0xd1, 0x9d, 0x03, 0xcf, 0x7a, 0x6e, 0xb3, + 0x95, 0x66, 0xb5, 0xef, 0x84, 0xeb, 0xb1, 0x63, 0xf3, 0xc9, 0xad, 0xbf, 0xf2, 0x03, 0x7c, 0x44, + 0x28, 0x99, 0x94, 0x1e, 0x7a, 0x02, 0x73, 0xe5, 0x56, 0xcb, 0x66, 0x18, 0x35, 0xcf, 0x76, 0x9a, + 0x76, 0xc7, 0x6a, 0xfb, 0x8b, 0x43, 0x57, 0x06, 0x6f, 0x8e, 0x73, 0xa6, 0xc8, 0xfa, 0x46, 0x47, + 0x02, 0x28, 0x4c, 0x49, 0x24, 0x80, 0xee, 0xc3, 0xd8, 0xca, 0x56, 0x9d, 0xf4, 0xdd, 0x5f, 0x1c, + 0xa6, 0xc4, 0x16, 0x4e, 0x8e, 0x4b, 0xb3, 0x2d, 0xc7, 0xa7, 0x43, 0x53, 0x09, 0x48, 0x40, 0xf4, + 0x3e, 0x4c, 0xd6, 0xba, 0xfb, 0x6d, 0xbb, 0xb9, 0xb3, 0x59, 0x7f, 0x84, 0x5f, 0x2d, 0x8e, 0x5c, + 0xc9, 0xdd, 0x9c, 0xac, 0xa0, 0x93, 0xe3, 0xd2, 0x74, 0x87, 0x96, 0x37, 0x82, 0xb6, 0xdf, 0x78, + 0x86, 0x5f, 0x99, 0x1a, 0x5c, 0x88, 0x57, 0xaf, 0xaf, 0x13, 0xbc, 0xd1, 0x18, 0x9e, 0xef, 0x1f, + 0xaa, 0x78, 0x0c, 0x0e, 0xdd, 0x01, 0x30, 0xf1, 0x91, 0x1b, 0xe0, 0x72, 0xab, 0xe5, 0x2d, 0x8e, + 0x51, 0xde, 0xce, 0x9c, 0x1c, 0x97, 0x26, 0x3c, 0x5a, 0xda, 0xb0, 0x5a, 0x2d, 0xcf, 0x54, 0x40, + 0x50, 0x15, 0xc6, 0x4c, 0x97, 0x31, 0x78, 0x71, 0xfc, 0x4a, 0xee, 0xe6, 0xc4, 0xf2, 0x0c, 0x5f, + 0x86, 0xa2, 0xb8, 0x72, 0xfe, 0xe4, 0xb8, 0x84, 0x3c, 0xfe, 0x4b, 0x1d, 0xa5, 0x80, 0x40, 0x25, + 0x18, 0xdd, 0x72, 0xab, 0x56, 0xf3, 0x10, 0x2f, 0x02, 0x5d, 0x7b, 0xc3, 0x27, 0xc7, 0xa5, 0xdc, + 0x77, 0x4c, 0x51, 0x8a, 0x9e, 0xc3, 0x44, 0x38, 0x51, 0xfe, 0xe2, 0x04, 0x65, 0xdf, 0xce, 0xc9, + 0x71, 0xe9, 0xbc, 0x4f, 0x8b, 0x1b, 0x64, 0xea, 0x15, 0x0e, 0xbe, 0xc1, 0x2a, 0x50, 0x1b, 0x7a, + 0x38, 0x34, 0x36, 0x59, 0x98, 0x32, 0x2f, 0xed, 0x3a, 0x7e, 0x60, 0xed, 0xb7, 0x71, 0x58, 0x55, + 0xf6, 0x7d, 0xec, 0x11, 0x7a, 0x1b, 0x2b, 0xc6, 0xff, 0xca, 0x01, 0xda, 0xee, 0x60, 0xa7, 0x5e, + 0x5f, 0x27, 0x2b, 0x5e, 0x2c, 0xf8, 0x6f, 0xc3, 0x38, 0x63, 0x2d, 0xe1, 0x7f, 0x9e, 0xf2, 0x7f, + 0xfa, 0xe4, 0xb8, 0x04, 0x9c, 0xff, 0x84, 0xf7, 0x21, 0x00, 0xba, 0x0e, 0x83, 0x3b, 0x3b, 0x9b, + 0x74, 0x35, 0x0f, 0x56, 0x66, 0x4f, 0x8e, 0x4b, 0x83, 0x41, 0xd0, 0xfe, 0xf9, 0x71, 0x69, 0x6c, + 0xa5, 0xeb, 0xd1, 0x8e, 0x9b, 0xa4, 0x1e, 0x5d, 0x87, 0xd1, 0x6a, 0xbb, 0xeb, 0x07, 0xd8, 0x5b, + 0x1c, 0x0a, 0x3f, 0xa3, 0x26, 0x2b, 0x32, 0x45, 0x1d, 0xfa, 0x16, 0x0c, 0xed, 0xfa, 0xd8, 0x5b, + 0x1c, 0xa6, 0x33, 0x32, 0xc5, 0x67, 0x84, 0x14, 0xed, 0x2d, 0x57, 0xc6, 0xc8, 0xb7, 0xd2, 0xf5, + 0xb1, 0x67, 0x52, 0x20, 0x74, 0x1b, 0x86, 0x19, 0x5b, 0x47, 0xe8, 0x36, 0x32, 0x25, 0xe7, 0xaf, + 0x8d, 0xf7, 0xde, 0xaf, 0x8c, 0x9f, 0x1c, 0x97, 0x86, 0x29, 0x7b, 0xcd, 0x61, 0xc1, 0x94, 0x5c, + 0x21, 0x6f, 0x8e, 0x11, 0x5c, 0xb2, 0x70, 0x8d, 0x6f, 0xc1, 0x84, 0x32, 0x7c, 0xb4, 0x04, 0x43, + 0xe4, 0x7f, 0xfa, 0x99, 0x4f, 0xb2, 0xc6, 0xc8, 0xfe, 0x6d, 0xd2, 0x52, 0xe3, 0x0f, 0x66, 0xa0, + 0x40, 0x30, 0xb5, 0xbd, 0x41, 0x63, 0x55, 0xae, 0x17, 0xab, 0x6e, 0x82, 0x6c, 0x9b, 0x6f, 0x12, + 0x93, 0x27, 0xc7, 0xa5, 0xb1, 0x2e, 0x2f, 0x0b, 0x7b, 0x86, 0xea, 0x30, 0xba, 0xfa, 0xb2, 0x63, + 0x7b, 0xd8, 0xa7, 0x8c, 0x9d, 0x58, 0x2e, 0xde, 0x66, 0x67, 0xd6, 0x6d, 0x71, 0x66, 0xdd, 0xde, + 0x11, 0x67, 0x56, 0xe5, 0x12, 0xdf, 0x2c, 0xcf, 0x61, 0x86, 0x12, 0xae, 0xa6, 0xdf, 0xfe, 0xf3, + 0x52, 0xce, 0x14, 0x94, 0xd0, 0xb7, 0x61, 0xe4, 0x81, 0xeb, 0x1d, 0x59, 0x01, 0x9f, 0x81, 0xb9, + 0x93, 0xe3, 0x52, 0xe1, 0x29, 0x2d, 0x51, 0x16, 0x37, 0x87, 0x41, 0x0f, 0x60, 0xda, 0x74, 0xbb, + 0x01, 0xde, 0x71, 0xc5, 0xbc, 0x0d, 0x53, 0xac, 0xcb, 0x27, 0xc7, 0xa5, 0xa2, 0x47, 0x6a, 0x1a, + 0x81, 0xdb, 0xe0, 0x13, 0xa8, 0xe0, 0x47, 0xb0, 0xd0, 0x2a, 0x4c, 0x97, 0xe9, 0xee, 0xca, 0x79, + 0xc6, 0x66, 0x6b, 0xbc, 0x72, 0xe9, 0xe4, 0xb8, 0x74, 0xc1, 0xa2, 0x35, 0x0d, 0x8f, 0x57, 0xa9, + 0x64, 0x74, 0x24, 0xb4, 0x05, 0xe7, 0x1e, 0x75, 0xf7, 0xb1, 0xe7, 0xe0, 0x00, 0xfb, 0xa2, 0x47, + 0xa3, 0xb4, 0x47, 0x57, 0x4e, 0x8e, 0x4b, 0x4b, 0xcf, 0x64, 0x65, 0x42, 0x9f, 0xe2, 0xa8, 0x08, + 0xc3, 0x0c, 0xef, 0xe8, 0x8a, 0x15, 0x58, 0xfb, 0x96, 0x8f, 0xe9, 0xa6, 0x31, 0xb1, 0x7c, 0x9e, + 0xb1, 0xf8, 0x76, 0xa4, 0xb6, 0x72, 0x8d, 0x73, 0xf9, 0xa2, 0x1c, 0x7b, 0x8b, 0x57, 0x29, 0x0d, + 0x45, 0x69, 0x92, 0xbd, 0x53, 0x9e, 0x0b, 0xe3, 0xb4, 0xb7, 0x74, 0xef, 0x94, 0xe7, 0x82, 0xba, + 0xab, 0xc8, 0x13, 0x62, 0x13, 0x86, 0x77, 0xc9, 0xe9, 0x49, 0xf7, 0x94, 0xe9, 0xe5, 0xab, 0xbc, + 0x47, 0xd1, 0xd5, 0x77, 0x9b, 0xfc, 0xa0, 0x80, 0xf4, 0xbb, 0x9b, 0xa1, 0x27, 0xae, 0x7a, 0x56, + 0xd2, 0x3a, 0xf4, 0x05, 0x00, 0xef, 0x55, 0xb9, 0xd3, 0x59, 0x9c, 0xa0, 0x83, 0x3c, 0xa7, 0x0f, + 0xb2, 0xdc, 0xe9, 0x54, 0x2e, 0xf3, 0xf1, 0x9d, 0x97, 0xe3, 0xb3, 0x3a, 0x1d, 0x85, 0x9a, 0x42, + 0x04, 0x7d, 0x0e, 0x93, 0x74, 0xcb, 0x11, 0x33, 0x3a, 0x49, 0x67, 0xf4, 0xe2, 0xc9, 0x71, 0x69, + 0x81, 0x7c, 0x70, 0x49, 0xf3, 0xa9, 0x21, 0xa0, 0x5f, 0x85, 0x79, 0x4e, 0xee, 0x89, 0xed, 0xb4, + 0xdc, 0x17, 0xfe, 0x0a, 0xf6, 0x9f, 0x05, 0x6e, 0x67, 0x71, 0x8a, 0x76, 0x6f, 0x49, 0xef, 0x9e, + 0x0e, 0x53, 0xb9, 0xc5, 0x7b, 0x6a, 0xc8, 0x9e, 0xbe, 0x60, 0x00, 0x8d, 0x16, 0x83, 0x50, 0x9a, + 0x4d, 0x6e, 0x06, 0x6d, 0xc0, 0xcc, 0xae, 0x8f, 0xb5, 0x31, 0x4c, 0xd3, 0xfd, 0xbb, 0x44, 0x66, + 0xb8, 0xeb, 0xe3, 0x46, 0xda, 0x38, 0xa2, 0x78, 0xc8, 0x04, 0xb4, 0xe2, 0xb9, 0x9d, 0xc8, 0x1a, + 0x9f, 0xa1, 0x1c, 0x31, 0x4e, 0x8e, 0x4b, 0x97, 0x5b, 0x9e, 0xdb, 0x69, 0xa4, 0x2f, 0xf4, 0x04, + 0x6c, 0xf4, 0x43, 0x38, 0x5f, 0x75, 0x1d, 0x07, 0x37, 0xc9, 0xfe, 0xb9, 0x62, 0x5b, 0x07, 0x8e, + 0xeb, 0x07, 0x76, 0x73, 0x63, 0x65, 0xb1, 0x40, 0xd7, 0xd0, 0x0d, 0x32, 0xfa, 0xa6, 0x84, 0x68, + 0xb4, 0x24, 0x48, 0xc3, 0x6e, 0x29, 0xb4, 0x53, 0xa8, 0xa0, 0x1f, 0xc0, 0x14, 0x6f, 0x0b, 0x7b, + 0x74, 0x69, 0x9e, 0xcb, 0x5e, 0x68, 0x12, 0x98, 0x1d, 0xc4, 0x9e, 0xf8, 0xc9, 0x44, 0x1b, 0x9d, + 0x16, 0xfa, 0x1a, 0x26, 0x1e, 0x3f, 0x28, 0x9b, 0xd8, 0xef, 0xb8, 0x8e, 0x8f, 0x17, 0x11, 0x9d, + 0xd1, 0xcb, 0x9c, 0xf4, 0xe3, 0x07, 0xe5, 0x72, 0x37, 0x38, 0xc4, 0x4e, 0x60, 0x37, 0xad, 0x00, + 0x0b, 0xa8, 0x4a, 0x91, 0xac, 0xbc, 0xa3, 0xa7, 0x56, 0xc3, 0xe3, 0x25, 0xca, 0x28, 0x54, 0x72, + 0xa8, 0x08, 0x63, 0xf5, 0xfa, 0xfa, 0xa6, 0x7b, 0x60, 0x3b, 0x8b, 0xb3, 0x84, 0x19, 0xa6, 0xfc, + 0x8d, 0xf6, 0x61, 0x5e, 0x11, 0xd0, 0x1b, 0xe4, 0x7f, 0x7c, 0x84, 0x9d, 0x60, 0x71, 0x8e, 0xf6, + 0xe1, 0x3b, 0xf2, 0x86, 0x71, 0x5b, 0x95, 0xe3, 0x9f, 0xdf, 0xbb, 0x5d, 0x0e, 0x7f, 0xd6, 0x05, + 0x92, 0x39, 0x67, 0x25, 0x94, 0xa2, 0x1d, 0x18, 0xad, 0x75, 0xbd, 0x8e, 0xeb, 0xe3, 0xc5, 0x79, + 0xca, 0xb4, 0x6b, 0x59, 0x5f, 0x27, 0x07, 0xad, 0xcc, 0x93, 0xed, 0xb9, 0xc3, 0x7e, 0x28, 0x23, + 0x13, 0xa4, 0x8c, 0x2f, 0x61, 0x5c, 0x7e, 0xcc, 0x68, 0x14, 0x06, 0xcb, 0xed, 0x76, 0x61, 0x80, + 0xfc, 0x51, 0xaf, 0xaf, 0x17, 0x72, 0x68, 0x1a, 0x20, 0xdc, 0xc1, 0x0a, 0x79, 0x34, 0x09, 0x63, + 0x62, 0x87, 0x29, 0x0c, 0x52, 0xf8, 0x4e, 0xa7, 0x30, 0x84, 0x10, 0x4c, 0xeb, 0xeb, 0xbc, 0x30, + 0x6c, 0xbc, 0x84, 0x71, 0x39, 0x3d, 0x68, 0x06, 0x26, 0x76, 0xb7, 0xea, 0xb5, 0xd5, 0xea, 0xc6, + 0x83, 0x8d, 0xd5, 0x95, 0xc2, 0x00, 0xba, 0x04, 0x17, 0x76, 0xea, 0xeb, 0x8d, 0x95, 0x4a, 0x63, + 0x73, 0xbb, 0x5a, 0xde, 0x6c, 0xd4, 0xcc, 0xed, 0x2f, 0xbf, 0x6a, 0xec, 0xec, 0x6e, 0x6d, 0xad, + 0x6e, 0x16, 0x72, 0x68, 0x11, 0xe6, 0x48, 0xf5, 0xa3, 0xdd, 0xca, 0xaa, 0x0a, 0x50, 0xc8, 0xa3, + 0xab, 0x70, 0x29, 0xa9, 0xa6, 0xb1, 0xbe, 0x5a, 0x5e, 0xd9, 0x5c, 0xad, 0xd7, 0x0b, 0x83, 0x46, + 0x1b, 0x26, 0x14, 0x16, 0xa0, 0x25, 0x58, 0xac, 0xae, 0x9a, 0x3b, 0x8d, 0xda, 0xae, 0x59, 0xdb, + 0xae, 0xaf, 0x36, 0xf4, 0x8e, 0x44, 0x6b, 0x37, 0xb7, 0xd7, 0x36, 0xb6, 0x1a, 0xa4, 0xa8, 0x5e, + 0xc8, 0x91, 0xd6, 0xb4, 0xda, 0xfa, 0xc6, 0xd6, 0xda, 0xe6, 0x6a, 0x63, 0xb7, 0xbe, 0xca, 0x41, + 0xf2, 0xc6, 0xaf, 0xe7, 0x63, 0x1b, 0x3a, 0x5a, 0x86, 0x89, 0x3a, 0xbb, 0x32, 0xd2, 0x45, 0xce, + 0xc4, 0xf7, 0xc2, 0xc9, 0x71, 0x69, 0x92, 0xdf, 0x24, 0xd9, 0xfa, 0x55, 0x81, 0xc8, 0x19, 0x5d, + 0x23, 0xf3, 0xd9, 0x74, 0xdb, 0xea, 0x19, 0xdd, 0xe1, 0x65, 0xa6, 0xac, 0x45, 0xcb, 0xca, 0x69, + 0xce, 0x64, 0x79, 0x2a, 0x2f, 0x8a, 0xd3, 0x5c, 0xdd, 0xd9, 0xe5, 0xb9, 0xbe, 0x1c, 0x4e, 0x1c, + 0x3f, 0x84, 0x29, 0x4e, 0xc2, 0x49, 0x22, 0xe1, 0xd0, 0x3b, 0x42, 0xca, 0x61, 0xb2, 0x37, 0xdd, + 0xea, 0x23, 0x52, 0x23, 0x17, 0x70, 0x8c, 0x6e, 0xca, 0xb6, 0x8a, 0x3e, 0x8e, 0xae, 0x0c, 0xce, + 0x0c, 0x4a, 0x2c, 0xb2, 0x7b, 0x9a, 0x11, 0x50, 0x54, 0x82, 0x61, 0xf6, 0xbd, 0x31, 0x7e, 0x50, + 0xb9, 0xaa, 0x4d, 0x0a, 0x4c, 0x56, 0x6e, 0xfc, 0xd6, 0xa0, 0x7a, 0xc4, 0x10, 0x39, 0x4a, 0xe1, + 0x37, 0x95, 0xa3, 0x28, 0x9f, 0x69, 0x29, 0x11, 0x99, 0xea, 0xd8, 0xf7, 0xa9, 0x04, 0xca, 0x29, + 0x52, 0x91, 0xc9, 0x67, 0x85, 0xe4, 0x52, 0x15, 0x02, 0x10, 0xb1, 0x9e, 0xc9, 0x4f, 0x54, 0xac, + 0x1f, 0x0c, 0xc5, 0x7a, 0x2e, 0x61, 0x31, 0xb1, 0x3e, 0x04, 0x21, 0x73, 0xce, 0x8f, 0x78, 0xda, + 0x87, 0xa1, 0x70, 0xce, 0xb9, 0x58, 0xc0, 0xe7, 0x5c, 0x01, 0x42, 0x1f, 0x01, 0x94, 0x9f, 0xd4, + 0xa9, 0x74, 0x6c, 0x6e, 0x71, 0x31, 0x87, 0x6e, 0x48, 0xd6, 0x0b, 0x9f, 0x1d, 0x04, 0x96, 0xa7, + 0xca, 0xff, 0x0a, 0x34, 0xaa, 0xc0, 0x54, 0xf9, 0x27, 0x5d, 0x0f, 0x6f, 0xb4, 0xc8, 0x9e, 0x16, + 0xb0, 0x8b, 0xce, 0x78, 0x65, 0xe9, 0xe4, 0xb8, 0xb4, 0x68, 0x91, 0x8a, 0x86, 0xcd, 0x6b, 0x14, + 0x02, 0x3a, 0x0a, 0xda, 0x86, 0x73, 0x6b, 0xd5, 0x1a, 0x5f, 0x85, 0xe5, 0x66, 0xd3, 0xed, 0x3a, + 0x01, 0x97, 0x6d, 0xae, 0x9e, 0x1c, 0x97, 0x2e, 0x1d, 0x34, 0x3b, 0x0d, 0xb1, 0x62, 0x2d, 0x56, + 0xad, 0x0a, 0x37, 0x31, 0x5c, 0xa3, 0x0d, 0xd3, 0x6b, 0x38, 0x20, 0xab, 0x4e, 0x08, 0xaa, 0xd9, + 0x73, 0xf2, 0x09, 0x4c, 0x3c, 0xb1, 0x83, 0xc3, 0x3a, 0x6e, 0x7a, 0x38, 0x10, 0xd7, 0x68, 0xca, + 0x81, 0x17, 0x76, 0x70, 0xd8, 0xf0, 0x59, 0xb9, 0xba, 0x25, 0x2b, 0xe0, 0xc6, 0x2a, 0xcc, 0xf0, + 0xd6, 0xa4, 0x5c, 0xbc, 0xac, 0x13, 0xcc, 0x51, 0x82, 0x74, 0x16, 0x54, 0x82, 0x3a, 0x99, 0x7f, + 0x9a, 0x87, 0xf9, 0xea, 0xa1, 0xe5, 0x1c, 0xe0, 0x9a, 0xe5, 0xfb, 0x2f, 0x5c, 0xaf, 0xa5, 0x74, + 0x9e, 0x5e, 0x0a, 0x62, 0x9d, 0xa7, 0xb7, 0x80, 0x65, 0x98, 0xd8, 0x6e, 0xb7, 0x04, 0x0e, 0xbf, + 0xb0, 0xd0, 0xb6, 0xdc, 0x76, 0xab, 0xd1, 0x11, 0xb4, 0x54, 0x20, 0x82, 0xb3, 0x85, 0x5f, 0x48, + 0x9c, 0xc1, 0x10, 0xc7, 0xc1, 0x2f, 0x14, 0x1c, 0x05, 0x08, 0xad, 0xc2, 0xb9, 0x3a, 0x6e, 0xba, + 0x4e, 0xeb, 0x81, 0xd5, 0x0c, 0x5c, 0x6f, 0xc7, 0x7d, 0x86, 0x1d, 0xbe, 0xbe, 0xa8, 0x4c, 0xe7, + 0xd3, 0xca, 0xc6, 0x53, 0x5a, 0xdb, 0x08, 0x48, 0xb5, 0x19, 0xc7, 0x40, 0xdb, 0x30, 0xf6, 0x84, + 0x6b, 0x5c, 0xf8, 0x2d, 0xe7, 0xfa, 0x6d, 0xa9, 0x82, 0xa9, 0x7a, 0x98, 0x2e, 0x0a, 0xab, 0x2d, + 0xef, 0x69, 0xf2, 0x88, 0xa4, 0xfb, 0x90, 0x80, 0x34, 0x25, 0x11, 0x63, 0x17, 0xa6, 0x6a, 0xed, + 0xee, 0x81, 0xed, 0x90, 0x1d, 0xa3, 0x8e, 0x7f, 0x8c, 0x56, 0x00, 0xc2, 0x02, 0xae, 0x62, 0x99, + 0xe5, 0x77, 0xa3, 0xb0, 0x62, 0xef, 0x3e, 0xff, 0x90, 0x68, 0x09, 0x15, 0x66, 0x4d, 0x05, 0xcf, + 0xf8, 0x1f, 0x83, 0x80, 0xf8, 0x04, 0xd0, 0xd3, 0xaf, 0x8e, 0x03, 0x72, 0x84, 0x9c, 0x87, 0xbc, + 0xd4, 0x84, 0x8c, 0x9c, 0x1c, 0x97, 0xf2, 0x76, 0xcb, 0xcc, 0x6f, 0xac, 0xa0, 0x77, 0x61, 0x98, + 0x82, 0x51, 0xfe, 0x4f, 0xcb, 0xf6, 0x54, 0x0a, 0x6c, 0xe7, 0xa0, 0xa7, 0xb2, 0xc9, 0x80, 0xd1, + 0x7b, 0x30, 0xbe, 0x82, 0xdb, 0xf8, 0xc0, 0x0a, 0x5c, 0xf1, 0x75, 0x33, 0xdd, 0x82, 0x28, 0x54, + 0xd6, 0x5c, 0x08, 0x49, 0x6e, 0x32, 0x26, 0xb6, 0x7c, 0xd7, 0x51, 0x6f, 0x32, 0x1e, 0x2d, 0x51, + 0x6f, 0x32, 0x0c, 0x06, 0xfd, 0x6e, 0x0e, 0x26, 0xca, 0x8e, 0xc3, 0xef, 0xec, 0x3e, 0xe7, 0xfa, + 0xfc, 0x6d, 0xa9, 0xc9, 0xda, 0xb4, 0xf6, 0x71, 0x7b, 0xcf, 0x6a, 0x77, 0xb1, 0x5f, 0xf9, 0x9a, + 0x08, 0x97, 0xff, 0xfe, 0xb8, 0xf4, 0xf1, 0x29, 0x6e, 0xe1, 0xa1, 0x4e, 0x6c, 0xc7, 0xb3, 0xec, + 0xc0, 0x3f, 0x39, 0x2e, 0xcd, 0x5b, 0x61, 0x83, 0xea, 0x77, 0xa3, 0xf4, 0x23, 0xdc, 0xd8, 0x47, + 0x7a, 0x6d, 0xec, 0xe8, 0x08, 0x66, 0xca, 0xbe, 0xdf, 0x3d, 0xc2, 0xf5, 0xc0, 0xf2, 0x02, 0x72, + 0xf5, 0xa3, 0xfb, 0x43, 0xf6, 0xbd, 0xf0, 0xed, 0x9f, 0x1e, 0x97, 0x72, 0x44, 0x9e, 0xb5, 0x28, + 0x2a, 0x91, 0x87, 0xbc, 0xa0, 0x11, 0xd8, 0xea, 0xd9, 0x44, 0x6f, 0x88, 0x51, 0xda, 0xc6, 0x35, + 0x29, 0x34, 0x6c, 0xac, 0xa4, 0xcd, 0xb8, 0x51, 0x85, 0xa5, 0x35, 0x1c, 0x98, 0xd8, 0xc7, 0x81, + 0xf8, 0x46, 0xe8, 0x0a, 0x0f, 0xf5, 0x66, 0xa3, 0xf4, 0xb7, 0x44, 0xa6, 0xd3, 0xcf, 0xbe, 0x0b, + 0x51, 0x63, 0xfc, 0x95, 0x1c, 0x94, 0xaa, 0x1e, 0x66, 0xa2, 0x60, 0x0a, 0xa1, 0xec, 0xbd, 0x6b, + 0x09, 0x86, 0x76, 0x5e, 0x75, 0xc4, 0x85, 0x9a, 0xd6, 0x92, 0x49, 0x31, 0x69, 0x69, 0x9f, 0xda, + 0x09, 0xe3, 0x29, 0xcc, 0x9b, 0xd8, 0xc1, 0x2f, 0xac, 0xfd, 0x36, 0xd6, 0x2e, 0xf8, 0x25, 0x18, + 0x66, 0x1f, 0x7a, 0x6c, 0x08, 0xac, 0xfc, 0x74, 0xca, 0x12, 0xe3, 0x1f, 0xe5, 0xa1, 0xc0, 0x86, + 0x5b, 0x71, 0x83, 0xfe, 0xc6, 0xc7, 0x47, 0x90, 0xef, 0xa1, 0x5f, 0xb9, 0x11, 0x72, 0x7b, 0x30, + 0x14, 0x5b, 0x68, 0x57, 0xc9, 0x91, 0x2a, 0x2a, 0xc9, 0x80, 0xd8, 0xa2, 0x63, 0x6a, 0xc1, 0x98, + 0x92, 0x04, 0xfd, 0x66, 0x0e, 0x46, 0xd8, 0x32, 0xce, 0xfe, 0x50, 0x9e, 0x9c, 0xcd, 0x87, 0x52, + 0x08, 0xe8, 0x5f, 0xea, 0x67, 0xcb, 0xea, 0x8c, 0x7f, 0x92, 0x87, 0x73, 0x0a, 0xaf, 0xb8, 0xfc, + 0xff, 0x0e, 0x93, 0xba, 0x14, 0x86, 0x51, 0x45, 0x2b, 0x91, 0xba, 0x1a, 0xa1, 0x12, 0x85, 0x72, + 0xee, 0x1d, 0x18, 0x23, 0x43, 0x8a, 0xea, 0x64, 0xe9, 0x81, 0xce, 0x40, 0x45, 0x75, 0xdf, 0xdc, + 0xbb, 0x03, 0x63, 0xf4, 0x4f, 0x32, 0x23, 0x43, 0xe9, 0x33, 0x22, 0x81, 0x90, 0x0d, 0xf0, 0xd0, + 0xb5, 0x9d, 0xc7, 0x38, 0x38, 0x74, 0x5b, 0x5c, 0xb4, 0xd8, 0x20, 0xdb, 0xee, 0xff, 0xe3, 0xda, + 0x4e, 0xe3, 0x88, 0x16, 0x9f, 0x56, 0xe7, 0x17, 0x12, 0x34, 0x15, 0xe2, 0xc6, 0x5d, 0x28, 0x90, + 0x1d, 0xb2, 0xff, 0xa5, 0x65, 0xcc, 0x01, 0x5a, 0xc3, 0x41, 0xc5, 0xd5, 0xce, 0x6e, 0x63, 0x0a, + 0x26, 0x6a, 0xb6, 0x73, 0x20, 0x7e, 0xfe, 0xd1, 0x20, 0x4c, 0xb2, 0xdf, 0x7c, 0x06, 0x22, 0x12, + 0x56, 0xae, 0x1f, 0x09, 0xeb, 0x03, 0x98, 0x22, 0x22, 0x0a, 0xf6, 0xf6, 0xb0, 0x47, 0x24, 0x3b, + 0x3e, 0x1f, 0xf4, 0x36, 0xe9, 0xd3, 0x8a, 0xc6, 0x73, 0x56, 0x63, 0xea, 0x80, 0x68, 0x13, 0xa6, + 0x59, 0xc1, 0x03, 0x6c, 0x05, 0xdd, 0x50, 0x21, 0x36, 0xc3, 0xaf, 0x5d, 0xa2, 0x98, 0x6d, 0x9f, + 0x9c, 0xd6, 0x53, 0x5e, 0x68, 0x46, 0x70, 0xd1, 0xe7, 0x30, 0x53, 0xf3, 0xdc, 0x97, 0xaf, 0x14, + 0x99, 0x92, 0x9d, 0x20, 0xec, 0x82, 0x46, 0xaa, 0x1a, 0xaa, 0x64, 0x19, 0x85, 0x26, 0x6b, 0x6a, + 0xc3, 0xaf, 0xb8, 0x9e, 0xed, 0x1c, 0xd0, 0xd9, 0x1c, 0x63, 0x6b, 0xca, 0xf6, 0x1b, 0xfb, 0xb4, + 0xd0, 0x94, 0xd5, 0x11, 0x8d, 0xf4, 0x68, 0x6f, 0x8d, 0xf4, 0x5d, 0x80, 0x4d, 0xd7, 0x6a, 0x95, + 0xdb, 0xed, 0x6a, 0xd9, 0xa7, 0xda, 0x28, 0x2e, 0x33, 0xb5, 0x5d, 0xab, 0xd5, 0xb0, 0xda, 0xed, + 0x46, 0xd3, 0xf2, 0x4d, 0x05, 0xe6, 0xe1, 0xd0, 0xd8, 0x48, 0x61, 0xd4, 0x9c, 0xd9, 0xb4, 0x9b, + 0xd8, 0xf1, 0xf1, 0x13, 0xcb, 0x73, 0x6c, 0xe7, 0xc0, 0x37, 0xfe, 0x60, 0x02, 0xc6, 0xe4, 0x90, + 0x6f, 0xab, 0x77, 0x47, 0x2e, 0x89, 0xd1, 0x1d, 0x2a, 0xd4, 0x98, 0x99, 0x0a, 0x04, 0xba, 0x40, + 0x6f, 0x93, 0x5c, 0x06, 0x1c, 0x25, 0xab, 0xdb, 0xea, 0x74, 0x4c, 0x52, 0x46, 0x4e, 0x82, 0x95, + 0x0a, 0xe5, 0xff, 0x18, 0x3b, 0x09, 0x5a, 0xfb, 0x66, 0x7e, 0xa5, 0x42, 0x56, 0xd9, 0xf6, 0xc6, + 0x4a, 0x95, 0xb2, 0x72, 0x8c, 0xad, 0x32, 0xd7, 0x6e, 0x35, 0x4d, 0x5a, 0x4a, 0x6a, 0xeb, 0xe5, + 0xc7, 0x9b, 0x9c, 0x5d, 0xb4, 0xd6, 0xb7, 0x8e, 0xda, 0x26, 0x2d, 0x25, 0x37, 0x13, 0xa6, 0xfc, + 0xa8, 0xba, 0x4e, 0xe0, 0xb9, 0x6d, 0x9f, 0x0a, 0xd0, 0x63, 0x6c, 0x3a, 0xb9, 0xd6, 0xa4, 0xc9, + 0xab, 0xcc, 0x08, 0x28, 0x7a, 0x02, 0x0b, 0xe5, 0xd6, 0x73, 0xcb, 0x69, 0xe2, 0x16, 0xab, 0x79, + 0xe2, 0x7a, 0xcf, 0x9e, 0xb6, 0xdd, 0x17, 0x3e, 0xe5, 0xf7, 0x18, 0x57, 0x32, 0x72, 0x10, 0xa1, + 0x84, 0x79, 0x21, 0x80, 0xcc, 0x34, 0x6c, 0xb2, 0x4b, 0x56, 0xdb, 0x6e, 0xb7, 0xc5, 0x67, 0x81, + 0xee, 0x92, 0x4d, 0x52, 0x60, 0xb2, 0x72, 0xc2, 0xa5, 0xf5, 0xfa, 0x63, 0xaa, 0xd2, 0xe3, 0x5c, + 0x3a, 0xf4, 0x8f, 0x4c, 0x52, 0x86, 0xae, 0xc3, 0xa8, 0xb8, 0x64, 0xb1, 0x37, 0x01, 0xaa, 0xe9, + 0x16, 0x97, 0x2b, 0x51, 0x47, 0x3e, 0x09, 0x13, 0x37, 0xdd, 0xe7, 0xd8, 0x7b, 0x55, 0x75, 0x5b, + 0x58, 0x28, 0xa0, 0xb8, 0x82, 0x85, 0x55, 0x34, 0x9a, 0xa4, 0xc6, 0xd4, 0x01, 0x49, 0x03, 0x4c, + 0x4e, 0xf3, 0x17, 0x67, 0xc2, 0x06, 0x98, 0x1c, 0xe7, 0x9b, 0xa2, 0x0e, 0xad, 0xc0, 0xb9, 0x72, + 0x37, 0x70, 0x8f, 0xac, 0xc0, 0x6e, 0xee, 0x76, 0x0e, 0x3c, 0x8b, 0x34, 0x52, 0xa0, 0x08, 0xf4, + 0xd2, 0x69, 0x89, 0xca, 0x46, 0x97, 0xd7, 0x9a, 0x71, 0x04, 0xf4, 0x3e, 0x4c, 0x6e, 0xf8, 0x4c, + 0xc9, 0x68, 0xf9, 0xb8, 0x45, 0x35, 0x45, 0xbc, 0x97, 0xb6, 0xdf, 0xa0, 0x2a, 0xc7, 0x06, 0xb9, + 0xa6, 0xb6, 0x4c, 0x0d, 0x0e, 0x19, 0x30, 0x52, 0xf6, 0x7d, 0xdb, 0x0f, 0xa8, 0x02, 0x68, 0xac, + 0x02, 0x27, 0xc7, 0xa5, 0x11, 0x8b, 0x96, 0x98, 0xbc, 0x06, 0x3d, 0x81, 0x89, 0x15, 0x4c, 0xee, + 0x2d, 0x3b, 0x5e, 0xd7, 0x0f, 0xa8, 0x3a, 0x67, 0x62, 0xf9, 0x02, 0xff, 0xb0, 0x95, 0x1a, 0xbe, + 0x96, 0xd9, 0x8d, 0xa4, 0x45, 0xcb, 0x1b, 0x01, 0xa9, 0x50, 0x25, 0x2b, 0x05, 0x9e, 0x5c, 0xca, + 0x38, 0xce, 0xba, 0xdd, 0x22, 0x9f, 0xea, 0x1c, 0xed, 0x03, 0xbd, 0x94, 0xf1, 0xbd, 0xa1, 0x71, + 0x48, 0x6b, 0xd4, 0x4b, 0x99, 0x86, 0x82, 0x9a, 0x31, 0xbd, 0xf5, 0xbc, 0xa6, 0x9b, 0xd4, 0x2b, + 0x45, 0x17, 0x4f, 0xa9, 0xd5, 0xfe, 0x04, 0x26, 0xaa, 0x5d, 0x3f, 0x70, 0x8f, 0x76, 0x0e, 0xf1, + 0x11, 0x5e, 0x3c, 0x1f, 0x5e, 0x3d, 0x9b, 0xb4, 0xb8, 0x11, 0x90, 0x72, 0x75, 0x98, 0x0a, 0x38, + 0xfa, 0x02, 0x90, 0xb8, 0x43, 0xae, 0x91, 0xf5, 0xe1, 0x90, 0xb5, 0xbc, 0xb8, 0x40, 0xc7, 0x4a, + 0x2f, 0x8e, 0xe2, 0xea, 0xd9, 0x38, 0x90, 0xd5, 0xaa, 0xe6, 0x31, 0x8e, 0x4c, 0x3a, 0xc4, 0xba, + 0xb8, 0xe6, 0x59, 0x9d, 0xc3, 0xc5, 0xc5, 0xf0, 0x26, 0xc8, 0x07, 0x75, 0x40, 0xca, 0x35, 0x89, + 0x36, 0x04, 0x47, 0x75, 0x00, 0xf6, 0x73, 0x93, 0x4c, 0xfc, 0x05, 0xca, 0xaf, 0x45, 0x8d, 0x5f, + 0xa4, 0x42, 0xf0, 0xea, 0x02, 0x95, 0x93, 0x19, 0xd9, 0xb6, 0xad, 0xcd, 0xa6, 0x42, 0x06, 0x3d, + 0x83, 0x02, 0xfb, 0xf5, 0xd8, 0x75, 0xec, 0x80, 0x6d, 0xbd, 0x45, 0x4d, 0xa9, 0x18, 0xad, 0x16, + 0x0d, 0x50, 0x65, 0x2e, 0x6f, 0xe0, 0x48, 0xd6, 0x2a, 0xcd, 0xc4, 0x08, 0xa3, 0x1a, 0x4c, 0xd4, + 0x3c, 0xb7, 0xd5, 0x6d, 0x06, 0x54, 0xa8, 0xbc, 0x48, 0x2f, 0x33, 0x88, 0xb7, 0xa3, 0xd4, 0x30, + 0x9e, 0x74, 0x58, 0x41, 0x83, 0x9c, 0xcb, 0x2a, 0x4f, 0x14, 0xc0, 0x87, 0x43, 0x63, 0x13, 0x85, + 0x49, 0xf6, 0x1e, 0xf7, 0x70, 0x68, 0x6c, 0xaa, 0x30, 0x6d, 0xfc, 0x5e, 0x0e, 0x50, 0x7c, 0x75, + 0xa3, 0x3b, 0x30, 0x8a, 0x1d, 0x22, 0x80, 0xb6, 0xf8, 0x2e, 0x4d, 0xcf, 0x24, 0x5e, 0xa4, 0x2a, + 0x0d, 0x79, 0x11, 0xfa, 0x02, 0x66, 0xd9, 0xc7, 0x20, 0xbe, 0xc3, 0xb6, 0x7d, 0x64, 0x07, 0x74, + 0xe7, 0x1e, 0x66, 0xf3, 0x9f, 0x50, 0xad, 0x2a, 0x0e, 0x78, 0x35, 0xfd, 0x6a, 0x37, 0x49, 0xa5, + 0xd1, 0x85, 0xf9, 0xc4, 0x75, 0x8d, 0x1e, 0xc3, 0xfc, 0x91, 0xeb, 0x04, 0x87, 0xed, 0x57, 0x62, + 0x59, 0xf3, 0xd6, 0x72, 0xb4, 0x35, 0x3a, 0x95, 0x89, 0x00, 0xe6, 0x2c, 0x2f, 0xe6, 0x14, 0x69, + 0x3b, 0x0f, 0x87, 0xc6, 0xf2, 0x85, 0x41, 0x39, 0x12, 0xc3, 0x84, 0x73, 0xb1, 0xe5, 0x81, 0x3e, + 0x85, 0xc9, 0x26, 0x15, 0xff, 0xb4, 0x96, 0xd8, 0xc7, 0xa1, 0x94, 0xab, 0x7c, 0x67, 0xe5, 0x6c, + 0x28, 0xff, 0x20, 0x07, 0x0b, 0x29, 0x0b, 0xe3, 0xf4, 0xac, 0xfe, 0x0a, 0xce, 0x1f, 0x59, 0x2f, + 0x1b, 0x1e, 0x15, 0xc5, 0x1a, 0x9e, 0xe5, 0x44, 0xb8, 0xfd, 0xd6, 0xc9, 0x71, 0xe9, 0x4a, 0x32, + 0x84, 0x6a, 0x73, 0x70, 0x64, 0xbd, 0x34, 0x29, 0x80, 0x49, 0xea, 0x59, 0x3f, 0xef, 0xc1, 0x39, + 0x26, 0xb6, 0xf5, 0xad, 0xae, 0x31, 0x6a, 0x00, 0x75, 0x7c, 0x64, 0x75, 0x0e, 0x5d, 0x72, 0xc0, + 0x57, 0xd4, 0x5f, 0xfc, 0xba, 0x8f, 0xf8, 0xf5, 0x5b, 0x56, 0xec, 0xdd, 0x17, 0x5a, 0x36, 0x01, 0x69, 0x2a, 0x58, 0xc6, 0x9f, 0xe4, 0x01, 0x95, 0xbb, 0x2d, 0x3b, 0xa8, 0x07, 0x1e, 0xb6, 0x8e, - 0x45, 0x37, 0x3e, 0x84, 0x09, 0x26, 0x81, 0xb3, 0x62, 0xda, 0x9d, 0xf1, 0xa5, 0x19, 0xfe, 0x39, - 0xa8, 0x55, 0x6b, 0x03, 0xa6, 0x06, 0x4a, 0x50, 0x4d, 0xcc, 0x6e, 0x95, 0x14, 0x35, 0xaf, 0xa1, - 0xaa, 0x55, 0x04, 0x55, 0xfd, 0x8d, 0x3e, 0x87, 0xa9, 0xaa, 0x7b, 0xdc, 0x21, 0x3c, 0xe1, 0xc8, - 0x83, 0xfc, 0x22, 0xc2, 0xdb, 0xd5, 0x2a, 0xd7, 0x06, 0xcc, 0x08, 0x38, 0xda, 0x82, 0x99, 0x87, - 0xed, 0xae, 0x7f, 0x54, 0x76, 0x5a, 0xd5, 0xb6, 0xeb, 0x0b, 0x2a, 0x43, 0xfc, 0xc6, 0xcc, 0x05, - 0xc7, 0x38, 0xc4, 0xda, 0x80, 0x99, 0x84, 0x88, 0x6e, 0xc0, 0xf0, 0xca, 0x33, 0xec, 0x04, 0xf2, - 0x55, 0x9a, 0x9b, 0xb5, 0x6c, 0x3b, 0x78, 0xfb, 0xc9, 0xda, 0x80, 0xc9, 0x6a, 0x2b, 0x63, 0x30, - 0x22, 0x84, 0xe6, 0xbb, 0xe4, 0xec, 0x95, 0xec, 0xac, 0x07, 0x56, 0xd0, 0xf5, 0x51, 0x11, 0x46, - 0x77, 0x3b, 0x44, 0x96, 0x13, 0x37, 0x62, 0x53, 0xfe, 0x36, 0xbe, 0xad, 0x73, 0x1a, 0x2d, 0xaa, - 0x5a, 0x52, 0x06, 0x1c, 0x16, 0x18, 0x6b, 0x3a, 0x73, 0xb3, 0xa1, 0xb5, 0x76, 0xf3, 0x91, 0x76, - 0x0b, 0x51, 0x5e, 0x1b, 0x73, 0x89, 0xcc, 0x33, 0xbe, 0x84, 0x2b, 0xbb, 0x1d, 0x1f, 0x7b, 0x41, - 0xb9, 0xd3, 0x69, 0xdb, 0x4d, 0xf6, 0x2a, 0x42, 0x85, 0x6b, 0xb1, 0x58, 0xde, 0x87, 0x73, 0xac, - 0x80, 0x2f, 0x13, 0xb1, 0x06, 0xcb, 0x9d, 0x0e, 0x17, 0xe9, 0x1f, 0x30, 0x29, 0x80, 0x09, 0xe9, - 0x26, 0x87, 0x36, 0x7e, 0x3b, 0x07, 0x57, 0xd8, 0x17, 0x90, 0x4a, 0xfa, 0x5b, 0x30, 0x46, 0xad, - 0x4a, 0x3a, 0x56, 0x53, 0xbb, 0xf5, 0x39, 0xa2, 0xd0, 0x0c, 0xeb, 0x15, 0x7b, 0x9d, 0x7c, 0xba, - 0xbd, 0x8e, 0xf8, 0xc0, 0x06, 0x13, 0x3f, 0xb0, 0x2f, 0xc0, 0xe0, 0x3d, 0x6a, 0xb7, 0x63, 0x9d, - 0xf2, 0x5f, 0xa5, 0x57, 0xc6, 0x7f, 0xca, 0xc3, 0xfc, 0x2a, 0x76, 0xb0, 0x67, 0xd1, 0x71, 0x6a, - 0x0a, 0x0e, 0xd5, 0x2e, 0x20, 0x97, 0x69, 0x17, 0x20, 0x6f, 0xef, 0xf9, 0x94, 0xdb, 0xfb, 0x45, - 0x18, 0xdc, 0x35, 0xd7, 0xf9, 0xb0, 0xa8, 0x5c, 0xda, 0xf5, 0x6c, 0x93, 0x94, 0xa1, 0xf5, 0xd0, - 0xa6, 0x60, 0xa8, 0xa7, 0xee, 0x68, 0x86, 0xbf, 0xb1, 0x8e, 0x70, 0x9b, 0x02, 0xdd, 0x92, 0x60, - 0x4b, 0x51, 0x11, 0x90, 0xed, 0xe6, 0x36, 0xff, 0xa6, 0x52, 0x06, 0xc8, 0x6f, 0xfb, 0x2b, 0x4e, - 0xe0, 0xbd, 0x64, 0x4b, 0x80, 0x5d, 0xfa, 0xc5, 0x55, 0xbf, 0xf8, 0x05, 0x8c, 0x2b, 0x20, 0xa8, - 0x00, 0x83, 0x4f, 0xb9, 0x3d, 0xc5, 0x98, 0x49, 0xfe, 0x44, 0xdf, 0x86, 0xe1, 0x67, 0x56, 0xbb, - 0x8b, 0xf9, 0x36, 0x72, 0x21, 0x54, 0x49, 0xd4, 0x03, 0xb2, 0xb1, 0x33, 0x9d, 0x84, 0xc9, 0x80, - 0x3e, 0xca, 0x7f, 0x90, 0x33, 0x3e, 0x86, 0x85, 0x78, 0x6f, 0xf8, 0x0d, 0xb6, 0x97, 0x52, 0xc7, - 0x58, 0x86, 0xd9, 0x55, 0x1c, 0xd0, 0x85, 0x4b, 0x3f, 0x22, 0xc5, 0xdc, 0x23, 0xf2, 0x9d, 0x65, - 0xbc, 0x5d, 0x18, 0x75, 0x98, 0x8b, 0x50, 0xe1, 0xed, 0x7f, 0x04, 0x23, 0xbc, 0x48, 0xee, 0xa8, - 0xdc, 0x00, 0x0e, 0x1f, 0xf0, 0x8a, 0xbd, 0x25, 0xb6, 0x6e, 0x39, 0x65, 0x53, 0x20, 0x18, 0x47, - 0x70, 0x81, 0x1c, 0x92, 0x21, 0x55, 0xb9, 0x1c, 0x2f, 0xc1, 0x58, 0x87, 0x1c, 0xf3, 0xbe, 0xfd, - 0x13, 0xb6, 0x8c, 0x86, 0xcd, 0x51, 0x52, 0x50, 0xb7, 0x7f, 0x82, 0xd1, 0x65, 0x00, 0x5a, 0x49, - 0x87, 0xc9, 0x77, 0x01, 0x0a, 0xce, 0xb4, 0x58, 0x08, 0xa8, 0x5d, 0x0d, 0x5b, 0x37, 0x26, 0xfd, - 0xdb, 0xf0, 0x60, 0x3e, 0xd6, 0x12, 0x1f, 0xc0, 0x5d, 0x18, 0xe5, 0x1d, 0xf3, 0x23, 0xfa, 0x65, - 0x75, 0x04, 0xa6, 0x04, 0x42, 0x37, 0x61, 0xda, 0xc1, 0x2f, 0x82, 0x46, 0xac, 0x0f, 0x93, 0xa4, - 0xb8, 0x26, 0xfa, 0x61, 0xfc, 0x12, 0xd5, 0x29, 0xd6, 0x1d, 0xf7, 0xf9, 0x93, 0xb6, 0xf5, 0x14, - 0xc7, 0x1a, 0xfe, 0x14, 0x46, 0xeb, 0xbd, 0x1b, 0x66, 0x9f, 0x8f, 0x68, 0xdc, 0x94, 0x28, 0x46, - 0x1b, 0x8a, 0x64, 0x48, 0xe4, 0xe2, 0xb9, 0xde, 0xaa, 0x7d, 0xd3, 0x0c, 0x7c, 0x06, 0x97, 0x12, - 0x5b, 0xfb, 0xa6, 0x99, 0xf8, 0x17, 0x79, 0x98, 0x67, 0x87, 0x49, 0x7c, 0x05, 0xf7, 0xbf, 0xd5, - 0xfc, 0x42, 0x5e, 0xde, 0xee, 0x25, 0xbc, 0xbc, 0x51, 0x14, 0xf5, 0xe5, 0x4d, 0x7b, 0x6f, 0xfb, - 0x20, 0xf9, 0xbd, 0x8d, 0x5e, 0x48, 0xf5, 0xf7, 0xb6, 0xe8, 0x2b, 0xdb, 0x4a, 0xfa, 0x2b, 0x1b, - 0x7d, 0x73, 0x48, 0x78, 0x65, 0x4b, 0x78, 0x5b, 0x63, 0xa2, 0xab, 0xb1, 0x07, 0x0b, 0x71, 0x16, - 0xbf, 0x81, 0xcf, 0xfb, 0x8f, 0x73, 0x70, 0x99, 0x0b, 0x02, 0x91, 0x8f, 0xe0, 0xec, 0x33, 0xf8, - 0x1e, 0x4c, 0x70, 0xdc, 0x9d, 0x70, 0xb1, 0x54, 0xce, 0x9f, 0x9e, 0x94, 0x26, 0xc5, 0x86, 0xc5, - 0x76, 0x3d, 0x0d, 0x0c, 0xbd, 0xa7, 0xe8, 0x38, 0x99, 0xde, 0x9c, 0x48, 0xf7, 0x63, 0x4c, 0x19, - 0x9a, 0xaa, 0xe9, 0x34, 0xbe, 0x86, 0x2b, 0x69, 0x1d, 0x7f, 0x03, 0x7c, 0xf9, 0xe7, 0x39, 0xb8, - 0xc4, 0xc9, 0x6b, 0x9f, 0xd3, 0x2b, 0xed, 0xcc, 0x67, 0x30, 0xc4, 0x7b, 0x04, 0xe3, 0xa4, 0x41, - 0xd1, 0xef, 0x41, 0x7e, 0xfc, 0x70, 0xe9, 0x3a, 0xac, 0x59, 0xb6, 0x02, 0x8b, 0x9b, 0x16, 0x58, - 0xc7, 0xed, 0x86, 0xe8, 0xbf, 0x8a, 0x6c, 0x7c, 0x1f, 0x16, 0x93, 0x87, 0xf0, 0x06, 0xf8, 0xf3, - 0x08, 0x8a, 0x09, 0x1b, 0xe7, 0xab, 0x9d, 0x5b, 0x5f, 0xc1, 0xa5, 0x44, 0x5a, 0x6f, 0xa0, 0x9b, - 0x6b, 0xe4, 0x54, 0x0e, 0xde, 0xc0, 0x14, 0x1a, 0xfb, 0x70, 0x31, 0x81, 0xd2, 0x1b, 0xe8, 0xe2, - 0x2a, 0xcc, 0x4b, 0x69, 0xf4, 0xb5, 0x7a, 0xb8, 0x09, 0x97, 0x19, 0xa1, 0x37, 0x33, 0x2b, 0x8f, - 0xe1, 0x12, 0x27, 0xf7, 0x06, 0xb8, 0xb7, 0x06, 0x8b, 0xe1, 0xa5, 0x33, 0x41, 0x96, 0xe8, 0x7b, - 0x93, 0x31, 0x36, 0xe0, 0x6a, 0x48, 0x29, 0xe5, 0x60, 0xed, 0x9f, 0x1a, 0x13, 0x99, 0xc2, 0x59, - 0x7a, 0x23, 0x33, 0xba, 0x0f, 0x17, 0x34, 0xa2, 0x6f, 0x4c, 0x9c, 0x58, 0x87, 0x19, 0x46, 0x58, - 0x17, 0x2f, 0x97, 0x54, 0xf1, 0x72, 0x7c, 0xe9, 0x7c, 0x48, 0x92, 0x16, 0xef, 0x3d, 0x48, 0x90, - 0x38, 0x37, 0xa9, 0xc4, 0x29, 0x40, 0xc2, 0x1e, 0xbe, 0x07, 0xe7, 0x58, 0x09, 0xef, 0x5f, 0x02, - 0x31, 0x26, 0x50, 0x33, 0x34, 0x0e, 0x6c, 0xfc, 0x10, 0x2e, 0xb3, 0xdb, 0x5a, 0xa8, 0xd8, 0xd7, - 0x6f, 0x54, 0x9f, 0x46, 0x2e, 0x6b, 0x17, 0x39, 0xdd, 0x28, 0x7c, 0xca, 0x9d, 0xed, 0x40, 0xac, - 0xed, 0x34, 0xfa, 0x7d, 0x39, 0x4d, 0x88, 0x4b, 0x58, 0x3e, 0xf1, 0x12, 0x76, 0x1d, 0xae, 0xc9, - 0x4b, 0x58, 0xb4, 0x19, 0xf9, 0x58, 0xf5, 0x7d, 0xb8, 0xc4, 0x06, 0x2a, 0xcc, 0xa5, 0xf4, 0x6e, - 0x7c, 0x1c, 0x19, 0xe6, 0x3c, 0x1f, 0xa6, 0x0e, 0x9d, 0x32, 0xc8, 0xbf, 0x9e, 0x13, 0x9f, 0x5c, - 0x32, 0xf1, 0x5f, 0xf4, 0xad, 0x74, 0x0b, 0x4a, 0x92, 0x21, 0x7a, 0x8f, 0x5e, 0xed, 0x4a, 0xba, - 0x09, 0x73, 0x2a, 0x19, 0xbb, 0x89, 0xf7, 0xee, 0x53, 0x8d, 0xeb, 0xbb, 0xe4, 0xb3, 0xa0, 0x05, - 0x62, 0xd9, 0x2d, 0x24, 0xf0, 0x8d, 0xc2, 0x9b, 0x12, 0xd2, 0x68, 0xc0, 0x62, 0x7c, 0x2a, 0xec, - 0xa6, 0xb0, 0x94, 0x45, 0x9f, 0x93, 0x4f, 0x98, 0x96, 0xf0, 0xc9, 0x48, 0x25, 0x2a, 0xbe, 0x63, - 0x86, 0x2e, 0xb0, 0x0c, 0x43, 0x6c, 0x35, 0x91, 0xf1, 0x93, 0xd6, 0xc5, 0x7a, 0xf8, 0x15, 0x40, - 0xa2, 0xaa, 0x5a, 0x37, 0x45, 0xd3, 0x17, 0x61, 0xb0, 0x5a, 0x37, 0xb9, 0x81, 0x3e, 0xbd, 0x15, - 0x37, 0x7d, 0xcf, 0x24, 0x65, 0x51, 0xa9, 0x35, 0xdf, 0x87, 0xd4, 0xfa, 0x68, 0x68, 0x74, 0xb0, - 0x30, 0x64, 0xa2, 0xba, 0x7d, 0xe8, 0xec, 0xdb, 0xc1, 0x91, 0x6c, 0xb0, 0x6c, 0xfc, 0x00, 0x66, - 0xb4, 0xe6, 0xf9, 0x57, 0x9c, 0xe9, 0x59, 0x80, 0x6e, 0xc2, 0x48, 0xb5, 0x4c, 0xad, 0x0e, 0xe8, - 0xb5, 0x7e, 0x82, 0xed, 0x37, 0x4d, 0xab, 0x41, 0xbd, 0xc7, 0x4c, 0x51, 0x69, 0xfc, 0xfd, 0x21, - 0x85, 0xba, 0xe2, 0xaf, 0x91, 0x31, 0xba, 0xfb, 0x00, 0x6c, 0x85, 0x28, 0x83, 0x23, 0x02, 0xe0, - 0x38, 0x7f, 0x28, 0x65, 0x5b, 0xb2, 0xa9, 0x00, 0xf5, 0xeb, 0xcf, 0xc1, 0x6d, 0x2b, 0x19, 0x92, - 0xb0, 0x26, 0x90, 0xb6, 0x95, 0x9c, 0xb4, 0x6f, 0xaa, 0x40, 0xe8, 0x87, 0x51, 0xb3, 0xe3, 0x61, - 0xaa, 0x5e, 0x7f, 0x4b, 0xbc, 0xf8, 0xc4, 0xc7, 0x76, 0x36, 0xcb, 0xe3, 0xe7, 0x30, 0x47, 0x70, - 0xed, 0x27, 0xd4, 0xb6, 0x78, 0xe5, 0x45, 0x80, 0x1d, 0xb6, 0xb7, 0x9f, 0xa3, 0xed, 0xdc, 0xc8, - 0x68, 0x27, 0x04, 0xe6, 0x1a, 0xe6, 0x90, 0x4e, 0x03, 0xcb, 0x3a, 0x33, 0x99, 0x3e, 0x5d, 0x44, - 0xe6, 0xc6, 0x8a, 0xd3, 0xea, 0xb8, 0xb6, 0xbc, 0x54, 0xb0, 0x45, 0xe4, 0xb5, 0x1b, 0x98, 0x97, - 0x9b, 0x2a, 0x90, 0x71, 0x33, 0xd3, 0x30, 0x77, 0x14, 0x86, 0x76, 0xaa, 0x3b, 0x1b, 0x85, 0x9c, - 0x71, 0x17, 0x40, 0x69, 0x09, 0xe0, 0xdc, 0xd6, 0xb6, 0xb9, 0x59, 0xde, 0x28, 0x0c, 0xa0, 0x39, - 0x38, 0xbf, 0xbf, 0xbe, 0xb5, 0xbc, 0xbd, 0x5f, 0x6f, 0xd4, 0x37, 0xcb, 0xe6, 0x4e, 0xb5, 0x6c, - 0x2e, 0x17, 0x72, 0xc6, 0xd7, 0x30, 0xab, 0x8f, 0xf0, 0x8d, 0x2e, 0xc2, 0x00, 0x66, 0xa4, 0x3c, - 0xf3, 0x68, 0x7f, 0x47, 0x31, 0xf8, 0xe3, 0x17, 0xa4, 0xa8, 0x51, 0x00, 0xbf, 0x4a, 0xf1, 0xcf, - 0x48, 0x01, 0xd2, 0x4c, 0x39, 0xf2, 0x99, 0xa6, 0x1c, 0xc6, 0x77, 0x61, 0x56, 0x6f, 0xb5, 0x5f, - 0x4d, 0xce, 0x5b, 0xd4, 0x12, 0x52, 0x31, 0xd8, 0x27, 0x37, 0xf5, 0xb0, 0x8b, 0x7c, 0x67, 0xfd, - 0x2e, 0x14, 0x38, 0x54, 0x78, 0xf2, 0x5e, 0x17, 0xaa, 0xb6, 0x5c, 0x82, 0x73, 0x91, 0x30, 0xb8, - 0x7d, 0x5f, 0x98, 0xa8, 0xa8, 0x2d, 0x5c, 0xe3, 0x0e, 0x7e, 0x39, 0xcd, 0x87, 0x89, 0x23, 0xd2, - 0x2a, 0x82, 0xb7, 0xdb, 0x69, 0xbd, 0x22, 0x1e, 0xd9, 0x63, 0xcf, 0x88, 0xf7, 0xb6, 0x78, 0x64, - 0xe8, 0xc5, 0x89, 0x3f, 0xc9, 0xc1, 0x42, 0xc4, 0x46, 0xbf, 0x7a, 0x64, 0xb5, 0xdb, 0xd8, 0x39, - 0xc4, 0xe8, 0x16, 0x0c, 0xed, 0x6c, 0xef, 0xd4, 0xb8, 0x12, 0x6e, 0x96, 0x7f, 0x4e, 0xa4, 0x48, - 0xc2, 0x98, 0x14, 0x02, 0x3d, 0x86, 0xf3, 0xc2, 0x3e, 0x51, 0x56, 0xf1, 0xcb, 0xd3, 0xe5, 0x6c, - 0x6b, 0xc7, 0x38, 0x1e, 0x7a, 0x97, 0x3b, 0x14, 0xfc, 0xb8, 0x6b, 0x7b, 0xb8, 0x45, 0x15, 0x0b, - 0xe1, 0x9b, 0x9c, 0x52, 0x63, 0xaa, 0x60, 0xcc, 0xd9, 0xcb, 0xf8, 0xdd, 0x1c, 0xcc, 0xa7, 0xf8, - 0x1c, 0xa0, 0x77, 0xb4, 0xe1, 0xcc, 0x28, 0xc3, 0x11, 0x20, 0x6b, 0x03, 0x7c, 0x3c, 0x55, 0xc5, - 0x68, 0x73, 0xf0, 0x0c, 0x46, 0x9b, 0x6b, 0x03, 0xa1, 0xa1, 0x66, 0x05, 0x60, 0x54, 0x94, 0x1b, - 0xd3, 0x30, 0xa9, 0xf1, 0xcd, 0x30, 0x60, 0x42, 0x6d, 0x99, 0x4c, 0x4e, 0xd5, 0x6d, 0xc9, 0xc9, - 0x21, 0x7f, 0x1b, 0x7f, 0x33, 0x07, 0xb3, 0x74, 0x88, 0x87, 0x36, 0xd9, 0x35, 0x42, 0x0e, 0x2d, - 0x69, 0x23, 0x59, 0xd4, 0x46, 0x12, 0x81, 0x95, 0x43, 0xfa, 0x28, 0x36, 0xa4, 0xc5, 0xa4, 0x21, - 0xd1, 0xe5, 0x6d, 0xbb, 0x8e, 0x36, 0x12, 0xe5, 0xa5, 0xe3, 0xf7, 0x72, 0x30, 0xa3, 0xf4, 0x49, - 0xf6, 0xff, 0xbe, 0xd6, 0xa5, 0x4b, 0x09, 0x5d, 0x8a, 0x31, 0xb9, 0x12, 0xeb, 0xd1, 0x5b, 0x59, - 0x3d, 0xea, 0xc9, 0xe3, 0xff, 0x98, 0x83, 0xb9, 0x44, 0x1e, 0xa0, 0x0b, 0x44, 0x2c, 0x6c, 0x7a, - 0x38, 0xe0, 0xec, 0xe5, 0xbf, 0x48, 0xf9, 0xba, 0xef, 0x77, 0xb1, 0xc7, 0x15, 0x6b, 0xfc, 0x17, - 0x7a, 0x0b, 0x26, 0x6b, 0xd8, 0xb3, 0xdd, 0x16, 0x33, 0xe7, 0x65, 0x36, 0x48, 0x93, 0xa6, 0x5e, - 0x88, 0x16, 0x61, 0xac, 0xdc, 0x3e, 0x74, 0x3d, 0x3b, 0x38, 0x62, 0x8f, 0x4d, 0x63, 0x66, 0x58, - 0x40, 0x68, 0x2f, 0xdb, 0x87, 0xc2, 0xac, 0x6e, 0xd2, 0xe4, 0xbf, 0xd0, 0x02, 0x8c, 0x08, 0x65, - 0x14, 0x55, 0x65, 0x99, 0xe2, 0x27, 0xc1, 0xf8, 0xc2, 0xa4, 0x8b, 0x80, 0x3a, 0xc1, 0x9a, 0xfc, - 0x17, 0x9a, 0xa2, 0x06, 0x99, 0xd4, 0xc5, 0x95, 0x1a, 0x62, 0x7e, 0x04, 0xb3, 0x49, 0x7c, 0x4d, - 0x5a, 0x42, 0x1c, 0x37, 0x2f, 0x71, 0xff, 0xff, 0x3c, 0xcc, 0x94, 0x5b, 0xad, 0xcd, 0x87, 0x65, - 0xf6, 0x22, 0x2d, 0xf6, 0x86, 0x77, 0x61, 0x68, 0xdd, 0xe1, 0x8f, 0xae, 0xca, 0x43, 0x7b, 0x1c, - 0x92, 0x40, 0x91, 0x19, 0x24, 0xff, 0x23, 0x13, 0x66, 0x56, 0x5e, 0xd8, 0x7e, 0x60, 0x3b, 0x87, - 0xaa, 0x0b, 0x50, 0xbe, 0x1f, 0x17, 0xa0, 0xb5, 0x01, 0x33, 0x09, 0x19, 0xed, 0xc0, 0x85, 0x2d, - 0xfc, 0x3c, 0x61, 0x89, 0x49, 0xcf, 0x48, 0x65, 0x23, 0x88, 0xad, 0xac, 0x14, 0x5c, 0x75, 0x05, - 0xff, 0x66, 0x9e, 0x3a, 0x4e, 0x2b, 0x03, 0xe3, 0x2d, 0xef, 0xc2, 0xac, 0xd2, 0xa1, 0x70, 0x1f, - 0x63, 0x3c, 0x29, 0x25, 0x0f, 0x47, 0xfd, 0xd0, 0x12, 0xd1, 0xd1, 0x3e, 0xcc, 0xeb, 0x9d, 0x0a, - 0x29, 0xeb, 0x1f, 0x4b, 0x12, 0xc8, 0xda, 0x80, 0x99, 0x86, 0x8d, 0x96, 0x60, 0xb0, 0xdc, 0x7c, - 0xca, 0xd9, 0x92, 0x3c, 0x65, 0x6c, 0x64, 0xe5, 0xe6, 0xd3, 0xb5, 0x01, 0x93, 0x00, 0x6b, 0xdf, - 0xcb, 0xbf, 0xcc, 0xc1, 0x7c, 0xca, 0x0c, 0xa3, 0x2b, 0x00, 0xac, 0x50, 0x39, 0x31, 0x94, 0x12, - 0x22, 0x68, 0x72, 0x93, 0x86, 0x97, 0x1d, 0x36, 0x33, 0x53, 0xd2, 0xc9, 0x30, 0xac, 0x30, 0x15, - 0x20, 0x54, 0x13, 0xd6, 0x3f, 0xcc, 0xd7, 0x51, 0xdf, 0xd6, 0x95, 0x1a, 0xcd, 0xec, 0x27, 0xea, - 0xe3, 0xa8, 0x92, 0xe0, 0xaa, 0xd9, 0x6a, 0x74, 0x14, 0x72, 0xd0, 0xe8, 0x16, 0x9c, 0x63, 0x85, - 0x7c, 0x0e, 0x45, 0xe0, 0x81, 0x10, 0x98, 0xd7, 0x1b, 0x7f, 0x27, 0x07, 0x17, 0xd8, 0x89, 0x19, - 0xfb, 0x34, 0xbe, 0xab, 0x7d, 0x1a, 0xd7, 0x64, 0x87, 0x93, 0x80, 0xb5, 0xaf, 0xa3, 0xa2, 0x3b, - 0xc6, 0xf5, 0xfb, 0x55, 0xa8, 0x48, 0xea, 0xba, 0xfd, 0x7b, 0x39, 0xa1, 0xa9, 0x8a, 0x2f, 0xdd, - 0x15, 0x98, 0x78, 0xb5, 0x25, 0xab, 0xa1, 0xa1, 0xf7, 0xd8, 0x8a, 0xca, 0x67, 0x8f, 0x34, 0x73, - 0x51, 0x7d, 0x02, 0xc5, 0x74, 0xd6, 0xf4, 0x5a, 0x56, 0xc6, 0xc3, 0x04, 0xec, 0x57, 0x99, 0xce, - 0xbf, 0xcc, 0xc5, 0x08, 0xd5, 0x5f, 0x3a, 0x4d, 0x31, 0xa5, 0x37, 0xa3, 0xa6, 0xea, 0xa9, 0xe6, - 0xbf, 0x6a, 0x77, 0xf3, 0xe1, 0x9b, 0x08, 0x5f, 0x9d, 0x54, 0x6a, 0x55, 0x3f, 0x8b, 0x6e, 0xf2, - 0x86, 0x38, 0xd8, 0x97, 0x4f, 0x24, 0x0d, 0xd9, 0x80, 0x39, 0x7a, 0x23, 0xc5, 0x39, 0x32, 0x89, - 0xbe, 0xf1, 0x5b, 0x83, 0xfa, 0x37, 0xf0, 0x2a, 0x63, 0xad, 0xc1, 0x78, 0xd5, 0x75, 0x02, 0xfc, - 0x22, 0x50, 0x1c, 0xf2, 0x91, 0x34, 0xc1, 0x90, 0x35, 0xfc, 0xbe, 0xc4, 0x0a, 0x1a, 0x44, 0x78, - 0xd7, 0xcc, 0xd5, 0x42, 0x40, 0x54, 0x85, 0xc9, 0x2d, 0xfc, 0x3c, 0xc6, 0x40, 0x6a, 0x32, 0xe7, - 0xe0, 0xe7, 0x0d, 0x85, 0x89, 0xaa, 0x59, 0x9e, 0x86, 0x83, 0x0e, 0x60, 0x4a, 0xec, 0x7f, 0xfd, - 0x1e, 0x03, 0xcc, 0x65, 0x9d, 0xb4, 0x90, 0xc2, 0xc3, 0x08, 0xc5, 0x37, 0xbf, 0x33, 0x19, 0x35, - 0x58, 0x88, 0xcf, 0x07, 0x6f, 0xed, 0xdd, 0x5e, 0xab, 0x98, 0x29, 0xa7, 0x5a, 0xfa, 0x8a, 0x5e, - 0xa3, 0x0a, 0x43, 0x09, 0x23, 0x35, 0x40, 0xf7, 0xa2, 0xd3, 0x4b, 0x6d, 0x3d, 0xc5, 0xf4, 0xaa, - 0xb6, 0x4d, 0xc2, 0x05, 0xa3, 0x4a, 0x75, 0xae, 0x2a, 0x25, 0xde, 0xb1, 0xdb, 0x30, 0xc2, 0x8b, - 0x22, 0x71, 0x5a, 0xc2, 0xef, 0x4b, 0x00, 0x18, 0xbf, 0x9f, 0x83, 0x8b, 0x54, 0x03, 0x6c, 0x3b, - 0x87, 0x6d, 0xbc, 0xeb, 0xeb, 0x5e, 0x14, 0xdf, 0xd1, 0xb6, 0xcc, 0xf9, 0x14, 0x8f, 0xd9, 0x6f, - 0x6a, 0xa3, 0xfc, 0xc3, 0x1c, 0x14, 0x93, 0xfa, 0xf6, 0x66, 0xf7, 0xca, 0x3b, 0xfc, 0x7a, 0x9d, - 0xd7, 0xac, 0x1e, 0x65, 0x9b, 0x62, 0xb0, 0x64, 0x90, 0xe4, 0x7f, 0x6d, 0x93, 0xfc, 0x6f, 0x39, - 0x98, 0x5d, 0xf7, 0xd5, 0xab, 0x0c, 0x67, 0xdc, 0x9d, 0xa4, 0xa8, 0x07, 0x74, 0x5e, 0xd7, 0x06, - 0x92, 0xa2, 0x1a, 0xbc, 0xab, 0xf8, 0x97, 0xe6, 0xb3, 0xc2, 0x19, 0x10, 0xa1, 0x59, 0x7a, 0x98, - 0xde, 0x84, 0xa1, 0x2d, 0x22, 0x28, 0x0e, 0xf2, 0xf5, 0xc7, 0x30, 0x48, 0x11, 0xf5, 0xef, 0x24, - 0x5d, 0x26, 0x3f, 0xd0, 0xc3, 0x98, 0x17, 0xe9, 0x50, 0x6f, 0x77, 0xfd, 0xb5, 0x81, 0xa8, 0x43, - 0x69, 0x65, 0x14, 0xce, 0xed, 0x58, 0xde, 0x21, 0x0e, 0x8c, 0xef, 0x43, 0x91, 0x9b, 0x48, 0x31, - 0x9d, 0x3a, 0x35, 0xa4, 0xf2, 0x43, 0x2b, 0xb8, 0x2c, 0xb3, 0xa6, 0x2b, 0x00, 0xd4, 0x63, 0x69, - 0xdd, 0x69, 0xe1, 0x17, 0xcc, 0x0e, 0xcf, 0x54, 0x4a, 0x8c, 0xf7, 0x60, 0x4c, 0x0e, 0x81, 0xde, - 0x75, 0x15, 0x59, 0x98, 0x0e, 0x67, 0x56, 0xf3, 0x6b, 0x15, 0xce, 0xac, 0x36, 0xcc, 0x45, 0xa6, - 0x22, 0xf4, 0x3c, 0x97, 0x77, 0x50, 0x6a, 0x35, 0x68, 0xca, 0xdf, 0xd1, 0x2b, 0x6a, 0xbe, 0xaf, - 0x2b, 0xaa, 0x51, 0x85, 0xf3, 0xb1, 0xf5, 0x81, 0x10, 0x75, 0xfa, 0x66, 0x5a, 0x1a, 0x72, 0xa0, - 0xd6, 0xeb, 0x6b, 0xa4, 0x6c, 0x67, 0xa3, 0xce, 0xdc, 0x8b, 0x48, 0xd9, 0xce, 0x46, 0xbd, 0x72, - 0x8e, 0xad, 0x37, 0xe3, 0x1f, 0xe7, 0xa9, 0xf2, 0x22, 0xc6, 0xb9, 0x88, 0x1e, 0x58, 0xd5, 0x45, - 0x57, 0x60, 0x8c, 0xf2, 0x69, 0x59, 0xf8, 0xeb, 0x65, 0xdb, 0x02, 0x8d, 0xfe, 0xf4, 0xa4, 0x34, - 0x40, 0x0d, 0x80, 0x42, 0x34, 0xf4, 0x19, 0x8c, 0xac, 0x38, 0x2d, 0x4a, 0x61, 0xf0, 0x0c, 0x14, - 0x04, 0x12, 0x99, 0x3d, 0xda, 0x65, 0x22, 0x0a, 0x72, 0xf5, 0xa1, 0xa9, 0x94, 0xd0, 0xc9, 0xa1, - 0x06, 0x96, 0xc3, 0x74, 0x62, 0xd9, 0x0f, 0xea, 0xfd, 0x4f, 0xba, 0x20, 0x22, 0x0a, 0x8d, 0x99, - 0xf2, 0x37, 0x32, 0x60, 0x78, 0xdb, 0x6b, 0xf1, 0xa8, 0x20, 0x53, 0x4b, 0x13, 0x9c, 0xfb, 0xb4, - 0xcc, 0x64, 0x55, 0xc6, 0x7f, 0xc9, 0xc1, 0xfc, 0x2a, 0x0e, 0x12, 0x57, 0x9b, 0xc6, 0x95, 0xdc, - 0x6b, 0x73, 0x25, 0xff, 0x2a, 0x5c, 0x91, 0xa3, 0x1e, 0x4c, 0x1b, 0xf5, 0x50, 0xda, 0xa8, 0x87, - 0xd3, 0x47, 0xbd, 0x0a, 0xe7, 0xd8, 0x50, 0xd1, 0x75, 0x18, 0x5e, 0x0f, 0xf0, 0x71, 0xa8, 0xd4, - 0x52, 0x2d, 0x19, 0x4d, 0x56, 0x47, 0x6e, 0xa4, 0x1b, 0x96, 0x1f, 0x08, 0x87, 0xb6, 0x31, 0x53, - 0xfc, 0x34, 0x7e, 0x44, 0x3d, 0x7d, 0x37, 0xdc, 0xe6, 0x53, 0xe5, 0xc5, 0x61, 0x84, 0x7d, 0xcb, - 0xd1, 0x17, 0x2a, 0x02, 0xc5, 0x6a, 0x4c, 0x01, 0x81, 0xae, 0xc2, 0xf8, 0xba, 0xf3, 0xd0, 0xf5, - 0x9a, 0x78, 0xdb, 0x69, 0x33, 0xea, 0xa3, 0xa6, 0x5a, 0xc4, 0x35, 0x71, 0xbc, 0x85, 0x50, 0x13, - 0x47, 0x0b, 0x22, 0x9a, 0x38, 0x52, 0xb6, 0xb7, 0x64, 0xb2, 0x3a, 0xae, 0xe8, 0x23, 0x7f, 0x67, - 0xa9, 0xb7, 0xa4, 0x1e, 0xac, 0x17, 0xe0, 0x01, 0x5c, 0x34, 0x71, 0xa7, 0x6d, 0x11, 0x81, 0xf3, - 0xd8, 0x65, 0xf0, 0x72, 0xcc, 0x57, 0x13, 0x3c, 0xa0, 0x74, 0xbb, 0x16, 0xd9, 0xe5, 0x7c, 0x46, - 0x97, 0x8f, 0xe1, 0xda, 0x2a, 0x0e, 0xf4, 0xbd, 0x31, 0x7c, 0xcf, 0xe0, 0x83, 0x5f, 0x83, 0x51, - 0x5f, 0x7f, 0x8b, 0xb9, 0x22, 0x9e, 0x00, 0x93, 0x10, 0xf7, 0x1e, 0x88, 0xd7, 0x4a, 0x4e, 0x47, - 0xfe, 0x65, 0x7c, 0x0e, 0xa5, 0xb4, 0xe6, 0xfa, 0x33, 0x3b, 0xb6, 0xe1, 0x6a, 0x3a, 0x01, 0x79, - 0x98, 0x8a, 0x77, 0x1b, 0xa9, 0x3a, 0xc8, 0xee, 0xad, 0xfe, 0xd4, 0xc3, 0xff, 0x30, 0x2a, 0xc2, - 0x00, 0xf3, 0x35, 0xba, 0xdb, 0xa0, 0x26, 0x11, 0x3a, 0x81, 0x90, 0xaf, 0x65, 0x18, 0x15, 0x65, - 0x9c, 0xaf, 0xf3, 0x89, 0x3d, 0x15, 0x0c, 0x6d, 0x09, 0x02, 0x12, 0xcd, 0xf8, 0x91, 0x78, 0x1e, - 0xd4, 0x31, 0xfa, 0x73, 0xeb, 0xec, 0xe7, 0x3d, 0xd0, 0x70, 0xe1, 0xa2, 0x4e, 0x5b, 0x7d, 0xf6, - 0x29, 0x28, 0xcf, 0x3e, 0xec, 0xb5, 0xe7, 0xaa, 0xfe, 0x0c, 0x91, 0xe7, 0xeb, 0x32, 0x2c, 0x42, - 0x57, 0xd4, 0xc7, 0x9d, 0x89, 0xb8, 0x1f, 0xec, 0x3d, 0x28, 0x26, 0x35, 0xa8, 0x28, 0x94, 0xe4, - 0x0b, 0x02, 0x0f, 0x8b, 0xf5, 0x6b, 0x39, 0x30, 0x34, 0x2b, 0x37, 0x3a, 0x43, 0x35, 0xcf, 0x7d, - 0x66, 0xb7, 0x94, 0x87, 0xc9, 0x77, 0xc4, 0xc6, 0xc6, 0xac, 0xf8, 0xa9, 0x77, 0x57, 0xd4, 0x3c, - 0x9e, 0xef, 0x76, 0xf7, 0x60, 0x64, 0x0b, 0xbf, 0x08, 0xb7, 0x1f, 0x26, 0xc1, 0x52, 0xcb, 0xb7, - 0xa7, 0x58, 0x8d, 0xa2, 0x20, 0xc0, 0x88, 0xf8, 0x74, 0x3d, 0xb3, 0x0f, 0xbc, 0xff, 0x07, 0x50, - 0x88, 0xd6, 0xf1, 0xb9, 0x2f, 0x29, 0x16, 0x3d, 0x71, 0x0a, 0x7b, 0xf7, 0x99, 0x83, 0x80, 0xb0, - 0x0e, 0xeb, 0x48, 0xca, 0x31, 0x7a, 0x67, 0xef, 0x3d, 0xfa, 0x10, 0x60, 0xc7, 0x0d, 0xac, 0x76, - 0x95, 0xea, 0x00, 0x07, 0x43, 0x7f, 0x8a, 0x80, 0x94, 0x36, 0xa2, 0xe1, 0x1e, 0x14, 0x60, 0xe3, - 0x7b, 0xf4, 0x8b, 0x4c, 0xee, 0x74, 0x7f, 0x1f, 0x49, 0x15, 0xae, 0x47, 0xac, 0x4a, 0x5e, 0x81, - 0x48, 0x00, 0x73, 0x84, 0xfd, 0x44, 0x84, 0x59, 0xf5, 0xdc, 0x6e, 0xe7, 0x17, 0x33, 0xeb, 0xff, - 0x26, 0xc7, 0x4c, 0x61, 0xd5, 0x66, 0xf9, 0x44, 0x57, 0x01, 0xc2, 0xd2, 0x88, 0x4b, 0x84, 0xac, - 0xd8, 0xbb, 0xcf, 0xee, 0xee, 0xf4, 0xbd, 0xe9, 0x90, 0x11, 0x50, 0xd0, 0x7e, 0xb1, 0x33, 0xf9, - 0x80, 0x9a, 0x92, 0xc8, 0xd6, 0xfb, 0xe3, 0xfb, 0xfb, 0x42, 0x47, 0x75, 0x46, 0xbc, 0x23, 0x98, - 0x25, 0xdf, 0x2e, 0xb9, 0xd7, 0xb8, 0x9e, 0x1d, 0x08, 0xd7, 0x1c, 0x54, 0xe3, 0xae, 0xf4, 0x0c, - 0xeb, 0x93, 0x9f, 0x9f, 0x94, 0x3e, 0x38, 0x8b, 0x5f, 0xb2, 0xa0, 0xb9, 0x23, 0xdd, 0xef, 0x8d, - 0x79, 0x18, 0xac, 0x9a, 0x1b, 0x74, 0xab, 0x32, 0x37, 0xe4, 0x56, 0x65, 0x6e, 0x18, 0xff, 0x39, - 0x0f, 0x25, 0x16, 0xec, 0x83, 0x5a, 0x20, 0x85, 0x37, 0x2c, 0xc5, 0xa4, 0xa9, 0x5f, 0x4d, 0x45, - 0x24, 0x98, 0x47, 0xbe, 0x9f, 0x60, 0x1e, 0xbf, 0xfc, 0xea, 0x5a, 0xe5, 0xca, 0xdb, 0xa7, 0x27, - 0xa5, 0xeb, 0xa1, 0x3a, 0x81, 0xd5, 0x26, 0xe9, 0x15, 0x52, 0x9a, 0x88, 0x2b, 0x42, 0x86, 0x5e, - 0x41, 0x11, 0x72, 0x0f, 0x46, 0xe8, 0x85, 0x65, 0xbd, 0xc6, 0xed, 0x66, 0xe9, 0xf2, 0xa4, 0x71, - 0x79, 0x1a, 0xb6, 0x1a, 0x02, 0x4d, 0x80, 0x19, 0x7f, 0x2b, 0x0f, 0x57, 0xd3, 0x79, 0xce, 0xfb, - 0xb6, 0x0c, 0x10, 0xda, 0x3e, 0x65, 0xd9, 0x5a, 0xd1, 0x6f, 0xe7, 0x39, 0x3e, 0x90, 0xb6, 0x8e, - 0x0a, 0x1e, 0x91, 0x5a, 0x84, 0xcf, 0x6a, 0xe4, 0xb5, 0x50, 0x73, 0x65, 0xe5, 0x11, 0x36, 0x79, - 0x91, 0x16, 0x61, 0x93, 0x97, 0xa1, 0x03, 0x98, 0xaf, 0x79, 0xf6, 0x33, 0x2b, 0xc0, 0x8f, 0xf1, - 0xcb, 0x9a, 0xdb, 0xb6, 0x9b, 0x2f, 0x57, 0xb8, 0xeb, 0x16, 0x73, 0x44, 0xbe, 0x75, 0x7a, 0x52, - 0x7a, 0xab, 0xc3, 0x40, 0xc8, 0x87, 0xd9, 0xe8, 0x50, 0xa0, 0x46, 0xdc, 0x9b, 0x2b, 0x8d, 0x90, - 0xf1, 0xaf, 0x73, 0x70, 0x89, 0x0a, 0xd4, 0xfc, 0xe5, 0x45, 0x34, 0xfe, 0x4a, 0x26, 0xb7, 0xea, - 0x00, 0xf9, 0x5a, 0xa4, 0x26, 0xb7, 0x9a, 0x4f, 0xaf, 0xa9, 0x81, 0xa1, 0x75, 0x18, 0xe7, 0xbf, - 0x15, 0xf5, 0xf9, 0x9c, 0xb2, 0x61, 0xd1, 0xa5, 0xce, 0x74, 0x4e, 0x74, 0x61, 0x73, 0x62, 0xd4, - 0xf1, 0xd0, 0x54, 0x71, 0x8d, 0x9f, 0xe5, 0x61, 0x71, 0x0f, 0x7b, 0xf6, 0x93, 0x97, 0x29, 0x83, - 0xd9, 0x86, 0x59, 0x51, 0xc4, 0x02, 0x7e, 0x68, 0x9f, 0x18, 0x8b, 0xe1, 0x27, 0xba, 0xca, 0x23, - 0x86, 0x88, 0x2f, 0x2e, 0x11, 0xf1, 0x0c, 0xc6, 0xb4, 0xef, 0xc2, 0x68, 0x24, 0xe4, 0x0e, 0x9d, - 0x7f, 0xf1, 0x85, 0x86, 0x53, 0xb5, 0x36, 0x60, 0x4a, 0x48, 0xf4, 0x1b, 0xe9, 0x4f, 0xb8, 0x5c, - 0xff, 0xd0, 0x4b, 0x91, 0x4a, 0x3f, 0x58, 0xf2, 0xb1, 0x5a, 0x4a, 0x6d, 0xc2, 0x07, 0xbb, 0x36, - 0x60, 0xa6, 0xb5, 0x54, 0x19, 0x87, 0xb1, 0x32, 0x7d, 0x96, 0x26, 0x17, 0xf7, 0xff, 0x9a, 0x87, - 0x2b, 0xc2, 0x6d, 0x2a, 0x85, 0xcd, 0x5f, 0xc2, 0xbc, 0x28, 0x2a, 0x77, 0x88, 0xc0, 0x80, 0x5b, - 0x3a, 0xa7, 0x59, 0x1c, 0x4d, 0xc1, 0x69, 0x8b, 0xc3, 0x84, 0xcc, 0x4e, 0x43, 0x7f, 0x33, 0x6a, - 0xd4, 0xcf, 0x92, 0x02, 0x20, 0x51, 0x75, 0xa6, 0xba, 0x67, 0x6a, 0xac, 0xd1, 0xf6, 0xcf, 0x56, - 0x4c, 0x0d, 0x3b, 0xf4, 0xba, 0x6a, 0xd8, 0xb5, 0x81, 0xa8, 0x22, 0xb6, 0x32, 0x05, 0x13, 0x5b, - 0xf8, 0x79, 0xc8, 0xf7, 0xbf, 0x9a, 0x8b, 0x38, 0xcd, 0x13, 0x09, 0x83, 0x79, 0xcf, 0xe7, 0xc2, - 0x18, 0x3a, 0xd4, 0x69, 0x5e, 0x95, 0x30, 0x18, 0xe8, 0x3a, 0x8c, 0x30, 0x5b, 0x8d, 0x56, 0x1f, - 0x77, 0x73, 0xe9, 0xff, 0xc4, 0x5c, 0x4a, 0x5b, 0xec, 0x9a, 0xce, 0xf1, 0x8d, 0xc7, 0x70, 0x8d, - 0x5b, 0xff, 0xeb, 0x93, 0x4f, 0x1b, 0x3a, 0xe3, 0xf1, 0x65, 0x58, 0x70, 0x65, 0x15, 0x47, 0xb7, - 0x1e, 0xcd, 0x3f, 0xec, 0x73, 0x98, 0xd6, 0xca, 0x25, 0x45, 0x2a, 0x95, 0xca, 0x35, 0x24, 0x49, - 0x47, 0xa1, 0x8d, 0xab, 0x49, 0x4d, 0xa8, 0x9d, 0x35, 0x30, 0x0d, 0x88, 0xe9, 0x85, 0xaf, 0xec, - 0xfe, 0x19, 0x76, 0xbd, 0x5b, 0xca, 0x77, 0xcd, 0x76, 0x3c, 0x16, 0x33, 0x4f, 0x9c, 0xbc, 0xb2, - 0xd6, 0x98, 0xd4, 0x1e, 0x15, 0x8c, 0x29, 0x98, 0x10, 0x55, 0x6d, 0xec, 0xfb, 0xc6, 0x6f, 0x0e, - 0x81, 0xc1, 0x19, 0x9b, 0xa4, 0x73, 0x15, 0xfc, 0x38, 0x88, 0x75, 0x96, 0x1f, 0x54, 0x17, 0x54, - 0xcd, 0x72, 0x58, 0xcb, 0x56, 0x1e, 0x95, 0xf3, 0x9a, 0x61, 0xa9, 0xb6, 0xf2, 0x62, 0xa3, 0xff, - 0x41, 0xca, 0x36, 0xc9, 0x3e, 0xb6, 0x1b, 0xa7, 0x27, 0xa5, 0x6b, 0x29, 0xdb, 0xa4, 0x46, 0x37, - 0x79, 0xcb, 0x34, 0xf5, 0xb7, 0x95, 0xc1, 0x57, 0x79, 0x5b, 0x21, 0x5f, 0xa4, 0xfa, 0xba, 0xb2, - 0xab, 0xf3, 0x92, 0x7f, 0x8f, 0xc2, 0xaa, 0x45, 0xad, 0xe2, 0xbe, 0xeb, 0x4a, 0x89, 0x46, 0x55, - 0x23, 0x83, 0x6c, 0x28, 0x28, 0x2a, 0xcb, 0xea, 0x11, 0x6e, 0x3e, 0xe5, 0x6f, 0x41, 0xe2, 0x99, - 0x3a, 0x49, 0x71, 0xcd, 0x62, 0xf2, 0xb2, 0xef, 0x9c, 0x55, 0x34, 0x9a, 0x04, 0x55, 0xf5, 0xbd, - 0x8f, 0x92, 0x55, 0x55, 0xf6, 0xbf, 0x23, 0xdd, 0x3d, 0xc8, 0x99, 0x6d, 0xb7, 0x31, 0xf7, 0x6d, - 0x12, 0x2b, 0x20, 0xe5, 0x5d, 0x2d, 0xf7, 0x0d, 0xbf, 0xab, 0xfd, 0x51, 0x5e, 0x38, 0xb9, 0xc4, - 0x5e, 0xdf, 0xcf, 0xfe, 0xbc, 0x96, 0x38, 0x82, 0xbe, 0x0e, 0xb4, 0x64, 0x43, 0x89, 0x8a, 0xf6, - 0x04, 0x9f, 0x4f, 0x79, 0x82, 0xd7, 0xde, 0x2b, 0x83, 0x1e, 0x6f, 0xf2, 0x83, 0xaf, 0xff, 0xf2, - 0xf5, 0xcf, 0x46, 0xe0, 0x7c, 0xcd, 0x3a, 0xb4, 0x1d, 0xb2, 0x71, 0x9a, 0xd8, 0x77, 0xbb, 0x5e, - 0x13, 0xa3, 0x32, 0x4c, 0xe9, 0x16, 0xcc, 0x3d, 0xec, 0xb3, 0xc9, 0xd9, 0xa0, 0x97, 0xa1, 0x25, - 0x18, 0x93, 0x9e, 0xc5, 0x7c, 0x43, 0x4f, 0xf0, 0x38, 0x5e, 0x1b, 0x30, 0x43, 0x30, 0xf4, 0xa1, - 0xf6, 0xd0, 0x31, 0x2d, 0x9d, 0xe4, 0x29, 0xec, 0x12, 0x33, 0x31, 0x75, 0xdc, 0x96, 0x7e, 0x28, - 0xb1, 0xc7, 0x82, 0x1f, 0xc5, 0xde, 0x3e, 0x86, 0xb5, 0x1e, 0xc7, 0xb4, 0x46, 0xf4, 0x3c, 0x4e, - 0x0d, 0x4c, 0x1c, 0x7f, 0x15, 0x41, 0xdf, 0x87, 0xf1, 0xc7, 0xdd, 0x03, 0x2c, 0x5e, 0x79, 0xce, - 0xf1, 0x33, 0x2a, 0x6a, 0x97, 0xcf, 0xeb, 0xf7, 0x1e, 0xb0, 0x39, 0x78, 0xda, 0x3d, 0xc0, 0xf1, - 0x88, 0xd7, 0x64, 0x73, 0x50, 0x88, 0xa1, 0x23, 0x28, 0x44, 0x4d, 0xe8, 0x79, 0x00, 0xb9, 0x0c, - 0xc3, 0x7f, 0x1a, 0x3e, 0x43, 0x89, 0xab, 0xcd, 0x0c, 0x7b, 0xb5, 0x46, 0x62, 0x54, 0xd1, 0xaf, - 0xc0, 0x5c, 0xa2, 0xce, 0x8e, 0x47, 0xd7, 0xee, 0xa5, 0x0e, 0xa4, 0x1b, 0x6b, 0x84, 0x6b, 0xc2, - 0x2b, 0x4f, 0x6b, 0x39, 0xb9, 0x15, 0xd4, 0x82, 0xe9, 0x88, 0x69, 0x38, 0x0f, 0xee, 0x9f, 0x6e, - 0x6c, 0x4e, 0x0f, 0x07, 0x11, 0x81, 0x35, 0xb1, 0xad, 0x28, 0x49, 0xb4, 0x01, 0x63, 0xf2, 0xca, - 0x4d, 0x83, 0xfc, 0x24, 0xab, 0x17, 0x16, 0x4e, 0x4f, 0x4a, 0xb3, 0xa1, 0x7a, 0x41, 0xa3, 0x19, - 0x12, 0x40, 0x3f, 0x81, 0x6b, 0x72, 0x89, 0x6e, 0x7b, 0xc9, 0x8a, 0x18, 0x1e, 0xb7, 0xfb, 0x76, - 0x74, 0x85, 0xa7, 0xc1, 0xef, 0xdd, 0x5f, 0x1b, 0x30, 0x7b, 0x93, 0xad, 0x00, 0x8c, 0x7a, 0xfc, - 0xa3, 0x7c, 0x34, 0x34, 0x3a, 0x54, 0x18, 0x66, 0xeb, 0x46, 0x98, 0xdc, 0xff, 0xf7, 0x73, 0xcc, - 0x87, 0x75, 0xd7, 0xb1, 0x9f, 0xd8, 0xe1, 0xf7, 0xab, 0x2a, 0x78, 0xc2, 0x44, 0x1e, 0x5c, 0xfc, - 0x4a, 0x49, 0xd9, 0x21, 0x75, 0x41, 0xf9, 0x9e, 0xba, 0xa0, 0x07, 0xca, 0x7b, 0x87, 0x12, 0x14, - 0x92, 0x1d, 0xb3, 0xba, 0xee, 0x25, 0x7c, 0x08, 0xf9, 0x1a, 0xce, 0xd1, 0xf0, 0x74, 0xec, 0x31, - 0x69, 0x7c, 0xe9, 0x0e, 0xdf, 0xb5, 0x32, 0xba, 0xcf, 0xe2, 0xd9, 0x71, 0xbf, 0x74, 0x1a, 0x43, - 0xb2, 0x4d, 0x0b, 0xd4, 0x60, 0x74, 0x0c, 0x04, 0xed, 0xc0, 0x4c, 0xcd, 0xc3, 0x2d, 0x6e, 0xf8, - 0xdd, 0xf1, 0xf8, 0xfd, 0x98, 0xdd, 0xbc, 0x69, 0x98, 0xef, 0x8e, 0xa8, 0x6e, 0x60, 0x59, 0xaf, - 0x9e, 0x27, 0x09, 0xe8, 0x68, 0x05, 0xa6, 0xea, 0xd8, 0xf2, 0x9a, 0x47, 0x8f, 0xf1, 0x4b, 0x72, - 0xe2, 0x6a, 0xb1, 0xf1, 0x7d, 0x5a, 0x43, 0xc6, 0x4b, 0xab, 0x54, 0x7b, 0x05, 0x1d, 0x09, 0x7d, - 0x0f, 0xce, 0xd5, 0x5d, 0x2f, 0xa8, 0xbc, 0xe4, 0xdf, 0xb4, 0x78, 0x6e, 0x60, 0x85, 0x95, 0x8b, - 0x22, 0x3f, 0x80, 0xef, 0x7a, 0x41, 0xe3, 0x40, 0x65, 0x1f, 0xc7, 0x43, 0x2f, 0x61, 0x56, 0xff, - 0x9e, 0x1e, 0xda, 0x6d, 0xb2, 0x09, 0x8d, 0xf2, 0x93, 0x3e, 0xe9, 0xa3, 0x65, 0x20, 0x95, 0x5b, - 0x9c, 0xfa, 0xd5, 0xe8, 0x57, 0xfb, 0x84, 0xd6, 0xab, 0xd9, 0x45, 0x92, 0xf0, 0xd1, 0x26, 0x4d, - 0xab, 0xc0, 0x46, 0x54, 0xf6, 0x99, 0xc9, 0xf5, 0x58, 0x18, 0xc2, 0xa8, 0x4b, 0xbf, 0x49, 0xca, - 0x09, 0xcb, 0x8f, 0x66, 0xcb, 0x30, 0x63, 0xa8, 0xa8, 0x06, 0xe7, 0x77, 0x7d, 0x5c, 0xf3, 0xf0, - 0x33, 0x1b, 0x3f, 0x17, 0xf4, 0x58, 0x1c, 0x2e, 0x3a, 0x4d, 0x84, 0x5e, 0x87, 0xd5, 0x26, 0x11, - 0x8c, 0x23, 0xa3, 0x0f, 0x01, 0x6a, 0xb6, 0xe3, 0xe0, 0x16, 0x7d, 0xb3, 0x1a, 0xa7, 0xa4, 0xa8, - 0x56, 0xaf, 0x43, 0x4b, 0x1b, 0xae, 0xd3, 0x56, 0x59, 0xaa, 0x00, 0x17, 0x3f, 0x84, 0x71, 0x65, - 0x89, 0x25, 0xc4, 0x35, 0x98, 0x55, 0xe3, 0x1a, 0x8c, 0xa9, 0xf1, 0x0b, 0xfe, 0x6e, 0x0e, 0x16, - 0x93, 0x97, 0x2e, 0x3f, 0xee, 0xb7, 0x61, 0x4c, 0x16, 0x4a, 0x2f, 0x1d, 0x21, 0xec, 0x45, 0xce, - 0x5b, 0xf6, 0xfd, 0x88, 0x0f, 0x5d, 0x1d, 0x6f, 0x48, 0xe3, 0x15, 0x34, 0xb0, 0xff, 0x62, 0x04, - 0x66, 0x49, 0x1f, 0x63, 0xdb, 0xc2, 0xe7, 0x34, 0x3e, 0x09, 0x2d, 0x53, 0x14, 0x8a, 0x5c, 0xb7, - 0xc0, 0xca, 0xa3, 0x31, 0x93, 0x34, 0x04, 0xf4, 0x9e, 0xfa, 0x7e, 0x9d, 0x57, 0xf2, 0x26, 0x88, - 0x42, 0x75, 0x08, 0xe1, 0xc3, 0xf6, 0x3b, 0xda, 0xf3, 0x69, 0xdf, 0x7b, 0xcc, 0x50, 0xbf, 0x7b, - 0xcc, 0xae, 0xdc, 0x63, 0x58, 0xdc, 0x8b, 0xb7, 0x95, 0x3d, 0xe6, 0xcd, 0x6f, 0x2e, 0xe7, 0xde, - 0xf4, 0xe6, 0x32, 0xf2, 0x7a, 0x9b, 0xcb, 0xe8, 0x2b, 0x6e, 0x2e, 0x0f, 0x61, 0x6a, 0x0b, 0xe3, - 0x96, 0xa2, 0x1a, 0x67, 0xdf, 0x37, 0xd7, 0x07, 0x50, 0xa5, 0x47, 0x92, 0x7e, 0x3c, 0x82, 0x95, - 0xba, 0x49, 0xc1, 0xff, 0x99, 0x4d, 0x6a, 0xfc, 0x0d, 0x6f, 0x52, 0x13, 0xaf, 0xb1, 0x49, 0xbd, - 0xce, 0x4e, 0xf3, 0x19, 0xb5, 0x24, 0xab, 0xd7, 0xd7, 0xf8, 0x2b, 0xbd, 0xf2, 0x2c, 0xbe, 0xe6, - 0xfa, 0xc2, 0x44, 0x9e, 0xfe, 0x4d, 0xca, 0x6a, 0xae, 0x27, 0x9e, 0x16, 0xe9, 0xdf, 0x46, 0x85, - 0xda, 0x8f, 0xa9, 0xf8, 0xd2, 0xbf, 0x62, 0x84, 0xbb, 0x27, 0xf2, 0xfd, 0x29, 0x2a, 0x70, 0x9b, - 0xa2, 0xde, 0xf8, 0x77, 0x39, 0xf6, 0x84, 0xf4, 0x7f, 0xe3, 0x36, 0xf7, 0x3a, 0xcf, 0x3a, 0xbf, - 0x11, 0x86, 0x2d, 0xe0, 0x21, 0x16, 0x3c, 0xab, 0xf9, 0x34, 0x7c, 0x57, 0xfb, 0x21, 0xf9, 0x46, - 0xd5, 0x0a, 0x1a, 0xd1, 0x31, 0xbc, 0x55, 0xe8, 0x95, 0x7b, 0xf7, 0xc5, 0xc7, 0xcb, 0xa3, 0x37, - 0xb0, 0x62, 0xfd, 0xe3, 0x55, 0x11, 0xa8, 0x13, 0xcc, 0xb4, 0x61, 0x32, 0xaf, 0xfb, 0xc4, 0x1e, - 0xbc, 0x1f, 0xf7, 0x1b, 0xa7, 0x62, 0x6b, 0xe8, 0x37, 0xae, 0xb2, 0x31, 0xf4, 0x20, 0xdf, 0x85, - 0x4b, 0x26, 0x3e, 0x76, 0x9f, 0xe1, 0x37, 0x4b, 0xf6, 0x07, 0x70, 0x51, 0x27, 0xc8, 0xdc, 0xa4, - 0x58, 0xb4, 0xf0, 0xcf, 0x92, 0x63, 0x8c, 0x73, 0x04, 0x16, 0x63, 0x9c, 0x85, 0x81, 0x25, 0x7f, - 0xaa, 0x7b, 0x3e, 0xad, 0x33, 0x5c, 0x58, 0xd4, 0x89, 0x97, 0x5b, 0x2d, 0x9a, 0x01, 0xae, 0x69, - 0x77, 0x2c, 0x27, 0x40, 0xdb, 0x30, 0xae, 0xfc, 0x8c, 0x5c, 0x2a, 0x95, 0x1a, 0x7e, 0xfc, 0x87, - 0x05, 0x5a, 0xec, 0xbf, 0xb0, 0xd8, 0xc0, 0x50, 0x8a, 0xb2, 0x87, 0xb0, 0x4c, 0x6d, 0xb3, 0x02, - 0x93, 0xca, 0x4f, 0xa9, 0x60, 0xa2, 0xa1, 0x2a, 0x95, 0x16, 0x74, 0x86, 0xe9, 0x28, 0x46, 0x13, - 0x8a, 0x49, 0x4c, 0xa3, 0xd1, 0x9a, 0x5e, 0xa2, 0x95, 0x30, 0xee, 0x53, 0x6f, 0xab, 0xa6, 0xe9, - 0xb4, 0x98, 0x4f, 0xc6, 0xdf, 0x18, 0x82, 0x4b, 0x7c, 0x32, 0xde, 0xe4, 0x8c, 0xa3, 0x1f, 0xc1, - 0xb8, 0x32, 0xc7, 0x9c, 0xe9, 0x57, 0x85, 0xf9, 0x64, 0xda, 0x5a, 0x60, 0x97, 0xdf, 0x2e, 0x2d, - 0x68, 0x44, 0xa6, 0x9b, 0x5c, 0x7e, 0xd5, 0x65, 0xd3, 0x86, 0x29, 0x7d, 0xa2, 0xf9, 0xfd, 0xff, - 0x7a, 0x62, 0x23, 0x3a, 0xa8, 0x88, 0x20, 0xdb, 0x6a, 0x24, 0x4e, 0x37, 0xb9, 0xc6, 0x47, 0x16, - 0xd1, 0x0b, 0x38, 0x1f, 0x9b, 0x65, 0xae, 0xd6, 0xb9, 0x99, 0xd8, 0x60, 0x0c, 0x9a, 0x29, 0xcf, - 0x3c, 0x5a, 0x9c, 0xda, 0x6c, 0xbc, 0x11, 0xd4, 0x82, 0x09, 0x75, 0xe2, 0xb9, 0x82, 0xe2, 0x5a, - 0x06, 0x2b, 0x19, 0x20, 0x13, 0xcc, 0x38, 0x2f, 0xe9, 0xdc, 0xbf, 0xd4, 0x15, 0x82, 0x1a, 0xf0, - 0x28, 0x9c, 0x63, 0xbf, 0xc9, 0x16, 0x50, 0xf3, 0xb0, 0x8f, 0x9d, 0x26, 0x56, 0x2d, 0x61, 0x5f, - 0x77, 0x0b, 0xf8, 0x57, 0x39, 0x58, 0x48, 0xa2, 0x5b, 0xc7, 0x4e, 0x0b, 0xd5, 0xa0, 0x10, 0x6d, - 0x88, 0xaf, 0x6a, 0x43, 0x06, 0xe9, 0x4c, 0xed, 0xd2, 0xda, 0x80, 0x19, 0xc3, 0x46, 0x5b, 0x70, - 0x5e, 0x29, 0x3b, 0xa3, 0xc9, 0x71, 0x1c, 0x55, 0xd5, 0x62, 0xae, 0xd1, 0x93, 0x71, 0xd9, 0x3d, - 0xb6, 0x6c, 0x87, 0x08, 0xa9, 0x4a, 0xe8, 0x27, 0x08, 0x4b, 0x39, 0x6f, 0x98, 0x5e, 0x8e, 0x96, - 0x0a, 0x3f, 0x02, 0x09, 0x62, 0x7c, 0x42, 0x77, 0x70, 0xae, 0xcd, 0x61, 0xae, 0xb8, 0x92, 0xd8, - 0x55, 0x18, 0xde, 0xd9, 0xa8, 0x57, 0xcb, 0xdc, 0xb1, 0x97, 0x85, 0x83, 0x68, 0xfb, 0x8d, 0xa6, - 0x65, 0xb2, 0x0a, 0xe3, 0x63, 0x1a, 0xe7, 0x9b, 0x47, 0x89, 0x96, 0x78, 0x37, 0x60, 0x84, 0x17, - 0x71, 0x4c, 0x6a, 0x82, 0xd4, 0xe6, 0x50, 0xa2, 0xce, 0xa8, 0x09, 0x19, 0xbf, 0x8d, 0x2d, 0x5f, - 0x39, 0x98, 0x3f, 0x80, 0x51, 0x8f, 0x97, 0xf1, 0x73, 0x79, 0x4a, 0xe6, 0x7c, 0xa0, 0xc5, 0x4c, - 0xf3, 0x29, 0x60, 0x4c, 0xf9, 0x97, 0xb1, 0x41, 0x43, 0xb7, 0x6c, 0xaf, 0x2f, 0x57, 0x09, 0x57, - 0x39, 0xb3, 0xc4, 0x74, 0xdc, 0xa5, 0x56, 0xbd, 0x01, 0x56, 0xdd, 0x7a, 0x29, 0x6b, 0xe8, 0x47, - 0xce, 0x03, 0x16, 0x29, 0x20, 0xc6, 0x03, 0x19, 0x08, 0x26, 0x81, 0x5a, 0x5a, 0xee, 0x82, 0x2d, - 0x1a, 0xe2, 0x66, 0x95, 0x1a, 0x37, 0xbc, 0x89, 0x4e, 0x58, 0x50, 0x64, 0xc7, 0x3c, 0x19, 0x15, - 0x4f, 0xba, 0xe5, 0xca, 0xad, 0xb1, 0x0a, 0x63, 0xb2, 0x4c, 0xbe, 0x54, 0x30, 0x5e, 0x69, 0xf0, - 0x7b, 0x0f, 0x98, 0x07, 0x74, 0x53, 0x12, 0x08, 0xf1, 0x48, 0x13, 0xec, 0xbb, 0xfb, 0x86, 0x9b, - 0xf0, 0xb1, 0x17, 0x7c, 0xa3, 0x4d, 0x84, 0x31, 0x90, 0xce, 0xd2, 0x84, 0x06, 0xbf, 0xb7, 0xd4, - 0x0f, 0xa3, 0xbe, 0xe1, 0x26, 0x08, 0xa3, 0xbe, 0xb9, 0x26, 0xb0, 0x08, 0x16, 0xc5, 0x16, 0x69, - 0xac, 0x91, 0x95, 0x78, 0x23, 0x42, 0xc5, 0x19, 0xc1, 0xc8, 0x9c, 0x0f, 0x0c, 0x8b, 0x8c, 0x59, - 0xbf, 0x80, 0x66, 0x08, 0xc3, 0xbe, 0xd9, 0x66, 0x7e, 0x3f, 0xc7, 0x42, 0x57, 0xd5, 0xb7, 0x95, - 0x74, 0x77, 0xce, 0x13, 0x57, 0x79, 0x48, 0x55, 0xbe, 0xf6, 0xc7, 0xb6, 0xd3, 0x52, 0x1f, 0x52, - 0xad, 0x6e, 0x70, 0x24, 0x83, 0x17, 0x3f, 0xb5, 0x9d, 0x96, 0x19, 0x85, 0x46, 0x1f, 0xc2, 0xa4, - 0x52, 0x24, 0xa5, 0x35, 0x16, 0xac, 0x5e, 0x45, 0xb7, 0x5b, 0xa6, 0x0e, 0x69, 0xfc, 0x4e, 0x1e, - 0x2e, 0xec, 0x76, 0x7c, 0xea, 0xed, 0xb0, 0xee, 0x3c, 0xc3, 0x4e, 0xe0, 0x7a, 0x2f, 0xa9, 0xdd, - 0x35, 0x7a, 0x0f, 0x86, 0xd7, 0x70, 0xbb, 0xed, 0xf2, 0x91, 0x5f, 0x16, 0xaf, 0x98, 0x51, 0x68, - 0x0a, 0xb4, 0x36, 0x60, 0x32, 0x68, 0xf4, 0x21, 0x8c, 0xad, 0x61, 0xcb, 0x0b, 0x0e, 0xb0, 0x25, - 0x84, 0x55, 0x11, 0x3c, 0x5d, 0x41, 0xe1, 0x00, 0x6b, 0x03, 0x66, 0x08, 0x8d, 0x96, 0xc8, 0x3d, - 0xce, 0x39, 0x94, 0x8e, 0xdf, 0x29, 0x0d, 0x12, 0x98, 0xb5, 0x01, 0x93, 0xc2, 0xa2, 0x4d, 0x98, - 0x2c, 0x1f, 0x62, 0x27, 0xd8, 0xc4, 0x81, 0xd5, 0xb2, 0x02, 0x8b, 0x0b, 0x35, 0x37, 0xd2, 0x90, - 0x35, 0xe0, 0xb5, 0x01, 0x53, 0xc7, 0xae, 0x0c, 0xc3, 0xe0, 0xa6, 0x7f, 0x68, 0x9c, 0xe4, 0x60, - 0x61, 0xd9, 0x7d, 0xee, 0x24, 0x32, 0xe6, 0xbb, 0x3a, 0x63, 0x84, 0x4f, 0x4e, 0x02, 0x7c, 0x84, - 0x35, 0xef, 0xc2, 0x50, 0xcd, 0x76, 0x0e, 0x23, 0xe7, 0x78, 0x02, 0x1e, 0x81, 0xa2, 0x23, 0xb4, - 0x9d, 0x43, 0xb4, 0x21, 0x04, 0x28, 0xae, 0xe4, 0x19, 0xd4, 0xa4, 0xb6, 0x04, 0x6c, 0x15, 0x3a, - 0x14, 0x94, 0xd8, 0x6f, 0x31, 0xc0, 0x77, 0x60, 0x3e, 0xa5, 0x5d, 0xee, 0x8c, 0x4d, 0xc6, 0x36, - 0x44, 0x4f, 0xa5, 0xb7, 0x61, 0x2e, 0x71, 0x0a, 0x62, 0x80, 0xff, 0x30, 0x69, 0x2d, 0xb1, 0x91, - 0x2f, 0xc0, 0x88, 0xc8, 0xb1, 0xc1, 0x2e, 0xee, 0xe2, 0x27, 0xf5, 0x22, 0xa0, 0xd7, 0xed, 0x30, - 0x0c, 0xb0, 0xf8, 0x8d, 0xf6, 0x94, 0x88, 0x3f, 0x83, 0x54, 0x4b, 0xf4, 0xd1, 0x6b, 0x64, 0x22, - 0x96, 0xb4, 0x48, 0x9b, 0x6b, 0xae, 0x1f, 0x38, 0xd2, 0xc8, 0xcd, 0x94, 0xbf, 0xd1, 0x6d, 0x28, - 0xac, 0xbc, 0x08, 0xb0, 0xe7, 0x58, 0x6d, 0x9e, 0x6d, 0x80, 0xa7, 0x98, 0x35, 0x63, 0xe5, 0xe8, - 0x03, 0x98, 0x8f, 0x96, 0x89, 0x51, 0x32, 0x37, 0x90, 0xb4, 0x6a, 0xe3, 0xcf, 0xf2, 0x34, 0x70, - 0x71, 0xc6, 0xd2, 0x24, 0xdc, 0xdd, 0xae, 0x73, 0x6e, 0xe5, 0xb7, 0xeb, 0x68, 0x11, 0xc6, 0xb6, - 0xeb, 0x5a, 0xa2, 0x12, 0x33, 0x2c, 0x20, 0xdd, 0x26, 0x43, 0x28, 0x7b, 0xcd, 0x23, 0x3b, 0xc0, - 0xcd, 0xa0, 0xeb, 0xf1, 0x78, 0x4d, 0x66, 0xac, 0x1c, 0x19, 0x30, 0xb1, 0xda, 0xb6, 0x0f, 0x9a, - 0x82, 0x18, 0x63, 0x81, 0x56, 0x86, 0x6e, 0xc2, 0xd4, 0xba, 0xe3, 0x07, 0x56, 0xbb, 0xcd, 0xf2, - 0xb8, 0xf0, 0x3c, 0x7f, 0x66, 0xa4, 0x94, 0xb4, 0x5b, 0x75, 0x9d, 0xc0, 0xb2, 0x1d, 0xec, 0x99, - 0x5d, 0x27, 0xb0, 0x8f, 0x31, 0x1f, 0x7b, 0xac, 0x1c, 0xbd, 0x0b, 0x73, 0xb2, 0x6c, 0xdb, 0x6b, - 0x1e, 0x61, 0x3f, 0xf0, 0x68, 0x8a, 0x2d, 0x1a, 0x99, 0xc6, 0x4c, 0xae, 0xa4, 0x2d, 0xb4, 0xdd, - 0x6e, 0x6b, 0xc5, 0x79, 0x66, 0x7b, 0xae, 0x43, 0x33, 0x67, 0x8e, 0xf2, 0x16, 0x22, 0xe5, 0x46, - 0x2d, 0xf1, 0xab, 0x7d, 0x8d, 0x25, 0x68, 0x9c, 0xe6, 0x60, 0x31, 0xf1, 0xc3, 0x12, 0x9b, 0xb7, - 0x8a, 0x9c, 0x8b, 0xac, 0xdf, 0xdb, 0x30, 0x44, 0x77, 0x73, 0xa6, 0x18, 0x10, 0x66, 0x20, 0x14, - 0x9f, 0x91, 0x22, 0xb5, 0x26, 0x85, 0x41, 0xab, 0x52, 0x89, 0x3b, 0x48, 0xc5, 0xd6, 0xbb, 0xd1, - 0x3d, 0x33, 0xa1, 0x71, 0x55, 0x99, 0x2b, 0xd4, 0xb6, 0xaf, 0xa3, 0x73, 0xfb, 0xb3, 0x1c, 0x94, - 0x7a, 0xec, 0x27, 0x72, 0x4c, 0xb9, 0x3e, 0xc6, 0xf4, 0x48, 0x8e, 0x89, 0x39, 0x9c, 0x2c, 0xf5, - 0xb7, 0x67, 0xbd, 0xe9, 0x61, 0x55, 0x01, 0xc5, 0x4f, 0x1e, 0xf4, 0x1d, 0x18, 0xab, 0xd7, 0xd7, - 0xb4, 0x77, 0xfe, 0x98, 0x26, 0x30, 0x84, 0x30, 0xde, 0x87, 0x0b, 0x92, 0x08, 0x8b, 0x9c, 0xae, - 0x78, 0xb5, 0xf1, 0xb3, 0x5e, 0xba, 0xe0, 0x85, 0x05, 0xc6, 0x9f, 0x0e, 0xc5, 0x10, 0xeb, 0xdd, - 0xe3, 0x63, 0xcb, 0x7b, 0x89, 0xca, 0x3a, 0xe2, 0x60, 0xcf, 0x43, 0xb6, 0x32, 0xf4, 0xd3, 0x93, - 0xd2, 0x80, 0x42, 0x1d, 0xbd, 0x05, 0x93, 0xf4, 0x83, 0x74, 0x9a, 0x98, 0xe9, 0x01, 0xf3, 0x2c, - 0x04, 0x88, 0x56, 0x88, 0xf6, 0x60, 0x92, 0xaf, 0x75, 0xfa, 0x5b, 0x2c, 0xb1, 0x7b, 0xd1, 0x25, - 0xa6, 0x75, 0xef, 0x8e, 0x86, 0xc2, 0x26, 0x43, 0x27, 0x83, 0xbe, 0x82, 0x29, 0xb1, 0xb1, 0x71, - 0xc2, 0xec, 0x91, 0xf3, 0x7e, 0x36, 0x61, 0x1d, 0x87, 0x51, 0x8e, 0x10, 0x22, 0x5d, 0xe6, 0xdb, - 0x35, 0xa7, 0x3c, 0xdc, 0x4f, 0x97, 0x35, 0x14, 0xde, 0x65, 0xad, 0xac, 0xf8, 0x3d, 0x40, 0xf1, - 0x71, 0xf5, 0x5a, 0x4d, 0x93, 0xca, 0x6a, 0x2a, 0x96, 0x61, 0x26, 0x61, 0x00, 0x67, 0x22, 0xf1, - 0x3d, 0x40, 0xf1, 0x9e, 0x9e, 0x85, 0x82, 0x71, 0x0b, 0x6e, 0x4a, 0x16, 0xc8, 0xd5, 0xa0, 0xd1, - 0x14, 0xb7, 0xfd, 0x5f, 0xcb, 0x43, 0xa9, 0x07, 0x28, 0xfa, 0xdb, 0xb9, 0x28, 0xb7, 0xd9, 0x6a, - 0xfc, 0x30, 0xca, 0xed, 0x64, 0xfc, 0x04, 0xb6, 0x57, 0x3e, 0xfa, 0xf5, 0x3f, 0x7f, 0xe5, 0x83, - 0x3a, 0x3e, 0x65, 0x67, 0xe7, 0xd6, 0x90, 0xca, 0x2d, 0x13, 0x66, 0x35, 0x11, 0xa7, 0x9f, 0xbd, - 0xfb, 0x0a, 0x00, 0x4f, 0xe8, 0xb4, 0xe1, 0x1e, 0x72, 0x9f, 0x40, 0xa5, 0xc4, 0x78, 0x08, 0x73, - 0x11, 0x9a, 0x5c, 0x03, 0xf1, 0x1d, 0x90, 0xde, 0x4b, 0x94, 0xe8, 0x60, 0xe5, 0xfc, 0xcf, 0x4f, - 0x4a, 0x93, 0xe4, 0x04, 0xbc, 0x13, 0x06, 0x28, 0x16, 0x7f, 0x19, 0x9b, 0xaa, 0x0e, 0xa5, 0xdc, - 0xd6, 0x7c, 0xc0, 0xef, 0xc3, 0x39, 0x56, 0x12, 0x09, 0x03, 0xaa, 0x42, 0xf3, 0x3d, 0x81, 0x03, - 0x1a, 0x73, 0xd4, 0x63, 0x83, 0xfe, 0x28, 0x87, 0xbe, 0x81, 0xc6, 0x2e, 0x0b, 0x1d, 0x1f, 0x16, - 0xcb, 0x50, 0xa3, 0x43, 0xe5, 0xd0, 0x87, 0x51, 0x3c, 0x56, 0x09, 0x38, 0xc7, 0x7d, 0xde, 0xc6, - 0xad, 0x43, 0x9a, 0x62, 0xba, 0x32, 0xc1, 0x1f, 0xab, 0x86, 0x2c, 0x42, 0x80, 0xa2, 0x19, 0x9f, - 0xc3, 0x5c, 0xb5, 0x8d, 0x2d, 0x2f, 0xda, 0x1e, 0xba, 0x09, 0x23, 0xb4, 0x4c, 0xb7, 0x37, 0xb3, - 0x48, 0x11, 0xb5, 0x37, 0xe3, 0x95, 0xc6, 0x06, 0x5c, 0x64, 0x37, 0x30, 0x75, 0x48, 0xa1, 0xbe, - 0x63, 0x98, 0xfe, 0x8e, 0xd8, 0xfb, 0x27, 0x8c, 0x9e, 0xc1, 0x19, 0x9f, 0x51, 0x83, 0xd2, 0xa4, - 0xec, 0xe2, 0xfd, 0x79, 0xa0, 0xfc, 0x7f, 0xb0, 0x58, 0xee, 0x74, 0xb0, 0xd3, 0x0a, 0x11, 0x77, - 0x3c, 0xab, 0x4f, 0xcf, 0x3e, 0x54, 0x86, 0x61, 0x0a, 0x2d, 0x95, 0xc5, 0xbc, 0xbb, 0x09, 0xdd, - 0xa1, 0x70, 0x3c, 0x2e, 0x1c, 0x6d, 0x80, 0x61, 0x1a, 0x2d, 0x98, 0xaf, 0x77, 0x0f, 0x8e, 0x6d, - 0x96, 0x72, 0x9b, 0x7a, 0xc7, 0x8a, 0xb6, 0xd7, 0x45, 0xb6, 0x0f, 0xc6, 0x8c, 0x5b, 0x61, 0xd6, - 0x70, 0x6a, 0xe8, 0xc6, 0x3d, 0x66, 0x9f, 0xdd, 0xbf, 0x13, 0xa2, 0xd2, 0xdb, 0x0a, 0x6b, 0x85, - 0x56, 0xf3, 0x8c, 0x20, 0xc6, 0x0c, 0x9c, 0x57, 0x15, 0x6f, 0x6c, 0x85, 0xcc, 0xc1, 0x8c, 0xae, - 0x50, 0x63, 0xc5, 0x5f, 0xc3, 0x2c, 0xbb, 0xf0, 0xb3, 0xb8, 0xae, 0x4b, 0x61, 0x08, 0xd3, 0xfc, - 0xde, 0x52, 0xc4, 0x3c, 0x8e, 0x9a, 0xef, 0xc8, 0x88, 0xdd, 0x7b, 0x4b, 0xcc, 0x29, 0xe0, 0xd9, - 0x92, 0xa6, 0xb6, 0xcd, 0xef, 0x2d, 0x55, 0x46, 0x78, 0x7c, 0x3c, 0x42, 0x9d, 0x4d, 0xff, 0x37, - 0x42, 0x7d, 0x89, 0xfa, 0xa1, 0xad, 0x61, 0x8b, 0xda, 0x8c, 0x26, 0x7b, 0xf3, 0x4c, 0x41, 0xde, - 0x6e, 0x09, 0x29, 0xdb, 0x6e, 0x19, 0x7f, 0x9c, 0x83, 0x5b, 0x4c, 0x16, 0x49, 0xc6, 0xa3, 0xda, - 0xb5, 0x14, 0x64, 0xf4, 0x01, 0xb0, 0x3c, 0xb2, 0x5c, 0xe0, 0x33, 0x78, 0xcf, 0xb3, 0x28, 0x31, - 0x04, 0x54, 0x86, 0x09, 0xd5, 0xe2, 0xb3, 0xbf, 0x50, 0x2c, 0xe6, 0xf8, 0xf1, 0x13, 0x4b, 0x5a, - 0x81, 0x3e, 0x85, 0x4b, 0x2b, 0x2f, 0xc8, 0x82, 0xe0, 0xa7, 0x13, 0x7f, 0x31, 0x0e, 0xbd, 0x45, - 0xa6, 0x77, 0xf8, 0x8a, 0xd1, 0xc5, 0xe0, 0x68, 0x31, 0xb9, 0x1e, 0x88, 0x03, 0x4e, 0x4a, 0xaf, - 0x63, 0xa6, 0x56, 0x66, 0xfc, 0x69, 0x0e, 0x16, 0x93, 0x5b, 0xe3, 0x1b, 0xcb, 0x3a, 0x9c, 0xaf, - 0x5a, 0x8e, 0xeb, 0xd8, 0x4d, 0xab, 0x5d, 0x6f, 0x1e, 0xe1, 0x56, 0x57, 0x86, 0x02, 0x94, 0xbb, - 0x0c, 0xb9, 0xee, 0x70, 0x74, 0x01, 0x62, 0xc6, 0xb1, 0xd0, 0xfb, 0x70, 0x81, 0x1a, 0x0d, 0xb2, - 0xbd, 0xb7, 0x8d, 0x3d, 0x49, 0x8f, 0xf5, 0x2c, 0xa5, 0x16, 0xdd, 0x83, 0x19, 0x76, 0xa8, 0xb4, - 0x76, 0x1d, 0x3b, 0x90, 0x48, 0xec, 0x56, 0x94, 0x54, 0x65, 0xd4, 0xe0, 0x2d, 0x2d, 0xcf, 0x54, - 0xb9, 0xdd, 0x76, 0x9f, 0xe3, 0x56, 0xcd, 0x73, 0x8f, 0xdd, 0x40, 0x0b, 0x76, 0xcf, 0x73, 0x00, - 0x86, 0x1a, 0x17, 0xce, 0xcb, 0x48, 0xb1, 0xf1, 0xff, 0xc2, 0x8d, 0x1e, 0x14, 0x39, 0xbf, 0xea, - 0x70, 0xde, 0x8a, 0xd4, 0x89, 0x87, 0xb1, 0x1b, 0x82, 0x5f, 0x59, 0x84, 0x7c, 0x33, 0x8e, 0x7f, - 0x7b, 0x47, 0x4b, 0x1b, 0x86, 0x16, 0x60, 0xb6, 0x66, 0x6e, 0x2f, 0xef, 0x56, 0x77, 0x1a, 0x3b, - 0x5f, 0xd5, 0x56, 0x1a, 0xbb, 0x5b, 0x8f, 0xb7, 0xb6, 0xf7, 0xb7, 0x58, 0xcc, 0x4e, 0xad, 0x66, - 0x67, 0xa5, 0xbc, 0x59, 0xc8, 0xa1, 0x59, 0x28, 0x68, 0xc5, 0x2b, 0xbb, 0x95, 0x42, 0xfe, 0x76, - 0x43, 0xb5, 0xe8, 0x45, 0x97, 0x60, 0x7e, 0x79, 0x65, 0x6f, 0xbd, 0xba, 0x22, 0x68, 0xaa, 0xf1, - 0x42, 0x67, 0xa1, 0xa0, 0x56, 0xee, 0x6c, 0xef, 0xd4, 0x58, 0xfe, 0x7e, 0xb5, 0x74, 0x7f, 0xa5, - 0x52, 0xde, 0xdd, 0x59, 0xdb, 0x2a, 0x0c, 0x1a, 0x43, 0xa3, 0xf9, 0x42, 0xfe, 0xf6, 0x8f, 0x34, - 0x73, 0x5f, 0xb4, 0x08, 0x0b, 0x1c, 0x7c, 0xb7, 0x5e, 0x5e, 0x4d, 0x6f, 0x82, 0xd5, 0x6e, 0x3e, - 0x2c, 0x17, 0x72, 0xe8, 0x32, 0x5c, 0xd4, 0x4a, 0x6b, 0xe5, 0x7a, 0x7d, 0x7f, 0xdb, 0x5c, 0xde, - 0x58, 0xa9, 0xd7, 0x0b, 0xf9, 0xdb, 0x7b, 0x5a, 0x60, 0x0c, 0xd2, 0xc2, 0xe6, 0xc3, 0x72, 0xc3, - 0x5c, 0xf9, 0x62, 0x77, 0xdd, 0x5c, 0x59, 0x8e, 0xb7, 0xa0, 0xd5, 0x7e, 0xb5, 0x52, 0x2f, 0xe4, - 0xd0, 0x0c, 0x4c, 0x6b, 0xa5, 0x5b, 0xdb, 0x85, 0xfc, 0xed, 0x9b, 0x3c, 0xec, 0x01, 0x9a, 0x02, - 0x58, 0x5e, 0xa9, 0x57, 0x57, 0xb6, 0x96, 0xd7, 0xb7, 0x56, 0x0b, 0x03, 0x68, 0x12, 0xc6, 0xca, - 0xf2, 0x67, 0xee, 0xf6, 0x47, 0x30, 0x1d, 0xb9, 0x31, 0x11, 0x08, 0x79, 0xd9, 0x28, 0x0c, 0x10, - 0x1e, 0xc9, 0x9f, 0xf4, 0x9a, 0xcb, 0x2e, 0x3f, 0x85, 0xdc, 0xd2, 0xff, 0xfc, 0xfd, 0x1c, 0x8c, - 0x93, 0xed, 0x40, 0x98, 0x7d, 0x7e, 0xad, 0x5c, 0x30, 0xf8, 0x67, 0xc0, 0x13, 0x30, 0xa5, 0xde, - 0x26, 0xe8, 0xc9, 0x50, 0xcc, 0x50, 0x5c, 0x51, 0x80, 0x5b, 0xb9, 0x7b, 0x39, 0x64, 0xd2, 0x57, - 0x9a, 0x88, 0xbc, 0x2d, 0x29, 0x27, 0x5f, 0x89, 0x8a, 0x97, 0x33, 0xc5, 0x74, 0xf4, 0xcb, 0x60, - 0xa8, 0x34, 0x53, 0xa4, 0xd2, 0xef, 0xf4, 0x27, 0x7d, 0x8a, 0x36, 0x6f, 0xf6, 0x07, 0x8e, 0x1e, - 0xc1, 0x24, 0x91, 0xd7, 0x24, 0x18, 0xba, 0x14, 0x45, 0x54, 0x44, 0xc4, 0xe2, 0x62, 0x72, 0xa5, - 0x8c, 0xff, 0x3e, 0x41, 0x07, 0xc2, 0x2e, 0x5b, 0x3e, 0x12, 0xce, 0x71, 0xa2, 0x84, 0xd9, 0xe9, - 0x14, 0xcf, 0x47, 0x8a, 0xf7, 0xee, 0xdf, 0xcb, 0xa1, 0x3a, 0x8d, 0x29, 0xa1, 0x09, 0x7e, 0x48, - 0xd8, 0x21, 0xc7, 0x25, 0x42, 0xd6, 0x9b, 0x92, 0xcc, 0x68, 0x94, 0x22, 0x31, 0x6e, 0x01, 0x8a, - 0xcb, 0x53, 0xe8, 0x6a, 0xb8, 0x0e, 0x92, 0x45, 0xad, 0xe2, 0x85, 0xd8, 0xe3, 0xfb, 0x0a, 0x39, - 0x51, 0xd1, 0x0a, 0x4c, 0x71, 0xcf, 0x17, 0x2e, 0xe1, 0xa1, 0x2c, 0x19, 0x31, 0x95, 0xcc, 0x2a, - 0xe5, 0x93, 0x94, 0x12, 0x51, 0x31, 0x1c, 0x47, 0x54, 0x74, 0x2c, 0x5e, 0x4a, 0xac, 0xe3, 0xe3, - 0x7b, 0x08, 0x53, 0xba, 0xc0, 0x89, 0xc4, 0x04, 0x25, 0xca, 0xa1, 0xa9, 0x1d, 0x6a, 0xc0, 0xfc, - 0xa6, 0x65, 0x53, 0x75, 0x13, 0x7f, 0xe2, 0x15, 0x0f, 0xb4, 0xa8, 0x94, 0xf1, 0x62, 0x5b, 0xc7, - 0x4e, 0xab, 0xd8, 0x2b, 0x06, 0x13, 0xfd, 0x6c, 0xea, 0x42, 0x6e, 0xd2, 0x1f, 0xb8, 0x91, 0xa1, - 0x67, 0xa9, 0x4b, 0xb2, 0x59, 0x28, 0xa6, 0x99, 0xd9, 0xa0, 0x4d, 0x2a, 0xb8, 0x45, 0x28, 0x2a, - 0x6b, 0xe2, 0xcc, 0xe4, 0x16, 0xa8, 0xff, 0x55, 0x60, 0x47, 0xed, 0x65, 0x7c, 0x94, 0xc2, 0xb8, - 0x54, 0x62, 0xf7, 0x72, 0xe8, 0x6b, 0xfa, 0x55, 0x27, 0x92, 0xdb, 0xb7, 0x83, 0x23, 0x6e, 0xb3, - 0x76, 0x29, 0x91, 0x00, 0xff, 0x50, 0x32, 0xa8, 0x9b, 0x30, 0x9b, 0x64, 0xd9, 0x23, 0x19, 0x9a, - 0x61, 0xf6, 0x93, 0xba, 0x0a, 0x4c, 0x22, 0x7e, 0xb6, 0xd2, 0x27, 0x29, 0xc3, 0xb0, 0x24, 0x95, - 0xe6, 0x27, 0x30, 0x45, 0x56, 0xc9, 0x63, 0x8c, 0x3b, 0xe5, 0xb6, 0xfd, 0x0c, 0xfb, 0x48, 0xc4, - 0x27, 0x93, 0x45, 0x69, 0xb8, 0xb7, 0x72, 0xe8, 0x5b, 0x30, 0xbe, 0x6f, 0x05, 0xcd, 0x23, 0x1e, - 0x18, 0x47, 0xc4, 0xcd, 0xa1, 0x65, 0x45, 0xf1, 0x8b, 0x56, 0xde, 0xcb, 0xa1, 0x4f, 0x61, 0x64, - 0x15, 0x07, 0xd4, 0x0f, 0xe4, 0x9a, 0x7c, 0xe4, 0x66, 0x06, 0x65, 0xeb, 0x8e, 0x34, 0x3f, 0x15, - 0x1d, 0x8e, 0x2a, 0xb7, 0xd0, 0x5d, 0x00, 0xb6, 0x21, 0x50, 0x0a, 0xd1, 0xea, 0x62, 0xac, 0xdb, - 0x68, 0x95, 0x1c, 0xfc, 0x6d, 0x1c, 0xe0, 0x7e, 0x9b, 0x4c, 0xe3, 0xd1, 0x06, 0x4c, 0xc9, 0x90, - 0xf9, 0x5b, 0xd4, 0x0b, 0xd2, 0x88, 0x10, 0xf3, 0xcf, 0x40, 0xed, 0x23, 0xf2, 0x55, 0xb0, 0x9c, - 0x6a, 0x32, 0x76, 0x1b, 0x4a, 0x8b, 0xe6, 0x26, 0x99, 0xc8, 0xc0, 0x14, 0xdc, 0x35, 0xd7, 0x0f, - 0x74, 0x5c, 0x59, 0x92, 0x8c, 0x8b, 0xa1, 0xa8, 0xb6, 0xab, 0xc7, 0x71, 0x0b, 0xf7, 0xdc, 0xb4, - 0xf0, 0x73, 0xc5, 0x6b, 0x19, 0x10, 0x6c, 0xbb, 0xa3, 0x3b, 0xc9, 0x32, 0xb9, 0xd1, 0xb3, 0x66, - 0xb6, 0x3b, 0xd8, 0xa9, 0xd7, 0xd7, 0x68, 0x40, 0x2e, 0xf1, 0xa6, 0xa6, 0x94, 0x09, 0xc2, 0x28, - 0x5e, 0x45, 0x4e, 0x3d, 0xcd, 0x23, 0x0e, 0x65, 0xf9, 0xc9, 0x85, 0xa7, 0x5e, 0x62, 0xc8, 0xb1, - 0xc7, 0x4c, 0xc7, 0xa0, 0x65, 0x64, 0xdd, 0x5b, 0x42, 0xc5, 0x24, 0x39, 0x95, 0x7f, 0xd8, 0x17, - 0x92, 0xea, 0xf6, 0x1e, 0xdc, 0xcb, 0xa1, 0x15, 0x98, 0x91, 0x4e, 0xab, 0x61, 0x15, 0x4a, 0x41, - 0xc8, 0x38, 0x61, 0xe6, 0x12, 0xc8, 0xec, 0x2d, 0x65, 0x10, 0x4a, 0x2c, 0x47, 0x9f, 0xc3, 0x0c, - 0x5f, 0x9b, 0x5a, 0x7f, 0x0a, 0x72, 0x9b, 0xe1, 0xa2, 0x7d, 0x6a, 0x4f, 0x1e, 0xc1, 0x5c, 0x3d, - 0xc2, 0x1d, 0x66, 0xf0, 0x75, 0x51, 0x27, 0x41, 0x0b, 0xeb, 0x38, 0x60, 0xec, 0x49, 0xa6, 0xf5, - 0x18, 0x10, 0xd3, 0x07, 0x08, 0x72, 0xcf, 0x6c, 0xfc, 0x1c, 0x5d, 0x8e, 0x74, 0x9d, 0x14, 0x52, - 0x30, 0xba, 0x4f, 0xa5, 0x8e, 0x6c, 0x87, 0x25, 0xfe, 0x63, 0xb9, 0xca, 0xad, 0x8e, 0x75, 0x60, - 0xb7, 0xed, 0xc0, 0xc6, 0x64, 0xa9, 0xaa, 0x08, 0x6a, 0x95, 0x58, 0x0f, 0x17, 0x53, 0x21, 0xd0, - 0xaf, 0xd2, 0x70, 0x51, 0xd9, 0x77, 0x13, 0xf4, 0xad, 0xa4, 0xec, 0xd4, 0x29, 0xb7, 0xab, 0xe2, - 0xb7, 0xfb, 0x03, 0xe6, 0x8b, 0xf1, 0x33, 0x98, 0x5c, 0xc5, 0x01, 0xcb, 0x2e, 0xbe, 0x6c, 0x05, - 0x16, 0x92, 0xfa, 0x02, 0x59, 0xc4, 0xd7, 0xa0, 0x88, 0xf5, 0x10, 0x56, 0xd4, 0xf1, 0x8f, 0xd1, - 0x3a, 0x14, 0xd8, 0x36, 0xaf, 0x90, 0xb8, 0x1c, 0x23, 0xc1, 0x41, 0x2c, 0xcf, 0x3a, 0xf6, 0x53, - 0x67, 0xeb, 0x2e, 0x7b, 0xde, 0x45, 0x32, 0x31, 0xb3, 0x22, 0x47, 0xce, 0x68, 0x65, 0x32, 0xa2, - 0x27, 0x99, 0x11, 0x13, 0xfb, 0x38, 0x10, 0xde, 0xad, 0x2c, 0xd9, 0xd9, 0xf5, 0xf0, 0x4c, 0x8f, - 0xd7, 0x86, 0x9f, 0x79, 0x24, 0x12, 0xc3, 0xde, 0x03, 0x24, 0x13, 0xc0, 0x25, 0x10, 0xbd, 0xa9, - 0x89, 0x1e, 0x67, 0xa3, 0x5b, 0x85, 0x31, 0x86, 0x56, 0x71, 0x03, 0xb9, 0x3f, 0xca, 0x12, 0x81, - 0xb9, 0x10, 0xaf, 0xe0, 0xca, 0x89, 0xc1, 0xbf, 0x96, 0xcf, 0xa1, 0x32, 0x8c, 0xb1, 0x4f, 0x4b, - 0x25, 0x22, 0x4b, 0x7a, 0x6c, 0xf3, 0x8c, 0xc4, 0x67, 0x30, 0xbe, 0x8a, 0x83, 0x8a, 0x4b, 0x9d, - 0x8b, 0x7d, 0xf9, 0x49, 0x29, 0x65, 0x82, 0xcc, 0xa4, 0x32, 0x8a, 0xbd, 0x25, 0x8a, 0x7d, 0x2f, - 0x87, 0xde, 0xa5, 0x47, 0x26, 0xf5, 0x4c, 0x9e, 0x0b, 0x71, 0x95, 0x1c, 0xc7, 0x49, 0x78, 0xe4, - 0x4c, 0x27, 0x12, 0x77, 0xd7, 0xf3, 0xb0, 0xc3, 0x90, 0xd3, 0xc4, 0xa3, 0x24, 0xec, 0xcf, 0xe8, - 0x76, 0xa9, 0x60, 0x33, 0x6b, 0xfb, 0x5e, 0x24, 0x58, 0xa6, 0x84, 0x7b, 0x39, 0xf4, 0x01, 0x8c, - 0xf2, 0x3e, 0x12, 0x24, 0xad, 0xd3, 0x3d, 0x46, 0xfb, 0x01, 0x00, 0x9b, 0x0a, 0xda, 0x67, 0x1d, - 0x26, 0x9b, 0xcf, 0x1f, 0x10, 0xd9, 0xa0, 0xf5, 0x2a, 0x98, 0x55, 0x21, 0x24, 0x50, 0xcc, 0x05, - 0x6d, 0x96, 0x55, 0x3e, 0x67, 0x12, 0x21, 0x62, 0x3e, 0x0d, 0x09, 0x23, 0x23, 0x3b, 0x48, 0x31, - 0x5f, 0x2b, 0xee, 0x25, 0x1a, 0xac, 0x43, 0xa1, 0xdc, 0xa4, 0xa7, 0x97, 0xcc, 0x2a, 0x2d, 0xef, - 0x58, 0xd1, 0x0a, 0x41, 0x6b, 0x2e, 0x9a, 0xa4, 0x7a, 0x03, 0x5b, 0x34, 0xe2, 0xdd, 0xbc, 0x94, - 0x84, 0x22, 0x55, 0xc9, 0x18, 0x19, 0x77, 0xaa, 0xd9, 0x2a, 0xb9, 0x05, 0xb6, 0x5f, 0x8f, 0xcc, - 0x47, 0x74, 0xe3, 0x53, 0x32, 0x6e, 0x5f, 0x88, 0xe2, 0xcb, 0xdb, 0xa7, 0x30, 0xb5, 0x95, 0xa0, - 0x65, 0x98, 0xe6, 0xf1, 0xb5, 0x24, 0x5b, 0xd2, 0xb0, 0xd3, 0x9a, 0xff, 0x2e, 0x4c, 0xad, 0x90, - 0x83, 0xa9, 0xdb, 0xb2, 0x59, 0x94, 0x4f, 0xa4, 0x87, 0x6d, 0x4c, 0x45, 0x5c, 0x13, 0xc9, 0x49, - 0x94, 0x54, 0xd4, 0xf2, 0x43, 0x8e, 0x67, 0xfb, 0x2e, 0xce, 0x0a, 0xb2, 0x6a, 0xd6, 0x6a, 0xae, - 0x9a, 0x98, 0x4f, 0x49, 0xfe, 0x8c, 0x6e, 0x68, 0x37, 0xde, 0xb4, 0x0c, 0xce, 0x09, 0x32, 0xee, - 0x97, 0x4a, 0x9e, 0xbd, 0x14, 0x9a, 0xd9, 0x59, 0xa1, 0x53, 0xc7, 0x2d, 0xe3, 0xf2, 0x25, 0x66, - 0x6f, 0x46, 0xef, 0xe8, 0xd4, 0x33, 0x32, 0x3c, 0xa7, 0xb6, 0x40, 0x35, 0x0a, 0x7a, 0x72, 0x61, - 0x74, 0x25, 0x3b, 0x07, 0xb2, 0xa2, 0x51, 0x48, 0xc9, 0x4a, 0xfc, 0x88, 0x2e, 0xb3, 0x30, 0x19, - 0x1f, 0x52, 0xef, 0xe7, 0xd1, 0x5c, 0x84, 0x52, 0x70, 0x4c, 0xce, 0x30, 0x5c, 0x83, 0xe9, 0x48, - 0xee, 0x5e, 0xa9, 0x48, 0x4a, 0xce, 0x1e, 0x5c, 0xbc, 0x92, 0x56, 0x2d, 0xd5, 0xa6, 0x85, 0x68, - 0xc2, 0x53, 0x39, 0xe4, 0x94, 0x64, 0xb3, 0x72, 0xc8, 0xa9, 0x99, 0x52, 0x1f, 0x41, 0x21, 0x9a, - 0x6b, 0x51, 0x12, 0x4d, 0x49, 0xc2, 0x98, 0x3a, 0x27, 0x0f, 0x61, 0x56, 0x9d, 0x51, 0x39, 0xee, - 0xb4, 0xdd, 0x3f, 0x8d, 0xce, 0x0e, 0xcc, 0x25, 0xa6, 0x46, 0x94, 0xa2, 0x42, 0x56, 0xe2, 0xc4, - 0x54, 0xaa, 0x18, 0x2e, 0x24, 0x67, 0x47, 0x45, 0x6f, 0xe9, 0x7a, 0x8a, 0xe4, 0x5c, 0x91, 0xc5, - 0x1b, 0x3d, 0xa0, 0x38, 0x43, 0xbf, 0xa6, 0x27, 0x60, 0xac, 0x8d, 0x6b, 0x8a, 0xe6, 0x22, 0xa5, - 0x01, 0x23, 0x0b, 0x44, 0xae, 0x81, 0xd9, 0xa4, 0xec, 0xcc, 0xa9, 0x2c, 0xbe, 0x9e, 0x4e, 0x33, - 0x5c, 0x58, 0x7b, 0x22, 0x88, 0x5d, 0x2a, 0x67, 0x32, 0xb3, 0x68, 0x66, 0x5c, 0x7d, 0x8b, 0x72, - 0x3d, 0xf4, 0xdf, 0xe5, 0x74, 0x35, 0xd6, 0x6c, 0x52, 0xee, 0xd6, 0xa8, 0x96, 0x29, 0x29, 0x35, - 0xa7, 0x64, 0x43, 0x66, 0xf2, 0xd7, 0x3d, 0xa6, 0x71, 0xd2, 0xa9, 0xab, 0x1a, 0xa7, 0x44, 0xd2, - 0x57, 0xd3, 0x01, 0xc2, 0x15, 0x91, 0x90, 0x84, 0x5a, 0xae, 0x88, 0xf4, 0x74, 0xd8, 0x72, 0x45, - 0x64, 0xe5, 0xb0, 0x36, 0xc5, 0x47, 0x97, 0xc2, 0x96, 0x8c, 0x8c, 0xa5, 0x19, 0xd7, 0xba, 0x85, - 0x70, 0xe2, 0x22, 0xdd, 0x3e, 0xeb, 0xb4, 0x7d, 0x0d, 0x17, 0x53, 0xb3, 0x93, 0xa2, 0xb7, 0x63, - 0x1f, 0x74, 0x0a, 0x27, 0xd2, 0x7b, 0x3a, 0xa9, 0x25, 0x16, 0x95, 0x2a, 0xb7, 0x48, 0x0e, 0xd3, - 0xd8, 0x8e, 0x9d, 0x90, 0xe0, 0x74, 0x95, 0x4a, 0xbe, 0x4a, 0x92, 0xd2, 0xd4, 0xb1, 0x5e, 0x4e, - 0xa2, 0xe3, 0xc7, 0xf7, 0x54, 0xa5, 0x5f, 0x42, 0x12, 0x8b, 0x56, 0x9c, 0x65, 0x4f, 0xed, 0xa7, - 0x6b, 0x69, 0x74, 0x96, 0xe9, 0x65, 0x42, 0xe4, 0x2c, 0x45, 0x17, 0x35, 0x36, 0x69, 0xa7, 0x64, - 0x51, 0x1b, 0x9c, 0x7e, 0x40, 0x56, 0xa9, 0x6e, 0x5b, 0xe6, 0x48, 0x4d, 0xed, 0xc5, 0xa5, 0x38, - 0x0d, 0x4d, 0xaf, 0x2d, 0xb9, 0xc0, 0x7a, 0xb3, 0x18, 0x65, 0x8e, 0xd6, 0xa1, 0xf4, 0x21, 0x21, - 0x95, 0x35, 0x3d, 0xba, 0x94, 0x2e, 0xa1, 0xce, 0xf0, 0x3c, 0x70, 0x34, 0xca, 0xb4, 0x08, 0xd7, - 0x72, 0x41, 0x2a, 0xe9, 0x94, 0xd2, 0x0c, 0x9d, 0x4c, 0x8d, 0x9a, 0x03, 0x27, 0xa4, 0x7b, 0x95, - 0x7b, 0x68, 0x66, 0x36, 0xd8, 0x04, 0xe9, 0x4c, 0xee, 0xca, 0xa9, 0x14, 0x33, 0xf3, 0xbf, 0xa6, - 0xf6, 0xf4, 0x87, 0xca, 0xae, 0x1c, 0x4b, 0xea, 0x8a, 0x6e, 0x45, 0x45, 0xb3, 0xb4, 0xbc, 0xaf, - 0x19, 0xbb, 0xfe, 0x6c, 0x52, 0x3e, 0x58, 0x45, 0xd1, 0x9c, 0x9a, 0x2c, 0x36, 0x81, 0x0b, 0x72, - 0x7b, 0x4b, 0xa1, 0x96, 0x91, 0x1d, 0x36, 0xb5, 0x87, 0xdf, 0x57, 0xb6, 0xb7, 0x48, 0x16, 0x57, - 0xa9, 0x38, 0xe8, 0x91, 0xe6, 0x35, 0x95, 0xf6, 0x16, 0x35, 0x20, 0x8f, 0xa7, 0x60, 0x95, 0xb2, - 0x4b, 0x56, 0x82, 0xd6, 0x44, 0x3d, 0xf4, 0x5c, 0x7c, 0x88, 0x84, 0xde, 0x85, 0x88, 0x16, 0xb9, - 0x57, 0xc7, 0xe4, 0x3e, 0x9c, 0x90, 0xba, 0x35, 0xb2, 0x0f, 0xa7, 0x27, 0x77, 0xcd, 0xb8, 0xe8, - 0x4c, 0xd7, 0xed, 0x43, 0x47, 0xc9, 0xbc, 0x2a, 0xaf, 0x39, 0xf1, 0x64, 0xb0, 0x72, 0x8b, 0x49, - 0x4a, 0xd4, 0xba, 0x4d, 0x24, 0x1c, 0x26, 0x9f, 0xab, 0x39, 0x34, 0x51, 0x31, 0x3d, 0x75, 0xa8, - 0xdc, 0x6e, 0x12, 0x93, 0x6e, 0x2a, 0x04, 0xd5, 0x04, 0x96, 0x92, 0x60, 0x42, 0x2e, 0x4d, 0x49, - 0x30, 0x31, 0xe3, 0xe5, 0x5d, 0xaa, 0x57, 0x31, 0xdd, 0x36, 0x56, 0xf5, 0x2a, 0x4a, 0x5a, 0xc7, - 0x88, 0x5a, 0x03, 0x7d, 0x4c, 0x95, 0x1a, 0xd9, 0x9a, 0x90, 0x79, 0x9d, 0x92, 0x9a, 0x7e, 0x1a, - 0xc2, 0xfc, 0x96, 0x48, 0xd7, 0x3a, 0x65, 0xb4, 0xf9, 0x9e, 0x50, 0x6a, 0x68, 0x68, 0xb1, 0x8c, - 0x97, 0x51, 0xb4, 0xef, 0xc2, 0x44, 0x98, 0xdd, 0x72, 0x6f, 0x49, 0x41, 0x8c, 0xa4, 0xbc, 0x8c, - 0x22, 0x7e, 0x20, 0x1e, 0x58, 0x68, 0x7b, 0x7a, 0x65, 0x2f, 0x35, 0x17, 0x84, 0x89, 0x31, 0x23, - 0x4a, 0x14, 0xb5, 0xc1, 0xf4, 0x9d, 0x77, 0x42, 0x4d, 0xec, 0x23, 0xe7, 0x35, 0x21, 0x8f, 0x9a, - 0x9c, 0xd7, 0xa4, 0xec, 0x64, 0xb4, 0x37, 0xf4, 0xae, 0xfd, 0x95, 0xd0, 0x18, 0x84, 0x44, 0x2f, - 0x67, 0xe6, 0x18, 0x2b, 0x5e, 0xc9, 0x4e, 0xcc, 0x15, 0x92, 0xae, 0x43, 0x21, 0x9a, 0x85, 0x08, - 0x25, 0xe5, 0x89, 0x53, 0xd2, 0x45, 0xc9, 0x3b, 0x5c, 0x6a, 0xfa, 0xa2, 0x9a, 0x50, 0xe3, 0xeb, - 0x74, 0x53, 0xb2, 0x85, 0xa9, 0xa4, 0xb3, 0xc5, 0xaa, 0x30, 0x21, 0x91, 0x7a, 0x11, 0x8e, 0x25, - 0x3c, 0x52, 0xc5, 0xaa, 0x84, 0x1c, 0x46, 0xb6, 0x88, 0xbf, 0x90, 0x9c, 0xd1, 0xf4, 0x1d, 0xfd, - 0x86, 0x9a, 0x11, 0x74, 0xb2, 0xe7, 0x63, 0x34, 0xfa, 0x25, 0x98, 0x4f, 0x89, 0x0d, 0x88, 0x6e, - 0x44, 0x14, 0xc2, 0xc9, 0xb1, 0x03, 0x8b, 0x59, 0x89, 0xff, 0xd0, 0x26, 0xb5, 0x62, 0xd0, 0x3c, - 0x2d, 0x63, 0x2f, 0x83, 0xfb, 0x76, 0x70, 0xc4, 0x52, 0x59, 0x2a, 0x7b, 0x66, 0xa2, 0x8b, 0x26, - 0xaa, 0xd3, 0xfb, 0x86, 0x56, 0x9a, 0xf0, 0x38, 0x98, 0x40, 0xb0, 0x98, 0x4c, 0x90, 0x26, 0x0e, - 0xaf, 0x89, 0x27, 0xa6, 0x68, 0x37, 0xd5, 0xe1, 0x27, 0x39, 0x97, 0xa6, 0x76, 0xb3, 0x26, 0x04, - 0xa4, 0x64, 0x8a, 0xe9, 0x1e, 0xb1, 0xa9, 0x14, 0x1f, 0x11, 0x8a, 0x31, 0x27, 0x57, 0x94, 0x02, - 0x9e, 0xbd, 0x7b, 0x98, 0xe2, 0xbc, 0xd5, 0xb1, 0x96, 0x94, 0xfe, 0xa5, 0xb9, 0xd3, 0xa6, 0xf6, - 0x6f, 0x45, 0x7c, 0x4f, 0xc9, 0xfd, 0xeb, 0xf7, 0xc4, 0x95, 0xcf, 0x74, 0x11, 0x3f, 0x6b, 0x6d, - 0xa0, 0x4a, 0x79, 0x31, 0xa5, 0x1c, 0x6d, 0x51, 0xb3, 0xa4, 0x68, 0xa9, 0x72, 0xf1, 0x4c, 0x76, - 0xe4, 0x4e, 0xa5, 0xc7, 0xd6, 0xb1, 0xe6, 0x08, 0x7b, 0x96, 0x75, 0x1c, 0xf1, 0xa0, 0xe5, 0xeb, - 0x58, 0x2b, 0x3d, 0xdb, 0x3a, 0x8e, 0x10, 0xd4, 0xd7, 0x71, 0xb4, 0x9b, 0xd1, 0x8b, 0x7c, 0xea, - 0xac, 0x46, 0xbb, 0x29, 0xd7, 0x71, 0x32, 0xc5, 0x74, 0x87, 0xe5, 0x54, 0x8a, 0x72, 0x1d, 0xeb, - 0x14, 0x53, 0xc0, 0xfb, 0x5c, 0xc7, 0xd1, 0x46, 0xf4, 0x75, 0x7c, 0xa6, 0xfe, 0xc9, 0x75, 0x9c, - 0xdc, 0xbf, 0x33, 0xaf, 0xe3, 0x88, 0x87, 0xbf, 0x36, 0xd0, 0xa4, 0x75, 0x1c, 0x85, 0x67, 0xeb, - 0x38, 0x5a, 0x1a, 0x51, 0xa0, 0x64, 0xac, 0xe3, 0x28, 0xe6, 0x17, 0x94, 0x5e, 0xc4, 0x3b, 0xb9, - 0x9f, 0x95, 0x9c, 0xea, 0xd8, 0x8c, 0xf6, 0xa9, 0xf6, 0x2e, 0x52, 0xde, 0xdf, 0x6a, 0x5e, 0x4c, - 0x23, 0x4a, 0xd7, 0xf3, 0x9e, 0x60, 0x62, 0xb4, 0xbb, 0xba, 0x6a, 0x2a, 0xd9, 0x39, 0x3b, 0xa3, - 0xc3, 0x7b, 0x64, 0xdd, 0xb4, 0x32, 0xe8, 0x66, 0xf9, 0x96, 0x67, 0xd0, 0x95, 0xf7, 0x98, 0x28, - 0xdd, 0x54, 0x94, 0xec, 0xf5, 0xfd, 0xa5, 0x78, 0xbf, 0x88, 0xe2, 0x2d, 0x45, 0x6e, 0x46, 0x67, - 0xee, 0xa9, 0xbc, 0x21, 0x45, 0x7b, 0x7a, 0xd6, 0x75, 0xbe, 0x29, 0xa4, 0x87, 0x58, 0x50, 0x8a, - 0xc8, 0xa0, 0xd5, 0xb5, 0x9e, 0x5a, 0x83, 0x76, 0xa8, 0xaa, 0x36, 0x5e, 0xae, 0xa8, 0x79, 0xd3, - 0xa2, 0x5f, 0xf4, 0xa4, 0x1a, 0x73, 0xaf, 0x57, 0xa9, 0xa6, 0xf9, 0xde, 0x4b, 0xaa, 0x71, 0xec, - 0xcf, 0xa9, 0xea, 0x8b, 0xfb, 0x03, 0x39, 0x4f, 0xdc, 0xf4, 0x7b, 0xca, 0x8c, 0x66, 0x3a, 0x45, - 0x60, 0xa9, 0xc5, 0xda, 0x27, 0xfc, 0x81, 0x4e, 0x14, 0xa6, 0x32, 0x3f, 0x09, 0x1f, 0x7d, 0x0e, - 0x05, 0xbe, 0xbd, 0x85, 0x04, 0x92, 0x00, 0x53, 0xa7, 0xae, 0x22, 0x34, 0x6e, 0x7d, 0xf4, 0xa0, - 0x1f, 0x4d, 0x5b, 0x3f, 0x9c, 0x48, 0x57, 0x4b, 0x91, 0xe3, 0x70, 0xc7, 0xeb, 0xfa, 0x01, 0x6e, - 0xc5, 0xd5, 0x49, 0x7a, 0x67, 0x84, 0x01, 0x87, 0x0e, 0xbe, 0xb7, 0x84, 0xd6, 0xe9, 0xde, 0xa6, - 0x17, 0x67, 0xe9, 0xdb, 0x92, 0xc9, 0xd0, 0xad, 0x67, 0x4d, 0x3a, 0x9e, 0xe8, 0x7d, 0x4a, 0x6b, - 0x3b, 0xbd, 0x53, 0x92, 0x45, 0x7d, 0x8e, 0x2e, 0x8d, 0x45, 0xec, 0x42, 0xcc, 0x74, 0x7f, 0xbd, - 0x38, 0x13, 0x75, 0x85, 0x41, 0xdf, 0x83, 0x31, 0x81, 0xdc, 0x9b, 0x21, 0x51, 0x6c, 0xca, 0x90, - 0x65, 0x98, 0xd4, 0xfc, 0x7c, 0xe4, 0xed, 0x26, 0xc9, 0xfb, 0x27, 0x63, 0x9e, 0x27, 0x35, 0x7f, - 0x1e, 0x49, 0x25, 0xc9, 0xcb, 0x27, 0x95, 0xca, 0xa7, 0x30, 0xce, 0x59, 0x9a, 0xc9, 0x8d, 0x74, - 0x65, 0xdb, 0x9c, 0x62, 0x1f, 0xdd, 0x6d, 0xd9, 0x41, 0xd5, 0x75, 0x9e, 0xd8, 0x87, 0x3d, 0x19, - 0x13, 0x47, 0xd9, 0x5b, 0x42, 0x7b, 0x34, 0x5f, 0x9b, 0xc8, 0xa2, 0x87, 0x83, 0xe7, 0xae, 0xf7, - 0xd4, 0x76, 0x0e, 0x7b, 0x90, 0xbc, 0xaa, 0x93, 0x8c, 0xe2, 0x31, 0xba, 0xf5, 0x74, 0xba, 0x3d, - 0xf1, 0x33, 0x94, 0x6d, 0x8b, 0xd4, 0xb4, 0xe7, 0xac, 0x3d, 0x4e, 0x7f, 0x78, 0xbc, 0x18, 0x5a, - 0x16, 0x9b, 0xb8, 0xe9, 0x7a, 0xad, 0xde, 0xc4, 0x4a, 0xba, 0x1d, 0x6f, 0x04, 0x6d, 0x6f, 0x89, - 0x50, 0xad, 0xa7, 0x52, 0xed, 0x85, 0x9d, 0x71, 0x5a, 0x5d, 0xa2, 0x63, 0x3f, 0x63, 0x6f, 0xb3, - 0x77, 0x2d, 0x72, 0xd2, 0xd4, 0x3c, 0xfc, 0x04, 0x7b, 0xd4, 0x3c, 0xbc, 0x97, 0x61, 0xb4, 0x0e, - 0xbe, 0xb7, 0x44, 0xa8, 0xd4, 0x63, 0x54, 0xd2, 0xa0, 0xb3, 0x54, 0xf2, 0x74, 0x68, 0x7d, 0xf6, - 0x26, 0x8d, 0xcc, 0x07, 0xf4, 0xc9, 0x63, 0x77, 0xbd, 0x07, 0x47, 0x84, 0xc3, 0x82, 0x00, 0xdc, - 0xbb, 0x4f, 0x30, 0xeb, 0x0a, 0x66, 0x1c, 0x22, 0xb5, 0xcd, 0xef, 0x89, 0xb7, 0x8d, 0x9e, 0xcd, - 0xa6, 0x51, 0x78, 0x40, 0xb7, 0x37, 0x6e, 0x13, 0xad, 0x68, 0x05, 0xb5, 0x4c, 0xa9, 0xc5, 0x49, - 0xd5, 0x3c, 0xda, 0x47, 0x65, 0x76, 0xa3, 0x53, 0x73, 0xaa, 0x2a, 0xd6, 0x10, 0x89, 0xc9, 0x56, - 0xa3, 0x24, 0x98, 0x56, 0x73, 0xc3, 0x6d, 0x3e, 0x55, 0xb5, 0x9a, 0x4a, 0x92, 0xce, 0xa2, 0x9e, - 0x42, 0x93, 0x6f, 0xe2, 0x34, 0x8f, 0xa6, 0x6a, 0xaa, 0xa5, 0xa6, 0xe9, 0x54, 0xb5, 0x9a, 0x7a, - 0x42, 0xd1, 0x07, 0x42, 0x5d, 0x48, 0x1b, 0xd4, 0x29, 0xa7, 0xb2, 0x46, 0x6a, 0x0a, 0x29, 0x92, - 0xae, 0x29, 0x54, 0x3b, 0x9a, 0xbe, 0x5d, 0xa0, 0x78, 0x46, 0x51, 0x79, 0xff, 0x48, 0x4d, 0x36, - 0x9a, 0x61, 0x71, 0x35, 0x93, 0x90, 0x3a, 0x59, 0xde, 0xd8, 0xd2, 0xd3, 0x2a, 0x17, 0x75, 0xf3, - 0xa1, 0x7b, 0x39, 0xb4, 0x05, 0x17, 0x56, 0x71, 0xc0, 0x37, 0x30, 0x13, 0xfb, 0x81, 0x67, 0x37, - 0x83, 0xcc, 0x87, 0x3e, 0x71, 0xdd, 0x48, 0xc0, 0xd9, 0x7b, 0x97, 0xd0, 0xab, 0x27, 0xd3, 0xcb, - 0xc4, 0xcb, 0x30, 0xce, 0xe5, 0xaf, 0x07, 0x67, 0xe9, 0x62, 0xfa, 0x12, 0x1f, 0x61, 0x36, 0x33, - 0xe9, 0xa8, 0x85, 0x30, 0xca, 0x3e, 0xbf, 0x40, 0xdd, 0x81, 0x73, 0x0c, 0x29, 0xf5, 0x8c, 0x9c, - 0x50, 0x71, 0xd0, 0x7d, 0x61, 0xc5, 0x49, 0x50, 0xb4, 0xaa, 0xd4, 0x7e, 0xdd, 0x87, 0x31, 0x76, - 0x5b, 0xea, 0x1f, 0xe5, 0x63, 0x61, 0xe6, 0x99, 0xd5, 0xb1, 0x34, 0xe4, 0xcf, 0x61, 0x52, 0xb5, - 0x97, 0x39, 0x3b, 0x23, 0x3f, 0xa5, 0xcf, 0xb1, 0xe2, 0xd5, 0x23, 0x1d, 0x7f, 0x2e, 0x92, 0x79, - 0x81, 0xb3, 0x94, 0x6d, 0x90, 0x32, 0x07, 0x79, 0x5a, 0xf7, 0xcf, 0xc7, 0xb0, 0xd1, 0xc7, 0xc2, - 0x55, 0x4a, 0x22, 0xc7, 0x81, 0x32, 0x78, 0x36, 0xc5, 0xd8, 0xfc, 0x2a, 0xc8, 0x72, 0x83, 0xed, - 0xd9, 0xed, 0x7e, 0x9e, 0x8d, 0x7b, 0xb3, 0x2e, 0x8d, 0xca, 0x36, 0x15, 0xbc, 0x62, 0x39, 0x41, - 0xd2, 0x09, 0x5d, 0x49, 0x4f, 0x23, 0x42, 0x27, 0xe3, 0x11, 0xbd, 0xd8, 0xc5, 0xf3, 0xc9, 0xa7, - 0x0d, 0x2f, 0x23, 0x2d, 0x49, 0x78, 0x93, 0x8d, 0x93, 0xcb, 0x40, 0xcb, 0xba, 0x18, 0x73, 0xe7, - 0xcd, 0x37, 0x42, 0x6e, 0x5d, 0x98, 0x1d, 0xf6, 0x3f, 0xd8, 0x0c, 0x21, 0x28, 0xe1, 0xa1, 0xba, - 0xe7, 0x5c, 0xa4, 0x91, 0xfb, 0x25, 0x2a, 0xff, 0x25, 0xa7, 0x83, 0x4e, 0x25, 0x76, 0x4b, 0xb1, - 0x75, 0xc8, 0x4e, 0x24, 0xfd, 0x94, 0xfa, 0xa0, 0x25, 0x67, 0x4d, 0xb9, 0xd9, 0x83, 0x8a, 0xe0, - 0xc4, 0xdb, 0x3d, 0xe1, 0xe4, 0xb3, 0xe7, 0x25, 0x76, 0xc2, 0x26, 0xb7, 0xd7, 0x23, 0x0b, 0x4c, - 0xc2, 0x4b, 0x74, 0x4a, 0xae, 0x65, 0x41, 0x50, 0xb7, 0xe9, 0xcc, 0x1c, 0x43, 0x1a, 0xfb, 0xbf, - 0x80, 0x52, 0x68, 0xd0, 0x71, 0xb6, 0x49, 0x48, 0x97, 0xe8, 0x51, 0x3c, 0x03, 0x35, 0xca, 0x0a, - 0x54, 0x5f, 0xbc, 0x96, 0xc6, 0x61, 0x5f, 0xb1, 0x14, 0xe2, 0xa6, 0x68, 0x91, 0xfc, 0x41, 0x69, - 0x99, 0x88, 0x32, 0x54, 0xab, 0xdc, 0x29, 0xef, 0x8d, 0x10, 0x8a, 0xcf, 0xf6, 0xd9, 0x09, 0x49, - 0x7b, 0x8b, 0x08, 0x21, 0x23, 0x63, 0x7a, 0xcf, 0x62, 0x4e, 0x16, 0x9d, 0x8a, 0xb3, 0x4e, 0xa8, - 0x15, 0x3a, 0xa2, 0xc5, 0xd3, 0x64, 0x4b, 0x59, 0x2e, 0x35, 0x65, 0xb7, 0x9c, 0xdd, 0x8c, 0x1c, - 0xdb, 0x55, 0xf2, 0x99, 0xb2, 0x26, 0xb4, 0x1c, 0xbd, 0x55, 0x73, 0x23, 0xd4, 0x14, 0x24, 0x24, - 0xef, 0x2d, 0x82, 0xa8, 0x34, 0x37, 0x50, 0x5d, 0x44, 0x59, 0x4d, 0x0a, 0x89, 0x22, 0x9d, 0x6e, - 0x92, 0x2a, 0x33, 0x6e, 0x17, 0x75, 0x11, 0x57, 0xf5, 0x4d, 0x12, 0x6d, 0xc0, 0x7c, 0x4a, 0x20, - 0x19, 0xf9, 0x68, 0x9a, 0x1d, 0x68, 0xa6, 0x98, 0xdd, 0x30, 0xfa, 0x01, 0xcc, 0x25, 0x46, 0x9a, - 0x91, 0x8a, 0xdf, 0xac, 0x38, 0x34, 0xbd, 0x88, 0x3f, 0x85, 0x85, 0xb4, 0x84, 0xba, 0xa1, 0x13, - 0x50, 0x76, 0x96, 0x63, 0xb9, 0xa7, 0xf6, 0xcc, 0xcc, 0xbb, 0x05, 0xb3, 0x49, 0x49, 0x6a, 0xe5, - 0xc7, 0x91, 0x91, 0xc1, 0x36, 0xd1, 0xd3, 0xa8, 0x06, 0x73, 0x89, 0x89, 0x62, 0x25, 0x67, 0xb2, - 0xd2, 0xc8, 0x26, 0x52, 0xfc, 0x12, 0xe6, 0x53, 0xb2, 0xa2, 0x86, 0x2f, 0xe0, 0x99, 0x59, 0x53, - 0x33, 0xec, 0x87, 0x8a, 0xe9, 0x09, 0x37, 0xa5, 0xd9, 0x58, 0xcf, 0x9c, 0x9c, 0xc5, 0xc4, 0x2c, - 0xc4, 0x68, 0x87, 0x2e, 0xc2, 0xa4, 0x0c, 0x9c, 0xea, 0x22, 0xcc, 0xc8, 0xd0, 0x99, 0xe2, 0x21, - 0x36, 0x9f, 0x92, 0x74, 0x33, 0x83, 0x6a, 0x1f, 0xbd, 0xdd, 0x12, 0xfb, 0xbf, 0x9e, 0x1a, 0x31, - 0x62, 0x8a, 0x9c, 0x98, 0x37, 0x31, 0xb1, 0x9f, 0x4a, 0x68, 0x85, 0x76, 0x3b, 0x43, 0x0c, 0x42, - 0x6a, 0x6c, 0x05, 0x02, 0x49, 0x75, 0xe7, 0x93, 0x2a, 0x6e, 0xd6, 0x8e, 0x1a, 0x43, 0xa6, 0x82, - 0xe7, 0x47, 0x30, 0x51, 0x57, 0x1b, 0x4f, 0x68, 0x24, 0x75, 0x51, 0x48, 0xdf, 0x9a, 0xde, 0x7d, - 0xcf, 0x50, 0xf6, 0xc8, 0xc3, 0xa1, 0xaf, 0x51, 0xa4, 0x5a, 0xac, 0x68, 0xd9, 0x4b, 0xe4, 0x4e, - 0x9d, 0x94, 0x18, 0x48, 0x5a, 0xac, 0x24, 0x27, 0x3c, 0x69, 0xb0, 0x78, 0xeb, 0xd1, 0xbc, 0x4f, - 0xc8, 0xe8, 0x9d, 0xcf, 0x4c, 0x5a, 0x9a, 0x67, 0x26, 0x8e, 0x62, 0xe6, 0x35, 0x61, 0xbe, 0x16, - 0xd5, 0xbc, 0x26, 0x96, 0x05, 0x46, 0x35, 0xaf, 0x49, 0x48, 0xf1, 0xb2, 0x42, 0x69, 0x85, 0x81, - 0xea, 0x33, 0x14, 0x06, 0x92, 0x4c, 0x42, 0x3c, 0xfc, 0xc7, 0x6a, 0x84, 0x0e, 0x16, 0xde, 0x3e, - 0x43, 0xe3, 0x19, 0x8d, 0xcc, 0x11, 0x89, 0x87, 0xff, 0x08, 0x0a, 0xd1, 0xd0, 0x5e, 0x52, 0x1d, - 0x95, 0x12, 0xf3, 0x2b, 0x63, 0x89, 0x41, 0x18, 0xc0, 0x4b, 0x2a, 0x7d, 0x62, 0x31, 0xbd, 0x8a, - 0x17, 0x13, 0x6a, 0xa4, 0xb8, 0x36, 0xa1, 0x86, 0xfb, 0x92, 0x16, 0x62, 0x09, 0x31, 0xc0, 0x8a, - 0x97, 0x12, 0xeb, 0x38, 0xa1, 0x80, 0xa5, 0xe2, 0x4b, 0x4e, 0xe4, 0x17, 0xba, 0x35, 0x65, 0xc0, - 0x88, 0x66, 0x6e, 0xf7, 0x03, 0xca, 0x5b, 0xc5, 0x32, 0xbc, 0x7e, 0x1c, 0x0a, 0xbd, 0x9d, 0xe0, - 0x7e, 0xa0, 0x41, 0x84, 0xc6, 0x53, 0xe1, 0x23, 0x7a, 0x52, 0xb2, 0x42, 0xb4, 0x2f, 0xc2, 0x9d, - 0xa7, 0xb4, 0xd4, 0x8b, 0x40, 0xea, 0x0c, 0xee, 0x8b, 0x00, 0xe7, 0x6f, 0x9a, 0xf0, 0x01, 0x2c, - 0x46, 0xbc, 0x1b, 0x74, 0xc2, 0xb7, 0x93, 0x5d, 0x20, 0x12, 0xd9, 0x93, 0x2e, 0x0f, 0x5f, 0x8d, - 0xbb, 0x42, 0x44, 0xe6, 0xfd, 0xac, 0x7b, 0xd5, 0x26, 0x4c, 0xd1, 0xed, 0x41, 0xa4, 0x9f, 0x0c, - 0x03, 0xbb, 0xe8, 0xc5, 0xd1, 0x08, 0x43, 0xd1, 0x5a, 0xe9, 0x15, 0x3e, 0xc1, 0x5d, 0x64, 0x59, - 0x32, 0xcb, 0xa2, 0xee, 0x37, 0x4b, 0x0b, 0x93, 0x4e, 0x1f, 0x9e, 0x23, 0x13, 0x7d, 0x0a, 0xd3, - 0xa1, 0xe7, 0x2c, 0x23, 0x91, 0x00, 0x96, 0xa1, 0x84, 0x9a, 0x0e, 0xdd, 0x67, 0xcf, 0x8e, 0xbe, - 0x26, 0x8e, 0x90, 0x10, 0xfd, 0x72, 0xcc, 0x2b, 0x44, 0x1b, 0x43, 0x3f, 0x27, 0x89, 0xc2, 0xdb, - 0xb3, 0xce, 0x4e, 0x93, 0x7e, 0x6e, 0xc9, 0x71, 0xec, 0xd4, 0xcf, 0x2d, 0x33, 0xd6, 0x9e, 0x14, - 0x5b, 0x53, 0xe8, 0x6c, 0xc2, 0x75, 0x1a, 0xe7, 0xa4, 0x86, 0x9d, 0x96, 0xed, 0x1c, 0x26, 0x43, - 0xa5, 0xf7, 0x3d, 0x1a, 0x1d, 0xa5, 0x0d, 0xd7, 0x7a, 0x06, 0xf2, 0x43, 0x77, 0x35, 0x8b, 0x90, - 0xde, 0x21, 0xff, 0xb2, 0x3c, 0xb1, 0x92, 0xe2, 0xe1, 0xc9, 0xf3, 0x31, 0x23, 0x34, 0x9f, 0x3c, - 0x1f, 0x33, 0x03, 0xea, 0x7d, 0x49, 0x73, 0x08, 0xf0, 0xb3, 0x85, 0xc6, 0x2e, 0xc2, 0x0e, 0x8b, - 0xf0, 0x9b, 0xf9, 0xa4, 0x72, 0x4d, 0x7f, 0x48, 0x8c, 0x21, 0xd2, 0xbb, 0xc8, 0x15, 0x7e, 0x83, - 0x4a, 0x23, 0xde, 0x9b, 0x48, 0x86, 0x25, 0xf2, 0x15, 0xb6, 0x00, 0xcf, 0xdc, 0xf3, 0x94, 0xf2, - 0xca, 0xf2, 0x4f, 0xff, 0xe2, 0x4a, 0xee, 0xa7, 0x3f, 0xbb, 0x92, 0xfb, 0xb7, 0x3f, 0xbb, 0x92, - 0xfb, 0x0f, 0x3f, 0xbb, 0x92, 0xfb, 0xfe, 0x52, 0x7f, 0x71, 0x66, 0x9b, 0x6d, 0x1b, 0x3b, 0xc1, - 0x5d, 0x46, 0xee, 0x1c, 0xfd, 0xef, 0xc1, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x98, 0xc2, 0x23, - 0x55, 0xdf, 0xdb, 0x00, 0x00, + 0x44, 0x37, 0x3e, 0x84, 0x49, 0x26, 0x81, 0xb3, 0x62, 0xda, 0x9d, 0x89, 0xe5, 0x59, 0xfe, 0x39, + 0xa8, 0x55, 0xeb, 0x03, 0xa6, 0x06, 0x4a, 0x50, 0x4d, 0xcc, 0x6e, 0x95, 0x14, 0x35, 0xaf, 0xa1, + 0xaa, 0x55, 0x04, 0x55, 0xfd, 0x8d, 0x3e, 0x87, 0xe9, 0xaa, 0x7b, 0xd4, 0x21, 0x3c, 0xe1, 0xc8, + 0x83, 0xfc, 0x22, 0xc2, 0xdb, 0xd5, 0x2a, 0xd7, 0x07, 0xcc, 0x08, 0x38, 0xda, 0x82, 0xd9, 0x07, + 0xed, 0xae, 0x7f, 0x58, 0x76, 0x5a, 0xd5, 0xb6, 0xeb, 0x0b, 0x2a, 0x43, 0xfc, 0xc6, 0xcc, 0x05, + 0xc7, 0x38, 0xc4, 0xfa, 0x80, 0x99, 0x84, 0x88, 0xae, 0xc3, 0xf0, 0xea, 0x73, 0xec, 0x04, 0xf2, + 0x55, 0x9a, 0x9b, 0xb5, 0x6c, 0x3b, 0x78, 0xfb, 0xe9, 0xfa, 0x80, 0xc9, 0x6a, 0x2b, 0xe3, 0x30, + 0x2a, 0x84, 0xe6, 0x3b, 0xe4, 0xec, 0x95, 0xec, 0xac, 0x07, 0x56, 0xd0, 0xf5, 0x51, 0x11, 0xc6, + 0x76, 0x3b, 0x44, 0x96, 0x13, 0x37, 0x62, 0x53, 0xfe, 0x36, 0xbe, 0xad, 0x73, 0x1a, 0x2d, 0xa9, + 0x5a, 0x52, 0x06, 0x1c, 0x16, 0x18, 0xeb, 0x3a, 0x73, 0xb3, 0xa1, 0xb5, 0x76, 0xf3, 0x91, 0x76, + 0x0b, 0x51, 0x5e, 0x1b, 0xf3, 0x89, 0xcc, 0x33, 0xbe, 0x84, 0xcb, 0xbb, 0x1d, 0x1f, 0x7b, 0x41, + 0xb9, 0xd3, 0x69, 0xdb, 0x4d, 0xf6, 0x2a, 0x42, 0x85, 0x6b, 0xb1, 0x58, 0xde, 0x87, 0x11, 0x56, + 0xc0, 0x97, 0x89, 0x58, 0x83, 0xe5, 0x4e, 0x87, 0x8b, 0xf4, 0xf7, 0x99, 0x14, 0xc0, 0x84, 0x74, + 0x93, 0x43, 0x1b, 0xbf, 0x9d, 0x83, 0xcb, 0xec, 0x0b, 0x48, 0x25, 0xfd, 0x2d, 0x18, 0xa7, 0x56, + 0x25, 0x1d, 0xab, 0xa9, 0xdd, 0xfa, 0x1c, 0x51, 0x68, 0x86, 0xf5, 0x8a, 0xbd, 0x4e, 0x3e, 0xdd, + 0x5e, 0x47, 0x7c, 0x60, 0x83, 0x89, 0x1f, 0xd8, 0x17, 0x60, 0xf0, 0x1e, 0xb5, 0xdb, 0xb1, 0x4e, + 0xf9, 0xaf, 0xd3, 0x2b, 0xe3, 0x3f, 0xe5, 0x61, 0x61, 0x0d, 0x3b, 0xd8, 0xb3, 0xe8, 0x38, 0x35, + 0x05, 0x87, 0x6a, 0x17, 0x90, 0xcb, 0xb4, 0x0b, 0x90, 0xb7, 0xf7, 0x7c, 0xca, 0xed, 0xfd, 0x02, + 0x0c, 0xee, 0x9a, 0x1b, 0x7c, 0x58, 0x54, 0x2e, 0xed, 0x7a, 0xb6, 0x49, 0xca, 0xd0, 0x46, 0x68, + 0x53, 0x30, 0xd4, 0x53, 0x77, 0x34, 0xcb, 0xdf, 0x58, 0x47, 0xb9, 0x4d, 0x81, 0x6e, 0x49, 0xb0, + 0xa5, 0xa8, 0x08, 0xc8, 0x76, 0x73, 0x8b, 0x7f, 0x53, 0x29, 0x03, 0xe4, 0xb7, 0xfd, 0x55, 0x27, + 0xf0, 0x5e, 0xb1, 0x25, 0xc0, 0x2e, 0xfd, 0xe2, 0xaa, 0x5f, 0xfc, 0x02, 0x26, 0x14, 0x10, 0x54, + 0x80, 0xc1, 0x67, 0xdc, 0x9e, 0x62, 0xdc, 0x24, 0x7f, 0xa2, 0x6f, 0xc3, 0xf0, 0x73, 0xab, 0xdd, + 0xc5, 0x7c, 0x1b, 0x39, 0x1f, 0xaa, 0x24, 0xea, 0x01, 0xd9, 0xd8, 0x99, 0x4e, 0xc2, 0x64, 0x40, + 0x1f, 0xe5, 0x3f, 0xc8, 0x19, 0x1f, 0xc3, 0x62, 0xbc, 0x37, 0xfc, 0x06, 0xdb, 0x4b, 0xa9, 0x63, + 0xac, 0xc0, 0xdc, 0x1a, 0x0e, 0xe8, 0xc2, 0xa5, 0x1f, 0x91, 0x62, 0xee, 0x11, 0xf9, 0xce, 0x32, + 0xde, 0x2e, 0x8c, 0x3a, 0xcc, 0x47, 0xa8, 0xf0, 0xf6, 0x3f, 0x82, 0x51, 0x5e, 0x24, 0x77, 0x54, + 0x6e, 0x00, 0x87, 0xf7, 0x79, 0xc5, 0xde, 0x32, 0x5b, 0xb7, 0x9c, 0xb2, 0x29, 0x10, 0x8c, 0x43, + 0x38, 0x4f, 0x0e, 0xc9, 0x90, 0xaa, 0x5c, 0x8e, 0x17, 0x61, 0xbc, 0x43, 0x8e, 0x79, 0xdf, 0xfe, + 0x09, 0x5b, 0x46, 0xc3, 0xe6, 0x18, 0x29, 0xa8, 0xdb, 0x3f, 0xc1, 0xe8, 0x12, 0x00, 0xad, 0xa4, + 0xc3, 0xe4, 0xbb, 0x00, 0x05, 0x67, 0x5a, 0x2c, 0x04, 0xd4, 0xae, 0x86, 0xad, 0x1b, 0x93, 0xfe, + 0x6d, 0x78, 0xb0, 0x10, 0x6b, 0x89, 0x0f, 0xe0, 0x0e, 0x8c, 0xf1, 0x8e, 0xf9, 0x11, 0xfd, 0xb2, + 0x3a, 0x02, 0x53, 0x02, 0xa1, 0x1b, 0x30, 0xe3, 0xe0, 0x97, 0x41, 0x23, 0xd6, 0x87, 0x29, 0x52, + 0x5c, 0x13, 0xfd, 0x30, 0x7e, 0x89, 0xea, 0x14, 0xeb, 0x8e, 0xfb, 0xe2, 0x69, 0xdb, 0x7a, 0x86, + 0x63, 0x0d, 0x7f, 0x0a, 0x63, 0xf5, 0xde, 0x0d, 0xb3, 0xcf, 0x47, 0x34, 0x6e, 0x4a, 0x14, 0xa3, + 0x0d, 0x45, 0x32, 0x24, 0x72, 0xf1, 0xdc, 0x68, 0xd5, 0xbe, 0x69, 0x06, 0x3e, 0x87, 0x8b, 0x89, + 0xad, 0x7d, 0xd3, 0x4c, 0xfc, 0x8b, 0x3c, 0x2c, 0xb0, 0xc3, 0x24, 0xbe, 0x82, 0xfb, 0xdf, 0x6a, + 0x7e, 0x21, 0x2f, 0x6f, 0x77, 0x13, 0x5e, 0xde, 0x28, 0x8a, 0xfa, 0xf2, 0xa6, 0xbd, 0xb7, 0x7d, + 0x90, 0xfc, 0xde, 0x46, 0x2f, 0xa4, 0xfa, 0x7b, 0x5b, 0xf4, 0x95, 0x6d, 0x35, 0xfd, 0x95, 0x8d, + 0xbe, 0x39, 0x24, 0xbc, 0xb2, 0x25, 0xbc, 0xad, 0x31, 0xd1, 0xd5, 0xd8, 0x83, 0xc5, 0x38, 0x8b, + 0xcf, 0xe0, 0xf3, 0xfe, 0xe3, 0x1c, 0x5c, 0xe2, 0x82, 0x40, 0xe4, 0x23, 0x38, 0xfd, 0x0c, 0xbe, + 0x07, 0x93, 0x1c, 0x77, 0x27, 0x5c, 0x2c, 0x95, 0x73, 0x27, 0xc7, 0xa5, 0x29, 0xb1, 0x61, 0xb1, + 0x5d, 0x4f, 0x03, 0x43, 0xef, 0x29, 0x3a, 0x4e, 0xa6, 0x37, 0x27, 0xd2, 0xfd, 0x38, 0x53, 0x86, + 0xa6, 0x6a, 0x3a, 0x8d, 0xaf, 0xe1, 0x72, 0x5a, 0xc7, 0xcf, 0x80, 0x2f, 0xff, 0x3c, 0x07, 0x17, + 0x39, 0x79, 0xed, 0x73, 0x7a, 0xad, 0x9d, 0xf9, 0x14, 0x86, 0x78, 0x0f, 0x61, 0x82, 0x34, 0x28, + 0xfa, 0x3d, 0xc8, 0x8f, 0x1f, 0x2e, 0x5d, 0x87, 0x35, 0x2b, 0x56, 0x60, 0x71, 0xd3, 0x02, 0xeb, + 0xa8, 0xdd, 0x10, 0xfd, 0x57, 0x91, 0x8d, 0xef, 0xc3, 0x52, 0xf2, 0x10, 0xce, 0x80, 0x3f, 0x0f, + 0xa1, 0x98, 0xb0, 0x71, 0xbe, 0xde, 0xb9, 0xf5, 0x15, 0x5c, 0x4c, 0xa4, 0x75, 0x06, 0xdd, 0x5c, + 0x27, 0xa7, 0x72, 0x70, 0x06, 0x53, 0x68, 0x3c, 0x81, 0x0b, 0x09, 0x94, 0xce, 0xa0, 0x8b, 0x6b, + 0xb0, 0x20, 0xa5, 0xd1, 0x37, 0xea, 0xe1, 0x63, 0xb8, 0xc4, 0x08, 0x9d, 0xcd, 0xac, 0x3c, 0x82, + 0x8b, 0x9c, 0xdc, 0x19, 0x70, 0x6f, 0x1d, 0x96, 0xc2, 0x4b, 0x67, 0x82, 0x2c, 0xd1, 0xf7, 0x26, + 0x63, 0x6c, 0xc2, 0x95, 0x90, 0x52, 0xca, 0xc1, 0xda, 0x3f, 0x35, 0x26, 0x32, 0x85, 0xb3, 0x74, + 0x26, 0x33, 0xfa, 0x04, 0xce, 0x6b, 0x44, 0xcf, 0x4c, 0x9c, 0xd8, 0x80, 0x59, 0x46, 0x58, 0x17, + 0x2f, 0x97, 0x55, 0xf1, 0x72, 0x62, 0xf9, 0x5c, 0x48, 0x92, 0x16, 0xef, 0xdd, 0x4f, 0x90, 0x38, + 0x1f, 0x53, 0x89, 0x53, 0x80, 0x84, 0x3d, 0x7c, 0x0f, 0x46, 0x58, 0x09, 0xef, 0x5f, 0x02, 0x31, + 0x26, 0x50, 0x33, 0x34, 0x0e, 0x6c, 0xfc, 0x10, 0x2e, 0xb1, 0xdb, 0x5a, 0xa8, 0xd8, 0xd7, 0x6f, + 0x54, 0x9f, 0x46, 0x2e, 0x6b, 0x17, 0x38, 0xdd, 0x28, 0x7c, 0xca, 0x9d, 0x6d, 0x5f, 0xac, 0xed, + 0x34, 0xfa, 0x7d, 0x39, 0x4d, 0x88, 0x4b, 0x58, 0x3e, 0xf1, 0x12, 0x76, 0x0d, 0xae, 0xca, 0x4b, + 0x58, 0xb4, 0x19, 0xf9, 0x58, 0xf5, 0x7d, 0xb8, 0xc8, 0x06, 0x2a, 0xcc, 0xa5, 0xf4, 0x6e, 0x7c, + 0x1c, 0x19, 0xe6, 0x02, 0x1f, 0xa6, 0x0e, 0x9d, 0x32, 0xc8, 0xbf, 0x9e, 0x13, 0x9f, 0x5c, 0x32, + 0xf1, 0x5f, 0xf4, 0xad, 0x74, 0x0b, 0x4a, 0x92, 0x21, 0x7a, 0x8f, 0x5e, 0xef, 0x4a, 0xfa, 0x18, + 0xe6, 0x55, 0x32, 0x76, 0x13, 0xef, 0xdd, 0xa3, 0x1a, 0xd7, 0x77, 0xc9, 0x67, 0x41, 0x0b, 0xc4, + 0xb2, 0x5b, 0x4c, 0xe0, 0x1b, 0x85, 0x37, 0x25, 0xa4, 0xd1, 0x80, 0xa5, 0xf8, 0x54, 0xd8, 0x4d, + 0x61, 0x29, 0x8b, 0x3e, 0x27, 0x9f, 0x30, 0x2d, 0xe1, 0x93, 0x91, 0x4a, 0x54, 0x7c, 0xc7, 0x0c, + 0x5d, 0x60, 0x19, 0x86, 0xd8, 0x6a, 0x22, 0xe3, 0x27, 0xad, 0x8b, 0xf5, 0xf0, 0x2b, 0x80, 0x44, + 0x55, 0xb5, 0x6e, 0x8a, 0xa6, 0x2f, 0xc0, 0x60, 0xb5, 0x6e, 0x72, 0x03, 0x7d, 0x7a, 0x2b, 0x6e, + 0xfa, 0x9e, 0x49, 0xca, 0xa2, 0x52, 0x6b, 0xbe, 0x0f, 0xa9, 0xf5, 0xe1, 0xd0, 0xd8, 0x60, 0x61, + 0xc8, 0x44, 0x75, 0xfb, 0xc0, 0x79, 0x62, 0x07, 0x87, 0xb2, 0xc1, 0xb2, 0xf1, 0x03, 0x98, 0xd5, + 0x9a, 0xe7, 0x5f, 0x71, 0xa6, 0x67, 0x01, 0xba, 0x01, 0xa3, 0xd5, 0x32, 0xb5, 0x3a, 0xa0, 0xd7, + 0xfa, 0x49, 0xb6, 0xdf, 0x34, 0xad, 0x06, 0xf5, 0x1e, 0x33, 0x45, 0xa5, 0xf1, 0xf7, 0x87, 0x14, + 0xea, 0x8a, 0xbf, 0x46, 0xc6, 0xe8, 0xee, 0x01, 0xb0, 0x15, 0xa2, 0x0c, 0x8e, 0x08, 0x80, 0x13, + 0xfc, 0xa1, 0x94, 0x6d, 0xc9, 0xa6, 0x02, 0xd4, 0xaf, 0x3f, 0x07, 0xb7, 0xad, 0x64, 0x48, 0xc2, + 0x9a, 0x40, 0xda, 0x56, 0x72, 0xd2, 0xbe, 0xa9, 0x02, 0xa1, 0x1f, 0x46, 0xcd, 0x8e, 0x87, 0xa9, + 0x7a, 0xfd, 0x2d, 0xf1, 0xe2, 0x13, 0x1f, 0xdb, 0xe9, 0x2c, 0x8f, 0x5f, 0xc0, 0x3c, 0xc1, 0xb5, + 0x9f, 0x52, 0xdb, 0xe2, 0xd5, 0x97, 0x01, 0x76, 0xd8, 0xde, 0x3e, 0x42, 0xdb, 0xb9, 0x9e, 0xd1, + 0x4e, 0x08, 0xcc, 0x35, 0xcc, 0x21, 0x9d, 0x06, 0x96, 0x75, 0x66, 0x32, 0x7d, 0xba, 0x88, 0xcc, + 0xcd, 0x55, 0xa7, 0xd5, 0x71, 0x6d, 0x79, 0xa9, 0x60, 0x8b, 0xc8, 0x6b, 0x37, 0x30, 0x2f, 0x37, + 0x55, 0x20, 0xe3, 0x46, 0xa6, 0x61, 0xee, 0x18, 0x0c, 0xed, 0x54, 0x77, 0x36, 0x0b, 0x39, 0xe3, + 0x0e, 0x80, 0xd2, 0x12, 0xc0, 0xc8, 0xd6, 0xb6, 0xf9, 0xb8, 0xbc, 0x59, 0x18, 0x40, 0xf3, 0x70, + 0xee, 0xc9, 0xc6, 0xd6, 0xca, 0xf6, 0x93, 0x7a, 0xa3, 0xfe, 0xb8, 0x6c, 0xee, 0x54, 0xcb, 0xe6, + 0x4a, 0x21, 0x67, 0x7c, 0x0d, 0x73, 0xfa, 0x08, 0xcf, 0x74, 0x11, 0x06, 0x30, 0x2b, 0xe5, 0x99, + 0x87, 0x4f, 0x76, 0x14, 0x83, 0x3f, 0x7e, 0x41, 0x8a, 0x1a, 0x05, 0xf0, 0xab, 0x14, 0xff, 0x8c, + 0x14, 0x20, 0xcd, 0x94, 0x23, 0x9f, 0x69, 0xca, 0x61, 0x7c, 0x17, 0xe6, 0xf4, 0x56, 0xfb, 0xd5, + 0xe4, 0xbc, 0x45, 0x2d, 0x21, 0x15, 0x83, 0x7d, 0x72, 0x53, 0x0f, 0xbb, 0xc8, 0x77, 0xd6, 0xef, + 0x42, 0x81, 0x43, 0x85, 0x27, 0xef, 0x35, 0xa1, 0x6a, 0xcb, 0x25, 0x38, 0x17, 0x09, 0x83, 0xdb, + 0xf7, 0x85, 0x89, 0x8a, 0xda, 0xc2, 0x55, 0xee, 0xe0, 0x97, 0xd3, 0x7c, 0x98, 0x38, 0x22, 0xad, + 0x22, 0x78, 0xbb, 0x9d, 0xd6, 0x6b, 0xe2, 0x91, 0x3d, 0xf6, 0x94, 0x78, 0x6f, 0x8b, 0x47, 0x86, + 0x5e, 0x9c, 0xf8, 0x93, 0x3c, 0x2c, 0x46, 0x6c, 0xf4, 0xab, 0x87, 0x56, 0xbb, 0x8d, 0x9d, 0x03, + 0x8c, 0x6e, 0xc2, 0xd0, 0xce, 0xf6, 0x4e, 0x8d, 0x2b, 0xe1, 0xe6, 0xf8, 0xe7, 0x44, 0x8a, 0x24, + 0x8c, 0x49, 0x21, 0xd0, 0x23, 0x38, 0x27, 0xec, 0x13, 0x65, 0x15, 0xbf, 0x3c, 0x5d, 0xca, 0xb6, + 0x76, 0x8c, 0xe3, 0xa1, 0x77, 0xb9, 0x43, 0xc1, 0x8f, 0xbb, 0xb6, 0x87, 0x5b, 0x54, 0xb1, 0x10, + 0xbe, 0xc9, 0x29, 0x35, 0xa6, 0x0a, 0x86, 0xaa, 0x30, 0x5c, 0x6f, 0xba, 0x1d, 0xb1, 0xc9, 0x2c, + 0x2a, 0xcd, 0x0a, 0xca, 0xb4, 0x9e, 0x1b, 0x8e, 0x90, 0x3f, 0x55, 0xbb, 0x3b, 0x5a, 0x87, 0x3e, + 0x04, 0xa0, 0x7e, 0xa2, 0x26, 0xee, 0xfa, 0x98, 0x5b, 0x26, 0xb0, 0x67, 0x4b, 0xea, 0x5e, 0xea, + 0x91, 0x62, 0xed, 0xd9, 0x52, 0x02, 0x33, 0x67, 0x33, 0xe3, 0x77, 0x73, 0xb0, 0x90, 0xe2, 0xf3, + 0x80, 0xde, 0xd1, 0xd8, 0x39, 0xab, 0xb0, 0x53, 0x80, 0xac, 0x0f, 0x70, 0x7e, 0x56, 0x15, 0xa3, + 0xd1, 0xc1, 0x53, 0x18, 0x8d, 0xae, 0x0f, 0x84, 0x86, 0xa2, 0x15, 0x80, 0x31, 0x51, 0x6e, 0xcc, + 0xc0, 0x94, 0x36, 0x6f, 0x86, 0x01, 0x93, 0x6a, 0xcb, 0x64, 0x71, 0x54, 0xdd, 0x96, 0x5c, 0x1c, + 0xe4, 0x6f, 0xe3, 0x6f, 0xe6, 0x60, 0x8e, 0xb2, 0xf8, 0xc0, 0x26, 0xbb, 0x56, 0x38, 0x43, 0xcb, + 0xda, 0x48, 0x96, 0xb4, 0x91, 0x44, 0x60, 0xe5, 0x90, 0x3e, 0x8a, 0x0d, 0x69, 0x29, 0x69, 0x48, + 0xf4, 0xf3, 0xb2, 0x5d, 0x47, 0x1b, 0x89, 0xf2, 0xd2, 0xf2, 0x7b, 0x39, 0x98, 0x55, 0xfa, 0x24, + 0xfb, 0x7f, 0x4f, 0xeb, 0xd2, 0xc5, 0x84, 0x2e, 0xc5, 0x98, 0x5c, 0x89, 0xf5, 0xe8, 0xad, 0xac, + 0x1e, 0xf5, 0xe4, 0xf1, 0x7f, 0xcc, 0xc1, 0x7c, 0x22, 0x0f, 0xd0, 0x79, 0x22, 0x96, 0x36, 0x3d, + 0x1c, 0x70, 0xf6, 0xf2, 0x5f, 0xa4, 0x7c, 0xc3, 0xf7, 0xbb, 0xd8, 0xe3, 0x8a, 0x3d, 0xfe, 0x0b, + 0xbd, 0x05, 0x53, 0x35, 0xec, 0xd9, 0x6e, 0x8b, 0x99, 0x13, 0x33, 0x1b, 0xa8, 0x29, 0x53, 0x2f, + 0x44, 0x4b, 0x30, 0x5e, 0x6e, 0x1f, 0xb8, 0x9e, 0x1d, 0x1c, 0xb2, 0xc7, 0xae, 0x71, 0x33, 0x2c, + 0x20, 0xb4, 0x57, 0xec, 0x03, 0x61, 0xd6, 0x37, 0x65, 0xf2, 0x5f, 0x68, 0x11, 0x46, 0x85, 0x32, + 0x8c, 0xaa, 0xd2, 0x4c, 0xf1, 0x93, 0x60, 0x7c, 0x61, 0xd2, 0x45, 0x40, 0x9d, 0x70, 0x4d, 0xfe, + 0x0b, 0x4d, 0x53, 0x83, 0x50, 0xea, 0x62, 0x4b, 0x0d, 0x41, 0x3f, 0x82, 0xb9, 0x24, 0xbe, 0x26, + 0x2d, 0x21, 0x8e, 0x9b, 0x97, 0xb8, 0xff, 0x7f, 0x1e, 0x66, 0xcb, 0xad, 0xd6, 0xe3, 0x07, 0x65, + 0xf6, 0x22, 0x2e, 0xf6, 0xa6, 0x77, 0x61, 0x68, 0xc3, 0xe1, 0x8f, 0xbe, 0xca, 0x43, 0x7f, 0x1c, + 0x92, 0x40, 0x91, 0x19, 0x24, 0xff, 0x23, 0x13, 0x66, 0x57, 0x5f, 0xda, 0x7e, 0x60, 0x3b, 0x07, + 0xaa, 0x0b, 0x52, 0xbe, 0x1f, 0x17, 0xa4, 0xf5, 0x01, 0x33, 0x09, 0x19, 0xed, 0xc0, 0xf9, 0x2d, + 0xfc, 0x22, 0x61, 0x89, 0x49, 0xcf, 0x4c, 0x65, 0x23, 0x8a, 0xad, 0xac, 0x14, 0x5c, 0x75, 0x05, + 0xff, 0x66, 0x9e, 0x3a, 0x6e, 0x2b, 0x03, 0xe3, 0x2d, 0xef, 0xc2, 0x9c, 0xd2, 0xa1, 0x70, 0x1f, + 0x65, 0x3c, 0x29, 0x25, 0x0f, 0x47, 0xfd, 0xd0, 0x12, 0xd1, 0xd1, 0x13, 0x58, 0xd0, 0x3b, 0x15, + 0x52, 0xd6, 0x3f, 0x96, 0x24, 0x90, 0xf5, 0x01, 0x33, 0x0d, 0x1b, 0x2d, 0xc3, 0x60, 0xb9, 0xf9, + 0x8c, 0xb3, 0x25, 0x79, 0xca, 0xd8, 0xc8, 0xca, 0xcd, 0x67, 0xeb, 0x03, 0x26, 0x01, 0xd6, 0xbe, + 0x97, 0x7f, 0x99, 0x83, 0x85, 0x94, 0x19, 0x46, 0x97, 0x01, 0x58, 0xa1, 0x72, 0x62, 0x29, 0x25, + 0x44, 0xd0, 0xe5, 0x26, 0x15, 0xaf, 0x3a, 0x6c, 0x66, 0xa6, 0xa5, 0x93, 0x63, 0x58, 0x61, 0x2a, + 0x40, 0xa8, 0x26, 0xac, 0x8f, 0x98, 0xaf, 0xa5, 0x7e, 0xac, 0x28, 0x35, 0x9a, 0xd9, 0x51, 0xd4, + 0xc7, 0x52, 0x25, 0xc1, 0x55, 0xc3, 0xd5, 0xe8, 0x28, 0xe4, 0xa0, 0xd1, 0x4d, 0x18, 0x61, 0x85, + 0x7c, 0x0e, 0x45, 0xe0, 0x83, 0x10, 0x98, 0xd7, 0x1b, 0x7f, 0x27, 0x07, 0xe7, 0xd9, 0x89, 0x1d, + 0xfb, 0x34, 0xbe, 0xab, 0x7d, 0x1a, 0x57, 0x65, 0x87, 0x93, 0x80, 0xb5, 0xaf, 0xa3, 0xa2, 0x3b, + 0xe6, 0xf5, 0xfb, 0x55, 0xa8, 0x48, 0xea, 0xba, 0xfd, 0x7b, 0x39, 0xa1, 0x29, 0x8b, 0x2f, 0xdd, + 0x55, 0x98, 0x7c, 0xbd, 0x25, 0xab, 0xa1, 0xa1, 0xf7, 0xd8, 0x8a, 0xca, 0x67, 0x8f, 0x34, 0x73, + 0x51, 0x7d, 0x02, 0xc5, 0x74, 0xd6, 0xf4, 0x5a, 0x56, 0xc6, 0x83, 0x04, 0xec, 0xd7, 0x99, 0xce, + 0xbf, 0xcc, 0xc5, 0x08, 0xd5, 0x5f, 0x39, 0x4d, 0x31, 0xa5, 0x37, 0xa2, 0xa6, 0xf2, 0xa9, 0xe6, + 0xc7, 0x6a, 0x77, 0xf3, 0xe1, 0x9b, 0x0c, 0x5f, 0x9d, 0x54, 0x6a, 0x56, 0x3f, 0x8b, 0x6e, 0xf2, + 0x86, 0x38, 0xd8, 0x97, 0x4f, 0x26, 0x0d, 0x19, 0x81, 0x39, 0x7a, 0x23, 0xc5, 0x39, 0x33, 0x89, + 0xbe, 0xf1, 0x5b, 0x83, 0xfa, 0x37, 0xf0, 0x3a, 0x63, 0xad, 0xc1, 0x44, 0xd5, 0x75, 0x02, 0xfc, + 0x32, 0x50, 0x02, 0x02, 0x20, 0x69, 0x02, 0x22, 0x6b, 0xf8, 0x7d, 0x8d, 0x15, 0x34, 0xc8, 0xe5, + 0x41, 0x33, 0x97, 0x0b, 0x01, 0x51, 0x15, 0xa6, 0xb6, 0xf0, 0x8b, 0x18, 0x03, 0xa9, 0xc9, 0x9e, + 0x83, 0x5f, 0x34, 0x14, 0x26, 0xaa, 0x66, 0x81, 0x1a, 0x0e, 0xda, 0x87, 0x69, 0xb1, 0xff, 0xf5, + 0x7b, 0x0c, 0x30, 0x97, 0x79, 0xd2, 0x42, 0x0a, 0x0f, 0x23, 0x14, 0xcf, 0x7e, 0x67, 0x32, 0x6a, + 0xb0, 0x18, 0x9f, 0x0f, 0xde, 0xda, 0xbb, 0xbd, 0x56, 0x31, 0x53, 0x8e, 0xb5, 0xf4, 0x15, 0xbd, + 0x4e, 0x15, 0x96, 0x12, 0x46, 0x6a, 0xa0, 0xee, 0x46, 0xa7, 0x97, 0xda, 0x9a, 0x8a, 0xe9, 0x55, + 0x6d, 0xab, 0x84, 0x0b, 0x48, 0x95, 0xea, 0x7c, 0x55, 0x4a, 0xbc, 0x63, 0xb7, 0x60, 0x94, 0x17, + 0x45, 0xe2, 0xc4, 0x84, 0xdf, 0x97, 0x00, 0x30, 0x7e, 0x3f, 0x07, 0x17, 0xa8, 0x06, 0xda, 0x76, + 0x0e, 0xda, 0x78, 0xd7, 0xd7, 0xbd, 0x38, 0xbe, 0xa3, 0x6d, 0x99, 0x0b, 0x29, 0x1e, 0xbb, 0xdf, + 0xd4, 0x46, 0xf9, 0x87, 0x39, 0x28, 0x26, 0xf5, 0xed, 0x6c, 0xf7, 0xca, 0xdb, 0xfc, 0x7a, 0x9f, + 0xd7, 0xac, 0x2e, 0x65, 0x9b, 0x62, 0xb0, 0x64, 0x90, 0xe4, 0x7f, 0x6d, 0x93, 0xfc, 0x6f, 0x39, + 0x98, 0xdb, 0xf0, 0xd5, 0xab, 0x14, 0x67, 0xdc, 0xed, 0xa4, 0xa8, 0x0b, 0x74, 0x5e, 0xd7, 0x07, + 0x92, 0xa2, 0x2a, 0xbc, 0xab, 0xf8, 0xb7, 0xe6, 0xb3, 0xc2, 0x29, 0x10, 0xa1, 0x59, 0x7a, 0xb8, + 0xde, 0x80, 0xa1, 0x2d, 0x22, 0x28, 0x0e, 0xf2, 0xf5, 0xc7, 0x30, 0x48, 0x11, 0xf5, 0x2f, 0x25, + 0x5d, 0x26, 0x3f, 0xd0, 0x83, 0x98, 0x17, 0xeb, 0x50, 0xef, 0x70, 0x01, 0xeb, 0x03, 0x51, 0x87, + 0xd6, 0xca, 0x18, 0x8c, 0xec, 0x58, 0xde, 0x01, 0x0e, 0x8c, 0xef, 0x43, 0x91, 0x9b, 0x68, 0x31, + 0x9d, 0x3e, 0x35, 0xe4, 0xf2, 0x43, 0x2b, 0xbc, 0x2c, 0xb3, 0xaa, 0xcb, 0x00, 0xd4, 0x63, 0x6a, + 0xc3, 0x69, 0xe1, 0x97, 0xcc, 0x0e, 0xd0, 0x54, 0x4a, 0x8c, 0xf7, 0x60, 0x5c, 0x0e, 0x81, 0xde, + 0xb5, 0x15, 0x59, 0x98, 0x0e, 0x67, 0x4e, 0xf3, 0xab, 0x15, 0xce, 0xb4, 0x36, 0xcc, 0x47, 0xa6, + 0x22, 0xf4, 0x7c, 0x97, 0x77, 0x60, 0x6a, 0xb5, 0x68, 0xca, 0xdf, 0xd1, 0x2b, 0x72, 0xbe, 0xaf, + 0x2b, 0xb2, 0x51, 0x85, 0x73, 0xb1, 0xf5, 0x81, 0x10, 0x75, 0x3a, 0x67, 0x5a, 0x22, 0x72, 0xa0, + 0xd6, 0xeb, 0xeb, 0xa4, 0x6c, 0x67, 0xb3, 0xce, 0xdc, 0x9b, 0x48, 0xd9, 0xce, 0x66, 0xbd, 0x32, + 0xc2, 0xd6, 0x9b, 0xf1, 0x8f, 0xf3, 0x54, 0x79, 0x12, 0xe3, 0x5c, 0x44, 0x0f, 0xad, 0xea, 0xc2, + 0x2b, 0x30, 0x4e, 0xf9, 0xb4, 0x22, 0xfc, 0x05, 0xb3, 0x6d, 0x91, 0xc6, 0x7e, 0x7a, 0x5c, 0x1a, + 0xa0, 0x06, 0x48, 0x21, 0x1a, 0xfa, 0x0c, 0x46, 0x57, 0x9d, 0x16, 0xa5, 0x30, 0x78, 0x0a, 0x0a, + 0x02, 0x89, 0xcc, 0x1e, 0xed, 0x32, 0x11, 0x05, 0xb9, 0xfa, 0xd2, 0x54, 0x4a, 0xe8, 0xe4, 0x50, + 0x03, 0xcf, 0x61, 0x3a, 0xb1, 0xec, 0x07, 0x8d, 0x3e, 0x40, 0xba, 0x20, 0x22, 0x1a, 0x8d, 0x9b, + 0xf2, 0x37, 0x32, 0x60, 0x78, 0xdb, 0x6b, 0xf1, 0xa8, 0x24, 0xd3, 0xcb, 0x93, 0x9c, 0xfb, 0xb4, + 0xcc, 0x64, 0x55, 0xc6, 0x7f, 0xc9, 0xc1, 0xc2, 0x1a, 0x0e, 0x12, 0x57, 0x9b, 0xc6, 0x95, 0xdc, + 0x1b, 0x73, 0x25, 0xff, 0x3a, 0x5c, 0x91, 0xa3, 0x1e, 0x4c, 0x1b, 0xf5, 0x50, 0xda, 0xa8, 0x87, + 0xd3, 0x47, 0xbd, 0x06, 0x23, 0x6c, 0xa8, 0xe8, 0x1a, 0x0c, 0x6f, 0x04, 0xf8, 0x28, 0x54, 0xaa, + 0xa9, 0x96, 0x94, 0x26, 0xab, 0x23, 0x37, 0xd2, 0x4d, 0xcb, 0x0f, 0x84, 0x43, 0xdd, 0xb8, 0x29, + 0x7e, 0x1a, 0x3f, 0xa2, 0x9e, 0xc6, 0x9b, 0x6e, 0xf3, 0x99, 0xf2, 0xe2, 0x31, 0xca, 0xbe, 0xe5, + 0xe8, 0x0b, 0x19, 0x81, 0x62, 0x35, 0xa6, 0x80, 0x40, 0x57, 0x60, 0x62, 0xc3, 0x79, 0xe0, 0x7a, + 0x4d, 0xbc, 0xed, 0xb4, 0x19, 0xf5, 0x31, 0x53, 0x2d, 0xe2, 0x9a, 0x40, 0xde, 0x42, 0xa8, 0x09, + 0xa4, 0x05, 0x11, 0x4d, 0x20, 0x29, 0xdb, 0x5b, 0x36, 0x59, 0x1d, 0x57, 0x34, 0x92, 0xbf, 0xb3, + 0xd4, 0x6b, 0x52, 0x0f, 0xd7, 0x0b, 0x70, 0x1f, 0x2e, 0x98, 0xb8, 0xd3, 0xb6, 0x88, 0xc0, 0x79, + 0xe4, 0x32, 0x78, 0x39, 0xe6, 0x2b, 0x09, 0x1e, 0x58, 0xba, 0x5d, 0x8d, 0xec, 0x72, 0x3e, 0xa3, + 0xcb, 0x47, 0x70, 0x75, 0x0d, 0x07, 0xfa, 0xde, 0x18, 0xbe, 0xa7, 0xf0, 0xc1, 0xaf, 0xc3, 0x98, + 0xaf, 0xbf, 0x05, 0x5d, 0x16, 0x4f, 0x90, 0x49, 0x88, 0x7b, 0xf7, 0xc5, 0x6b, 0x29, 0xa7, 0x23, + 0xff, 0x32, 0x3e, 0x87, 0x52, 0x5a, 0x73, 0xfd, 0x99, 0x3d, 0xdb, 0x70, 0x25, 0x9d, 0x80, 0x3c, + 0x4c, 0xc5, 0xbb, 0x91, 0x54, 0x1d, 0x64, 0xf7, 0x56, 0x7f, 0x6a, 0xe2, 0x7f, 0x18, 0x15, 0x61, + 0x00, 0xfa, 0x06, 0xdd, 0x6d, 0x50, 0x93, 0x0c, 0x9d, 0x40, 0xc8, 0xd7, 0x32, 0x8c, 0x89, 0x32, + 0xce, 0xd7, 0x85, 0xc4, 0x9e, 0x0a, 0x86, 0xb6, 0x04, 0x01, 0x89, 0x66, 0xfc, 0x48, 0x3c, 0x4f, + 0xea, 0x18, 0xfd, 0xb9, 0x95, 0xf6, 0xf3, 0x1e, 0x69, 0xb8, 0x70, 0x41, 0xa7, 0xad, 0x3e, 0x3b, + 0x15, 0x94, 0x67, 0x27, 0xf6, 0xda, 0x74, 0x45, 0x7f, 0x06, 0xc9, 0xf3, 0x75, 0x19, 0x16, 0xa1, + 0xcb, 0xea, 0xe3, 0xd2, 0x64, 0xdc, 0x0f, 0xf7, 0x2e, 0x14, 0x93, 0x1a, 0x54, 0x14, 0x4a, 0xf2, + 0x05, 0x83, 0x87, 0xe5, 0xfa, 0xb5, 0x1c, 0x18, 0x9a, 0x95, 0x1d, 0x9d, 0xa1, 0x9a, 0xe7, 0x3e, + 0xb7, 0x5b, 0xca, 0xc3, 0xe8, 0x3b, 0x62, 0x63, 0x63, 0x5e, 0x04, 0x54, 0xe7, 0x1b, 0x35, 0xcf, + 0xe7, 0xbb, 0xdd, 0x5d, 0x18, 0xdd, 0xc2, 0x2f, 0xc3, 0xed, 0x87, 0x49, 0xb0, 0xd4, 0xf2, 0xee, + 0x19, 0x56, 0xa3, 0x38, 0x08, 0x30, 0x22, 0x3e, 0x5d, 0xcb, 0xec, 0x03, 0xef, 0xff, 0x3e, 0x14, + 0xa2, 0x75, 0x7c, 0xee, 0x4b, 0x8a, 0x45, 0x51, 0x9c, 0xc2, 0xde, 0x3d, 0xe6, 0xa0, 0x20, 0xac, + 0xd3, 0x3a, 0x92, 0x72, 0x8c, 0xde, 0xe9, 0x7b, 0x8f, 0x3e, 0x04, 0xd8, 0x71, 0x03, 0xab, 0x5d, + 0xa5, 0x3a, 0xc0, 0xc1, 0xd0, 0x9f, 0x23, 0x20, 0xa5, 0x8d, 0x68, 0xb8, 0x09, 0x05, 0xd8, 0xf8, + 0x1e, 0xfd, 0x22, 0x93, 0x3b, 0xdd, 0xdf, 0x47, 0x52, 0x85, 0x6b, 0x11, 0xab, 0x96, 0xd7, 0x20, + 0x12, 0xc0, 0x3c, 0x61, 0x3f, 0x11, 0x61, 0xd6, 0x3c, 0xb7, 0xdb, 0xf9, 0xc5, 0xcc, 0xfa, 0xbf, + 0xc9, 0x31, 0x53, 0x5c, 0xb5, 0x59, 0x3e, 0xd1, 0x55, 0x80, 0xb0, 0x34, 0xe2, 0x92, 0x21, 0x2b, + 0xf6, 0xee, 0xb1, 0xbb, 0x3b, 0x7d, 0xef, 0x3a, 0x60, 0x04, 0x14, 0xb4, 0x5f, 0xec, 0x4c, 0xde, + 0xa7, 0xa6, 0x2c, 0xb2, 0xf5, 0xfe, 0xf8, 0xfe, 0xbe, 0xd0, 0x51, 0x9d, 0x12, 0xef, 0x10, 0xe6, + 0xc8, 0xb7, 0x4b, 0xee, 0x35, 0xae, 0x67, 0x07, 0xc2, 0x35, 0x08, 0xd5, 0xb8, 0x2b, 0x3f, 0xc3, + 0xfa, 0xe4, 0xe7, 0xc7, 0xa5, 0x0f, 0x4e, 0xe3, 0x17, 0x2d, 0x68, 0xee, 0x48, 0xf7, 0x7f, 0x63, + 0x01, 0x06, 0xab, 0xe6, 0x26, 0xdd, 0xaa, 0xcc, 0x4d, 0xb9, 0x55, 0x99, 0x9b, 0xc6, 0x7f, 0xce, + 0x43, 0x89, 0x05, 0x1b, 0xa1, 0x16, 0x50, 0xe1, 0x0d, 0x4b, 0x31, 0xa9, 0xea, 0x57, 0x53, 0x11, + 0x09, 0x26, 0x92, 0xef, 0x27, 0x98, 0xc8, 0x2f, 0xbf, 0xbe, 0x56, 0xb9, 0xf2, 0xf6, 0xc9, 0x71, + 0xe9, 0x5a, 0xa8, 0x4e, 0x60, 0xb5, 0x49, 0x7a, 0x85, 0x94, 0x26, 0xe2, 0x8a, 0x90, 0xa1, 0xd7, + 0x50, 0x84, 0xdc, 0x85, 0x51, 0x7a, 0x61, 0xd9, 0xa8, 0x71, 0xbb, 0x5d, 0xba, 0x3c, 0x69, 0x5c, + 0xa0, 0x86, 0xad, 0x86, 0x60, 0x13, 0x60, 0xc6, 0xdf, 0xca, 0xc3, 0x95, 0x74, 0x9e, 0xf3, 0xbe, + 0xad, 0x00, 0x84, 0xb6, 0x57, 0x59, 0xb6, 0x5e, 0xf4, 0xdb, 0x79, 0x81, 0xf7, 0xa5, 0xad, 0xa5, + 0x82, 0x47, 0xa4, 0x16, 0xe1, 0x33, 0x1b, 0x79, 0xad, 0xd4, 0x5c, 0x69, 0x79, 0x84, 0x4f, 0x5e, + 0xa4, 0x45, 0xf8, 0xe4, 0x65, 0x68, 0x1f, 0x16, 0x6a, 0x9e, 0xfd, 0xdc, 0x0a, 0xf0, 0x23, 0xfc, + 0xaa, 0xe6, 0xb6, 0xed, 0xe6, 0xab, 0x55, 0xee, 0x3a, 0xc6, 0x1c, 0xa1, 0x6f, 0x9e, 0x1c, 0x97, + 0xde, 0xea, 0x30, 0x10, 0xf2, 0x61, 0x36, 0x3a, 0x14, 0xa8, 0x11, 0xf7, 0x26, 0x4b, 0x23, 0x64, + 0xfc, 0xeb, 0x1c, 0x5c, 0xa4, 0x02, 0x35, 0x7f, 0x79, 0x11, 0x8d, 0xbf, 0x96, 0xc9, 0xaf, 0x3a, + 0x40, 0xbe, 0x16, 0xa9, 0xc9, 0xaf, 0xe6, 0x53, 0x6c, 0x6a, 0x60, 0x68, 0x03, 0x26, 0xf8, 0x6f, + 0x45, 0x7d, 0x3e, 0xaf, 0x6c, 0x58, 0x74, 0xa9, 0x33, 0x9d, 0x13, 0x5d, 0xd8, 0x9c, 0x18, 0x75, + 0x7c, 0x34, 0x55, 0x5c, 0xe3, 0x67, 0x79, 0x58, 0xda, 0xc3, 0x9e, 0xfd, 0xf4, 0x55, 0xca, 0x60, + 0xb6, 0x61, 0x4e, 0x14, 0xb1, 0x80, 0x23, 0xda, 0x27, 0xc6, 0x62, 0x08, 0x8a, 0xae, 0xf2, 0x88, + 0x25, 0xe2, 0x8b, 0x4b, 0x44, 0x3c, 0x85, 0x31, 0xef, 0xbb, 0x30, 0x16, 0x09, 0xf9, 0x43, 0xe7, + 0x5f, 0x7c, 0xa1, 0xe1, 0x54, 0xad, 0x0f, 0x98, 0x12, 0x12, 0xfd, 0x46, 0xfa, 0x13, 0x2e, 0xd7, + 0x3f, 0xf4, 0x52, 0xa4, 0xd2, 0x0f, 0x96, 0x7c, 0xac, 0x96, 0x52, 0x9b, 0xf0, 0xc1, 0xae, 0x0f, + 0x98, 0x69, 0x2d, 0x55, 0x26, 0x60, 0xbc, 0x4c, 0x9f, 0xc5, 0xc9, 0xc5, 0xfd, 0xbf, 0xe6, 0xe1, + 0xb2, 0x70, 0xdb, 0x4a, 0x61, 0xf3, 0x97, 0xb0, 0x20, 0x8a, 0xca, 0x1d, 0x22, 0x30, 0xe0, 0x96, + 0xce, 0x69, 0x16, 0xc7, 0x53, 0x70, 0xda, 0xe2, 0x30, 0x21, 0xb3, 0xd3, 0xd0, 0xcf, 0x46, 0x8d, + 0xfa, 0x59, 0x52, 0x00, 0x26, 0xaa, 0xce, 0x54, 0xf7, 0x4c, 0x8d, 0x35, 0xda, 0xfe, 0xd9, 0x8a, + 0xa9, 0x61, 0x87, 0xde, 0x54, 0x0d, 0xbb, 0x3e, 0x10, 0x55, 0xc4, 0x56, 0xa6, 0x61, 0x72, 0x0b, + 0xbf, 0x08, 0xf9, 0xfe, 0x57, 0x73, 0x11, 0xa7, 0x7d, 0x22, 0x61, 0x30, 0xef, 0xfd, 0x5c, 0x18, + 0xc3, 0x87, 0x3a, 0xed, 0xab, 0x12, 0x06, 0x03, 0xdd, 0x80, 0x51, 0x66, 0x2b, 0xd2, 0xea, 0xe3, + 0x6e, 0x2e, 0xfd, 0xaf, 0x98, 0x4b, 0x6b, 0x8b, 0x5d, 0xd3, 0x39, 0xbe, 0xf1, 0x08, 0xae, 0x72, + 0xef, 0x03, 0x7d, 0xf2, 0x69, 0x43, 0xa7, 0x3c, 0xbe, 0x0c, 0x0b, 0x2e, 0xaf, 0xe1, 0xe8, 0xd6, + 0xa3, 0xf9, 0xa7, 0x7d, 0x0e, 0x33, 0x5a, 0xb9, 0xa4, 0x48, 0xa5, 0x52, 0xb9, 0x86, 0x24, 0xe9, + 0x28, 0xb4, 0x71, 0x25, 0xa9, 0x09, 0xb5, 0xb3, 0x06, 0xa6, 0x01, 0x39, 0xbd, 0xf0, 0x95, 0xdd, + 0x3f, 0xc5, 0xae, 0x77, 0x53, 0xf9, 0xae, 0xd9, 0x8e, 0xc7, 0x62, 0xf6, 0x89, 0x93, 0x57, 0xd6, + 0x1a, 0x53, 0xda, 0xa3, 0x82, 0x31, 0x0d, 0x93, 0xa2, 0xaa, 0x8d, 0x7d, 0xdf, 0xf8, 0xcd, 0x61, + 0x30, 0x38, 0x63, 0x93, 0x74, 0xae, 0x82, 0x1f, 0xfb, 0xb1, 0xce, 0xf2, 0x83, 0xea, 0xbc, 0xaa, + 0x59, 0x0e, 0x6b, 0xd9, 0xca, 0xa3, 0x72, 0x5e, 0x33, 0x2c, 0xd5, 0x56, 0x5e, 0x6c, 0xf4, 0x3f, + 0x48, 0xd9, 0x26, 0xd9, 0xc7, 0x76, 0xfd, 0xe4, 0xb8, 0x74, 0x35, 0x65, 0x9b, 0xd4, 0xe8, 0x26, + 0x6f, 0x99, 0xa6, 0xfe, 0xb6, 0x32, 0xf8, 0x3a, 0x6f, 0x2b, 0xe4, 0x8b, 0x54, 0x5f, 0x57, 0x76, + 0x75, 0x5e, 0xf2, 0xef, 0x51, 0x58, 0xb5, 0xa8, 0x55, 0xdc, 0x77, 0x5e, 0x29, 0xd1, 0xa8, 0x6a, + 0x64, 0x90, 0x0d, 0x05, 0x45, 0x65, 0x59, 0x3d, 0xc4, 0xcd, 0x67, 0xfc, 0x2d, 0x48, 0x3c, 0x53, + 0x27, 0x29, 0xae, 0x59, 0x4c, 0x60, 0xf6, 0x9d, 0xb3, 0x8a, 0x46, 0x93, 0xa0, 0xaa, 0xbe, 0xff, + 0x51, 0xb2, 0xa1, 0xc5, 0xd0, 0xc8, 0x99, 0x59, 0x0c, 0x8d, 0x9e, 0xc2, 0x62, 0x48, 0x7d, 0x32, + 0xf8, 0x1d, 0xe9, 0xee, 0x42, 0x64, 0x06, 0xbb, 0x8d, 0xb9, 0x6f, 0x97, 0x58, 0x81, 0x29, 0xef, + 0x7a, 0xb9, 0x6f, 0xf8, 0x5d, 0xef, 0x8f, 0xf2, 0xc2, 0xc9, 0x27, 0xf6, 0xfa, 0x7f, 0xfa, 0xe7, + 0xbd, 0xc4, 0x11, 0xf4, 0x75, 0xa0, 0x26, 0x1b, 0x6a, 0x54, 0x34, 0x13, 0x80, 0x7c, 0x8a, 0x09, + 0x80, 0xf6, 0x5e, 0x1a, 0xf4, 0xb0, 0x09, 0x18, 0x7c, 0xf3, 0x97, 0xb7, 0x7f, 0x36, 0x0a, 0xe7, + 0x6a, 0xd6, 0x81, 0xed, 0x90, 0x8d, 0xdb, 0xc4, 0xbe, 0xdb, 0xf5, 0x9a, 0x18, 0x95, 0x61, 0x5a, + 0xb7, 0xe0, 0xee, 0x61, 0x9f, 0x4e, 0xce, 0x26, 0xbd, 0x0c, 0x2d, 0xc3, 0xb8, 0xf4, 0xac, 0xe6, + 0x07, 0x4a, 0x82, 0xc7, 0xf5, 0xfa, 0x80, 0x19, 0x82, 0xa1, 0x0f, 0xb5, 0x87, 0x96, 0x19, 0x19, + 0x24, 0x80, 0xc2, 0x2e, 0x33, 0x13, 0x5b, 0xc7, 0x6d, 0xe9, 0x87, 0x22, 0x7b, 0xac, 0xf8, 0x51, + 0xec, 0xed, 0x65, 0x58, 0xeb, 0x71, 0x4c, 0x6b, 0x45, 0xe5, 0x81, 0xd4, 0xc0, 0xcc, 0xf1, 0x57, + 0x19, 0xf4, 0x7d, 0x98, 0x78, 0xd4, 0xdd, 0xc7, 0xe2, 0x95, 0x69, 0x84, 0x9f, 0x91, 0x51, 0xbf, + 0x04, 0x5e, 0xbf, 0x77, 0x9f, 0xcd, 0xc1, 0xb3, 0xee, 0x3e, 0x8e, 0x47, 0xfc, 0x26, 0x9b, 0x93, + 0x42, 0x0c, 0x1d, 0x42, 0x21, 0xea, 0x42, 0xc0, 0x03, 0xe8, 0x65, 0x38, 0x3e, 0xd0, 0xf0, 0x21, + 0x4a, 0x5c, 0x71, 0x66, 0xd8, 0xac, 0x35, 0x12, 0xa3, 0x8a, 0x7e, 0x05, 0xe6, 0x13, 0x75, 0x86, + 0x3c, 0xba, 0x78, 0x2f, 0x75, 0x24, 0xdd, 0xd8, 0x23, 0x5c, 0x13, 0x5e, 0x89, 0x5a, 0xcb, 0xc9, + 0xad, 0xa0, 0x16, 0xcc, 0x44, 0x4c, 0xe3, 0x79, 0x72, 0x83, 0x74, 0x63, 0x7b, 0x7a, 0x38, 0x89, + 0x08, 0xb4, 0x89, 0x6d, 0x45, 0x49, 0xa2, 0x4d, 0x18, 0x97, 0x57, 0x7e, 0x1a, 0xe4, 0x28, 0x59, + 0xbd, 0xb1, 0x78, 0x72, 0x5c, 0x9a, 0x0b, 0xd5, 0x1b, 0x1a, 0xcd, 0x90, 0x00, 0xfa, 0x09, 0x5c, + 0x95, 0x4b, 0x74, 0xdb, 0x4b, 0x56, 0x04, 0xf1, 0xb8, 0xe5, 0xb7, 0xa2, 0x2b, 0x3c, 0x0d, 0x7e, + 0xef, 0xde, 0xfa, 0x80, 0xd9, 0x9b, 0x6c, 0x05, 0x60, 0xcc, 0xe3, 0x1f, 0xe5, 0xc3, 0xa1, 0xb1, + 0xa1, 0xc2, 0x30, 0x5b, 0x37, 0xc2, 0xe5, 0xe0, 0xbf, 0x8f, 0x30, 0x1f, 0xde, 0x5d, 0xc7, 0x7e, + 0x6a, 0x87, 0xdf, 0xaf, 0xaa, 0x60, 0x0a, 0x13, 0x99, 0x70, 0xf1, 0x2f, 0x25, 0x65, 0x89, 0xd4, + 0x45, 0xe5, 0x7b, 0xea, 0xa2, 0xee, 0x2b, 0xef, 0x2d, 0x4a, 0x50, 0x4c, 0x76, 0xcc, 0xeb, 0xba, + 0x9f, 0xf0, 0x21, 0xe6, 0x6b, 0x18, 0xa1, 0xe1, 0xf9, 0xd8, 0x63, 0xd6, 0xc4, 0xf2, 0x6d, 0xbe, + 0x6b, 0x65, 0x74, 0x9f, 0xc5, 0xf3, 0xe3, 0x7e, 0xf9, 0x34, 0x86, 0x66, 0x9b, 0x16, 0xa8, 0xc1, + 0xf8, 0x18, 0x08, 0xda, 0x81, 0xd9, 0x9a, 0x87, 0x5b, 0xdc, 0xf0, 0xbd, 0xe3, 0xf1, 0xfb, 0x39, + 0xbb, 0xf9, 0xd3, 0x30, 0xe7, 0x1d, 0x51, 0xdd, 0xc0, 0xb2, 0x5e, 0x3d, 0x4f, 0x12, 0xd0, 0xd1, + 0x2a, 0x4c, 0xd7, 0xb1, 0xe5, 0x35, 0x0f, 0x1f, 0xe1, 0x57, 0xe4, 0xc4, 0xd7, 0x72, 0x03, 0xf8, + 0xb4, 0x86, 0x8c, 0x97, 0x56, 0xa9, 0xf6, 0x12, 0x3a, 0x12, 0xfa, 0x1e, 0x8c, 0xd4, 0x5d, 0x2f, + 0xa8, 0xbc, 0xe2, 0xdf, 0xb4, 0x78, 0xee, 0x60, 0x85, 0x95, 0x0b, 0x22, 0x3f, 0x82, 0xef, 0x7a, + 0x41, 0x63, 0x5f, 0x65, 0x1f, 0xc7, 0x43, 0xaf, 0x60, 0x4e, 0xff, 0x9e, 0x1e, 0xd8, 0x6d, 0xb2, + 0x09, 0x8d, 0x71, 0x49, 0x23, 0xe9, 0xa3, 0x65, 0x20, 0x95, 0x9b, 0x9c, 0xfa, 0x95, 0xe8, 0x57, + 0xfb, 0x94, 0xd6, 0xab, 0xd9, 0x55, 0x92, 0xf0, 0xd1, 0x63, 0x9a, 0x56, 0x82, 0x8d, 0xa8, 0xec, + 0x33, 0x93, 0xf3, 0xf1, 0x30, 0x84, 0x53, 0x97, 0x7e, 0x93, 0x94, 0x13, 0x96, 0x1f, 0xcd, 0x16, + 0x62, 0xc6, 0x50, 0x51, 0x0d, 0xce, 0xed, 0xfa, 0xb8, 0xe6, 0xe1, 0xe7, 0x36, 0x7e, 0x21, 0xe8, + 0xb1, 0x38, 0x64, 0x74, 0x9a, 0x08, 0xbd, 0x0e, 0xab, 0x4d, 0x22, 0x18, 0x47, 0x26, 0x12, 0x4d, + 0xcd, 0x76, 0x1c, 0xdc, 0xa2, 0x6f, 0x66, 0x13, 0xa1, 0x44, 0xd3, 0xa1, 0xa5, 0x0d, 0xd7, 0x69, + 0xab, 0x2c, 0x55, 0x80, 0x8b, 0x1f, 0xc2, 0x84, 0xb2, 0xc4, 0x12, 0xe2, 0x3a, 0xcc, 0xa9, 0x71, + 0x1d, 0xc6, 0xd5, 0xf8, 0x0d, 0x7f, 0x37, 0x07, 0x4b, 0xc9, 0x4b, 0x97, 0x1f, 0xf7, 0xdb, 0x30, + 0x2e, 0x0b, 0xa5, 0x97, 0x92, 0x10, 0x36, 0x23, 0xe7, 0x2d, 0xfb, 0x7e, 0xc4, 0x87, 0xae, 0x8e, + 0x37, 0xa4, 0xf1, 0x1a, 0x1a, 0xe0, 0x7f, 0x31, 0x0a, 0x73, 0xa4, 0x8f, 0xb1, 0x6d, 0xe1, 0x73, + 0x1a, 0x9f, 0x85, 0x96, 0x29, 0x0a, 0x4d, 0xae, 0xdb, 0x60, 0xe5, 0xd1, 0x98, 0x51, 0x1a, 0x02, + 0x7a, 0x4f, 0x7d, 0x3f, 0xcf, 0x2b, 0x79, 0x23, 0x44, 0xa1, 0x3a, 0x84, 0xf0, 0x61, 0xfd, 0x1d, + 0xed, 0xf9, 0xb6, 0xef, 0x3d, 0x66, 0xa8, 0xdf, 0x3d, 0x66, 0x57, 0xee, 0x31, 0x2c, 0xee, 0xc7, + 0xdb, 0xca, 0x1e, 0x73, 0xf6, 0x9b, 0xcb, 0xc8, 0x59, 0x6f, 0x2e, 0xa3, 0x6f, 0xb6, 0xb9, 0x8c, + 0xbd, 0xe6, 0xe6, 0xf2, 0x00, 0xa6, 0xb7, 0x30, 0x6e, 0x29, 0xaa, 0x79, 0xf6, 0x7d, 0x73, 0x7d, + 0x04, 0x55, 0xba, 0x24, 0xe9, 0xe7, 0x23, 0x58, 0xa9, 0x9b, 0x14, 0xfc, 0x9f, 0xd9, 0xa4, 0x26, + 0xce, 0x78, 0x93, 0x9a, 0x7c, 0x83, 0x4d, 0xea, 0x4d, 0x76, 0x9a, 0xcf, 0xa8, 0x25, 0x5b, 0xbd, + 0xbe, 0xce, 0xad, 0x04, 0x94, 0x67, 0xf9, 0x75, 0xd7, 0x17, 0x26, 0xfa, 0xf4, 0x6f, 0x52, 0x56, + 0x73, 0x3d, 0xf1, 0xb4, 0x49, 0xff, 0x36, 0x2a, 0xd4, 0x7e, 0x4d, 0xc5, 0x97, 0xfe, 0x1d, 0xa3, + 0xdc, 0x3d, 0x93, 0xef, 0x4f, 0x51, 0x81, 0xdb, 0x14, 0xf5, 0xc6, 0xbf, 0xcb, 0xb1, 0x27, 0xac, + 0xff, 0x1b, 0xb7, 0xb9, 0x37, 0x79, 0x56, 0xfa, 0x8d, 0x30, 0x6c, 0x03, 0x0f, 0x31, 0xe1, 0x59, + 0xcd, 0x67, 0xe1, 0xbb, 0xde, 0x0f, 0xc9, 0x37, 0xaa, 0x56, 0xd0, 0x88, 0x96, 0xe1, 0xad, 0x42, + 0xaf, 0xdc, 0xbb, 0x27, 0x3e, 0x5e, 0x1e, 0xbd, 0x82, 0x15, 0xeb, 0x1f, 0xaf, 0x8a, 0x40, 0x9d, + 0x70, 0x66, 0x0c, 0x93, 0x45, 0x1d, 0x48, 0xec, 0xc1, 0xfb, 0x71, 0xbf, 0x79, 0x2a, 0xb6, 0x86, + 0x7e, 0xf3, 0x2a, 0x1b, 0x43, 0x0f, 0xfa, 0x5d, 0xb8, 0x68, 0xe2, 0x23, 0xf7, 0x39, 0x3e, 0x5b, + 0xb2, 0x3f, 0x80, 0x0b, 0x3a, 0x41, 0xe6, 0x26, 0xc6, 0xa2, 0xa5, 0x7f, 0x96, 0x1c, 0x63, 0x9d, + 0x23, 0xb0, 0x18, 0xeb, 0x4c, 0x37, 0x41, 0xfe, 0xd4, 0x74, 0x13, 0xa4, 0xc0, 0x70, 0x61, 0x49, + 0x27, 0x5e, 0x6e, 0xb5, 0x68, 0x06, 0xbc, 0xa6, 0xdd, 0xb1, 0x9c, 0x00, 0x6d, 0xc3, 0x84, 0xf2, + 0x33, 0x72, 0xa9, 0x54, 0x6a, 0xf8, 0xf1, 0x1f, 0x16, 0x68, 0xb1, 0x0f, 0xc3, 0x62, 0x03, 0x43, + 0x29, 0xca, 0x1e, 0xc2, 0x32, 0xb5, 0xcd, 0x0a, 0x4c, 0x29, 0x3f, 0xa5, 0x82, 0x8b, 0x86, 0xea, + 0x54, 0x5a, 0xd0, 0x19, 0xa6, 0xa3, 0x18, 0x4d, 0x28, 0x26, 0x31, 0x8d, 0x46, 0xab, 0x7a, 0x85, + 0x56, 0xc3, 0xb8, 0x57, 0xbd, 0xad, 0xaa, 0x66, 0xd2, 0x62, 0x5e, 0x19, 0x7f, 0x63, 0x08, 0x2e, + 0xf2, 0xc9, 0x38, 0xcb, 0x19, 0x47, 0x3f, 0x82, 0x09, 0x65, 0x8e, 0x39, 0xd3, 0xaf, 0x08, 0xf3, + 0xcd, 0xb4, 0xb5, 0xc0, 0x2e, 0xbf, 0x5d, 0x5a, 0xd0, 0x88, 0x4c, 0x37, 0xb9, 0xfc, 0xaa, 0xcb, + 0xa6, 0x0d, 0xd3, 0xfa, 0x44, 0xf3, 0xfb, 0xff, 0xb5, 0xc4, 0x46, 0x74, 0x50, 0x11, 0x41, 0xb7, + 0xd5, 0x48, 0x9c, 0x6e, 0x72, 0x8d, 0x8f, 0x2c, 0xa2, 0x97, 0x70, 0x2e, 0x36, 0xcb, 0x5c, 0xad, + 0x73, 0x23, 0xb1, 0xc1, 0x18, 0x34, 0x53, 0xde, 0x79, 0xb4, 0x38, 0xb5, 0xd9, 0x78, 0x23, 0xa8, + 0x05, 0x93, 0xea, 0xc4, 0x73, 0x05, 0xc5, 0xd5, 0x0c, 0x56, 0x32, 0x40, 0x26, 0x98, 0x71, 0x5e, + 0xd2, 0xb9, 0x7f, 0xa5, 0x2b, 0x24, 0x35, 0xe0, 0x31, 0x18, 0x61, 0xbf, 0xc9, 0x16, 0x50, 0xf3, + 0xb0, 0x8f, 0x9d, 0x26, 0x56, 0x2d, 0x71, 0xdf, 0x74, 0x0b, 0xf8, 0x57, 0x39, 0x58, 0x4c, 0xa2, + 0x5b, 0xc7, 0x4e, 0x0b, 0xd5, 0xa0, 0x10, 0x6d, 0x88, 0xaf, 0x6a, 0x43, 0x06, 0x29, 0x4d, 0xed, + 0xd2, 0xfa, 0x80, 0x19, 0xc3, 0x46, 0x5b, 0x70, 0x4e, 0x29, 0x3b, 0xa5, 0xc9, 0x73, 0x1c, 0x55, + 0xd5, 0x62, 0xae, 0xd3, 0x93, 0x71, 0xc5, 0x3d, 0xb2, 0x6c, 0x87, 0x08, 0xa9, 0x4a, 0xe8, 0x2b, + 0x08, 0x4b, 0x39, 0x6f, 0x98, 0x5e, 0x8e, 0x96, 0x0a, 0x3f, 0x06, 0x09, 0x62, 0x7c, 0x42, 0x77, + 0x70, 0xae, 0xcd, 0x61, 0xae, 0xc8, 0x92, 0xd8, 0x15, 0x18, 0xde, 0xd9, 0xac, 0x57, 0xcb, 0xdc, + 0xb1, 0x99, 0x85, 0xc3, 0x68, 0xfb, 0x8d, 0xa6, 0x65, 0xb2, 0x0a, 0xe3, 0x63, 0x1a, 0xe7, 0x9c, + 0x47, 0xc9, 0x96, 0x78, 0xd7, 0x61, 0x94, 0x17, 0x71, 0x4c, 0x6a, 0x02, 0xd5, 0xe6, 0x50, 0xa2, + 0xce, 0xa8, 0x09, 0x19, 0xbf, 0x8d, 0x2d, 0x5f, 0x39, 0x98, 0x3f, 0x80, 0x31, 0x8f, 0x97, 0xf1, + 0x73, 0x79, 0x5a, 0xe6, 0xbc, 0xa0, 0xc5, 0x4c, 0xf3, 0x29, 0x60, 0x4c, 0xf9, 0x97, 0xb1, 0x49, + 0x43, 0xd7, 0x6c, 0x6f, 0xac, 0x54, 0x09, 0x57, 0x39, 0xb3, 0xc4, 0x74, 0xdc, 0xa1, 0x56, 0xc5, + 0x01, 0x56, 0xdd, 0x9a, 0x29, 0x6b, 0xe8, 0x47, 0xce, 0x03, 0x36, 0x29, 0x20, 0xc6, 0x7d, 0x19, + 0x08, 0x27, 0x81, 0x5a, 0x5a, 0xee, 0x86, 0x2d, 0x1a, 0xe2, 0x67, 0x8d, 0x1a, 0x57, 0x9c, 0x45, + 0x27, 0x2c, 0x28, 0xb2, 0x63, 0x9e, 0x8c, 0x8a, 0x27, 0x1d, 0x73, 0xe5, 0xd6, 0x58, 0x85, 0x71, + 0x59, 0x26, 0x5f, 0x4a, 0x18, 0xaf, 0x34, 0xf8, 0xbd, 0xfb, 0xcc, 0x03, 0xbc, 0x29, 0x09, 0x84, + 0x78, 0xa4, 0x09, 0xf6, 0xdd, 0x7d, 0xc3, 0x4d, 0xf8, 0xd8, 0x0b, 0xbe, 0xd1, 0x26, 0xc2, 0x18, + 0x50, 0xa7, 0x69, 0x42, 0x83, 0xdf, 0x5b, 0xee, 0x87, 0x51, 0xdf, 0x70, 0x13, 0x84, 0x51, 0xdf, + 0x5c, 0x13, 0x58, 0x04, 0xcb, 0x62, 0x8b, 0x34, 0xd6, 0xc8, 0x6a, 0xbc, 0x11, 0xa1, 0xe2, 0x8c, + 0x60, 0x64, 0xce, 0x07, 0x86, 0x25, 0xc6, 0xac, 0x5f, 0x40, 0x33, 0x84, 0x61, 0xdf, 0x6c, 0x33, + 0xbf, 0x9f, 0x63, 0xa1, 0xbb, 0xea, 0xdb, 0x4a, 0xba, 0x3f, 0xe7, 0xa9, 0xab, 0x3c, 0xe4, 0x2a, + 0x5f, 0xfb, 0x23, 0xdb, 0x69, 0xa9, 0x0f, 0xb9, 0x56, 0x37, 0x38, 0x94, 0xc1, 0x9b, 0x9f, 0xd9, + 0x4e, 0xcb, 0x8c, 0x42, 0xa3, 0x0f, 0x61, 0x4a, 0x29, 0x92, 0xd2, 0x1a, 0x0b, 0xd6, 0xaf, 0xa2, + 0xdb, 0x2d, 0x53, 0x87, 0x34, 0x7e, 0x27, 0x0f, 0xe7, 0x77, 0x3b, 0x3e, 0xf5, 0xb6, 0xd8, 0x70, + 0x9e, 0x63, 0x27, 0x70, 0xbd, 0x57, 0xd4, 0xee, 0x1b, 0xbd, 0x07, 0xc3, 0xeb, 0xb8, 0xdd, 0x76, + 0xf9, 0xc8, 0x2f, 0x89, 0x57, 0xd4, 0x28, 0x34, 0x05, 0x5a, 0x1f, 0x30, 0x19, 0x34, 0xfa, 0x10, + 0xc6, 0xd7, 0xb1, 0xe5, 0x05, 0xfb, 0xd8, 0x12, 0xc2, 0xaa, 0x08, 0x1e, 0xaf, 0xa0, 0x70, 0x80, + 0xf5, 0x01, 0x33, 0x84, 0x46, 0xcb, 0xe4, 0x1e, 0xe7, 0x1c, 0x48, 0xc7, 0xf3, 0x94, 0x06, 0x09, + 0xcc, 0xfa, 0x80, 0x49, 0x61, 0xd1, 0x63, 0x98, 0x2a, 0x1f, 0x60, 0x27, 0x78, 0x8c, 0x03, 0xab, + 0x65, 0x05, 0x16, 0x17, 0x6a, 0xae, 0xa7, 0x21, 0x6b, 0xc0, 0xeb, 0x03, 0xa6, 0x8e, 0x5d, 0x19, + 0x86, 0xc1, 0xc7, 0xfe, 0x81, 0x71, 0x9c, 0x83, 0xc5, 0x15, 0xf7, 0x85, 0x93, 0xc8, 0x98, 0xef, + 0xea, 0x8c, 0x11, 0x3e, 0x41, 0x09, 0xf0, 0x11, 0xd6, 0xbc, 0x0b, 0x43, 0x35, 0xdb, 0x39, 0x88, + 0x9c, 0xe3, 0x09, 0x78, 0x04, 0x8a, 0x8e, 0xd0, 0x76, 0x0e, 0xd0, 0xa6, 0x10, 0xa0, 0xb8, 0x92, + 0x67, 0x50, 0x93, 0xda, 0x12, 0xb0, 0x55, 0xe8, 0x50, 0x50, 0x62, 0xbf, 0xc5, 0x00, 0xdf, 0x81, + 0x85, 0x94, 0x76, 0xb9, 0x33, 0x38, 0x19, 0xdb, 0x10, 0x3d, 0x95, 0xde, 0x86, 0xf9, 0xc4, 0x29, + 0x88, 0x01, 0xfe, 0xc3, 0xa4, 0xb5, 0xc4, 0x46, 0xbe, 0x08, 0xa3, 0x22, 0xc7, 0x08, 0xbb, 0xb8, + 0x8b, 0x9f, 0xd4, 0x8b, 0x81, 0x5e, 0xb7, 0xc3, 0x30, 0xc8, 0xe2, 0x37, 0xda, 0x53, 0x22, 0x1e, + 0x0d, 0x52, 0x2d, 0xd1, 0x47, 0x6f, 0x90, 0x89, 0x59, 0xd2, 0x22, 0x6d, 0xae, 0xbb, 0x7e, 0xe0, + 0x48, 0x23, 0x3b, 0x53, 0xfe, 0x46, 0xb7, 0xa0, 0xb0, 0xfa, 0x32, 0xc0, 0x9e, 0x63, 0xb5, 0x79, + 0xb6, 0x05, 0x9e, 0x62, 0xd7, 0x8c, 0x95, 0xa3, 0x0f, 0x60, 0x21, 0x5a, 0x26, 0x46, 0xc9, 0xdc, + 0x50, 0xd2, 0xaa, 0x8d, 0x3f, 0xcb, 0xd3, 0xc0, 0xcd, 0x19, 0x4b, 0x93, 0x70, 0x77, 0xbb, 0xce, + 0xb9, 0x95, 0xdf, 0xae, 0xa3, 0x25, 0x18, 0xdf, 0xae, 0x6b, 0x89, 0x5a, 0xcc, 0xb0, 0x80, 0x74, + 0x9b, 0x0c, 0xa1, 0xec, 0x35, 0x0f, 0xed, 0x00, 0x37, 0x83, 0xae, 0xc7, 0xe3, 0x55, 0x99, 0xb1, + 0x72, 0x64, 0xc0, 0xe4, 0x5a, 0xdb, 0xde, 0x6f, 0x0a, 0x62, 0x8c, 0x05, 0x5a, 0x19, 0xba, 0x01, + 0xd3, 0x1b, 0x8e, 0x1f, 0x58, 0xed, 0x36, 0xcb, 0x63, 0xc3, 0xf3, 0x1c, 0x9a, 0x91, 0x52, 0xd2, + 0x6e, 0xd5, 0x75, 0x02, 0xcb, 0x76, 0xb0, 0x67, 0x76, 0x9d, 0xc0, 0x3e, 0xc2, 0x7c, 0xec, 0xb1, + 0x72, 0xf4, 0x2e, 0xcc, 0xcb, 0xb2, 0x6d, 0xaf, 0x79, 0x88, 0xfd, 0xc0, 0xa3, 0x29, 0xc6, 0x68, + 0x64, 0x1e, 0x33, 0xb9, 0x92, 0xb6, 0xd0, 0x76, 0xbb, 0xad, 0x55, 0xe7, 0xb9, 0xed, 0xb9, 0x0e, + 0xcd, 0x1c, 0x3a, 0xc6, 0x5b, 0x88, 0x94, 0x1b, 0xb5, 0xc4, 0xaf, 0xf6, 0x0d, 0x96, 0xa0, 0x71, + 0x92, 0x83, 0xa5, 0xc4, 0x0f, 0x4b, 0x6c, 0xde, 0x2a, 0x72, 0x2e, 0xb2, 0x7e, 0x6f, 0xc1, 0x10, + 0xdd, 0xcd, 0x99, 0x62, 0x40, 0x98, 0xa1, 0x50, 0x7c, 0x46, 0x8a, 0xd4, 0x9a, 0x14, 0x06, 0xad, + 0x49, 0x25, 0xee, 0x20, 0x15, 0x5b, 0xef, 0x44, 0xf7, 0xcc, 0x84, 0xc6, 0x55, 0x65, 0xae, 0x50, + 0xdb, 0xbe, 0x89, 0xce, 0xed, 0xcf, 0x72, 0x50, 0xea, 0xb1, 0x9f, 0xc8, 0x31, 0xe5, 0xfa, 0x18, + 0xd3, 0x43, 0x39, 0x26, 0xe6, 0xf0, 0xb2, 0xdc, 0xdf, 0x9e, 0x75, 0xd6, 0xc3, 0xaa, 0x02, 0x8a, + 0x9f, 0x3c, 0xe8, 0x3b, 0x30, 0x5e, 0xaf, 0xaf, 0x6b, 0xef, 0xfc, 0x31, 0x4d, 0x60, 0x08, 0x61, + 0xbc, 0x0f, 0xe7, 0x25, 0x11, 0x16, 0x39, 0x5e, 0xf1, 0xaa, 0xe3, 0x67, 0xbd, 0x74, 0x01, 0x0c, + 0x0b, 0x8c, 0x3f, 0x1d, 0x8a, 0x21, 0xd6, 0xbb, 0x47, 0x47, 0x96, 0xf7, 0x0a, 0x95, 0x75, 0xc4, + 0xc1, 0x9e, 0x87, 0x6c, 0x65, 0xe8, 0xa7, 0xc7, 0xa5, 0x01, 0x85, 0x3a, 0x7a, 0x0b, 0xa6, 0xe8, + 0x07, 0xe9, 0x34, 0x31, 0xd3, 0x03, 0xe6, 0x59, 0x08, 0x12, 0xad, 0x10, 0xed, 0xc1, 0x14, 0x5f, + 0xeb, 0xf4, 0xb7, 0x58, 0x62, 0x77, 0xa3, 0x4b, 0x4c, 0xeb, 0xde, 0x6d, 0x0d, 0x85, 0x4d, 0x86, + 0x4e, 0x06, 0x7d, 0x05, 0xd3, 0x62, 0x63, 0xe3, 0x84, 0xd9, 0x23, 0xe7, 0xbd, 0x6c, 0xc2, 0x3a, + 0x0e, 0xa3, 0x1c, 0x21, 0x44, 0xba, 0xcc, 0xb7, 0x6b, 0x4e, 0x79, 0xb8, 0x9f, 0x2e, 0x6b, 0x28, + 0xbc, 0xcb, 0x5a, 0x59, 0xf1, 0x7b, 0x80, 0xe2, 0xe3, 0xea, 0xb5, 0x9a, 0xa6, 0x94, 0xd5, 0x54, + 0x2c, 0xc3, 0x6c, 0xc2, 0x00, 0x4e, 0x45, 0xe2, 0x7b, 0x80, 0xe2, 0x3d, 0x3d, 0x0d, 0x05, 0xe3, + 0x26, 0xdc, 0x90, 0x2c, 0x90, 0xab, 0x41, 0xa3, 0x29, 0x6e, 0xfb, 0xbf, 0x96, 0x87, 0x52, 0x0f, + 0x50, 0xf4, 0xb7, 0x73, 0x51, 0x6e, 0xb3, 0xd5, 0xf8, 0x61, 0x94, 0xdb, 0xc9, 0xf8, 0x09, 0x6c, + 0xaf, 0x7c, 0xf4, 0xeb, 0x7f, 0xfe, 0xda, 0x07, 0x75, 0x7c, 0xca, 0x4e, 0xcf, 0xad, 0x21, 0x95, + 0x5b, 0x26, 0xcc, 0x69, 0x22, 0x4e, 0x3f, 0x7b, 0xf7, 0x65, 0x00, 0x9e, 0xd0, 0x6a, 0xd3, 0x3d, + 0xe0, 0x3e, 0x89, 0x4a, 0x89, 0xf1, 0x00, 0xe6, 0x23, 0x34, 0xb9, 0x06, 0xe2, 0x3b, 0x20, 0xbd, + 0xa7, 0x28, 0xd1, 0xc1, 0xca, 0xb9, 0x9f, 0x1f, 0x97, 0xa6, 0xc8, 0x09, 0x78, 0x3b, 0x0c, 0xd0, + 0x2c, 0xfe, 0x32, 0x1e, 0xab, 0x3a, 0x94, 0x72, 0x5b, 0xf3, 0x41, 0xbf, 0x07, 0x23, 0xac, 0x24, + 0x12, 0x06, 0x55, 0x85, 0xe6, 0x7b, 0x02, 0x07, 0x34, 0xe6, 0xa9, 0xc7, 0x08, 0xfd, 0x51, 0x0e, + 0x7d, 0x13, 0x8d, 0x5d, 0x16, 0x3a, 0x3f, 0x2c, 0x96, 0xa1, 0x56, 0x87, 0xca, 0xa1, 0x0f, 0xa5, + 0x78, 0xac, 0x12, 0x70, 0x8e, 0xfb, 0xa2, 0x8d, 0x5b, 0x07, 0x34, 0xc5, 0x76, 0x65, 0x92, 0x3f, + 0x56, 0x0d, 0x59, 0x84, 0x00, 0x45, 0x33, 0x3e, 0x87, 0xf9, 0x6a, 0x1b, 0x5b, 0x5e, 0xb4, 0x3d, + 0x74, 0x03, 0x46, 0x69, 0x99, 0x6e, 0x6f, 0x66, 0x91, 0x22, 0x6a, 0x6f, 0xc6, 0x2b, 0x8d, 0x4d, + 0xb8, 0xc0, 0x6e, 0x60, 0xea, 0x90, 0x42, 0x7d, 0xc7, 0x30, 0xfd, 0x1d, 0xf1, 0x37, 0x48, 0x18, + 0x3d, 0x83, 0x33, 0x3e, 0xa3, 0x06, 0xad, 0x49, 0xd9, 0xd5, 0xfb, 0xf3, 0x80, 0xf9, 0xff, 0x60, + 0xa9, 0xdc, 0xe9, 0x60, 0xa7, 0x15, 0x22, 0xee, 0x78, 0x56, 0x9f, 0x9e, 0x85, 0xa8, 0x0c, 0xc3, + 0x14, 0x5a, 0x2a, 0x8b, 0x79, 0x77, 0x13, 0xba, 0x43, 0xe1, 0x78, 0x5c, 0x3c, 0xda, 0x00, 0xc3, + 0x34, 0x5a, 0xb0, 0x50, 0xef, 0xee, 0x1f, 0xd9, 0x2c, 0xe5, 0x38, 0xf5, 0xce, 0x15, 0x6d, 0x6f, + 0x88, 0x6c, 0x27, 0x8c, 0x19, 0x37, 0xc3, 0xac, 0xe9, 0xd4, 0xd0, 0x8d, 0x7b, 0xec, 0x3e, 0xbf, + 0x77, 0x3b, 0x44, 0xa5, 0xb7, 0x15, 0xd6, 0x0a, 0xad, 0xe6, 0x19, 0x51, 0x8c, 0x59, 0x38, 0xa7, + 0x2a, 0xde, 0xd8, 0x0a, 0x99, 0x87, 0x59, 0x5d, 0xa1, 0xc6, 0x8a, 0xbf, 0x86, 0x39, 0x76, 0xe1, + 0x67, 0x71, 0x6d, 0x97, 0xc3, 0x10, 0xae, 0xf9, 0xbd, 0xe5, 0x88, 0x79, 0x1c, 0x35, 0xdf, 0x91, + 0x11, 0xcb, 0xf7, 0x96, 0x99, 0x53, 0xc2, 0xf3, 0x65, 0x4d, 0x6d, 0x9b, 0xdf, 0x5b, 0xae, 0x8c, + 0xf2, 0xf8, 0x80, 0x84, 0x3a, 0x9b, 0xfe, 0x6f, 0x84, 0xfa, 0x32, 0xf5, 0x83, 0x5b, 0xc7, 0x16, + 0xb5, 0x59, 0x4d, 0xf6, 0x26, 0x9a, 0x86, 0xbc, 0xdd, 0x12, 0x52, 0xb6, 0xdd, 0x32, 0xfe, 0x38, + 0x07, 0x37, 0x99, 0x2c, 0x92, 0x8c, 0x47, 0xb5, 0x6b, 0x29, 0xc8, 0xe8, 0x03, 0x60, 0x79, 0x74, + 0xb9, 0xc0, 0x67, 0xf0, 0x9e, 0x67, 0x51, 0x62, 0x08, 0xa8, 0x0c, 0x93, 0xaa, 0xc5, 0x67, 0x7f, + 0xa1, 0x60, 0xcc, 0x89, 0xa3, 0xa7, 0x96, 0xb4, 0x02, 0x7d, 0x06, 0x17, 0x57, 0x5f, 0x92, 0x05, + 0xc1, 0x4f, 0x27, 0xfe, 0x62, 0x1c, 0x7a, 0xab, 0xcc, 0xec, 0xf0, 0x15, 0xa3, 0x8b, 0xc1, 0xd1, + 0x62, 0x72, 0x3d, 0x10, 0x07, 0x9c, 0x94, 0x5e, 0xc7, 0x4d, 0xad, 0xcc, 0xf8, 0xd3, 0x1c, 0x2c, + 0x25, 0xb7, 0xc6, 0x37, 0x96, 0x0d, 0x38, 0x57, 0xb5, 0x1c, 0xd7, 0xb1, 0x9b, 0x56, 0xbb, 0xde, + 0x3c, 0xc4, 0xad, 0xae, 0x0c, 0x85, 0x28, 0x77, 0x19, 0x72, 0xdd, 0xe1, 0xe8, 0x02, 0xc4, 0x8c, + 0x63, 0xa1, 0xf7, 0xe1, 0x3c, 0x35, 0x1a, 0x64, 0x7b, 0x6f, 0x1b, 0x7b, 0x92, 0x1e, 0xeb, 0x59, + 0x4a, 0x2d, 0xba, 0x0b, 0xb3, 0xec, 0x50, 0x69, 0xed, 0x3a, 0x76, 0x20, 0x91, 0xd8, 0xad, 0x28, + 0xa9, 0xca, 0xa8, 0xc1, 0x5b, 0x5a, 0x9e, 0x2d, 0x6a, 0x05, 0x8c, 0x5b, 0x35, 0xcf, 0x3d, 0x72, + 0x03, 0x2d, 0xd8, 0x3f, 0xcf, 0x81, 0x18, 0x6a, 0x5c, 0x38, 0x2f, 0x23, 0xc5, 0xc6, 0xff, 0x0b, + 0xd7, 0x7b, 0x50, 0xe4, 0xfc, 0xaa, 0xc3, 0x39, 0x2b, 0x52, 0x27, 0x1e, 0xc6, 0xae, 0x0b, 0x7e, + 0x65, 0x11, 0xf2, 0xcd, 0x38, 0xfe, 0xad, 0x1d, 0x2d, 0x6d, 0x1a, 0x5a, 0x84, 0xb9, 0x9a, 0xb9, + 0xbd, 0xb2, 0x5b, 0xdd, 0x69, 0xec, 0x7c, 0x55, 0x5b, 0x6d, 0xec, 0x6e, 0x3d, 0xda, 0xda, 0x7e, + 0xb2, 0xc5, 0x62, 0x96, 0x6a, 0x35, 0x3b, 0xab, 0xe5, 0xc7, 0x85, 0x1c, 0x9a, 0x83, 0x82, 0x56, + 0xbc, 0xba, 0x5b, 0x29, 0xe4, 0x6f, 0x35, 0x54, 0x8b, 0x5e, 0x74, 0x11, 0x16, 0x56, 0x56, 0xf7, + 0x36, 0xaa, 0xab, 0x82, 0xa6, 0x1a, 0x2f, 0x75, 0x0e, 0x0a, 0x6a, 0xe5, 0xce, 0xf6, 0x4e, 0xad, + 0x90, 0x23, 0xfd, 0x50, 0x4b, 0x9f, 0xac, 0x56, 0xca, 0xbb, 0x3b, 0xeb, 0x5b, 0x85, 0x41, 0x63, + 0x68, 0x2c, 0x5f, 0xc8, 0xdf, 0xfa, 0x91, 0x66, 0xee, 0x8b, 0x96, 0x60, 0x91, 0x83, 0xef, 0xd6, + 0xcb, 0x6b, 0xe9, 0x4d, 0xb0, 0xda, 0xc7, 0x0f, 0xca, 0x85, 0x1c, 0xba, 0x04, 0x17, 0xb4, 0xd2, + 0x5a, 0xb9, 0x5e, 0x7f, 0xb2, 0x6d, 0xae, 0x6c, 0xae, 0xd6, 0xeb, 0x85, 0xfc, 0xad, 0x3d, 0x2d, + 0x30, 0x07, 0x69, 0xe1, 0xf1, 0x83, 0x72, 0xc3, 0x5c, 0xfd, 0x62, 0x77, 0xc3, 0x5c, 0x5d, 0x89, + 0xb7, 0xa0, 0xd5, 0x7e, 0xb5, 0x5a, 0x2f, 0xe4, 0xd0, 0x2c, 0xcc, 0x68, 0xa5, 0x5b, 0xdb, 0x85, + 0xfc, 0xad, 0x1b, 0x3c, 0xec, 0x02, 0x9a, 0x06, 0x58, 0x59, 0xad, 0x57, 0x57, 0xb7, 0x56, 0x36, + 0xb6, 0xd6, 0x0a, 0x03, 0x68, 0x0a, 0xc6, 0xcb, 0xf2, 0x67, 0xee, 0xd6, 0x47, 0x30, 0x13, 0xb9, + 0x31, 0x11, 0x08, 0x79, 0xd9, 0x28, 0x0c, 0x10, 0x1e, 0xc9, 0x9f, 0xf4, 0x9a, 0xcb, 0x2e, 0x3f, + 0x85, 0xdc, 0xf2, 0xff, 0xfc, 0xfd, 0x1c, 0x4c, 0x90, 0xed, 0x40, 0x98, 0x7d, 0x7e, 0xad, 0x5c, + 0x30, 0xf8, 0x67, 0xc0, 0x13, 0x50, 0xa5, 0xde, 0x26, 0xe8, 0xc9, 0x50, 0xcc, 0x50, 0x5c, 0x51, + 0x80, 0x9b, 0xb9, 0xbb, 0x39, 0x64, 0xd2, 0x57, 0x9a, 0x88, 0xbc, 0x2d, 0x29, 0x27, 0x5f, 0x89, + 0x8a, 0x97, 0x32, 0xc5, 0x74, 0xf4, 0xcb, 0x60, 0xa8, 0x34, 0x53, 0xa4, 0xd2, 0xef, 0xf4, 0x27, + 0x7d, 0x8a, 0x36, 0x6f, 0xf4, 0x07, 0x8e, 0x1e, 0xc2, 0x14, 0x91, 0xd7, 0x24, 0x18, 0xba, 0x18, + 0x45, 0x54, 0x44, 0xc4, 0xe2, 0x52, 0x72, 0xa5, 0x8c, 0x7f, 0x3f, 0x49, 0x07, 0xc2, 0x2e, 0x5b, + 0x3e, 0x12, 0xce, 0x79, 0xa2, 0x84, 0xd9, 0xe9, 0x14, 0xcf, 0x45, 0x8a, 0xf7, 0xee, 0xdd, 0xcd, + 0xa1, 0x3a, 0x8d, 0x69, 0xa1, 0x09, 0x7e, 0x48, 0xd8, 0x21, 0xc7, 0x25, 0x42, 0xd6, 0x9b, 0x92, + 0xcc, 0xe8, 0x94, 0x22, 0x31, 0x6e, 0x01, 0x8a, 0xcb, 0x53, 0xe8, 0x4a, 0xb8, 0x0e, 0x92, 0x45, + 0xad, 0xe2, 0xf9, 0xd8, 0xe3, 0xfb, 0x2a, 0x39, 0x51, 0xd1, 0x2a, 0x4c, 0x73, 0xcf, 0x1b, 0x2e, + 0xe1, 0xa1, 0x2c, 0x19, 0x31, 0x95, 0xcc, 0x1a, 0xe5, 0x93, 0x94, 0x12, 0x51, 0x31, 0x1c, 0x47, + 0x54, 0x74, 0x2c, 0x5e, 0x4c, 0xac, 0xe3, 0xe3, 0x7b, 0x00, 0xd3, 0xba, 0xc0, 0x89, 0xc4, 0x04, + 0x25, 0xca, 0xa1, 0xa9, 0x1d, 0x6a, 0xc0, 0xc2, 0x63, 0xcb, 0xa6, 0xea, 0x26, 0xfe, 0xc4, 0x2b, + 0x1e, 0x68, 0x51, 0x29, 0xe3, 0xc5, 0xb6, 0x8e, 0x9d, 0x56, 0xb1, 0x57, 0x0c, 0x28, 0xfa, 0xd9, + 0xd4, 0x85, 0xdc, 0xa4, 0x3f, 0x70, 0x23, 0x43, 0xcf, 0xd2, 0x97, 0x64, 0xb3, 0x50, 0x4c, 0x33, + 0xb3, 0x41, 0x8f, 0xa9, 0xe0, 0x16, 0xa1, 0xa8, 0xac, 0x89, 0x53, 0x93, 0x5b, 0xa4, 0xfe, 0x5f, + 0x81, 0x1d, 0xb5, 0x97, 0xf1, 0x51, 0x0a, 0xe3, 0x52, 0x89, 0xdd, 0xcd, 0xa1, 0xaf, 0xe9, 0x57, + 0x9d, 0x48, 0xee, 0x89, 0x1d, 0x1c, 0x72, 0x9b, 0xb5, 0x8b, 0x89, 0x04, 0xf8, 0x87, 0x92, 0x41, + 0xdd, 0x84, 0xb9, 0x24, 0xcb, 0x1e, 0xc9, 0xd0, 0x0c, 0xb3, 0x9f, 0xd4, 0x55, 0x60, 0x12, 0xf1, + 0xb3, 0x95, 0x3e, 0x49, 0x19, 0x86, 0x25, 0xa9, 0x34, 0x3f, 0x81, 0x69, 0xb2, 0x4a, 0x1e, 0x61, + 0xdc, 0x29, 0xb7, 0xed, 0xe7, 0xd8, 0x47, 0x22, 0x3e, 0x9a, 0x2c, 0x4a, 0xc3, 0xbd, 0x99, 0x43, + 0xdf, 0x82, 0x89, 0x27, 0x56, 0xd0, 0x3c, 0xe4, 0x81, 0x79, 0x44, 0xdc, 0x1e, 0x5a, 0x56, 0x14, + 0xbf, 0x68, 0xe5, 0xdd, 0x1c, 0xfa, 0x14, 0x46, 0xd7, 0x70, 0x40, 0xfd, 0x40, 0xae, 0xca, 0x47, + 0x6e, 0x66, 0x50, 0xb6, 0xe1, 0x48, 0xf3, 0x53, 0xd1, 0xe1, 0xa8, 0x72, 0x0b, 0xdd, 0x01, 0x60, + 0x1b, 0x02, 0xa5, 0x10, 0xad, 0x2e, 0xc6, 0xba, 0x8d, 0xd6, 0xc8, 0xc1, 0xdf, 0xc6, 0x01, 0xee, + 0xb7, 0xc9, 0x34, 0x1e, 0x6d, 0xc2, 0xb4, 0x4c, 0x19, 0xb0, 0x45, 0xbd, 0x30, 0x8d, 0x08, 0x31, + 0xff, 0x14, 0xd4, 0x3e, 0x22, 0x5f, 0x05, 0xcb, 0x29, 0x27, 0x63, 0xc7, 0xa1, 0xb4, 0x68, 0x72, + 0x92, 0x89, 0x0c, 0x4c, 0xc1, 0x5d, 0x77, 0xfd, 0x40, 0xc7, 0x95, 0x25, 0xc9, 0xb8, 0x18, 0x8a, + 0x6a, 0xbb, 0x7a, 0x1c, 0xb9, 0x70, 0xcf, 0x4d, 0x0b, 0x7f, 0x57, 0xbc, 0x9a, 0x01, 0xc1, 0xb6, + 0x3b, 0xba, 0x93, 0xac, 0x90, 0x1b, 0x3d, 0x6b, 0x66, 0xbb, 0x83, 0x9d, 0x7a, 0x7d, 0x9d, 0x06, + 0x04, 0x13, 0x6f, 0x6a, 0x4a, 0x99, 0x20, 0x8c, 0xe2, 0x55, 0xe4, 0xd4, 0xd3, 0x3c, 0xf2, 0x50, + 0x96, 0x9f, 0x5e, 0x78, 0xea, 0x25, 0x86, 0x3c, 0x7b, 0xc4, 0x74, 0x0c, 0x5a, 0x46, 0xda, 0xbd, + 0x65, 0x54, 0x4c, 0x92, 0x53, 0xf9, 0x87, 0x7d, 0x3e, 0xa9, 0x6e, 0xef, 0xfe, 0xdd, 0x1c, 0x5a, + 0x85, 0x59, 0xe9, 0x34, 0x1b, 0x56, 0xa1, 0x14, 0x84, 0x8c, 0x13, 0x66, 0x3e, 0x81, 0xcc, 0xde, + 0x72, 0x06, 0xa1, 0xc4, 0x72, 0xf4, 0x39, 0xcc, 0xf2, 0xb5, 0xa9, 0xf5, 0xa7, 0x20, 0xb7, 0x19, + 0x2e, 0xda, 0xa7, 0xf6, 0xe4, 0x21, 0xcc, 0xd7, 0x23, 0xdc, 0x61, 0x06, 0x5f, 0x17, 0x74, 0x12, + 0xb4, 0xb0, 0x8e, 0x03, 0xc6, 0x9e, 0x64, 0x5a, 0x8f, 0x00, 0x31, 0x7d, 0x80, 0x20, 0xf7, 0xdc, + 0xc6, 0x2f, 0xd0, 0xa5, 0x48, 0xd7, 0x49, 0x21, 0x05, 0xa3, 0xfb, 0x54, 0xea, 0xc8, 0x76, 0x58, + 0xe2, 0x43, 0x96, 0xab, 0xdd, 0xea, 0x58, 0xfb, 0x76, 0xdb, 0x0e, 0x6c, 0x4c, 0x96, 0xaa, 0x8a, + 0xa0, 0x56, 0x89, 0xf5, 0x70, 0x21, 0x15, 0x02, 0xfd, 0x2a, 0x0d, 0x57, 0x95, 0x7d, 0x37, 0x41, + 0xdf, 0x4a, 0xca, 0xce, 0x9d, 0x72, 0xbb, 0x2a, 0x7e, 0xbb, 0x3f, 0x60, 0xbe, 0x18, 0x3f, 0x83, + 0xa9, 0x35, 0x1c, 0xb0, 0xec, 0xea, 0x2b, 0x56, 0x60, 0x21, 0xa9, 0x2f, 0x90, 0x45, 0x7c, 0x0d, + 0x8a, 0x58, 0x13, 0x61, 0x45, 0x1d, 0xff, 0x18, 0x6d, 0x40, 0x81, 0x6d, 0xf3, 0x0a, 0x89, 0x4b, + 0x31, 0x12, 0x1c, 0xc4, 0xf2, 0xac, 0x23, 0x3f, 0x75, 0xb6, 0xee, 0xb0, 0xe7, 0x5d, 0x24, 0x13, + 0x53, 0x2b, 0x72, 0xe4, 0xac, 0x56, 0x26, 0x23, 0x8a, 0x92, 0x19, 0x31, 0xb1, 0x8f, 0x03, 0xe1, + 0x5d, 0xcb, 0x92, 0xbd, 0x5d, 0x0b, 0xcf, 0xf4, 0x78, 0x6d, 0xf8, 0x99, 0x47, 0x22, 0x41, 0xec, + 0xdd, 0x47, 0x32, 0x01, 0x5e, 0x02, 0xd1, 0x1b, 0x9a, 0xe8, 0x71, 0x3a, 0xba, 0x55, 0x18, 0x67, + 0x68, 0x15, 0x37, 0x90, 0xfb, 0xa3, 0x2c, 0x11, 0x98, 0x8b, 0xf1, 0x0a, 0xae, 0x9c, 0x18, 0xfc, + 0x6b, 0xf9, 0x1c, 0x2a, 0xc3, 0x38, 0xfb, 0xb4, 0x54, 0x22, 0xb2, 0xa4, 0xc7, 0x36, 0xcf, 0x48, + 0x7c, 0x06, 0x13, 0x6b, 0x38, 0xa8, 0xb8, 0xd4, 0xb9, 0xd9, 0x97, 0x9f, 0x94, 0x52, 0x26, 0xc8, + 0x4c, 0x29, 0xa3, 0xd8, 0x5b, 0xa6, 0xd8, 0x77, 0x73, 0xe8, 0x5d, 0x7a, 0x64, 0x52, 0xcf, 0xe8, + 0xf9, 0x10, 0x57, 0xc9, 0xf1, 0x9c, 0x84, 0x47, 0xce, 0x74, 0x22, 0x71, 0x77, 0x3d, 0x0f, 0x3b, + 0x0c, 0x39, 0x4d, 0x3c, 0x4a, 0xc2, 0xfe, 0x8c, 0x6e, 0x97, 0x0a, 0x36, 0xb3, 0xb6, 0xef, 0x45, + 0x82, 0x65, 0x8a, 0xb8, 0x9b, 0x43, 0x1f, 0xc0, 0x18, 0xef, 0x23, 0x41, 0xd2, 0x3a, 0xdd, 0x63, + 0xb4, 0x1f, 0x00, 0xb0, 0xa9, 0xa0, 0x7d, 0xd6, 0x61, 0xb2, 0xf9, 0xfc, 0x01, 0x91, 0x0d, 0x5a, + 0xaf, 0x83, 0x59, 0x15, 0x42, 0x02, 0xc5, 0x5c, 0xd4, 0x66, 0x59, 0xe5, 0x73, 0x26, 0x11, 0x22, + 0xe6, 0xd3, 0x90, 0x34, 0x32, 0xb2, 0x84, 0x14, 0xf3, 0xb5, 0xe2, 0x5e, 0xa2, 0xc1, 0x06, 0x14, + 0xca, 0x4d, 0x7a, 0x7a, 0xc9, 0xac, 0xda, 0xf2, 0x8e, 0x15, 0xad, 0x10, 0xb4, 0xe6, 0xa3, 0x49, + 0xba, 0x37, 0xb1, 0x45, 0x23, 0xee, 0x2d, 0x48, 0x49, 0x28, 0x52, 0x95, 0x8c, 0x91, 0x71, 0xa7, + 0x9a, 0xab, 0x92, 0x5b, 0x60, 0xfb, 0xcd, 0xc8, 0x7c, 0x44, 0x37, 0x3e, 0x25, 0xe3, 0xf8, 0xf9, + 0x28, 0xbe, 0xbc, 0x7d, 0x0a, 0x53, 0x5b, 0x09, 0x5a, 0x86, 0x19, 0x1e, 0xdf, 0x4b, 0xb2, 0x25, + 0x0d, 0x3b, 0xad, 0xf9, 0xef, 0xc2, 0xf4, 0x2a, 0x39, 0x98, 0xba, 0x2d, 0x9b, 0x45, 0x19, 0x45, + 0x7a, 0xd8, 0xc8, 0x54, 0xc4, 0x75, 0x91, 0x9c, 0x45, 0x49, 0xc5, 0x2d, 0x3f, 0xe4, 0x78, 0xb6, + 0xf3, 0xe2, 0x9c, 0x20, 0xab, 0x66, 0xed, 0xe6, 0xaa, 0x89, 0x85, 0x94, 0xe4, 0xd7, 0xe8, 0xba, + 0x76, 0xe3, 0x4d, 0xcb, 0x60, 0x9d, 0x20, 0xe3, 0x7e, 0xa9, 0xe4, 0x19, 0x4c, 0xa1, 0x99, 0x9d, + 0x15, 0x3b, 0x75, 0xdc, 0x32, 0x2e, 0x60, 0x62, 0xf6, 0x6a, 0xf4, 0x8e, 0x4e, 0x3d, 0x23, 0xc3, + 0x75, 0x6a, 0x0b, 0x54, 0xa3, 0xa0, 0x27, 0x57, 0x46, 0x97, 0xb3, 0x73, 0x40, 0x2b, 0x1a, 0x85, + 0x94, 0xac, 0xcc, 0x0f, 0xe9, 0x32, 0x0b, 0x93, 0x11, 0x22, 0xf5, 0x7e, 0x1e, 0xcd, 0xc5, 0x28, + 0x05, 0xc7, 0xe4, 0x0c, 0xcb, 0x35, 0x98, 0x89, 0xe4, 0x2e, 0x96, 0x8a, 0xa4, 0xe4, 0xec, 0xc9, + 0xc5, 0xcb, 0x69, 0xd5, 0x52, 0x6d, 0x5a, 0x88, 0x26, 0x7c, 0x95, 0x43, 0x4e, 0x49, 0xb6, 0x2b, + 0x87, 0x9c, 0x9a, 0x29, 0xf6, 0x21, 0x14, 0xa2, 0xb9, 0x26, 0x25, 0xd1, 0x94, 0x24, 0x94, 0xa9, + 0x73, 0xf2, 0x00, 0xe6, 0xd4, 0x19, 0x95, 0xe3, 0x4e, 0xdb, 0xfd, 0xd3, 0xe8, 0xec, 0xc0, 0x7c, + 0x62, 0x6a, 0x48, 0x29, 0x2a, 0x64, 0x25, 0x8e, 0x4c, 0xa5, 0x8a, 0xe1, 0x7c, 0x72, 0x76, 0x58, + 0xf4, 0x96, 0xae, 0xa7, 0x48, 0xce, 0x95, 0x59, 0xbc, 0xde, 0x03, 0x8a, 0x33, 0xf4, 0x6b, 0x7a, + 0x02, 0xc6, 0xda, 0xb8, 0xaa, 0x68, 0x2e, 0x52, 0x1a, 0x30, 0xb2, 0x40, 0xe4, 0x1a, 0x98, 0x4b, + 0xca, 0x4e, 0x9d, 0xca, 0xe2, 0x6b, 0xe9, 0x34, 0xc3, 0x85, 0xb5, 0x27, 0x82, 0xe8, 0xa5, 0x72, + 0x26, 0x33, 0x8b, 0x68, 0xc6, 0xd5, 0xb7, 0x28, 0xd7, 0x43, 0xff, 0x5d, 0x4e, 0x57, 0x63, 0xcd, + 0x25, 0xe5, 0xae, 0x8d, 0x6a, 0x99, 0x92, 0x52, 0x93, 0x4a, 0x36, 0x64, 0x26, 0xbf, 0xdd, 0x63, + 0x1a, 0x27, 0x9d, 0xba, 0xaa, 0x71, 0x4a, 0x24, 0x7d, 0x25, 0x1d, 0x20, 0x5c, 0x11, 0x09, 0x49, + 0xb8, 0xe5, 0x8a, 0x48, 0x4f, 0x07, 0x2e, 0x57, 0x44, 0x56, 0x0e, 0x6f, 0x53, 0x7c, 0x74, 0x29, + 0x6c, 0xc9, 0xc8, 0xd8, 0x9a, 0x71, 0xad, 0x5b, 0x0c, 0x27, 0x2e, 0xd2, 0xed, 0xd3, 0x4e, 0xdb, + 0xd7, 0x70, 0x21, 0x35, 0x3b, 0x2b, 0x7a, 0x3b, 0xf6, 0x41, 0xa7, 0x70, 0x22, 0xbd, 0xa7, 0x53, + 0x5a, 0x62, 0x55, 0xa9, 0x72, 0x8b, 0xe4, 0x70, 0x8d, 0xed, 0xd8, 0x09, 0x09, 0x5e, 0xd7, 0xa8, + 0xe4, 0xab, 0x24, 0x69, 0x4d, 0x1d, 0xeb, 0xa5, 0x24, 0x3a, 0x7e, 0x7c, 0x4f, 0x55, 0xfa, 0x25, + 0x24, 0xb1, 0x68, 0xc5, 0x69, 0xf6, 0xd4, 0x7e, 0xba, 0x96, 0x46, 0x67, 0x85, 0x5e, 0x26, 0x44, + 0xce, 0x56, 0x74, 0x41, 0x63, 0x93, 0x76, 0x4a, 0x16, 0xb5, 0xc1, 0xe9, 0x07, 0x64, 0x95, 0xea, + 0xb6, 0x65, 0x8e, 0xd8, 0xd4, 0x5e, 0x5c, 0x8c, 0xd3, 0xd0, 0xf4, 0xda, 0x92, 0x0b, 0xac, 0x37, + 0x4b, 0x51, 0xe6, 0x68, 0x1d, 0x4a, 0x1f, 0x12, 0x52, 0x59, 0xd3, 0xa3, 0x4b, 0xe9, 0x12, 0xea, + 0x2c, 0xcf, 0x83, 0x47, 0xa3, 0x5c, 0x8b, 0x70, 0x2d, 0xe7, 0xa5, 0x92, 0x4e, 0x29, 0xcd, 0xd0, + 0xc9, 0xd4, 0xa8, 0x39, 0x70, 0x42, 0xba, 0x5b, 0xb9, 0x87, 0x66, 0x66, 0xc3, 0x4d, 0x90, 0xce, + 0xe4, 0xae, 0x9c, 0x4a, 0x31, 0x33, 0xff, 0x6d, 0x6a, 0x4f, 0x7f, 0xa8, 0xec, 0xca, 0xb1, 0xa4, + 0xb6, 0xe8, 0x66, 0x54, 0x34, 0x4b, 0xcb, 0x7b, 0x9b, 0xb1, 0xeb, 0xcf, 0x25, 0xe5, 0xc3, 0x55, + 0x14, 0xcd, 0xa9, 0xc9, 0x72, 0x13, 0xb8, 0x20, 0xb7, 0xb7, 0x14, 0x6a, 0x19, 0xd9, 0x71, 0x53, + 0x7b, 0xf8, 0x7d, 0x65, 0x7b, 0x8b, 0x64, 0xb1, 0x95, 0x8a, 0x83, 0x1e, 0x69, 0x6e, 0x53, 0x69, + 0x6f, 0x51, 0x03, 0xf2, 0x78, 0x0a, 0x5a, 0x29, 0xbb, 0x64, 0x25, 0xa8, 0x4d, 0xd4, 0x43, 0xcf, + 0xc7, 0x87, 0x48, 0xe8, 0x9d, 0x8f, 0x68, 0x91, 0x7b, 0x75, 0x4c, 0xee, 0xc3, 0x09, 0xa9, 0x6b, + 0x23, 0xfb, 0x70, 0x7a, 0x72, 0xdb, 0x8c, 0x8b, 0xce, 0x4c, 0xdd, 0x3e, 0x70, 0x94, 0xcc, 0xb3, + 0xf2, 0x9a, 0x13, 0x4f, 0x86, 0x2b, 0xb7, 0x98, 0xa4, 0x44, 0xb5, 0xdb, 0x44, 0xc2, 0x61, 0xf2, + 0xb9, 0x9a, 0x43, 0x14, 0x15, 0xd3, 0x53, 0xa7, 0xca, 0xed, 0x26, 0x31, 0xe9, 0xa8, 0x42, 0x50, + 0x4d, 0xe0, 0x29, 0x09, 0x26, 0xe4, 0x12, 0x95, 0x04, 0x13, 0x33, 0x7e, 0xde, 0xa1, 0x7a, 0x15, + 0xd3, 0x6d, 0x63, 0x55, 0xaf, 0xa2, 0xa4, 0xb5, 0x8c, 0xa8, 0x35, 0xd0, 0xc7, 0x54, 0xa9, 0x91, + 0xad, 0x09, 0x59, 0xd0, 0x29, 0xa9, 0xe9, 0xb7, 0x21, 0xcc, 0xef, 0x89, 0x74, 0xad, 0x53, 0x46, + 0x9b, 0xef, 0x09, 0xa5, 0x86, 0x86, 0x16, 0xcb, 0xf8, 0x19, 0x45, 0xfb, 0x2e, 0x4c, 0x86, 0xd9, + 0x3d, 0xf7, 0x96, 0x15, 0xc4, 0x48, 0xca, 0xcf, 0x28, 0xe2, 0x07, 0xe2, 0x81, 0x85, 0xb6, 0xa7, + 0x57, 0xf6, 0x52, 0x73, 0x41, 0x98, 0x18, 0x34, 0xa2, 0x44, 0x51, 0x1b, 0x4c, 0xdf, 0x79, 0x27, + 0xd5, 0xc4, 0x42, 0x72, 0x5e, 0x13, 0xf2, 0xb8, 0xc9, 0x79, 0x4d, 0xca, 0x8e, 0x46, 0x7b, 0x43, + 0xef, 0xda, 0x5f, 0x09, 0x8d, 0x41, 0x48, 0xf4, 0x52, 0x66, 0x8e, 0xb3, 0xe2, 0xe5, 0xec, 0xc4, + 0x60, 0x21, 0xe9, 0x3a, 0x14, 0xa2, 0x59, 0x90, 0x50, 0x52, 0x9e, 0x3a, 0x25, 0x5d, 0x95, 0xbc, + 0xc3, 0xa5, 0xa6, 0x4f, 0xaa, 0x09, 0x35, 0xbe, 0x4e, 0x37, 0x25, 0x5b, 0x99, 0x4a, 0x3a, 0x5b, + 0xac, 0x0a, 0x13, 0x22, 0xa9, 0x17, 0xe1, 0x58, 0xc2, 0x25, 0x55, 0xac, 0x4a, 0xc8, 0xa1, 0x64, + 0x8b, 0xf8, 0x0b, 0xc9, 0x19, 0x5d, 0xdf, 0xd1, 0x6f, 0xa8, 0x19, 0x41, 0x2f, 0x7b, 0x3e, 0x46, + 0xa3, 0x5f, 0x82, 0x85, 0x94, 0xd8, 0x80, 0xe8, 0x7a, 0x44, 0x21, 0x9c, 0x1c, 0x3b, 0xb0, 0x98, + 0x95, 0x78, 0x10, 0x3d, 0xa6, 0x56, 0x0c, 0x9a, 0xa7, 0x65, 0xec, 0x65, 0xf0, 0x89, 0x1d, 0x1c, + 0xb2, 0x54, 0x9a, 0xca, 0x9e, 0x99, 0xe8, 0xa2, 0x89, 0xea, 0xf4, 0xbe, 0xa1, 0x95, 0x26, 0x3c, + 0x0e, 0x26, 0x10, 0x2c, 0x26, 0x13, 0xa4, 0x89, 0xd3, 0x6b, 0xe2, 0x89, 0x29, 0xda, 0x4d, 0x75, + 0xf8, 0x49, 0xce, 0xa5, 0xa9, 0xdd, 0xac, 0x09, 0x01, 0x29, 0x99, 0x62, 0xba, 0x47, 0x6c, 0x2a, + 0xc5, 0x87, 0x84, 0x62, 0xcc, 0xc9, 0x15, 0xa5, 0x80, 0x67, 0xef, 0x1e, 0xa6, 0x38, 0x6f, 0x75, + 0xac, 0x65, 0xa5, 0x7f, 0x69, 0xee, 0xb4, 0xa9, 0xfd, 0x5b, 0x15, 0xdf, 0x53, 0x72, 0xff, 0xfa, + 0x3d, 0x71, 0xe5, 0x33, 0x5d, 0xc4, 0xcf, 0x5a, 0x1b, 0xa8, 0x52, 0x5e, 0x4c, 0x29, 0x47, 0x5b, + 0xd4, 0x2c, 0x29, 0x5a, 0xaa, 0x5c, 0x3c, 0x93, 0x1d, 0xb9, 0x53, 0xe9, 0xb1, 0x75, 0xac, 0x39, + 0xc2, 0x9e, 0x66, 0x1d, 0x47, 0x3c, 0x68, 0xf9, 0x3a, 0xd6, 0x4a, 0x4f, 0xb7, 0x8e, 0x23, 0x04, + 0xf5, 0x75, 0x1c, 0xed, 0x66, 0xf4, 0x22, 0x9f, 0x3a, 0xab, 0xd1, 0x6e, 0xca, 0x75, 0x9c, 0x4c, + 0x31, 0xdd, 0x61, 0x39, 0x95, 0xa2, 0x5c, 0xc7, 0x3a, 0xc5, 0x14, 0xf0, 0x3e, 0xd7, 0x71, 0xb4, + 0x11, 0x7d, 0x1d, 0x9f, 0xaa, 0x7f, 0x72, 0x1d, 0x27, 0xf7, 0xef, 0xd4, 0xeb, 0x38, 0xe2, 0xe1, + 0xaf, 0x0d, 0x34, 0x69, 0x1d, 0x47, 0xe1, 0xd9, 0x3a, 0x8e, 0x96, 0x46, 0x14, 0x28, 0x19, 0xeb, + 0x38, 0x8a, 0xf9, 0x05, 0xa5, 0x17, 0xf1, 0x4e, 0xee, 0x67, 0x25, 0xa7, 0x3a, 0x36, 0xa3, 0x27, + 0x54, 0x7b, 0x17, 0x29, 0xef, 0x6f, 0x35, 0x2f, 0xa5, 0x11, 0xa5, 0xeb, 0x79, 0x4f, 0x30, 0x31, + 0xda, 0x5d, 0x5d, 0x35, 0x95, 0xec, 0x9c, 0x9d, 0xd1, 0xe1, 0x3d, 0xb2, 0x6e, 0x5a, 0x19, 0x74, + 0xb3, 0x7c, 0xcb, 0x33, 0xe8, 0xca, 0x7b, 0x4c, 0x94, 0x6e, 0x2a, 0x4a, 0xf6, 0xfa, 0xfe, 0x52, + 0xbc, 0x5f, 0x44, 0xf1, 0x96, 0x23, 0x37, 0xa3, 0x53, 0xf7, 0x54, 0xde, 0x90, 0xa2, 0x3d, 0x3d, + 0xed, 0x3a, 0x7f, 0x2c, 0xa4, 0x87, 0x58, 0x50, 0x8a, 0xc8, 0xa0, 0xd5, 0xb5, 0x9e, 0x5a, 0x83, + 0x76, 0xa8, 0xaa, 0x36, 0x5e, 0xae, 0xa8, 0x79, 0xd3, 0xa2, 0x5f, 0xf4, 0xa4, 0x1a, 0x73, 0xaf, + 0x57, 0xa9, 0xa6, 0xf9, 0xde, 0x4b, 0xaa, 0x71, 0xec, 0xcf, 0xa9, 0xea, 0x8b, 0xfb, 0x03, 0x39, + 0x4f, 0xdd, 0xf4, 0x7b, 0xca, 0xac, 0x66, 0x3a, 0x45, 0x60, 0xa9, 0xc5, 0xda, 0x27, 0xfc, 0x81, + 0x4e, 0x14, 0xa6, 0x32, 0x3f, 0x09, 0x1f, 0x7d, 0x0e, 0x05, 0xbe, 0xbd, 0x85, 0x04, 0x92, 0x00, + 0x53, 0xa7, 0xae, 0x22, 0x34, 0x6e, 0x7d, 0xf4, 0xa0, 0x1f, 0x4d, 0x5b, 0x3f, 0x9c, 0x48, 0x57, + 0x4b, 0x91, 0xe3, 0x70, 0xc7, 0xeb, 0xfa, 0x01, 0x6e, 0xc5, 0xd5, 0x49, 0x7a, 0x67, 0x84, 0x01, + 0x87, 0x0e, 0xbe, 0xb7, 0x8c, 0x36, 0xe8, 0xde, 0xa6, 0x17, 0x67, 0xe9, 0xdb, 0x92, 0xc9, 0xd0, + 0xad, 0x67, 0x5d, 0x3a, 0x9e, 0xe8, 0x7d, 0x4a, 0x6b, 0x3b, 0xbd, 0x53, 0x92, 0x45, 0x7d, 0x8e, + 0x2e, 0x8d, 0x45, 0xec, 0x42, 0xcc, 0x74, 0x7f, 0xbd, 0x38, 0x13, 0x75, 0x85, 0x41, 0xdf, 0x83, + 0x71, 0x81, 0xdc, 0x9b, 0x21, 0x51, 0x6c, 0xca, 0x90, 0x15, 0x98, 0xd2, 0xfc, 0x7c, 0xe4, 0xed, + 0x26, 0xc9, 0xfb, 0x27, 0x63, 0x9e, 0xa7, 0x34, 0x7f, 0x1e, 0x49, 0x25, 0xc9, 0xcb, 0x27, 0x95, + 0xca, 0xa7, 0x30, 0xc1, 0x59, 0x9a, 0xc9, 0x8d, 0x74, 0x65, 0xdb, 0xbc, 0x62, 0x1f, 0xdd, 0x6d, + 0xd9, 0x41, 0xd5, 0x75, 0x9e, 0xda, 0x07, 0x3d, 0x19, 0x13, 0x47, 0xd9, 0x5b, 0x46, 0x7b, 0x34, + 0x5f, 0x9c, 0xc8, 0xe2, 0x87, 0x83, 0x17, 0xae, 0xf7, 0xcc, 0x76, 0x0e, 0x7a, 0x90, 0xbc, 0xa2, + 0x93, 0x8c, 0xe2, 0x31, 0xba, 0xf5, 0x74, 0xba, 0x3d, 0xf1, 0x33, 0x94, 0x6d, 0x4b, 0xd4, 0xb4, + 0xe7, 0xb4, 0x3d, 0x4e, 0x7f, 0x78, 0xbc, 0x10, 0x5a, 0x16, 0x9b, 0xb8, 0xe9, 0x7a, 0xad, 0xde, + 0xc4, 0x4a, 0xba, 0x1d, 0x6f, 0x04, 0x6d, 0x6f, 0x99, 0x50, 0xad, 0xa7, 0x52, 0xed, 0x85, 0x9d, + 0x71, 0x5a, 0x5d, 0xa4, 0x63, 0x3f, 0x65, 0x6f, 0xb3, 0x77, 0x2d, 0x72, 0xd2, 0xd4, 0x3c, 0xfc, + 0x14, 0x7b, 0xd4, 0x3c, 0xbc, 0x97, 0x61, 0xb4, 0x0e, 0xbe, 0xb7, 0x4c, 0xa8, 0xd4, 0x63, 0x54, + 0xd2, 0xa0, 0xb3, 0x54, 0xf2, 0x74, 0x68, 0x7d, 0xf6, 0x26, 0x8d, 0xcc, 0x07, 0xf4, 0xc9, 0x63, + 0x77, 0xa3, 0x07, 0x47, 0x84, 0xc3, 0x82, 0x00, 0xdc, 0xbb, 0x47, 0x30, 0xeb, 0x0a, 0x66, 0x1c, + 0x22, 0xb5, 0xcd, 0xef, 0x89, 0xb7, 0x8d, 0x9e, 0xcd, 0xa6, 0x51, 0xb8, 0x4f, 0xb7, 0x37, 0x6e, + 0x13, 0xad, 0x68, 0x05, 0xb5, 0x4c, 0xad, 0xc5, 0x29, 0xd5, 0x3c, 0xda, 0x47, 0x65, 0x76, 0xa3, + 0x53, 0x73, 0xba, 0x2a, 0xd6, 0x10, 0x89, 0xc9, 0x5e, 0xa3, 0x24, 0x98, 0x56, 0x73, 0xd3, 0x6d, + 0x3e, 0x53, 0xb5, 0x9a, 0x4a, 0x92, 0xd0, 0xa2, 0x9e, 0xc2, 0x93, 0x6f, 0xe2, 0x34, 0x8f, 0xa7, + 0x6a, 0xaa, 0xa5, 0xa6, 0x09, 0x55, 0xb5, 0x9a, 0x7a, 0x42, 0xd3, 0xfb, 0x42, 0x5d, 0x48, 0x1b, + 0xd4, 0x29, 0xa7, 0xb2, 0x46, 0x6a, 0x0a, 0x29, 0x92, 0xae, 0x29, 0x54, 0x3b, 0x9a, 0xbe, 0x5d, + 0xa0, 0x78, 0x46, 0x53, 0x79, 0xff, 0x48, 0x4d, 0x76, 0x9a, 0x61, 0x71, 0x35, 0x9b, 0x90, 0xba, + 0x59, 0xde, 0xd8, 0xd2, 0xd3, 0x3a, 0x17, 0x75, 0xf3, 0xa1, 0xbb, 0x39, 0xb4, 0x05, 0xe7, 0xd7, + 0x70, 0xc0, 0x37, 0x30, 0x13, 0xfb, 0x81, 0x67, 0x37, 0x83, 0xcc, 0x87, 0x3e, 0x71, 0xdd, 0x48, + 0xc0, 0xd9, 0x7b, 0x97, 0xd0, 0xab, 0x27, 0xd3, 0xcb, 0xc4, 0xcb, 0x30, 0xce, 0xe5, 0xaf, 0x07, + 0xa7, 0xe9, 0x62, 0xfa, 0x12, 0x1f, 0x65, 0x36, 0x33, 0xe9, 0xa8, 0x85, 0x30, 0xca, 0x3e, 0xbf, + 0x40, 0xdd, 0x86, 0x11, 0x86, 0x94, 0x7a, 0x46, 0x4e, 0xaa, 0x38, 0xe8, 0x9e, 0xb0, 0xe2, 0x24, + 0x28, 0x5a, 0x55, 0x6a, 0xbf, 0xee, 0xc1, 0x38, 0xbb, 0x2d, 0xf5, 0x8f, 0xf2, 0xb1, 0x30, 0xf3, + 0xcc, 0xea, 0x58, 0x1a, 0xf2, 0xe7, 0x30, 0xa5, 0xda, 0xcb, 0x9c, 0x9e, 0x91, 0x9f, 0xd2, 0xe7, + 0x58, 0xf1, 0xea, 0x91, 0x8e, 0x3f, 0x1f, 0xc9, 0xbc, 0xc0, 0x59, 0xca, 0x36, 0x48, 0x99, 0x03, + 0x3d, 0xad, 0xfb, 0xe7, 0x62, 0xd8, 0xe8, 0x63, 0xe1, 0x2a, 0x25, 0x91, 0xe3, 0x40, 0x19, 0x3c, + 0x9b, 0x66, 0x6c, 0x7e, 0x1d, 0x64, 0xb9, 0xc1, 0xf6, 0xec, 0x76, 0x3f, 0xcf, 0xc6, 0xbd, 0x59, + 0x97, 0x46, 0x65, 0x9b, 0x0a, 0x5e, 0xb1, 0x9c, 0x20, 0xe9, 0x84, 0x2e, 0xa7, 0xa7, 0x11, 0xa1, + 0x93, 0xf1, 0x90, 0x5e, 0xec, 0xe2, 0xf9, 0xec, 0xd3, 0x86, 0x97, 0x91, 0x96, 0x24, 0xbc, 0xc9, + 0xc6, 0xc9, 0x65, 0xa0, 0x65, 0x5d, 0x8c, 0xb9, 0xf3, 0xe6, 0x99, 0x90, 0xdb, 0x10, 0x66, 0x87, + 0xfd, 0x0f, 0x36, 0x43, 0x08, 0x4a, 0x78, 0xa8, 0xee, 0x39, 0x17, 0x69, 0xe4, 0x7e, 0x89, 0xca, + 0x7f, 0xc9, 0xe9, 0xa8, 0x53, 0x89, 0xdd, 0x54, 0x6c, 0x1d, 0xb2, 0x13, 0x59, 0x3f, 0xa3, 0x3e, + 0x68, 0xc9, 0x59, 0x53, 0x6e, 0xf4, 0xa0, 0x22, 0x38, 0xf1, 0x76, 0x4f, 0x38, 0xf9, 0xec, 0x79, + 0x91, 0x9d, 0xb0, 0xc9, 0xed, 0xf5, 0xc8, 0x02, 0x93, 0xf0, 0x12, 0x9d, 0x92, 0xeb, 0x59, 0x10, + 0xd4, 0x6d, 0x3a, 0x33, 0xc7, 0x90, 0xc6, 0xfe, 0x2f, 0xa0, 0x14, 0x1a, 0x74, 0x9c, 0x6e, 0x12, + 0xd2, 0x25, 0x7a, 0x14, 0xcf, 0x80, 0x8d, 0xb2, 0x02, 0xd5, 0x17, 0xaf, 0xa6, 0x71, 0xd8, 0x57, + 0x2c, 0x85, 0xb8, 0x29, 0x5a, 0x24, 0x7f, 0x50, 0x5a, 0x26, 0xa2, 0x0c, 0xd5, 0x2a, 0x77, 0xca, + 0x3b, 0x13, 0x42, 0xf1, 0xd9, 0x3e, 0x3d, 0x21, 0x69, 0x6f, 0x11, 0x21, 0x64, 0x64, 0x4c, 0xef, + 0x69, 0xcc, 0xc9, 0xa2, 0x53, 0x71, 0xda, 0x09, 0xb5, 0x42, 0x47, 0xb4, 0x78, 0x9a, 0x6e, 0x29, + 0xcb, 0xa5, 0xa6, 0x0c, 0x97, 0xb3, 0x9b, 0x91, 0xe3, 0xbb, 0x4a, 0x3e, 0x53, 0xd6, 0x84, 0x96, + 0x23, 0xb8, 0x6a, 0x6e, 0x86, 0x9a, 0x82, 0x84, 0xe4, 0xc1, 0x45, 0x10, 0x95, 0xe6, 0x26, 0xaa, + 0x8b, 0x28, 0xab, 0x49, 0x21, 0x51, 0xa4, 0xd3, 0x4d, 0x52, 0x65, 0xc6, 0xed, 0xa2, 0x2e, 0xe2, + 0xaa, 0x9e, 0x25, 0xd1, 0x06, 0x2c, 0xa4, 0x04, 0x92, 0x91, 0x8f, 0xa6, 0xd9, 0x81, 0x66, 0x8a, + 0xd9, 0x0d, 0xa3, 0x1f, 0xc0, 0x7c, 0x62, 0xa4, 0x19, 0xa9, 0xf8, 0xcd, 0x8a, 0x43, 0xd3, 0x8b, + 0xf8, 0x33, 0x58, 0x4c, 0x4b, 0xe8, 0x1b, 0x3a, 0x01, 0x65, 0x67, 0x59, 0x96, 0x7b, 0x6a, 0xcf, + 0xcc, 0xc0, 0x5b, 0x30, 0x97, 0x94, 0x24, 0x57, 0x7e, 0x1c, 0x19, 0x19, 0x74, 0x13, 0x3d, 0x8d, + 0x6a, 0x30, 0x9f, 0x98, 0xa8, 0x56, 0x72, 0x26, 0x2b, 0x8d, 0x6d, 0x22, 0xc5, 0x2f, 0x61, 0x21, + 0x25, 0x2b, 0x6b, 0xf8, 0x02, 0x9e, 0x99, 0xb5, 0x35, 0xc3, 0x7e, 0xa8, 0x98, 0x9e, 0xf0, 0x53, + 0x9a, 0x8d, 0xf5, 0xcc, 0x09, 0x5a, 0x4c, 0xcc, 0x82, 0x8c, 0x76, 0xe8, 0x22, 0x4c, 0xca, 0x00, + 0xaa, 0x2e, 0xc2, 0x8c, 0x0c, 0xa1, 0x29, 0x1e, 0x62, 0x0b, 0x29, 0x49, 0x3f, 0x33, 0xa8, 0xf6, + 0xd1, 0xdb, 0x2d, 0xb1, 0xff, 0xeb, 0xa9, 0x11, 0x23, 0xa6, 0xc8, 0x89, 0x79, 0x13, 0x13, 0xfb, + 0xa9, 0x84, 0x56, 0x68, 0xb7, 0x33, 0xc4, 0x20, 0xa4, 0xc6, 0x56, 0x20, 0x90, 0x54, 0x77, 0x3e, + 0xa5, 0xe2, 0x66, 0xed, 0xa8, 0x31, 0x64, 0x2a, 0x78, 0x7e, 0x04, 0x93, 0x75, 0xb5, 0xf1, 0x84, + 0x46, 0x52, 0x17, 0x85, 0xf4, 0xad, 0xe9, 0xdd, 0xf7, 0x0c, 0x65, 0x8f, 0x3c, 0x1c, 0xfa, 0x1a, + 0x45, 0xaa, 0xc5, 0x8a, 0x96, 0xbd, 0x44, 0xee, 0xd4, 0x49, 0x89, 0x81, 0xa4, 0xc5, 0x4a, 0x72, + 0xc2, 0x93, 0x06, 0x8b, 0xb7, 0x1e, 0xcd, 0xfb, 0x84, 0x8c, 0xde, 0xf9, 0xcc, 0xa4, 0xa5, 0x79, + 0x66, 0xe2, 0x28, 0x66, 0x5e, 0x13, 0xe6, 0x6b, 0x51, 0xcd, 0x6b, 0x62, 0x59, 0x60, 0x54, 0xf3, + 0x9a, 0x84, 0x14, 0x2f, 0xab, 0x94, 0x56, 0x18, 0xa8, 0x3e, 0x43, 0x61, 0x20, 0xc9, 0x24, 0xc4, + 0xc3, 0x7f, 0xa4, 0x46, 0xe8, 0x60, 0xe1, 0xed, 0x33, 0x34, 0x9e, 0xd1, 0xc8, 0x1c, 0x91, 0x78, + 0xf8, 0x0f, 0xa1, 0x10, 0x0d, 0xed, 0x25, 0xd5, 0x51, 0x29, 0x31, 0xbf, 0x32, 0x96, 0x18, 0x84, + 0x01, 0xbc, 0xa4, 0xd2, 0x27, 0x16, 0xd3, 0xab, 0x78, 0x21, 0xa1, 0x46, 0x8a, 0x6b, 0x93, 0x6a, + 0xb8, 0x2f, 0x69, 0x21, 0x96, 0x10, 0x03, 0xac, 0x78, 0x31, 0xb1, 0x8e, 0x13, 0x0a, 0x58, 0x2a, + 0xbe, 0xe4, 0x44, 0x7e, 0xa1, 0x5b, 0x53, 0x06, 0x8c, 0x68, 0xe6, 0x56, 0x3f, 0xa0, 0xbc, 0x55, + 0x2c, 0xc3, 0xeb, 0xc7, 0xa1, 0xd0, 0xdb, 0x09, 0xee, 0x07, 0x1a, 0x44, 0x68, 0x3c, 0x15, 0x3e, + 0xa2, 0x27, 0x25, 0x2b, 0x44, 0x4f, 0x44, 0xb8, 0xf3, 0x94, 0x96, 0x7a, 0x11, 0x48, 0x9d, 0xc1, + 0x27, 0x22, 0xc0, 0xf9, 0x59, 0x13, 0xde, 0x87, 0xa5, 0x88, 0x77, 0x83, 0x4e, 0xf8, 0x56, 0xb2, + 0x0b, 0x44, 0x22, 0x7b, 0xd2, 0xe5, 0xe1, 0x2b, 0x71, 0x57, 0x88, 0xc8, 0xbc, 0x9f, 0x76, 0xaf, + 0x7a, 0x0c, 0xd3, 0x74, 0x7b, 0x10, 0xe9, 0x27, 0xc3, 0xc0, 0x2e, 0x7a, 0x71, 0x34, 0xc2, 0x50, + 0xb4, 0x56, 0x7a, 0x85, 0x4f, 0x72, 0x17, 0x59, 0x96, 0xcc, 0xb2, 0xa8, 0xfb, 0xcd, 0xd2, 0xc2, + 0xa4, 0xd3, 0x87, 0xe7, 0xc8, 0x44, 0x9f, 0xc2, 0x4c, 0xe8, 0x39, 0xcb, 0x48, 0x24, 0x80, 0x65, + 0x28, 0xa1, 0x66, 0x42, 0xf7, 0xd9, 0xd3, 0xa3, 0xaf, 0x8b, 0x23, 0x24, 0x44, 0xbf, 0x14, 0xf3, + 0x0a, 0xd1, 0xc6, 0xd0, 0xcf, 0x49, 0xa2, 0xf0, 0xf6, 0xb4, 0xb3, 0xd3, 0xa4, 0x9f, 0x5b, 0x72, + 0x1c, 0x3b, 0xf5, 0x73, 0xcb, 0x8c, 0xb5, 0x27, 0xc5, 0xd6, 0x14, 0x3a, 0x8f, 0xe1, 0x1a, 0x8d, + 0x73, 0x52, 0xc3, 0x4e, 0xcb, 0x76, 0x0e, 0x92, 0xa1, 0xd2, 0xfb, 0x1e, 0x8d, 0x8e, 0xd2, 0x86, + 0xab, 0x3d, 0x03, 0xf9, 0xa1, 0x3b, 0x9a, 0x45, 0x48, 0xef, 0x90, 0x7f, 0x59, 0x9e, 0x58, 0x49, + 0xf1, 0xf0, 0xe4, 0xf9, 0x98, 0x11, 0x9a, 0x4f, 0x9e, 0x8f, 0x99, 0x01, 0xf5, 0xbe, 0xa4, 0x39, + 0x04, 0xf8, 0xd9, 0x42, 0x63, 0x17, 0x61, 0x87, 0x45, 0xf8, 0xcd, 0x7c, 0x52, 0xb9, 0xaa, 0x3f, + 0x24, 0xc6, 0x10, 0xe9, 0x5d, 0xe4, 0x32, 0xbf, 0x41, 0xa5, 0x11, 0xef, 0x4d, 0x24, 0xc3, 0x12, + 0xf9, 0x32, 0x5b, 0x80, 0xa7, 0xee, 0x79, 0x4a, 0x79, 0x65, 0xe5, 0xa7, 0x7f, 0x71, 0x39, 0xf7, + 0xd3, 0x9f, 0x5d, 0xce, 0xfd, 0xdb, 0x9f, 0x5d, 0xce, 0xfd, 0x87, 0x9f, 0x5d, 0xce, 0x7d, 0x7f, + 0xb9, 0xbf, 0x38, 0xb3, 0xcd, 0xb6, 0x8d, 0x9d, 0xe0, 0x0e, 0x23, 0x37, 0x42, 0xff, 0xbb, 0xff, + 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x10, 0xd3, 0x86, 0x95, 0xdf, 0xdc, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -31035,6 +31084,21 @@ func (m *MFAAuthenticateChallenge) MarshalToSizedBuffer(dAtA []byte) (int, error i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.AllowReuse { + i-- + if m.AllowReuse { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if m.Scope != 0 { + i = encodeVarintAuthservice(dAtA, i, uint64(m.Scope)) + i-- + dAtA[i] = 0x28 + } if m.MFARequired != 0 { i = encodeVarintAuthservice(dAtA, i, uint64(m.MFARequired)) i-- @@ -34384,6 +34448,21 @@ func (m *CreateAuthenticateChallengeRequest) MarshalToSizedBuffer(dAtA []byte) ( i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.AllowReuse { + i-- + if m.AllowReuse { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } + if m.Scope != 0 { + i = encodeVarintAuthservice(dAtA, i, uint64(m.Scope)) + i-- + dAtA[i] = 0x30 + } if m.MFARequiredCheck != nil { { size, err := m.MFARequiredCheck.MarshalToSizedBuffer(dAtA[:i]) @@ -40037,6 +40116,12 @@ func (m *MFAAuthenticateChallenge) Size() (n int) { if m.MFARequired != 0 { n += 1 + sovAuthservice(uint64(m.MFARequired)) } + if m.Scope != 0 { + n += 1 + sovAuthservice(uint64(m.Scope)) + } + if m.AllowReuse { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -41637,6 +41722,12 @@ func (m *CreateAuthenticateChallengeRequest) Size() (n int) { l = m.MFARequiredCheck.Size() n += 1 + l + sovAuthservice(uint64(l)) } + if m.Scope != 0 { + n += 1 + sovAuthservice(uint64(m.Scope)) + } + if m.AllowReuse { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -54695,6 +54786,45 @@ func (m *MFAAuthenticateChallenge) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Scope", wireType) + } + m.Scope = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Scope |= webauthn.ChallengeScope(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowReuse", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowReuse = bool(v != 0) default: iNdEx = preIndex skippy, err := skipAuthservice(dAtA[iNdEx:]) @@ -62389,6 +62519,45 @@ func (m *CreateAuthenticateChallengeRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Scope", wireType) + } + m.Scope = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Scope |= webauthn.ChallengeScope(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowReuse", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowReuse = bool(v != 0) default: iNdEx = preIndex skippy, err := skipAuthservice(dAtA[iNdEx:]) diff --git a/api/proto/teleport/legacy/client/proto/authservice.proto b/api/proto/teleport/legacy/client/proto/authservice.proto index 02a394c658b71..85e578ff6d199 100644 --- a/api/proto/teleport/legacy/client/proto/authservice.proto +++ b/api/proto/teleport/legacy/client/proto/authservice.proto @@ -1147,6 +1147,15 @@ message MFAAuthenticateChallenge { // communications, in case of streaming RPCs. It may also return empty // challenges for all other fields. MFARequired MFARequired = 4; + // Scope is an authorization scope for this MFA challenge. + // Required. Only applies to webauthn challenges. + webauthn.ChallengeScope Scope = 5 [(gogoproto.jsontag) = "scope,omitempty"]; + // AllowReuse means webauthn credentials resolved from this challenge can be + // reused for a short span of time before the challenge expires. + // + // Reuse is only permitted for specific actions by the discretion of the server. + // See the server implementation for details. + bool AllowReuse = 6 [(gogoproto.jsontag) = "allow_reuse,omitempty"]; } // MFAAuthenticateResponse is a response to MFAAuthenticateChallenge using one @@ -1841,6 +1850,15 @@ message CreateAuthenticateChallengeRequest { // If you are issuing challenges from the root cluster, but accessing a leaf, // call [AuthService.IsMFARequired] in the leaf instead of setting this field. IsMFARequiredRequest MFARequiredCheck = 5 [(gogoproto.jsontag) = "mfa_required_check,omitempty"]; + // Scope is an authorization scope for this MFA challenge. + // Required. Only applies to webauthn challenges. + webauthn.ChallengeScope Scope = 6 [(gogoproto.jsontag) = "scope,omitempty"]; + // AllowReuse means webauthn credentials resolved from this challenge can be + // reused for a short span of time before the challenge expires. + // + // Reuse is only permitted for specific actions by the discretion of the server. + // See the server implementation for details. + bool AllowReuse = 7 [(gogoproto.jsontag) = "allow_reuse,omitempty"]; } // CreatePrivilegeTokenRequest defines a request to obtain a privilege token. diff --git a/api/proto/teleport/legacy/types/webauthn/webauthn.proto b/api/proto/teleport/legacy/types/webauthn/webauthn.proto index 8b3f0c4a8dfe0..d7b256627c7cd 100644 --- a/api/proto/teleport/legacy/types/webauthn/webauthn.proto +++ b/api/proto/teleport/legacy/types/webauthn/webauthn.proto @@ -56,6 +56,36 @@ message SessionData { // "required". // An empty value is treated equivalently to "discouraged". string user_verification = 5 [(gogoproto.jsontag) = "userVerification,omitempty"]; + // Scope authorized by this webauthn session. + ChallengeScope scope = 6 [(gogoproto.jsontag) = "scope,omitempty"]; + // AllowReuse indicates that this session can be used multiple times for + // authentication, until the session expires. + bool allow_reuse = 7 [(gogoproto.jsontag) = "allow_reuse,omitempty"]; +} + +// ChallengeScope is a scope authorized by a webauthn challenge's resolution. +enum ChallengeScope { + // Invalid, scope should always be specified. + CHALLENGE_SCOPE_UNSPECIFIED = 0; + // Standard webauthn login. + CHALLENGE_SCOPE_LOGIN = 1; + // Passwordless webauthn login. + CHALLENGE_SCOPE_PASSWORDLESS_LOGIN = 2; + // MFA device management. + CHALLENGE_SCOPE_MANAGE_DEVICES = 3; + // Account recovery. + CHALLENGE_SCOPE_RECOVERY = 4; + // Used for per-session MFA and moderated session presence checks. + CHALLENGE_SCOPE_SESSION = 5; + // Headless login approval. + CHALLENGE_SCOPE_HEADLESS = 6; + // Used for various administrative actions, such as adding, updating, or + // deleting administrative resources (users, roles, etc.). + // + // Note: this scope should not be used for new MFA capabilities that have + // more precise scope. Instead, new scopes should be added. This scope may + // also be split into multiple smaller scopes in the future. + CHALLENGE_SCOPE_ADMIN_ACTION = 7; } // User represents a WebAuthn user. diff --git a/api/types/webauthn/webauthn.pb.go b/api/types/webauthn/webauthn.pb.go index 35fdb48a7605a..2a889271c0cb8 100644 --- a/api/types/webauthn/webauthn.pb.go +++ b/api/types/webauthn/webauthn.pb.go @@ -39,6 +39,63 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// ChallengeScope is a scope authorized by a webauthn challenge's resolution. +type ChallengeScope int32 + +const ( + // Invalid, scope should always be specified. + ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED ChallengeScope = 0 + // Standard webauthn login. + ChallengeScope_CHALLENGE_SCOPE_LOGIN ChallengeScope = 1 + // Passwordless webauthn login. + ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN ChallengeScope = 2 + // MFA device management. + ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES ChallengeScope = 3 + // Account recovery. + ChallengeScope_CHALLENGE_SCOPE_RECOVERY ChallengeScope = 4 + // Used for per-session MFA and moderated session presence checks. + ChallengeScope_CHALLENGE_SCOPE_SESSION ChallengeScope = 5 + // Headless login approval. + ChallengeScope_CHALLENGE_SCOPE_HEADLESS ChallengeScope = 6 + // Used for various administrative actions, such as adding, updating, or + // deleting administrative resources (users, roles, etc.). + // + // Note: this scope should not be used for new MFA capabilities that have + // more precise scope. Instead, new scopes should be added. This scope may + // also be split into multiple smaller scopes in the future. + ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION ChallengeScope = 7 +) + +var ChallengeScope_name = map[int32]string{ + 0: "CHALLENGE_SCOPE_UNSPECIFIED", + 1: "CHALLENGE_SCOPE_LOGIN", + 2: "CHALLENGE_SCOPE_PASSWORDLESS_LOGIN", + 3: "CHALLENGE_SCOPE_MANAGE_DEVICES", + 4: "CHALLENGE_SCOPE_RECOVERY", + 5: "CHALLENGE_SCOPE_SESSION", + 6: "CHALLENGE_SCOPE_HEADLESS", + 7: "CHALLENGE_SCOPE_ADMIN_ACTION", +} + +var ChallengeScope_value = map[string]int32{ + "CHALLENGE_SCOPE_UNSPECIFIED": 0, + "CHALLENGE_SCOPE_LOGIN": 1, + "CHALLENGE_SCOPE_PASSWORDLESS_LOGIN": 2, + "CHALLENGE_SCOPE_MANAGE_DEVICES": 3, + "CHALLENGE_SCOPE_RECOVERY": 4, + "CHALLENGE_SCOPE_SESSION": 5, + "CHALLENGE_SCOPE_HEADLESS": 6, + "CHALLENGE_SCOPE_ADMIN_ACTION": 7, +} + +func (x ChallengeScope) String() string { + return proto.EnumName(ChallengeScope_name, int32(x)) +} + +func (ChallengeScope) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0d490a6db28e8798, []int{0} +} + // SessionData stored by the Relying Party during authentication ceremonies. // Mirrors https://pkg.go.dev/github.com/go-webauthn/webauthn/webauthn#SessionData. type SessionData struct { @@ -53,7 +110,12 @@ type SessionData struct { // Requested user verification requirement, either "discouraged" or // "required". // An empty value is treated equivalently to "discouraged". - UserVerification string `protobuf:"bytes,5,opt,name=user_verification,json=userVerification,proto3" json:"userVerification,omitempty"` + UserVerification string `protobuf:"bytes,5,opt,name=user_verification,json=userVerification,proto3" json:"userVerification,omitempty"` + // Scope authorized by this webauthn session. + Scope ChallengeScope `protobuf:"varint,6,opt,name=scope,proto3,enum=webauthn.ChallengeScope" json:"scope,omitempty"` + // AllowReuse indicates that this session can be used multiple times for + // authentication, until the session expires. + AllowReuse bool `protobuf:"varint,7,opt,name=allow_reuse,json=allowReuse,proto3" json:"allow_reuse,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -127,6 +189,20 @@ func (m *SessionData) GetUserVerification() string { return "" } +func (m *SessionData) GetScope() ChallengeScope { + if m != nil { + return m.Scope + } + return ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED +} + +func (m *SessionData) GetAllowReuse() bool { + if m != nil { + return m.AllowReuse + } + return false +} + // User represents a WebAuthn user. // Used mainly to correlated a WebAuthn user handle with a Teleport user. type User struct { @@ -1220,6 +1296,7 @@ func (m *UserEntity) GetDisplayName() string { } func init() { + proto.RegisterEnum("webauthn.ChallengeScope", ChallengeScope_name, ChallengeScope_value) proto.RegisterType((*SessionData)(nil), "webauthn.SessionData") proto.RegisterType((*User)(nil), "webauthn.User") proto.RegisterType((*CredentialAssertion)(nil), "webauthn.CredentialAssertion") @@ -1244,75 +1321,87 @@ func init() { } var fileDescriptor_0d490a6db28e8798 = []byte{ - // 1073 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5b, 0x6f, 0x1b, 0x45, - 0x14, 0xd6, 0xda, 0xeb, 0xd4, 0x3e, 0x36, 0x95, 0x3b, 0x71, 0x5b, 0x53, 0x5a, 0xc7, 0x5d, 0x40, - 0xb2, 0xc8, 0xc5, 0x28, 0x88, 0x07, 0x28, 0x17, 0xe5, 0x52, 0x44, 0x12, 0xb5, 0x89, 0xb6, 0x02, - 0x09, 0x5e, 0x56, 0xe3, 0xdd, 0x83, 0x3d, 0x65, 0xbd, 0xbb, 0x9d, 0x99, 0x6d, 0x6a, 0xf1, 0x93, - 0x78, 0xe3, 0x89, 0x37, 0x5e, 0x91, 0x78, 0xe1, 0x17, 0x84, 0x2a, 0x8f, 0xf9, 0x15, 0x68, 0x67, - 0xaf, 0xb6, 0x37, 0x4d, 0x00, 0x89, 0xb7, 0xd9, 0x73, 0xce, 0x77, 0x66, 0xe6, 0x7c, 0xe7, 0x3b, - 0x3b, 0xb0, 0x29, 0xd1, 0xc5, 0xc0, 0xe7, 0x72, 0xe8, 0xe2, 0x98, 0xda, 0xb3, 0xa1, 0x9c, 0x05, - 0x28, 0x86, 0xa7, 0x38, 0xa2, 0xa1, 0x9c, 0x78, 0xd9, 0x62, 0x2b, 0xe0, 0xbe, 0xf4, 0x49, 0x3d, - 0xfd, 0xbe, 0xd7, 0x19, 0xfb, 0x63, 0x5f, 0x19, 0x87, 0xd1, 0x2a, 0xf6, 0x1b, 0x7f, 0x54, 0xa0, - 0xf9, 0x0c, 0x85, 0x60, 0xbe, 0xb7, 0x4f, 0x25, 0x25, 0x1f, 0x43, 0xc3, 0x9e, 0x50, 0xd7, 0x45, - 0x6f, 0x8c, 0x5d, 0xad, 0xaf, 0x0d, 0x5a, 0xbb, 0x77, 0x2f, 0xce, 0xd6, 0x56, 0x33, 0xe3, 0x86, - 0x3f, 0x65, 0x12, 0xa7, 0x81, 0x9c, 0x99, 0x79, 0x24, 0xd9, 0x84, 0x1b, 0xa1, 0x40, 0x6e, 0x31, - 0xa7, 0x5b, 0x51, 0xa0, 0xce, 0xc5, 0xd9, 0x5a, 0x3b, 0x32, 0x1d, 0x38, 0x05, 0xc4, 0x4a, 0x6c, - 0x21, 0x47, 0x70, 0x8b, 0xba, 0xae, 0x7f, 0x6a, 0xd9, 0x1c, 0x1d, 0xf4, 0x24, 0xa3, 0xae, 0xe8, - 0x56, 0xfb, 0xd5, 0x41, 0x6b, 0xb7, 0x77, 0x71, 0xb6, 0x76, 0x4f, 0x39, 0xf7, 0x72, 0x5f, 0x21, - 0x45, 0x7b, 0xd1, 0x47, 0x3e, 0x83, 0x16, 0x47, 0xc1, 0xa2, 0x6f, 0xeb, 0x47, 0x9c, 0x75, 0xf5, - 0xbe, 0x36, 0xa8, 0xef, 0xbe, 0x7d, 0x71, 0xb6, 0x76, 0x3b, 0xb5, 0x1f, 0xe1, 0xac, 0x90, 0xa2, - 0x59, 0x30, 0x47, 0x47, 0x51, 0x27, 0x7f, 0x89, 0x9c, 0xfd, 0xc0, 0x6c, 0x2a, 0x99, 0xef, 0x75, - 0x6b, 0x7d, 0x6d, 0xd0, 0x88, 0x8f, 0x12, 0x39, 0xbf, 0x2d, 0xf8, 0x8a, 0x47, 0x59, 0xf4, 0x19, - 0xeb, 0xa0, 0x7f, 0x23, 0x90, 0x93, 0x77, 0xe1, 0xad, 0x94, 0x26, 0x2b, 0x0a, 0x52, 0x95, 0x6c, - 0x98, 0xad, 0xd4, 0x18, 0x05, 0x19, 0x14, 0x56, 0xf3, 0x6b, 0xec, 0x08, 0x81, 0x3c, 0xca, 0x41, - 0x0e, 0x01, 0x82, 0x70, 0xe4, 0x32, 0x5b, 0x5d, 0x26, 0x02, 0x36, 0xb7, 0xd7, 0xb7, 0x32, 0x5a, - 0x4f, 0x94, 0xef, 0x08, 0x67, 0x39, 0xd6, 0xc4, 0x17, 0x21, 0x0a, 0x79, 0x1c, 0x44, 0x78, 0x61, - 0x36, 0x82, 0x34, 0xc4, 0xf8, 0xad, 0x02, 0x0f, 0xaf, 0x04, 0x90, 0xfb, 0x4b, 0x9c, 0x17, 0xa9, - 0x7d, 0x00, 0x20, 0xd9, 0x14, 0xfd, 0x50, 0x5a, 0x53, 0xa1, 0xd8, 0xad, 0x9a, 0x8d, 0xc4, 0xf2, - 0x44, 0x90, 0x55, 0xa8, 0xf1, 0x20, 0xe2, 0xbd, 0xaa, 0xae, 0xa8, 0xf3, 0xe0, 0x32, 0x7e, 0xf5, - 0x7e, 0x75, 0xd0, 0xdc, 0xee, 0xe5, 0x57, 0xc9, 0x0f, 0xb4, 0x8f, 0xc2, 0xe6, 0x2c, 0x90, 0x3e, - 0x2f, 0xe1, 0xf7, 0x29, 0x00, 0xbe, 0x92, 0xe8, 0x45, 0x3d, 0x2a, 0x14, 0x35, 0xcd, 0xed, 0xad, - 0x3c, 0xcb, 0x4e, 0x28, 0x27, 0x51, 0x68, 0x4c, 0xc1, 0xe3, 0x2c, 0x72, 0xcf, 0x65, 0xe8, 0xc9, - 0x03, 0x2f, 0x08, 0xa5, 0x30, 0x0b, 0x19, 0xc8, 0x7a, 0x19, 0xe3, 0x2b, 0xea, 0xf4, 0xcb, 0x8c, - 0xfe, 0xa5, 0xc1, 0x3b, 0x25, 0x2c, 0x99, 0x28, 0x02, 0xdf, 0x13, 0x48, 0x08, 0xe8, 0x91, 0x00, - 0x13, 0x82, 0xd5, 0x9a, 0xdc, 0x86, 0x15, 0x4e, 0x4f, 0x33, 0x2d, 0x98, 0x35, 0x4e, 0x4f, 0x0f, - 0x1c, 0xb2, 0x0f, 0x75, 0x9e, 0xc0, 0x54, 0xb1, 0x9a, 0xdb, 0x83, 0xd2, 0x5b, 0xf8, 0x7c, 0x69, - 0x1b, 0x33, 0x43, 0x92, 0xe3, 0xb9, 0x6a, 0xe8, 0x2a, 0xcf, 0xf0, 0xba, 0xd5, 0x38, 0x0e, 0xe5, - 0x62, 0x39, 0x8c, 0x5f, 0x35, 0xe8, 0xbd, 0x79, 0x77, 0x32, 0x80, 0xb6, 0xad, 0xf0, 0x96, 0x43, - 0x25, 0xb5, 0x9e, 0x0b, 0xdf, 0x4b, 0xfa, 0xe4, 0x66, 0x6c, 0x8f, 0x46, 0xc7, 0xa1, 0xf0, 0x3d, - 0xb2, 0x09, 0x84, 0x16, 0x73, 0x29, 0x40, 0x52, 0x86, 0x5b, 0x73, 0x1e, 0x35, 0x6d, 0xee, 0x43, - 0x43, 0xb0, 0xb1, 0x47, 0x65, 0xc8, 0xe3, 0x9a, 0xb4, 0xcc, 0xdc, 0x40, 0xd6, 0xa0, 0xa9, 0x88, - 0x9a, 0x50, 0xcf, 0x71, 0x51, 0xdd, 0xb5, 0x65, 0x42, 0x64, 0xfa, 0x5a, 0x59, 0x0c, 0x0a, 0x24, - 0xe7, 0x66, 0x8f, 0xa3, 0xba, 0x33, 0x39, 0x2a, 0x11, 0xd0, 0xc6, 0x1b, 0x05, 0x94, 0x42, 0x4b, - 0x14, 0xf4, 0xb3, 0x0e, 0xc6, 0xd5, 0x88, 0x2b, 0x24, 0xb4, 0x01, 0x15, 0x1e, 0xa8, 0x2a, 0x34, - 0xb7, 0xef, 0xe7, 0x27, 0x31, 0xd1, 0x9d, 0x31, 0x6f, 0x7c, 0x42, 0xb9, 0x9c, 0x3d, 0xf6, 0x24, - 0x93, 0x33, 0xb3, 0xc2, 0x03, 0x32, 0x00, 0x5d, 0xcd, 0x8c, 0xb8, 0x47, 0x3a, 0x79, 0x7c, 0x34, - 0x35, 0x92, 0x38, 0x15, 0x41, 0x4c, 0xb8, 0x9d, 0x0b, 0xcc, 0x0a, 0x28, 0xa7, 0x53, 0x94, 0xc8, - 0x53, 0xa9, 0x3d, 0x28, 0x93, 0xda, 0x49, 0x1a, 0x65, 0x76, 0xec, 0x65, 0xa3, 0x58, 0x90, 0x7b, - 0x6d, 0x51, 0xee, 0xc7, 0xb0, 0x8a, 0xaf, 0x6c, 0x37, 0x74, 0x70, 0x4e, 0xdb, 0x2b, 0xd7, 0xd2, - 0x36, 0x49, 0xa0, 0x45, 0x75, 0xf7, 0xa1, 0x49, 0xa5, 0x44, 0x21, 0x63, 0x1d, 0xde, 0x50, 0x3a, - 0x2a, 0x9a, 0x16, 0xf4, 0x5f, 0xff, 0xcf, 0xfa, 0xff, 0x0e, 0xee, 0xce, 0xf7, 0xa8, 0x40, 0x17, - 0x6d, 0xb5, 0x7b, 0x43, 0x25, 0xef, 0x5f, 0x22, 0xcb, 0x67, 0x69, 0x9c, 0x79, 0x87, 0x96, 0xda, - 0x8d, 0xd7, 0x1a, 0xdc, 0x5b, 0x6e, 0x92, 0x7f, 0x33, 0x2c, 0xbe, 0x5a, 0x1a, 0x16, 0x1f, 0x5c, - 0x36, 0x2c, 0xf2, 0x52, 0xfd, 0x1f, 0xe3, 0xe2, 0x27, 0xe8, 0x5f, 0xb5, 0xfd, 0x3f, 0x9c, 0x17, - 0x79, 0x02, 0xcb, 0x1f, 0x3d, 0x47, 0x5b, 0x66, 0xf3, 0x22, 0xf7, 0x1c, 0x2b, 0x87, 0xf1, 0x39, - 0xbc, 0x77, 0x1d, 0xba, 0xa3, 0xa2, 0xd2, 0x40, 0xfd, 0x95, 0xe2, 0x52, 0xd7, 0x68, 0x10, 0x1c, - 0x38, 0xc6, 0x17, 0xf0, 0xfe, 0xb5, 0x2e, 0xbc, 0x80, 0xaf, 0xa7, 0xf8, 0x5f, 0x34, 0xb8, 0x53, - 0xde, 0x11, 0xe4, 0x13, 0xe8, 0xce, 0x37, 0x15, 0x95, 0x92, 0xda, 0x93, 0x29, 0x7a, 0x32, 0x39, - 0xc3, 0x7c, 0xd3, 0xed, 0x64, 0x6e, 0xf2, 0x21, 0x74, 0x38, 0xbe, 0x08, 0x19, 0x47, 0x6b, 0xee, - 0x1d, 0x53, 0x51, 0x5b, 0x93, 0xc4, 0x67, 0x16, 0xde, 0x2c, 0xa5, 0x7f, 0xb0, 0xea, 0x25, 0x7f, - 0xb0, 0x4f, 0xa1, 0x53, 0x26, 0xc6, 0xd2, 0x66, 0xbc, 0x09, 0x95, 0xac, 0x11, 0x2b, 0xcc, 0x31, - 0x1e, 0x15, 0x9f, 0x28, 0xd9, 0x90, 0x28, 0x85, 0xb6, 0xa1, 0x4a, 0xdd, 0xb1, 0xc2, 0xd6, 0xcc, - 0x68, 0x69, 0xec, 0x03, 0x59, 0x9e, 0x70, 0xc9, 0x16, 0x31, 0xb2, 0xc2, 0x9c, 0x28, 0x97, 0x47, - 0xa7, 0xa8, 0x80, 0x0d, 0x53, 0xad, 0x0f, 0xf5, 0x7a, 0xb5, 0xad, 0x9b, 0x3a, 0xb3, 0x7d, 0xcf, - 0xb0, 0x00, 0xf2, 0xb9, 0x57, 0x40, 0xb7, 0x2e, 0x43, 0x93, 0x87, 0xd0, 0x72, 0x98, 0x08, 0x5c, - 0x3a, 0xb3, 0x94, 0x2f, 0x2e, 0x4c, 0x33, 0xb1, 0x3d, 0x8d, 0x37, 0xd0, 0xdb, 0xb5, 0x78, 0x83, - 0xdd, 0x27, 0xbf, 0x9f, 0xf7, 0xb4, 0x3f, 0xcf, 0x7b, 0xda, 0xeb, 0xf3, 0x9e, 0xf6, 0xfd, 0x97, - 0x63, 0x26, 0x27, 0xe1, 0x68, 0xcb, 0xf6, 0xa7, 0xc3, 0x31, 0xa7, 0x2f, 0x59, 0xdc, 0x7f, 0xd4, - 0x1d, 0x66, 0xef, 0x6e, 0x1a, 0xb0, 0x85, 0x47, 0xf7, 0xa3, 0x74, 0x11, 0x8c, 0x46, 0x2b, 0xea, - 0x5d, 0xfd, 0xd1, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x89, 0xb7, 0x8c, 0x49, 0xa8, 0x0b, 0x00, - 0x00, + // 1275 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xcb, 0x6e, 0xdb, 0x46, + 0x17, 0xfe, 0x29, 0x51, 0xb2, 0x75, 0xa4, 0xdf, 0x55, 0xc6, 0x76, 0xa2, 0x24, 0x8e, 0xa4, 0xb0, + 0x17, 0x08, 0xb9, 0x58, 0x85, 0x8b, 0x2e, 0x9a, 0xf4, 0x02, 0x59, 0x62, 0x12, 0xc5, 0xb6, 0x64, + 0x90, 0x4d, 0x8a, 0x74, 0x43, 0x8c, 0xa9, 0xa9, 0xc4, 0x94, 0x22, 0x99, 0x99, 0x61, 0x1c, 0xa1, + 0x8f, 0xd1, 0xc7, 0xe8, 0xae, 0xab, 0xee, 0xba, 0xed, 0xa2, 0x8b, 0x3e, 0x81, 0x1b, 0x78, 0xe9, + 0xa7, 0x28, 0x38, 0x94, 0x44, 0x8a, 0xa2, 0x63, 0xb7, 0x05, 0xba, 0x1b, 0x9e, 0xef, 0x7c, 0x73, + 0x39, 0xf3, 0x7d, 0x87, 0x24, 0xdc, 0xe7, 0xc4, 0x26, 0x9e, 0x4b, 0x79, 0xd3, 0x26, 0x43, 0x6c, + 0x4e, 0x9a, 0x7c, 0xe2, 0x11, 0xd6, 0x3c, 0x26, 0x47, 0xd8, 0xe7, 0x23, 0x67, 0x3e, 0xd8, 0xf6, + 0xa8, 0xcb, 0x5d, 0xb4, 0x3a, 0x7b, 0xbe, 0xb1, 0x31, 0x74, 0x87, 0xae, 0x08, 0x36, 0x83, 0x51, + 0x88, 0x2b, 0xbf, 0x67, 0xa1, 0xa8, 0x13, 0xc6, 0x2c, 0xd7, 0xe9, 0x60, 0x8e, 0xd1, 0xa7, 0x50, + 0x30, 0x47, 0xd8, 0xb6, 0x89, 0x33, 0x24, 0x15, 0xa9, 0x2e, 0x35, 0x4a, 0xbb, 0xd7, 0xce, 0x4e, + 0x6a, 0xeb, 0xf3, 0xe0, 0x3d, 0x77, 0x6c, 0x71, 0x32, 0xf6, 0xf8, 0x44, 0x8b, 0x32, 0xd1, 0x7d, + 0x58, 0xf1, 0x19, 0xa1, 0x86, 0x35, 0xa8, 0x64, 0x04, 0x69, 0xe3, 0xec, 0xa4, 0x56, 0x0e, 0x42, + 0xdd, 0x41, 0x8c, 0x91, 0x0f, 0x23, 0x68, 0x0f, 0xae, 0x60, 0xdb, 0x76, 0x8f, 0x0d, 0x93, 0x92, + 0x01, 0x71, 0xb8, 0x85, 0x6d, 0x56, 0xc9, 0xd6, 0xb3, 0x8d, 0xd2, 0x6e, 0xf5, 0xec, 0xa4, 0x76, + 0x43, 0x80, 0xed, 0x08, 0x8b, 0x4d, 0x51, 0x4e, 0x62, 0xe8, 0x73, 0x28, 0x51, 0xc2, 0xac, 0xe0, + 0xd9, 0xf8, 0x9e, 0x4c, 0x2a, 0x72, 0x5d, 0x6a, 0xac, 0xee, 0x5e, 0x3f, 0x3b, 0xa9, 0x6d, 0xce, + 0xe2, 0x7b, 0x64, 0x12, 0x9b, 0xa2, 0x18, 0x0b, 0x07, 0x5b, 0x11, 0x3b, 0x7f, 0x4d, 0xa8, 0xf5, + 0x9d, 0x65, 0x62, 0x6e, 0xb9, 0x4e, 0x25, 0x57, 0x97, 0x1a, 0x85, 0x70, 0x2b, 0x01, 0xf8, 0x3c, + 0x86, 0xc5, 0xb7, 0x92, 0xc4, 0x50, 0x1b, 0x72, 0xcc, 0x74, 0x3d, 0x52, 0xc9, 0xd7, 0xa5, 0xc6, + 0xda, 0x4e, 0x65, 0x7b, 0x7e, 0x1b, 0xed, 0x59, 0xa9, 0xf4, 0x00, 0xdf, 0x5d, 0x3f, 0x3b, 0xa9, + 0xbd, 0x27, 0x52, 0x63, 0xf3, 0x85, 0x5c, 0xf4, 0x00, 0x8a, 0x61, 0x71, 0x28, 0xf1, 0x19, 0xa9, + 0xac, 0x44, 0xc7, 0x89, 0x85, 0x63, 0x34, 0x10, 0x61, 0x2d, 0x88, 0x2a, 0x77, 0x41, 0x7e, 0xc6, + 0x08, 0x45, 0xef, 0xc3, 0xff, 0x67, 0x3a, 0x31, 0x82, 0x5d, 0x8a, 0xab, 0x2c, 0x68, 0xa5, 0x59, + 0x30, 0x48, 0x52, 0x30, 0xac, 0x47, 0x75, 0x6c, 0x31, 0x46, 0xa8, 0x38, 0xc4, 0x53, 0x00, 0xcf, + 0x3f, 0xb2, 0x2d, 0x53, 0x54, 0x33, 0x20, 0x16, 0x77, 0xee, 0x46, 0x27, 0x39, 0x14, 0xd8, 0x1e, + 0x99, 0x44, 0x5c, 0x8d, 0xbc, 0xf2, 0x09, 0xe3, 0x7d, 0x2f, 0xe0, 0x33, 0xad, 0xe0, 0xcd, 0x52, + 0x94, 0x5f, 0x33, 0x70, 0xfb, 0x42, 0x02, 0xda, 0x5a, 0x12, 0x5d, 0x5c, 0x5b, 0xb7, 0x00, 0xb8, + 0x35, 0x26, 0xae, 0xcf, 0x8d, 0x31, 0x13, 0xf2, 0xca, 0x6a, 0x85, 0x69, 0xe4, 0x80, 0xa1, 0x75, + 0xc8, 0x51, 0x2f, 0x10, 0x5e, 0x56, 0x1c, 0x51, 0xa6, 0xde, 0x79, 0x02, 0x93, 0xeb, 0xd9, 0x46, + 0x71, 0xa7, 0x1a, 0xbb, 0x94, 0x39, 0xd8, 0x21, 0xcc, 0xa4, 0x96, 0xc7, 0x5d, 0x9a, 0x22, 0xb0, + 0x1e, 0x00, 0x79, 0xc3, 0x89, 0x13, 0x98, 0x84, 0x09, 0x6d, 0x14, 0x77, 0xb6, 0xa3, 0x59, 0x5a, + 0x3e, 0x1f, 0x05, 0xa9, 0xa1, 0x06, 0xd4, 0x79, 0x66, 0xdb, 0xb6, 0x88, 0xc3, 0xbb, 0x8e, 0xe7, + 0x73, 0xa6, 0xc5, 0x66, 0x40, 0x77, 0xd3, 0x24, 0x97, 0x17, 0xbb, 0x5f, 0x92, 0x94, 0xf2, 0xa7, + 0x04, 0x37, 0x53, 0x6e, 0x49, 0x23, 0xcc, 0x73, 0x1d, 0x46, 0x10, 0x02, 0x39, 0xe8, 0x00, 0xd3, + 0x0b, 0x16, 0x63, 0xb4, 0x09, 0x79, 0x8a, 0x8f, 0xe7, 0x66, 0xd4, 0x72, 0x14, 0x1f, 0x77, 0x07, + 0xa8, 0x03, 0xab, 0x74, 0x4a, 0x13, 0xc5, 0x2a, 0xee, 0x34, 0x52, 0x4f, 0xe1, 0xd2, 0xa5, 0x65, + 0xb4, 0x39, 0x13, 0xf5, 0x17, 0xaa, 0x21, 0x8b, 0x79, 0x9a, 0x97, 0xad, 0x46, 0xdf, 0xe7, 0xc9, + 0x72, 0x28, 0xbf, 0x48, 0x50, 0x7d, 0xf7, 0xea, 0xa8, 0x01, 0x65, 0x53, 0xf0, 0x8d, 0x01, 0xe6, + 0xd8, 0x78, 0xc9, 0x5c, 0x67, 0xaa, 0x93, 0xb5, 0x30, 0x1e, 0xf4, 0xae, 0xa7, 0xcc, 0x75, 0xd0, + 0x7d, 0x40, 0x38, 0x3e, 0x97, 0x20, 0x4c, 0xcb, 0x70, 0x65, 0x01, 0x11, 0xed, 0x6e, 0x0b, 0x0a, + 0xcc, 0x1a, 0x3a, 0x98, 0xfb, 0x34, 0xac, 0x49, 0x49, 0x8b, 0x02, 0xa8, 0x06, 0x45, 0x71, 0x51, + 0x23, 0xec, 0x0c, 0x6c, 0x22, 0xce, 0x5a, 0xd2, 0x20, 0x08, 0x3d, 0x11, 0x11, 0x05, 0x03, 0x8a, + 0xee, 0xa6, 0x4d, 0x49, 0xd8, 0x05, 0xf6, 0x52, 0x0c, 0x74, 0xef, 0x9d, 0x06, 0x9a, 0x51, 0x53, + 0x1c, 0xf4, 0x93, 0x0c, 0xca, 0xc5, 0x8c, 0x0b, 0x2c, 0x74, 0x0f, 0x32, 0xd4, 0x13, 0x55, 0x28, + 0xee, 0x6c, 0x45, 0x3b, 0xd1, 0x88, 0x3d, 0xb1, 0x9c, 0xe1, 0x21, 0xa6, 0x7c, 0xa2, 0x3a, 0xdc, + 0xe2, 0x13, 0x2d, 0x43, 0x3d, 0xd4, 0x00, 0x59, 0xf4, 0x8c, 0x50, 0x23, 0x1b, 0x51, 0x7e, 0xd0, + 0x35, 0xa6, 0x79, 0x22, 0x03, 0x69, 0xb0, 0x19, 0x19, 0xcc, 0xf0, 0x30, 0xc5, 0x63, 0xc2, 0x09, + 0x9d, 0x59, 0xed, 0x56, 0x9a, 0xd5, 0x0e, 0x67, 0x59, 0xda, 0x86, 0xb9, 0x1c, 0x64, 0x09, 0xbb, + 0xe7, 0x92, 0x76, 0xef, 0xc3, 0x3a, 0x79, 0x63, 0xda, 0xfe, 0x80, 0x2c, 0x78, 0x3b, 0x7f, 0x29, + 0x6f, 0xa3, 0x29, 0x35, 0xee, 0xee, 0x3a, 0x14, 0x31, 0xe7, 0x84, 0xf1, 0xd0, 0x87, 0x2b, 0xc2, + 0x47, 0xf1, 0x50, 0xc2, 0xff, 0xab, 0xff, 0xda, 0xff, 0x2f, 0xe0, 0xda, 0xa2, 0x46, 0x19, 0xb1, + 0x89, 0x29, 0x56, 0x2f, 0x88, 0xc9, 0xeb, 0xe7, 0xd8, 0x52, 0x9f, 0xe5, 0x69, 0x57, 0x71, 0x6a, + 0x5c, 0x79, 0x2b, 0xc1, 0x8d, 0x65, 0x91, 0xfc, 0x93, 0x66, 0xf1, 0x68, 0xa9, 0x59, 0xdc, 0x39, + 0xaf, 0x59, 0x44, 0xa5, 0xfa, 0x2f, 0xda, 0xc5, 0x0f, 0x50, 0xbf, 0x68, 0xf9, 0xbf, 0xd9, 0x2f, + 0xa2, 0x09, 0x0c, 0xf7, 0xe8, 0x25, 0x31, 0xf9, 0xbc, 0x5f, 0x44, 0x48, 0x5f, 0x00, 0xca, 0x17, + 0xf0, 0xc1, 0x65, 0xae, 0x3b, 0x28, 0x2a, 0xf6, 0xc4, 0x5b, 0x29, 0x2c, 0x75, 0x0e, 0x7b, 0x5e, + 0x77, 0xa0, 0x7c, 0x09, 0x1f, 0x5e, 0xea, 0xc0, 0x09, 0xfe, 0xea, 0x8c, 0xff, 0xb3, 0x04, 0x57, + 0xd3, 0x15, 0x81, 0x3e, 0x83, 0xca, 0xa2, 0xa8, 0x30, 0xe7, 0xd8, 0x1c, 0x8d, 0x89, 0xc3, 0xa7, + 0x7b, 0x58, 0x14, 0x5d, 0x6b, 0x0e, 0xa3, 0x8f, 0x61, 0x83, 0x92, 0x57, 0xbe, 0x45, 0x89, 0xb1, + 0xf0, 0x21, 0x95, 0x11, 0x4b, 0xa3, 0x29, 0xa6, 0xc5, 0x3e, 0x9a, 0x52, 0xdf, 0x60, 0xd9, 0x73, + 0xde, 0x60, 0x0f, 0x60, 0x23, 0xcd, 0x8c, 0xa9, 0x62, 0x5c, 0x83, 0xcc, 0x5c, 0x88, 0x19, 0x6b, + 0xa0, 0x3c, 0x8c, 0x7f, 0xa2, 0xcc, 0x9b, 0x44, 0x2a, 0xb5, 0x0c, 0x59, 0x6c, 0x0f, 0x05, 0x37, + 0xa7, 0x05, 0x43, 0xa5, 0x03, 0x68, 0xb9, 0xc3, 0x4d, 0x97, 0x08, 0x99, 0x19, 0x6b, 0x10, 0xcc, + 0xe5, 0xe0, 0x31, 0x11, 0xc4, 0x82, 0x26, 0xc6, 0x4f, 0xe5, 0xd5, 0x6c, 0x59, 0xd6, 0x64, 0xcb, + 0x74, 0x1d, 0xc5, 0x00, 0x88, 0xfa, 0x5e, 0x8c, 0x5d, 0x3a, 0x8f, 0x8d, 0x6e, 0x43, 0x69, 0x60, + 0x31, 0xcf, 0xc6, 0x13, 0x43, 0x60, 0x61, 0x61, 0x8a, 0xd3, 0x58, 0x2f, 0x5c, 0x40, 0x2e, 0xe7, + 0xc2, 0x05, 0xee, 0xfc, 0x98, 0x81, 0xb5, 0xc5, 0xcf, 0x43, 0x54, 0x83, 0x9b, 0xed, 0x27, 0xad, + 0xfd, 0x7d, 0xb5, 0xf7, 0x58, 0x35, 0xf4, 0x76, 0xff, 0x50, 0x35, 0x9e, 0xf5, 0xf4, 0x43, 0xb5, + 0xdd, 0x7d, 0xd4, 0x55, 0x3b, 0xe5, 0xff, 0xa1, 0xeb, 0xb0, 0x99, 0x4c, 0xd8, 0xef, 0x3f, 0xee, + 0xf6, 0xca, 0x12, 0xfa, 0x08, 0x94, 0x24, 0x74, 0xd8, 0xd2, 0xf5, 0x6f, 0xfa, 0x5a, 0x67, 0x5f, + 0xd5, 0xf5, 0x69, 0x5e, 0x06, 0x29, 0x50, 0x4d, 0xe6, 0x1d, 0xb4, 0x7a, 0xad, 0xc7, 0xaa, 0xd1, + 0x51, 0x9f, 0x77, 0xdb, 0xaa, 0x5e, 0xce, 0xa2, 0x2d, 0xa8, 0x24, 0x73, 0x34, 0xb5, 0xdd, 0x7f, + 0xae, 0x6a, 0x2f, 0xca, 0x32, 0xba, 0x09, 0xd7, 0x92, 0xa8, 0xae, 0xea, 0x7a, 0xb7, 0xdf, 0x2b, + 0xe7, 0xd2, 0xa8, 0x4f, 0xd4, 0x96, 0xd8, 0x42, 0x39, 0x8f, 0xea, 0xb0, 0x95, 0x44, 0x5b, 0x9d, + 0x83, 0x6e, 0xcf, 0x68, 0xb5, 0xbf, 0x0e, 0xf8, 0x2b, 0xbb, 0x07, 0xbf, 0x9d, 0x56, 0xa5, 0x3f, + 0x4e, 0xab, 0xd2, 0xdb, 0xd3, 0xaa, 0xf4, 0xed, 0x57, 0x43, 0x8b, 0x8f, 0xfc, 0xa3, 0x6d, 0xd3, + 0x1d, 0x37, 0x87, 0x14, 0xbf, 0xb6, 0x42, 0x57, 0x62, 0xbb, 0x39, 0xff, 0x1d, 0xc2, 0x9e, 0x95, + 0xf8, 0x17, 0x7a, 0x38, 0x1b, 0x78, 0x47, 0x47, 0x79, 0xf1, 0xbb, 0xf3, 0xc9, 0x5f, 0x01, 0x00, + 0x00, 0xff, 0xff, 0xa3, 0x95, 0xc6, 0x0d, 0x3f, 0x0d, 0x00, 0x00, } func (m *SessionData) Marshal() (dAtA []byte, err error) { @@ -1339,6 +1428,21 @@ func (m *SessionData) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.AllowReuse { + i-- + if m.AllowReuse { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } + if m.Scope != 0 { + i = encodeVarintWebauthn(dAtA, i, uint64(m.Scope)) + i-- + dAtA[i] = 0x30 + } if len(m.UserVerification) > 0 { i -= len(m.UserVerification) copy(dAtA[i:], m.UserVerification) @@ -2250,6 +2354,12 @@ func (m *SessionData) Size() (n int) { if l > 0 { n += 1 + l + sovWebauthn(uint64(l)) } + if m.Scope != 0 { + n += 1 + sovWebauthn(uint64(m.Scope)) + } + if m.AllowReuse { + n += 2 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -2820,6 +2930,45 @@ func (m *SessionData) Unmarshal(dAtA []byte) error { } m.UserVerification = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Scope", wireType) + } + m.Scope = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWebauthn + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Scope |= ChallengeScope(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowReuse", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWebauthn + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowReuse = bool(v != 0) default: iNdEx = preIndex skippy, err := skipWebauthn(dAtA[iNdEx:]) diff --git a/lib/auth/accountrecovery.go b/lib/auth/accountrecovery.go index 21981cbbf45a5..feda9ba83b8e6 100644 --- a/lib/auth/accountrecovery.go +++ b/lib/auth/accountrecovery.go @@ -32,6 +32,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/defaults" @@ -264,8 +265,7 @@ func (a *Server) VerifyAccountRecovery(ctx context.Context, req *proto.VerifyAcc } if err := a.verifyAuthnWithRecoveryLock(ctx, startToken, func() error { - _, _, err := a.ValidateMFAAuthResponse( - ctx, req.GetMFAAuthenticateResponse(), startToken.GetUser(), false /* passwordless */) + _, err := a.ValidateMFAAuthResponse(ctx, req.GetMFAAuthenticateResponse(), startToken.GetUser(), webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES) return err }); err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/api.go b/lib/auth/api.go index de5153969f27e..c425ebd49386c 100644 --- a/lib/auth/api.go +++ b/lib/auth/api.go @@ -90,10 +90,6 @@ type accessPoint interface { // ConnectionDiagnosticTraceAppender adds a method to append traces into ConnectionDiagnostics. services.ConnectionDiagnosticTraceAppender - - // ValidateMFAAuthResponse validates an MFA or passwordless challenge. - // Returns the device used to solve the challenge (if applicable) and the username. - ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) } // ReadNodeAccessPoint is a read only API interface implemented by a certificate authority (CA) to be diff --git a/lib/auth/assist/assistv1/test/service_test.go b/lib/auth/assist/assistv1/test/service_test.go index 87a3870b67724..a5641fd9ff49c 100644 --- a/lib/auth/assist/assistv1/test/service_test.go +++ b/lib/auth/assist/assistv1/test/service_test.go @@ -31,7 +31,6 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/gravitational/teleport" - "github.com/gravitational/teleport/api/client/proto" assistpb "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/retryutils" @@ -321,10 +320,6 @@ type testClient struct { services.UserGetter } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T) (map[string]context.Context, *assistv1.Service) { ctx := context.Background() backend, err := memory.New(memory.Config{}) diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 8f3f4ecda568c..0f8dad8e3552c 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -70,6 +70,7 @@ import ( "github.com/gravitational/teleport/api/metadata" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/types/wrappers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/keys" @@ -2935,11 +2936,12 @@ func (a *Server) PreAuthenticatedSignIn(ctx context.Context, user string, identi // CreateAuthenticateChallenge implements AuthService.CreateAuthenticateChallenge. func (a *Server) CreateAuthenticateChallenge(ctx context.Context, req *proto.CreateAuthenticateChallengeRequest) (*proto.MFAAuthenticateChallenge, error) { var username string - var passwordless bool + scope := req.Scope switch req.GetRequest().(type) { case *proto.CreateAuthenticateChallengeRequest_UserCredentials: username = req.GetUserCredentials().GetUsername() + scope = webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN if err := a.WithUserLock(ctx, username, func() error { return a.checkPasswordWOToken(username, req.GetUserCredentials().GetPassword()) @@ -2959,11 +2961,13 @@ func (a *Server) CreateAuthenticateChallenge(ctx context.Context, req *proto.Cre } username = token.GetUser() + scope = webauthnpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN case *proto.CreateAuthenticateChallengeRequest_Passwordless: - passwordless = true // Allows empty username. + scope = webauthnpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN default: // unset or CreateAuthenticateChallengeRequest_ContextUser. + // TODO(Joerger): in v16.0.0, require scope to be specified in the request. var err error username, err = authz.GetClientUsername(ctx) if err != nil { @@ -2971,7 +2975,7 @@ func (a *Server) CreateAuthenticateChallenge(ctx context.Context, req *proto.Cre } } - challenges, err := a.mfaAuthChallenge(ctx, username, passwordless) + challenges, err := a.mfaAuthChallenge(ctx, username, scope, req.AllowReuse) if err != nil { log.Error(trace.DebugReport(err)) return nil, trace.AccessDenied("unable to create MFA challenges") @@ -3213,9 +3217,7 @@ func (a *Server) DeleteMFADeviceSync(ctx context.Context, req *proto.DeleteMFADe return trace.Wrap(err) } - if _, _, err := a.ValidateMFAAuthResponse( - ctx, req.ExistingMFAResponse, user, false, /* passwordless */ - ); err != nil { + if _, err := a.ValidateMFAAuthResponse(ctx, req.ExistingMFAResponse, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES); err != nil { return trace.Wrap(err) } @@ -5736,7 +5738,7 @@ func (a *Server) isMFARequired(ctx context.Context, checker services.AccessCheck // mfaAuthChallenge constructs an MFAAuthenticateChallenge for all MFA devices // registered by the user. -func (a *Server) mfaAuthChallenge(ctx context.Context, user string, passwordless bool) (*proto.MFAAuthenticateChallenge, error) { +func (a *Server) mfaAuthChallenge(ctx context.Context, user string, scope webauthnpb.ChallengeScope, allowReuse bool) (*proto.MFAAuthenticateChallenge, error) { // Check what kind of MFA is enabled. apref, err := a.GetAuthPreference(ctx) if err != nil { @@ -5764,8 +5766,13 @@ func (a *Server) mfaAuthChallenge(ctx context.Context, user string, passwordless webConfig = val } + challenge := &proto.MFAAuthenticateChallenge{ + Scope: scope, + AllowReuse: allowReuse, + } + // Handle passwordless separately, it works differently from MFA. - if passwordless { + if scope == webauthnpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN { if !enableWebauthn { return nil, trace.BadParameter("passwordless requires WebAuthn") } @@ -5777,9 +5784,8 @@ func (a *Server) mfaAuthChallenge(ctx context.Context, user string, passwordless if err != nil { return nil, trace.Wrap(err) } - return &proto.MFAAuthenticateChallenge{ - WebauthnChallenge: wantypes.CredentialAssertionToProto(assertion), - }, nil + challenge.WebauthnChallenge = wantypes.CredentialAssertionToProto(assertion) + return challenge, nil } // User required for non-passwordless. @@ -5792,7 +5798,6 @@ func (a *Server) mfaAuthChallenge(ctx context.Context, user string, passwordless return nil, trace.Wrap(err) } groupedDevs := groupByDeviceType(devs, enableWebauthn) - challenge := &proto.MFAAuthenticateChallenge{} // TOTP challenge. if enableTOTP && groupedDevs.TOTP { @@ -5806,7 +5811,7 @@ func (a *Server) mfaAuthChallenge(ctx context.Context, user string, passwordless Webauthn: webConfig, Identity: wanlib.WithDevices(a.Services, groupedDevs.Webauthn), } - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, scope, allowReuse) if err != nil { return nil, trace.Wrap(err) } @@ -5880,8 +5885,7 @@ func (a *Server) validateMFAAuthResponseForRegister( } if err := a.WithUserLock(ctx, username, func() error { - _, _, err := a.ValidateMFAAuthResponse( - ctx, resp, username, false /* passwordless */) + _, err := a.ValidateMFAAuthResponse(ctx, resp, username, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES) return err }); err != nil { return false, trace.Wrap(err) @@ -5890,13 +5894,16 @@ func (a *Server) validateMFAAuthResponseForRegister( return true, nil } -// ValidateMFAAuthResponse validates an MFA or passwordless challenge. -// Returns the device used to solve the challenge (if applicable) and the -// username. -func (a *Server) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { +// ValidateMFAAuthResponse validates an MFA or passwordless challenge. If the challenge +// response if of type webauthn, this also validates that the challenge response scope +// and reusability is satisfied by the stored webauthn credentials. Returns the device +// used to solve the challenge (if applicable) and the username. +func (a *Server) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, requiredScope webauthnpb.ChallengeScope) (*authz.MFAAuthData, error) { + isPasswordless := requiredScope == webauthnpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN + // Sanity check user/passwordless. - if user == "" && !passwordless { - return nil, "", trace.BadParameter("user required") + if user == "" && !isPasswordless { + return nil, trace.BadParameter("user required") } switch res := resp.Response.(type) { @@ -5905,46 +5912,59 @@ func (a *Server) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAut // Read necessary configurations. cap, err := a.GetAuthPreference(ctx) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } u2f, err := cap.GetU2F() switch { case trace.IsNotFound(err): // OK, may happen. case err != nil: // Unexpected. - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } webConfig, err := cap.GetWebauthn() if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } assertionResp := wantypes.CredentialAssertionResponseFromProto(res.Webauthn) - var dev *types.MFADevice - if passwordless { + var webauthnData *wanlib.WebauthnSessionData + if isPasswordless { webLogin := &wanlib.PasswordlessFlow{ Webauthn: webConfig, Identity: a.Services, } - dev, user, err = webLogin.Finish(ctx, assertionResp) + webauthnData, err = webLogin.Finish(ctx, assertionResp) } else { webLogin := &wanlib.LoginFlow{ U2F: u2f, Webauthn: webConfig, Identity: a.Services, } - dev, err = webLogin.Finish(ctx, user, wantypes.CredentialAssertionResponseFromProto(res.Webauthn)) + webauthnData, err = webLogin.Finish(ctx, user, wantypes.CredentialAssertionResponseFromProto(res.Webauthn), requiredScope) } if err != nil { - return nil, "", trace.AccessDenied("MFA response validation failed: %v", err) + return nil, trace.AccessDenied("MFA response validation failed: %v", err) } - return dev, user, nil + return &authz.MFAAuthData{ + Device: webauthnData.Device, + User: webauthnData.User, + Reusable: webauthnData.Reusable, + }, nil case *proto.MFAAuthenticateResponse_TOTP: dev, err := a.checkOTP(user, res.TOTP.Code) - return dev, user, trace.Wrap(err) + if err != nil { + return nil, trace.Wrap(err) + } + + return &authz.MFAAuthData{ + Device: dev, + User: user, + // We store the last used token to prevent OTP reuse. + Reusable: false, + }, nil default: - return nil, "", trace.BadParameter("unknown or missing MFAAuthenticateResponse type %T", resp.Response) + return nil, trace.BadParameter("unknown or missing MFAAuthenticateResponse type %T", resp.Response) } } diff --git a/lib/auth/auth_login_test.go b/lib/auth/auth_login_test.go index b232b5948a091..a3b930eb5289c 100644 --- a/lib/auth/auth_login_test.go +++ b/lib/auth/auth_login_test.go @@ -33,6 +33,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/types" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/lib/auth/mocku2f" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" "github.com/gravitational/teleport/lib/defaults" @@ -185,14 +186,16 @@ func TestCreateAuthenticateChallenge_WithAuth(t *testing.T) { clt, err := srv.NewClient(TestUser(u.username)) require.NoError(t, err) - res, err := clt.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{}) + res, err := clt.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, + }) require.NoError(t, err) // MFA authentication works. // TODO(codingllama): Use a public endpoint to verify? mfaResp, err := u.webDev.SolveAuthn(res) require.NoError(t, err) - _, _, err = srv.Auth().ValidateMFAAuthResponse(ctx, mfaResp, u.username, false /* passwordless */) + _, err = srv.Auth().ValidateMFAAuthResponse(ctx, mfaResp, u.username, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) require.NoError(t, err) } @@ -414,6 +417,7 @@ func TestCreateAuthenticateChallenge_mfaVerification(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION, MFARequiredCheck: &proto.IsMFARequiredRequest{ Target: &proto.IsMFARequiredRequest_Node{ Node: &proto.NodeLogin{ @@ -537,6 +541,7 @@ func TestCreateRegisterChallenge(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err, "CreateAuthenticateChallenge") authnSolved, err := u.webDev.SolveAuthn(authnChal) @@ -776,6 +781,7 @@ func TestServer_Authenticate_passwordless(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, // already authenticated }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err) mfaResp, err := webDev.SolveAuthn(mfaChallenge) @@ -975,6 +981,7 @@ func TestServer_Authenticate_nonPasswordlessRequiresUsername(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }) require.NoError(t, err) diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go index 607b5787f156f..46bfa6a58bc05 100644 --- a/lib/auth/auth_test.go +++ b/lib/auth/auth_test.go @@ -56,6 +56,7 @@ import ( "github.com/gravitational/teleport/api/types/installers" "github.com/gravitational/teleport/api/types/trait" "github.com/gravitational/teleport/api/types/userloginstate" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/types/wrappers" "github.com/gravitational/teleport/api/utils/keys" "github.com/gravitational/teleport/api/utils/sshutils" @@ -2352,6 +2353,7 @@ func TestDeleteMFADeviceSync(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err, "CreateAuthenticateChallenge") @@ -2596,6 +2598,7 @@ func TestDeleteMFADeviceSync_lastDevice(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) if err != nil { return err @@ -2727,6 +2730,7 @@ func TestAddMFADeviceSync(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err, "CreateAuthenticateChallenge") diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 8a5b388261273..440b3f564f8a6 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -43,6 +43,7 @@ import ( "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/types/wrappers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/keys" @@ -2086,7 +2087,8 @@ func (a *ServerWithRoles) UpsertToken(ctx context.Context, token types.Provision return trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -2812,12 +2814,11 @@ func (a *ServerWithRoles) generateUserCerts(ctx context.Context, req proto.UserC var verifiedMFADeviceID string if req.MFAResponse != nil { - dev, _, err := a.authServer.ValidateMFAAuthResponse( - ctx, req.GetMFAResponse(), req.Username, false /* passwordless */) + mfaData, err := a.authServer.ValidateMFAAuthResponse(ctx, req.GetMFAResponse(), req.Username, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION) if err != nil { return nil, trace.Wrap(err) } - verifiedMFADeviceID = dev.Id + verifiedMFADeviceID = mfaData.Device.Id } // this prevents clients who have no chance at getting a cert and impersonating anyone @@ -3139,7 +3140,8 @@ func (a *ServerWithRoles) CreateResetPasswordToken(ctx context.Context, req Crea return nil, trace.AccessDenied("access denied") } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Allow reused MFA responses to allow creating a reset token after creating a user. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -3285,7 +3287,8 @@ func (a *ServerWithRoles) UpsertOIDCConnector(ctx context.Context, connector typ return nil, trace.AccessDenied("OIDC is only available in Teleport Enterprise") } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -3325,7 +3328,8 @@ func (a *ServerWithRoles) CreateOIDCConnector(ctx context.Context, connector typ return nil, trace.AccessDenied("OIDC is only available in Teleport Enterprise") } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -3440,7 +3444,8 @@ func (a *ServerWithRoles) UpsertSAMLConnector(ctx context.Context, connector typ return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -3641,7 +3646,8 @@ func (a *ServerWithRoles) UpsertGithubConnector(ctx context.Context, connector t return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -3659,7 +3665,8 @@ func (a *ServerWithRoles) CreateGithubConnector(ctx context.Context, connector t return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -4046,7 +4053,8 @@ func (a *ServerWithRoles) UpsertRole(ctx context.Context, role types.Role) (type return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return nil, trace.Wrap(err) } @@ -4238,7 +4246,8 @@ func (a *ServerWithRoles) SetAuthPreference(ctx context.Context, newAuthPref typ return trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -4310,7 +4319,8 @@ func (a *ServerWithRoles) SetClusterNetworkingConfig(ctx context.Context, newNet } } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -4372,7 +4382,8 @@ func (a *ServerWithRoles) SetSessionRecordingConfig(ctx context.Context, newRecC } } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -5292,7 +5303,8 @@ func (a *ServerWithRoles) SetNetworkRestrictions(ctx context.Context, nr types.N return trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -6343,7 +6355,8 @@ func (a *ServerWithRoles) CreateSAMLIdPServiceProvider(ctx context.Context, sp t return trace.Wrap(err) } - if err = authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err = authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -6381,7 +6394,8 @@ func (a *ServerWithRoles) UpdateSAMLIdPServiceProvider(ctx context.Context, sp t return trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, &a.context); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, &a.context); err != nil { return trace.Wrap(err) } @@ -6704,13 +6718,13 @@ func (a *ServerWithRoles) UpdateHeadlessAuthenticationState(ctx context.Context, return err } - mfaDevice, _, err := a.authServer.ValidateMFAAuthResponse(ctx, mfaResp, headlessAuthn.User, false /* passwordless */) + mfaData, err := a.authServer.ValidateMFAAuthResponse(ctx, mfaResp, headlessAuthn.User, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_HEADLESS) if err != nil { emitHeadlessLoginEvent(ctx, events.UserHeadlessLoginApprovedFailureCode, a.authServer.emitter, headlessAuthn, err) return trace.Wrap(err) } - replaceHeadlessAuthn.MfaDevice = mfaDevice + replaceHeadlessAuthn.MfaDevice = mfaData.Device eventCode = events.UserHeadlessLoginApprovedCode case types.HeadlessAuthenticationState_HEADLESS_AUTHENTICATION_STATE_DENIED: eventCode = events.UserHeadlessLoginRejectedCode diff --git a/lib/auth/auth_with_roles_test.go b/lib/auth/auth_with_roles_test.go index 6079c5d352f81..460b89218cb60 100644 --- a/lib/auth/auth_with_roles_test.go +++ b/lib/auth/auth_with_roles_test.go @@ -51,6 +51,7 @@ import ( apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/api/types/installers" wanpb "github.com/gravitational/teleport/api/types/webauthn" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/types/wrappers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/sshutils" @@ -1818,9 +1819,9 @@ func serverWithAllowRules(t *testing.T, srv *TestAuthServer, allowRules []types. require.NoError(t, err) localUser := authz.LocalUser{Username: username, Identity: tlsca.Identity{Username: username}} - authContext, err := authz.ContextForLocalUser(ctx, localUser, srv.AuthServer, srv.ClusterName, true /* disableDeviceAuthz */) + authContext, err := authz.ContextForLocalUser(ctx, localUser, srv.AuthServer.Services, srv.ClusterName, true /* disableDeviceAuthz */) require.NoError(t, err) - authContext.AdminActionAuthorized = true + authContext.AdminActionAuthState = authz.AdminActionAuthMFAVerified return &ServerWithRoles{ authServer: srv.AuthServer, @@ -5838,6 +5839,7 @@ func TestUpdateHeadlessAuthenticationState(t *testing.T) { challenge, err := client.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{}, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_HEADLESS, }) require.NoError(t, err) diff --git a/lib/auth/clt.go b/lib/auth/clt.go index 97d567ef4f66d..7f2de25c8a25f 100644 --- a/lib/auth/clt.go +++ b/lib/auth/clt.go @@ -495,13 +495,6 @@ func (c *Client) DiscoveryConfigClient() services.DiscoveryConfigs { return c.APIClient.DiscoveryConfigClient() } -// ValidateMFAAuthResponse validates an MFA or passwordless challenge. -// Returns the device used to solve the challenge (if applicable) and the -// username. -func (c *Client) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", trace.NotImplemented(notImplementedMessage) -} - // DeleteStaticTokens deletes static tokens func (c *Client) DeleteStaticTokens() error { return trace.NotImplemented(notImplementedMessage) @@ -987,8 +980,4 @@ type ClientI interface { // which is what we want when handling things like ambiguous host errors and resource-based access requests, // but may result in confusing behavior if it is used outside of those contexts. GetSSHTargets(ctx context.Context, req *proto.GetSSHTargetsRequest) (*proto.GetSSHTargetsResponse, error) - - // ValidateMFAAuthResponse validates an MFA or passwordless challenge. - // Returns the device used to solve the challenge (if applicable) and the username. - ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) } diff --git a/lib/auth/discoveryconfig/discoveryconfigv1/service_test.go b/lib/auth/discoveryconfig/discoveryconfigv1/service_test.go index edda25f5c6ff9..b52e0b9c23a35 100644 --- a/lib/auth/discoveryconfig/discoveryconfigv1/service_test.go +++ b/lib/auth/discoveryconfig/discoveryconfigv1/service_test.go @@ -26,7 +26,6 @@ import ( "github.com/gravitational/trace" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/client/proto" discoveryconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/discoveryconfig" @@ -379,10 +378,6 @@ type testClient struct { services.Presence } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T, clusterName string) (context.Context, localClient, *Service) { ctx := context.Background() backend, err := memory.New(memory.Config{}) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index 5173a43520c63..f1766c46075fe 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -63,6 +63,7 @@ import ( "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/api/types/installers" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/types/wrappers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/auth/assist/assistv1" @@ -2272,8 +2273,7 @@ func (g *GRPCServer) DeleteRole(ctx context.Context, req *authpb.DeleteRoleReque func doMFAPresenceChallenge(ctx context.Context, actx *grpcContext, stream authpb.AuthService_MaintainSessionPresenceServer, challengeReq *authpb.PresenceMFAChallengeRequest) error { user := actx.User.GetName() - const passwordless = false - authChallenge, err := actx.authServer.mfaAuthChallenge(ctx, user, passwordless) + authChallenge, err := actx.authServer.mfaAuthChallenge(ctx, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION, false /* allowReuse */) if err != nil { return trace.Wrap(err) } @@ -2295,7 +2295,7 @@ func doMFAPresenceChallenge(ctx context.Context, actx *grpcContext, stream authp return trace.BadParameter("expected MFAAuthenticateResponse, got %T", challengeResp) } - if _, _, err := actx.authServer.ValidateMFAAuthResponse(ctx, challengeResp, user, passwordless); err != nil { + if _, err := actx.authServer.ValidateMFAAuthResponse(ctx, challengeResp, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION); err != nil { return trace.Wrap(err) } @@ -2429,8 +2429,7 @@ func addMFADeviceAuthChallenge(gctx *grpcContext, stream authpb.AuthService_AddM ctx := stream.Context() // Note: authChallenge may be empty if this user has no existing MFA devices. - const passwordless = false - authChallenge, err := auth.mfaAuthChallenge(ctx, user, passwordless) + authChallenge, err := auth.mfaAuthChallenge(ctx, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, false /* allowReuse */) if err != nil { return trace.Wrap(err) } @@ -2451,7 +2450,7 @@ func addMFADeviceAuthChallenge(gctx *grpcContext, stream authpb.AuthService_AddM } // Only validate if there was a challenge. if authChallenge.TOTP != nil || authChallenge.WebauthnChallenge != nil { - if _, _, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, passwordless); err != nil { + if _, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES); err != nil { return trace.Wrap(err) } } @@ -2572,8 +2571,7 @@ func deleteMFADeviceAuthChallenge(gctx *grpcContext, stream authpb.AuthService_D auth := gctx.authServer user := gctx.User.GetName() - const passwordless = false - authChallenge, err := auth.mfaAuthChallenge(ctx, user, passwordless) + authChallenge, err := auth.mfaAuthChallenge(ctx, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, false /* allowReuse */) if err != nil { return trace.Wrap(err) } @@ -2593,7 +2591,7 @@ func deleteMFADeviceAuthChallenge(gctx *grpcContext, stream authpb.AuthService_D if authResp == nil { return trace.BadParameter("expected MFAAuthenticateResponse, got %T", req) } - if _, _, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, passwordless); err != nil { + if _, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES); err != nil { return trace.Wrap(err) } return nil @@ -2803,8 +2801,7 @@ func userSingleUseCertsAuthChallenge(gctx *grpcContext, stream authpb.AuthServic auth := gctx.authServer user := gctx.User.GetName() - const passwordless = false - challenge, err := auth.mfaAuthChallenge(ctx, user, passwordless) + challenge, err := auth.mfaAuthChallenge(ctx, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION, false /* allowReuse */) if err != nil { return nil, trace.Wrap(err) } @@ -2829,11 +2826,11 @@ func userSingleUseCertsAuthChallenge(gctx *grpcContext, stream authpb.AuthServic if authResp == nil { return nil, trace.BadParameter("expected MFAAuthenticateResponse, got %T", req.Request) } - mfaDev, _, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, passwordless) + mfaData, err := auth.ValidateMFAAuthResponse(ctx, authResp, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION) if err != nil { return nil, trace.Wrap(err) } - return mfaDev, nil + return mfaData.Device, nil } func userSingleUseCertsGenerate(ctx context.Context, actx *grpcContext, req authpb.UserCertsRequest, mfaDev *types.MFADevice) (*authpb.SingleUseUserCert, error) { diff --git a/lib/auth/grpcserver_test.go b/lib/auth/grpcserver_test.go index 335d0c9d3809d..b679d3d32a73e 100644 --- a/lib/auth/grpcserver_test.go +++ b/lib/auth/grpcserver_test.go @@ -59,6 +59,7 @@ import ( "github.com/gravitational/teleport/api/observability/tracing" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/installers" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/sshutils" "github.com/gravitational/teleport/lib/auth/mocku2f" @@ -525,6 +526,7 @@ func testAddMFADevice(ctx context.Context, t *testing.T, authClient *Client, opt Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err, "CreateAuthenticateChallenge") authnSolved := opts.authHandler(t, authChal) @@ -566,6 +568,7 @@ func testDeleteMFADevice(ctx context.Context, t *testing.T, authClient *Client, Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) require.NoError(t, err, "CreateAuthenticateChallenge") authnSolved := opts.authHandler(t, authnChal) @@ -875,6 +878,7 @@ func TestGenerateUserCerts_deviceAuthz(t *testing.T) { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) if err != nil { return nil, err @@ -1757,6 +1761,7 @@ func testGenerateUserSingleUseCertsUnary(ctx context.Context, t *testing.T, cl * Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION, }) require.NoError(t, err, "CreateAuthenticateChallenge") @@ -3375,7 +3380,9 @@ func TestCustomRateLimiting(t *testing.T) { name: "RPC CreateAuthenticateChallenge", burst: defaults.LimiterBurst, fn: func(clt *Client) error { - _, err := clt.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{}) + _, err := clt.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, + }) return err }, }, diff --git a/lib/auth/helpers_mfa.go b/lib/auth/helpers_mfa.go index ddadf6e56a91c..769e139e6699d 100644 --- a/lib/auth/helpers_mfa.go +++ b/lib/auth/helpers_mfa.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/lib/auth/mocku2f" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" ) @@ -76,7 +77,8 @@ func NewTestDeviceFromChallenge(c *proto.MFARegisterChallenge, opts ...TestDevic // RegisterTestDevice creates and registers a TestDevice. // TOTP devices require a clock option. func RegisterTestDevice( - ctx context.Context, clt authClientI, devName string, devType proto.DeviceType, authenticator *TestDevice, opts ...TestDeviceOpt) (*TestDevice, error) { + ctx context.Context, clt authClientI, devName string, devType proto.DeviceType, authenticator *TestDevice, opts ...TestDeviceOpt, +) (*TestDevice, error) { dev := &TestDevice{} // Remaining parameters set during registration for _, opt := range opts { opt(dev) @@ -101,12 +103,14 @@ type authClientI interface { } func (d *TestDevice) registerDevice( - ctx context.Context, authClient authClientI, devName string, devType proto.DeviceType, authenticator *TestDevice) error { + ctx context.Context, authClient authClientI, devName string, devType proto.DeviceType, authenticator *TestDevice, +) error { // Re-authenticate using MFA. authnChal, err := authClient.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) if err != nil { return trace.Wrap(err) @@ -209,7 +213,6 @@ func (d *TestDevice) solveRegister(c *proto.MFARegisterChallenge) (*proto.MFAReg default: return nil, trace.BadParameter("unexpected challenge type: %T", c.Request) } - } func (d *TestDevice) solveRegisterWebauthn(c *proto.MFARegisterChallenge) (*proto.MFARegisterResponse, error) { diff --git a/lib/auth/integration/integrationv1/service_test.go b/lib/auth/integration/integrationv1/service_test.go index 910ed8ee588db..2cfb93bc16ea0 100644 --- a/lib/auth/integration/integrationv1/service_test.go +++ b/lib/auth/integration/integrationv1/service_test.go @@ -26,7 +26,6 @@ import ( "github.com/gravitational/trace" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/client/proto" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/auth/keystore" @@ -331,10 +330,6 @@ type testClient struct { services.UserGetter } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T, kind string, ca types.CertAuthority, clusterName string) (context.Context, localClient, *Service) { ctx := context.Background() backend, err := memory.New(memory.Config{}) diff --git a/lib/auth/machineid/machineidv1/bot_service.go b/lib/auth/machineid/machineidv1/bot_service.go index 9e6a4f1b6088e..1a0e6003d7ee6 100644 --- a/lib/auth/machineid/machineidv1/bot_service.go +++ b/lib/auth/machineid/machineidv1/bot_service.go @@ -263,7 +263,8 @@ func (bs *BotService) createBotAuthz(ctx context.Context) (*authz.Context, error } bs.logger.Warn("CreateBot authz fell back to legacy resource/verbs. Explicitly grant access to the Bot resource. From V16.0.0, this will fail!") } - if err := authz.AuthorizeAdminAction(ctx, authCtx); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authCtx); err != nil { return nil, trace.Wrap(err) } return authCtx, nil @@ -382,7 +383,8 @@ func (bs *BotService) UpsertBot(ctx context.Context, req *pb.UpsertBotRequest) ( if err != nil { return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, authCtx); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authCtx); err != nil { return nil, trace.Wrap(err) } diff --git a/lib/auth/methods.go b/lib/auth/methods.go index d590ee081318a..6550482c94dd0 100644 --- a/lib/auth/methods.go +++ b/lib/auth/methods.go @@ -32,6 +32,7 @@ import ( "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/utils/keys" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" "github.com/gravitational/teleport/lib/authz" @@ -379,8 +380,8 @@ func (a *Server) authenticateUserInternal(ctx context.Context, req AuthenticateU Webauthn: wantypes.CredentialAssertionResponseToProto(req.Webauthn), }, } - mfaDev, _, err := a.ValidateMFAAuthResponse(ctx, mfaResponse, user, passwordless) - return mfaDev, trace.Wrap(err) + mfaData, err := a.ValidateMFAAuthResponse(ctx, mfaResponse, user, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) + return mfaData.Device, trace.Wrap(err) } authErr = authenticateWebauthnError case req.OTP != nil: @@ -472,7 +473,7 @@ func (a *Server) authenticatePasswordless(ctx context.Context, req AuthenticateU Webauthn: wantypes.CredentialAssertionResponseToProto(req.Webauthn), }, } - dev, user, err := a.ValidateMFAAuthResponse(ctx, mfaResponse, "", true /* passwordless */) + mfaData, err := a.ValidateMFAAuthResponse(ctx, mfaResponse, "" /* user */, webauthnpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN) if err != nil { log.Debugf("Passwordless authentication failed: %v", err) return nil, "", trace.Wrap(authenticateWebauthnError) @@ -481,12 +482,12 @@ func (a *Server) authenticatePasswordless(ctx context.Context, req AuthenticateU // A distinction between passwordless and "plain" MFA is that we can't // acquire the user lock beforehand (or at all on failures!) // We do grab it here so successful logins go through the regular process. - if err := a.WithUserLock(ctx, user, func() error { return nil }); err != nil { - log.Debugf("WithUserLock for user %q failed during passwordless authentication: %v", user, err) - return nil, user, trace.Wrap(authenticateWebauthnError) + if err := a.WithUserLock(ctx, mfaData.User, func() error { return nil }); err != nil { + log.Debugf("WithUserLock for user %q failed during passwordless authentication: %v", mfaData.User, err) + return nil, mfaData.User, trace.Wrap(authenticateWebauthnError) } - return dev, user, nil + return mfaData.Device, mfaData.User, nil } func (a *Server) authenticateHeadless(ctx context.Context, req AuthenticateUserRequest) (mfa *types.MFADevice, err error) { diff --git a/lib/auth/okta/service_test.go b/lib/auth/okta/service_test.go index 52e3f4090675f..6fea653312f02 100644 --- a/lib/auth/okta/service_test.go +++ b/lib/auth/okta/service_test.go @@ -27,7 +27,6 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/constants" oktapb "github.com/gravitational/teleport/api/gen/proto/go/teleport/okta/v1" "github.com/gravitational/teleport/api/types" @@ -174,10 +173,6 @@ type testClient struct { services.UserGetter } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T, kind string) (context.Context, *Service) { ctx := context.Background() backend, err := memory.New(memory.Config{}) diff --git a/lib/auth/trust/trustv1/service.go b/lib/auth/trust/trustv1/service.go index 670680bf90bcd..b642262f02f72 100644 --- a/lib/auth/trust/trustv1/service.go +++ b/lib/auth/trust/trustv1/service.go @@ -195,7 +195,8 @@ func (s *Service) UpsertCertAuthority(ctx context.Context, req *trustpb.UpsertCe return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, authzCtx); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authzCtx); err != nil { return nil, trace.Wrap(err) } diff --git a/lib/auth/trust/trustv1/service_test.go b/lib/auth/trust/trustv1/service_test.go index 294824b70c872..7254c58066f11 100644 --- a/lib/auth/trust/trustv1/service_test.go +++ b/lib/auth/trust/trustv1/service_test.go @@ -68,8 +68,8 @@ type fakeAuthorizer struct { func (f *fakeAuthorizer) Authorize(ctx context.Context) (*authz.Context, error) { return &authz.Context{ - Checker: f.checker, - AdminActionAuthorized: true, + Checker: f.checker, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, }, nil } diff --git a/lib/auth/userloginstate/service_test.go b/lib/auth/userloginstate/service_test.go index cfec14b3bb992..b47075a2ae480 100644 --- a/lib/auth/userloginstate/service_test.go +++ b/lib/auth/userloginstate/service_test.go @@ -28,7 +28,6 @@ import ( "github.com/jonboulle/clockwork" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/client/proto" userloginstatev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userloginstate/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/header" @@ -203,10 +202,6 @@ type testClient struct { services.UserGetter } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T) (userContext context.Context, noAccessContext context.Context, svc *Service) { ctx := context.Background() clock := clockwork.NewFakeClock() diff --git a/lib/auth/userpreferences/userpreferencesv1/service_test.go b/lib/auth/userpreferences/userpreferencesv1/service_test.go index 10e489ed6bdf6..90f5b3e541844 100644 --- a/lib/auth/userpreferences/userpreferencesv1/service_test.go +++ b/lib/auth/userpreferences/userpreferencesv1/service_test.go @@ -25,7 +25,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/gravitational/teleport/api/client/proto" userpreferencesv1 "github.com/gravitational/teleport/api/gen/proto/go/userpreferences/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/authz" @@ -162,10 +161,6 @@ type testClient struct { services.UserGetter } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - return nil, "", nil -} - func initSvc(t *testing.T) (map[string]context.Context, *Service) { ctx := context.Background() backend, err := memory.New(memory.Config{}) diff --git a/lib/auth/users/usersv1/service.go b/lib/auth/users/usersv1/service.go index 060a1d279396b..a1c5566dcce8f 100644 --- a/lib/auth/users/usersv1/service.go +++ b/lib/auth/users/usersv1/service.go @@ -218,7 +218,8 @@ func (s *Service) CreateUser(ctx context.Context, req *userspb.CreateUserRequest return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, authzCtx); err != nil { + // Support reused MFA for bulk tctl create requests and chained invite commands (CreateResetPasswordToken). + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authzCtx); err != nil { return nil, trace.Wrap(err) } @@ -285,7 +286,8 @@ func (s *Service) UpdateUser(ctx context.Context, req *userspb.UpdateUserRequest return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, authzCtx); err != nil { + // Allow reused MFA responses to allow Updating a user after get (WebUI). + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authzCtx); err != nil { return nil, trace.Wrap(err) } @@ -356,7 +358,8 @@ func (s *Service) UpsertUser(ctx context.Context, req *userspb.UpsertUserRequest return nil, trace.Wrap(err) } - if err := authz.AuthorizeAdminAction(ctx, authzCtx); err != nil { + // Support reused MFA for bulk tctl create requests. + if err := authz.AuthorizeAdminActionAllowReusedMFA(ctx, authzCtx); err != nil { return nil, trace.Wrap(err) } diff --git a/lib/auth/users/usersv1/service_test.go b/lib/auth/users/usersv1/service_test.go index 71774e1267e01..e517ca206ab96 100644 --- a/lib/auth/users/usersv1/service_test.go +++ b/lib/auth/users/usersv1/service_test.go @@ -73,8 +73,8 @@ func (a fakeAuthorizer) Authorize(ctx context.Context) (*authz.Context, error) { }, }, }, - Identity: identity, - AdminActionAuthorized: true, + Identity: identity, + AdminActionAuthState: authz.AdminActionAuthNotRequired, }, nil } @@ -103,7 +103,7 @@ func (a fakeAuthorizer) Authorize(ctx context.Context) (*authz.Context, error) { Username: "alice", }, }, - AdminActionAuthorized: true, + AdminActionAuthState: authz.AdminActionAuthNotRequired, }, nil } @@ -876,7 +876,7 @@ func TestRBAC(t *testing.T) { Groups: []string{"dev"}, }, }, - AdminActionAuthorized: true, + AdminActionAuthState: authz.AdminActionAuthNotRequired, }})) require.NoError(t, err, "creating test service") diff --git a/lib/auth/webauthn/login.go b/lib/auth/webauthn/login.go index cfd659278a542..0d15ffbe11f48 100644 --- a/lib/auth/webauthn/login.go +++ b/lib/auth/webauthn/login.go @@ -67,13 +67,18 @@ type loginFlow struct { sessionData sessionIdentity } -func (f *loginFlow) begin(ctx context.Context, user string, passwordless bool) (*wantypes.CredentialAssertion, error) { - if user == "" && !passwordless { +func (f *loginFlow) begin(ctx context.Context, user string, scope wanpb.ChallengeScope, allowReuse bool) (*wantypes.CredentialAssertion, error) { + if allowReuse && scope != wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION { + return nil, trace.BadParameter("mfa challenges with scope %v cannot allow reuse", scope) + } + + isPasswordless := scope == wanpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN + if user == "" && !isPasswordless { return nil, trace.BadParameter("user required") } var u *webUser - if passwordless { + if isPasswordless { u = &webUser{} // Issue anonymous challenge. } else { webID, err := f.getWebID(ctx, user) @@ -145,7 +150,7 @@ func (f *loginFlow) begin(ctx context.Context, user string, passwordless bool) ( web, err := newWebAuthn(webAuthnParams{ cfg: f.Webauthn, rpID: f.Webauthn.RPID, - requireUserVerification: passwordless, + requireUserVerification: isPasswordless, }) if err != nil { return nil, trace.Wrap(err) @@ -153,7 +158,7 @@ func (f *loginFlow) begin(ctx context.Context, user string, passwordless bool) ( var assertion *protocol.CredentialAssertion var sessionData *wan.SessionData - if passwordless { + if isPasswordless { assertion, sessionData, err = web.BeginDiscoverableLogin(opts...) } else { assertion, sessionData, err = web.BeginLogin(u, opts...) @@ -167,6 +172,9 @@ func (f *loginFlow) begin(ctx context.Context, user string, passwordless bool) ( if err != nil { return nil, trace.Wrap(err) } + + sessionDataPB.AllowReuse = allowReuse + sessionDataPB.Scope = scope if err := f.sessionData.Upsert(ctx, user, sessionDataPB); err != nil { return nil, trace.Wrap(err) } @@ -185,44 +193,52 @@ func (f *loginFlow) getWebID(ctx context.Context, user string) ([]byte, error) { return wla.UserID, nil } -func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.CredentialAssertionResponse, passwordless bool) (*types.MFADevice, string, error) { +type WebauthnSessionData struct { + Device *types.MFADevice + User string + Reusable bool +} + +func (f *loginFlow) finish(ctx context.Context, user string, scope wanpb.ChallengeScope, resp *wantypes.CredentialAssertionResponse) (*WebauthnSessionData, error) { + isPasswordless := scope == wanpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN + switch { - case user == "" && !passwordless: - return nil, "", trace.BadParameter("user required") + case user == "" && !isPasswordless: + return nil, trace.BadParameter("user required") case resp == nil: // resp != nil is good enough to proceed, we leave remaining validations to // duo-labs/webauthn. - return nil, "", trace.BadParameter("credential assertion response required") + return nil, trace.BadParameter("credential assertion response required") } parsedResp, err := parseCredentialResponse(resp) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } origin := parsedResp.Response.CollectedClientData.Origin if err := validateOrigin(origin, f.Webauthn.RPID); err != nil { log.WithError(err).Debugf("WebAuthn: origin validation failed") - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } var webID []byte - if passwordless { + if isPasswordless { webID = parsedResp.Response.UserHandle if len(webID) == 0 { - return nil, "", trace.BadParameter("webauthn user handle required for passwordless") + return nil, trace.BadParameter("webauthn user handle required for passwordless") } // Fetch user from WebAuthn UserHandle (aka User ID). teleportUser, err := f.identity.GetTeleportUserByWebauthnID(ctx, webID) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } user = teleportUser } else { webID, err = f.getWebID(ctx, user) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } } @@ -230,11 +246,11 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred // registered device. devices, err := f.identity.GetMFADevices(ctx, user, false /* withSecrets */) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } dev, ok := findDeviceByID(devices, parsedResp.RawID) if !ok { - return nil, "", trace.BadParameter( + return nil, trace.BadParameter( "unknown device credential: %q", base64.RawURLEncoding.EncodeToString(parsedResp.RawID)) } @@ -245,7 +261,7 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred rpID := f.Webauthn.RPID switch { case dev.GetU2F() != nil && f.U2F == nil: - return nil, "", trace.BadParameter("U2F device attempted login, but U2F configuration not present") + return nil, trace.BadParameter("U2F device attempted login, but U2F configuration not present") case dev.GetU2F() != nil: rpID = f.U2F.AppID } @@ -256,10 +272,19 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred challenge := parsedResp.Response.CollectedClientData.Challenge sessionDataPB, err := f.sessionData.Get(ctx, user, challenge) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } sessionData := sessionFromPB(sessionDataPB) + // Check if the given requiredScope is satisfied by the challenge scope. + if scope != sessionDataPB.GetScope() { + // old clients do not yet provide a scope, so we only enforce scope opportunistically. + // TODO(Joerger): DELETE IN v16.0.0 + if sessionDataPB.GetScope() != wanpb.ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED { + return nil, trace.AccessDenied("required scope %q is not satisfied by the given webauthn credentials with scope %q", scope, sessionDataPB.GetScope()) + } + } + // Make sure _all_ credentials in the session are accounted for by the user. // webauthn.ValidateLogin requires it. for _, allowedCred := range sessionData.AllowedCredentialIDs { @@ -277,21 +302,21 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred cfg: f.Webauthn, rpID: rpID, origin: origin, - requireUserVerification: passwordless, + requireUserVerification: isPasswordless, }) if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } var credential *wan.Credential - if passwordless { + if isPasswordless { discoverUser := func(_, _ []byte) (wan.User, error) { return u, nil } credential, err = web.ValidateDiscoverableLogin(discoverUser, *sessionData, parsedResp) } else { credential, err = web.ValidateLogin(u, *sessionData, parsedResp) } if err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } if credential.Authenticator.CloneWarning { log.Warnf( @@ -300,7 +325,7 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred // Update last used timestamp and device counter. if err := setCounterAndTimestamps(dev, credential); err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } // Retroactively write the credential RPID, now that it cleared authn. if webDev := dev.GetWebauthn(); webDev != nil && webDev.CredentialRpId == "" { @@ -309,16 +334,22 @@ func (f *loginFlow) finish(ctx context.Context, user string, resp *wantypes.Cred } if err := f.identity.UpsertMFADevice(ctx, user, dev); err != nil { - return nil, "", trace.Wrap(err) + return nil, trace.Wrap(err) } // The user just solved the challenge, so let's make sure it won't be used - // again. - if err := f.sessionData.Delete(ctx, user, challenge); err != nil { - log.Warnf("WebAuthn: failed to delete login SessionData for user %v (passwordless = %v)", user, passwordless) + // again, unless reuse is explicitly allowed. + if !sessionDataPB.AllowReuse { + if err := f.sessionData.Delete(ctx, user, challenge); err != nil { + log.Warnf("WebAuthn: failed to delete login SessionData for user %v (scope = %v)", user, scope.String()) + } } - return dev, user, nil + return &WebauthnSessionData{ + Device: dev, + User: user, + Reusable: sessionDataPB.AllowReuse, + }, nil } func parseCredentialResponse(resp *wantypes.CredentialAssertionResponse) (*protocol.ParsedCredentialAssertionData, error) { diff --git a/lib/auth/webauthn/login_mfa.go b/lib/auth/webauthn/login_mfa.go index 0d8b100ca6029..fccbbf9aef336 100644 --- a/lib/auth/webauthn/login_mfa.go +++ b/lib/auth/webauthn/login_mfa.go @@ -22,8 +22,6 @@ import ( "context" "errors" - "github.com/gravitational/trace" - "github.com/gravitational/teleport/api/types" wanpb "github.com/gravitational/teleport/api/types/webauthn" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" @@ -94,29 +92,28 @@ type LoginFlow struct { // assertion. // As a side effect Begin may assign (and record in storage) a WebAuthn ID for // the user. -func (f *LoginFlow) Begin(ctx context.Context, user string) (*wantypes.CredentialAssertion, error) { +func (f *LoginFlow) Begin(ctx context.Context, user string, scope wanpb.ChallengeScope, allowReuse bool) (*wantypes.CredentialAssertion, error) { lf := &loginFlow{ U2F: f.U2F, Webauthn: f.Webauthn, identity: mfaIdentity{f.Identity}, sessionData: (*userSessionStorage)(f), } - return lf.begin(ctx, user, false /* passwordless */) + return lf.begin(ctx, user, scope, allowReuse) } // Finish is the second and last step of the LoginFlow. // It returns the MFADevice used to solve the challenge. If login is successful, // Finish has the side effect of updating the counter and last used timestamp of // the returned device. -func (f *LoginFlow) Finish(ctx context.Context, user string, resp *wantypes.CredentialAssertionResponse) (*types.MFADevice, error) { +func (f *LoginFlow) Finish(ctx context.Context, user string, resp *wantypes.CredentialAssertionResponse, scope wanpb.ChallengeScope) (*WebauthnSessionData, error) { lf := &loginFlow{ U2F: f.U2F, Webauthn: f.Webauthn, identity: mfaIdentity{f.Identity}, sessionData: (*userSessionStorage)(f), } - dev, _, err := lf.finish(ctx, user, resp, false /* passwordless */) - return dev, trace.Wrap(err) + return lf.finish(ctx, user, scope, resp) } type mfaIdentity struct { diff --git a/lib/auth/webauthn/login_passwordless.go b/lib/auth/webauthn/login_passwordless.go index 932df3b2c107b..ec8d4eaf5abf4 100644 --- a/lib/auth/webauthn/login_passwordless.go +++ b/lib/auth/webauthn/login_passwordless.go @@ -55,19 +55,19 @@ func (f *PasswordlessFlow) Begin(ctx context.Context) (*wantypes.CredentialAsser identity: passwordlessIdentity{f.Identity}, sessionData: (*globalSessionStorage)(f), } - return lf.begin(ctx, "" /* user */, true /* passwordless */) + return lf.begin(ctx, "" /* user */, wanpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN, false /* allowReuse */) } // Finish is the last step of the passwordless login flow. // It works similarly to LoginFlow.Finish, but the user identity is established // via the response UserHandle, instead of an explicit Teleport username. -func (f *PasswordlessFlow) Finish(ctx context.Context, resp *wantypes.CredentialAssertionResponse) (*types.MFADevice, string, error) { +func (f *PasswordlessFlow) Finish(ctx context.Context, resp *wantypes.CredentialAssertionResponse) (*WebauthnSessionData, error) { lf := &loginFlow{ Webauthn: f.Webauthn, identity: passwordlessIdentity{f.Identity}, sessionData: (*globalSessionStorage)(f), } - return lf.finish(ctx, "" /* user */, resp, true /* passwordless */) + return lf.finish(ctx, "" /* user */, wanpb.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN, resp) } type passwordlessIdentity struct { diff --git a/lib/auth/webauthn/login_test.go b/lib/auth/webauthn/login_test.go index 2b472c81a9ac1..6c5495df8f5a0 100644 --- a/lib/auth/webauthn/login_test.go +++ b/lib/auth/webauthn/login_test.go @@ -120,7 +120,7 @@ func TestLoginFlow_BeginFinish(t *testing.T) { } // 1st step of the login ceremony. - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) // We care about a few specific settings, for everything else defaults are // OK. @@ -148,15 +148,15 @@ func TestLoginFlow_BeginFinish(t *testing.T) { // 2nd and last step of the login ceremony. beforeLastUsed := time.Now().Add(-1 * time.Second) - loginDevice, err := webLogin.Finish(ctx, user, assertionResp) + webauthnData, err := webLogin.Finish(ctx, user, assertionResp, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) require.NoError(t, err) // Last used time and counter are updated. - require.True(t, beforeLastUsed.Before(loginDevice.LastUsed)) - require.Equal(t, wantCounter, getSignatureCounter(loginDevice)) + require.True(t, beforeLastUsed.Before(webauthnData.Device.LastUsed)) + require.Equal(t, wantCounter, getSignatureCounter(webauthnData.Device)) // Did we update the device in storage? require.NotEmpty(t, identity.UpdatedDevices) got := identity.UpdatedDevices[len(identity.UpdatedDevices)-1] - if diff := cmp.Diff(loginDevice, got); diff != "" { + if diff := cmp.Diff(webauthnData.Device, got); diff != "" { t.Errorf("Updated device mismatch (-want +got):\n%s", diff) } // Did we delete the challenge? @@ -222,7 +222,7 @@ func TestLoginFlow_Begin_errors(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - _, err := webLogin.Begin(ctx, test.user) + _, err := webLogin.Begin(ctx, test.user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.True(t, test.assertErrType(err), "got err = %v, want BadParameter", err) require.Contains(t, err.Error(), test.wantErr) }) @@ -260,7 +260,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { Webauthn: webConfig, Identity: identity, } - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) okResp, err := key.SignAssertion(webOrigin, assertion) require.NoError(t, err) @@ -289,7 +289,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { name: "NOK assertion with bad origin", user: user, createResp: func() *wantypes.CredentialAssertionResponse { - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) resp, err := key.SignAssertion("https://badorigin.com", assertion) require.NoError(t, err) @@ -300,7 +300,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { name: "NOK assertion with bad RPID", user: user, createResp: func() *wantypes.CredentialAssertionResponse { - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) assertion.Response.RelyingPartyID = "badrpid.com" @@ -313,7 +313,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { name: "NOK assertion signed by unknown device", user: user, createResp: func() *wantypes.CredentialAssertionResponse { - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) unknownKey, err := mocku2f.Create() @@ -330,7 +330,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { name: "NOK assertion with invalid signature", user: user, createResp: func() *wantypes.CredentialAssertionResponse { - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) // Flip a challenge bit, this should be enough to consistently fail // signature checking. @@ -344,7 +344,7 @@ func TestLoginFlow_Finish_errors(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - _, err := webLogin.Finish(ctx, test.user, test.createResp()) + _, err := webLogin.Finish(ctx, test.user, test.createResp(), wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) require.Error(t, err) }) } @@ -439,10 +439,10 @@ func TestPasswordlessFlow_BeginAndFinish(t *testing.T) { assertionResp.AssertionResponse.UserHandle = wla.UserID // 2nd and last step of the login ceremony. - mfaDevice, user, err := webLogin.Finish(ctx, assertionResp) + webauthnData, err := webLogin.Finish(ctx, assertionResp) require.NoError(t, err) - require.NotNil(t, mfaDevice) - require.Equal(t, test.user, user) + require.NotNil(t, webauthnData.Device) + require.Equal(t, user, test.user) }) } } @@ -501,7 +501,7 @@ func TestPasswordlessFlow_Finish_errors(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - _, _, err := webLogin.Finish(ctx, test.createResp()) + _, err := webLogin.Finish(ctx, test.createResp()) require.True(t, test.assertErrType(err), "assertErrType failed, err = %v", err) require.Contains(t, err.Error(), test.wantErrMsg) }) @@ -568,7 +568,7 @@ func TestCredentialRPID(t *testing.T) { Identity: identity, } - _, err := webLogin.Begin(ctx, user) + _, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) assert.NoError(t, err, "Begin failed, expected assertion for `dev1`") }) @@ -578,15 +578,15 @@ func TestCredentialRPID(t *testing.T) { Identity: identity, } - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err, "Begin failed") car, err := dev1Key.SignAssertion(origin, assertion) require.NoError(t, err, "SignAssertion failed") - mfaDev, err := webLogin.Finish(ctx, user, car) + webauthnData, err := webLogin.Finish(ctx, user, car, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) require.NoError(t, err, "Finish failed") - assert.Equal(t, rpID, mfaDev.GetWebauthn().CredentialRpId, "CredentialRpId mismatch") + assert.Equal(t, rpID, webauthnData.Device.GetWebauthn().CredentialRpId, "CredentialRpId mismatch") }) t.Run("login doesn't issue challenges for the wrong RPIDs", func(t *testing.T) { @@ -595,7 +595,7 @@ func TestCredentialRPID(t *testing.T) { Identity: identity, } - _, err := webLogin.Begin(ctx, user) + _, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) assert.ErrorIs(t, err, wanlib.ErrInvalidCredentials, "Begin error mismatch") }) @@ -612,7 +612,7 @@ func TestCredentialRPID(t *testing.T) { Webauthn: webOtherRP, Identity: identity, } - assertion, err := webLogin.Begin(ctx, user) + assertion, err := webLogin.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err, "Begin failed, expected assertion for device `other1`") // Verify that we got the correct device. @@ -624,6 +624,126 @@ func TestCredentialRPID(t *testing.T) { }) } +func TestLoginScopeAndReuse(t *testing.T) { + // webUser gets a newly registered device and a webID. + const webUser = "llama" + webIdentity := newFakeIdentity(webUser) + webConfig := &types.Webauthn{RPID: "example.com"} + + const webOrigin = "https://example.com" + ctx := context.Background() + + // Register a Webauthn device. + // Last registration step creates the user webID and adds the new device to + // identity. + webKey, err := mocku2f.Create() + require.NoError(t, err) + webKey.PreferRPID = true // Webauthn-registered device + webRegistration := &wanlib.RegistrationFlow{ + Webauthn: webConfig, + Identity: webIdentity, + } + cc, err := webRegistration.Begin(ctx, webUser, false /* passwordless */) + require.NoError(t, err) + ccr, err := webKey.SignCredentialCreation(webOrigin, cc) + require.NoError(t, err) + _, err = webRegistration.Finish(ctx, wanlib.RegisterResponse{ + User: webUser, + DeviceName: "webauthn1", + CreationResponse: ccr, + }) + require.NoError(t, err) + + tests := []struct { + name string + beginScope wanpb.ChallengeScope + beginAllowReuse bool + beginErr bool + finishScope wanpb.ChallengeScope + finishReusable bool + finishErr bool + }{ + { + name: "NOK mismatched scope", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED, + finishErr: true, + }, { + name: "OK matching scope", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + }, { + // old clients do not yet provide a scope, so we only enforce scope + // opportunistically during login finish. + // TODO(Joerger): DELETE IN v16.0.0 + name: "OK scope not specified", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_UNSPECIFIED, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + }, { + name: "NOK reuse not allowed for scope", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, + beginAllowReuse: true, + beginErr: true, + }, { + name: "NOK reuse requested but not allowed", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + beginAllowReuse: true, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + finishReusable: false, + finishErr: true, + }, { + name: "OK reuse not requested but allowed", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + beginAllowReuse: false, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + finishReusable: true, + }, { + name: "OK reuse requested allowed", + beginScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + beginAllowReuse: true, + finishScope: wanpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION, + finishReusable: true, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + identity := webIdentity + user := webUser + + webLogin := &wanlib.LoginFlow{ + Webauthn: webConfig, + Identity: webIdentity, + } + + assertion, err := webLogin.Begin(ctx, user, test.beginScope, test.beginAllowReuse) + if test.beginErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + assertionResp, err := webKey.SignAssertion(webOrigin, assertion) + require.NoError(t, err) + + webauthnData, err := webLogin.Finish(ctx, user, assertionResp, test.finishScope) + if test.finishErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, test.finishReusable, webauthnData.Reusable) + + // Session data should only be deleted if reuse was not requested on begin. + if test.beginAllowReuse { + require.NotEmpty(t, identity.SessionData) + } else { + require.Empty(t, identity.SessionData) + } + }) + } +} + type fakeIdentity struct { User *types.UserV2 // MappedUser is used as the reply to GetTeleportUserByWebauthnID. diff --git a/lib/auth/webauthncli/u2f_login_test.go b/lib/auth/webauthncli/u2f_login_test.go index 187a8278cddce..36383be498cc7 100644 --- a/lib/auth/webauthncli/u2f_login_test.go +++ b/lib/auth/webauthncli/u2f_login_test.go @@ -141,7 +141,7 @@ func TestLogin(t *testing.T) { } test.setUserPresence.SetUserPresence(true) - assertion, err := loginFlow.Begin(ctx, username) + assertion, err := loginFlow.Begin(ctx, username, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) if test.removeAppID { assertion.Response.Extensions = nil @@ -160,7 +160,7 @@ func TestLogin(t *testing.T) { require.NotNil(t, mfaResp.GetWebauthn()) require.Equal(t, test.wantRawID, mfaResp.GetWebauthn().RawId) - _, err = loginFlow.Finish(ctx, username, wantypes.CredentialAssertionResponseFromProto(mfaResp.GetWebauthn())) + _, err = loginFlow.Finish(ctx, username, wantypes.CredentialAssertionResponseFromProto(mfaResp.GetWebauthn()), wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN) require.NoError(t, err) }) } @@ -183,7 +183,7 @@ func TestLogin_errors(t *testing.T) { const user = "llama" const origin = "https://localhost" ctx := context.Background() - okAssertion, err := loginFlow.Begin(ctx, user) + okAssertion, err := loginFlow.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) tests := []struct { @@ -216,7 +216,7 @@ func TestLogin_errors(t *testing.T) { name: "NOK assertion missing challenge", origin: origin, getAssertion: func() *wantypes.CredentialAssertion { - assertion, err := loginFlow.Begin(ctx, user) + assertion, err := loginFlow.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) assertion.Response.Challenge = nil return assertion @@ -226,7 +226,7 @@ func TestLogin_errors(t *testing.T) { name: "NOK assertion missing RPID", origin: origin, getAssertion: func() *wantypes.CredentialAssertion { - assertion, err := loginFlow.Begin(ctx, user) + assertion, err := loginFlow.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) assertion.Response.RelyingPartyID = "" return assertion @@ -236,7 +236,7 @@ func TestLogin_errors(t *testing.T) { name: "NOK assertion missing credentials", origin: origin, getAssertion: func() *wantypes.CredentialAssertion { - assertion, err := loginFlow.Begin(ctx, user) + assertion, err := loginFlow.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) assertion.Response.AllowedCredentials = nil return assertion @@ -246,7 +246,7 @@ func TestLogin_errors(t *testing.T) { name: "NOK assertion invalid user verification requirement", origin: origin, getAssertion: func() *wantypes.CredentialAssertion { - assertion, err := loginFlow.Begin(ctx, user) + assertion, err := loginFlow.Begin(ctx, user, wanpb.ChallengeScope_CHALLENGE_SCOPE_LOGIN, false) require.NoError(t, err) assertion.Response.UserVerification = protocol.VerificationRequired return assertion diff --git a/lib/authz/permissions.go b/lib/authz/permissions.go index c5517d6e76056..0c95de7e50199 100644 --- a/lib/authz/permissions.go +++ b/lib/authz/permissions.go @@ -39,6 +39,7 @@ import ( "github.com/gravitational/teleport/api/mfa" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/keys" dtauthz "github.com/gravitational/teleport/lib/devicetrust/authz" @@ -73,10 +74,11 @@ type DeviceAuthorizationOpts struct { // AuthorizerOpts holds creation options for [NewAuthorizer]. type AuthorizerOpts struct { - ClusterName string - AccessPoint AuthorizerAccessPoint - LockWatcher *services.LockWatcher - Logger logrus.FieldLogger + ClusterName string + AccessPoint AuthorizerAccessPoint + MFAAuthenticator MFAAuthenticator + LockWatcher *services.LockWatcher + Logger logrus.FieldLogger // DeviceAuthorization holds Device Trust authorization options. // @@ -98,9 +100,11 @@ func NewAuthorizer(opts AuthorizerOpts) (Authorizer, error) { if logger == nil { logger = logrus.WithFields(logrus.Fields{trace.Component: "authorizer"}) } + return &authorizer{ clusterName: opts.ClusterName, accessPoint: opts.AccessPoint, + mfaAuthentictor: opts.MFAAuthenticator, lockWatcher: opts.LockWatcher, logger: logger, disableGlobalDeviceMode: opts.DeviceAuthorization.DisableGlobalMode, @@ -150,18 +154,32 @@ type AuthorizerAccessPoint interface { // GetSessionRecordingConfig returns session recording configuration. GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) +} - // ValidateMFAAuthResponse validates an MFA or passwordless challenge. - // Returns the device used to solve the challenge (if applicable) and the username. - ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) +// MFAAuthenticator authenticates MFA responses. +type MFAAuthenticator interface { + // ValidateMFAAuthResponse validates an MFA challenge response. + ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, requiredScope webauthnpb.ChallengeScope) (*MFAAuthData, error) +} + +// MFAAuthData contains a user's MFA authentication data for a validated MFA response. +type MFAAuthData struct { + // User is the authenticated Teleport User. + User string + // Device is the user's MFA device used to authenticate. + Device *types.MFADevice + // Reusable determines whether the MFA challenge response used to authenticate + // can be reused. Reusable MFAAuthData may be denied for specific actions. + Reusable bool } // authorizer creates new local authorizer type authorizer struct { - clusterName string - accessPoint AuthorizerAccessPoint - lockWatcher *services.LockWatcher - logger logrus.FieldLogger + clusterName string + accessPoint AuthorizerAccessPoint + mfaAuthentictor MFAAuthenticator + lockWatcher *services.LockWatcher + logger logrus.FieldLogger disableGlobalDeviceMode bool disableRoleDeviceMode bool @@ -193,9 +211,22 @@ type Context struct { // AdminActionVerified is whether this auth request is verified for admin actions. This // either means that the request was MFA verified through the context or Hardware Key support, // or the identity does not require admin MFA (built in roles, bot impersonated user, etc). + // TODO(Joerger): Deprecated in favor of AdminActionAuthState, remove once e is no longer dependent. AdminActionAuthorized bool + + // AdminActionAuthState is the state of admin action authorization for this auth context. + AdminActionAuthState AdminActionAuthState } +type AdminActionAuthState int + +const ( + AdminActionAuthUnauthorized AdminActionAuthState = iota + AdminActionAuthNotRequired + AdminActionAuthMFAVerified + AdminActionAuthMFAVerifiedWithReuse +) + // GetUserMetadata returns information about the authenticated identity // to be included in audit events. func (c *Context) GetUserMetadata() apievents.UserMetadata { @@ -376,39 +407,44 @@ func (a *authorizer) fromUser(ctx context.Context, userI interface{}) (*Context, // checkAdminActionVerification checks if this auth request is verified for admin actions. func (a *authorizer) checkAdminActionVerification(ctx context.Context, authContext *Context) error { + required, err := a.isAdminActionAuthorizationRequired(ctx, authContext) + if err != nil { + return trace.Wrap(err) + } + + if !required { + authContext.AdminActionAuthState = AdminActionAuthNotRequired + return nil + } + if err := a.authorizeAdminAction(ctx, authContext); err != nil { - if trace.IsNotFound(err) { - // missing MFA verification should be a noop. - return nil - } return trace.Wrap(err) } - authContext.AdminActionAuthorized = true return nil } -func (a *authorizer) authorizeAdminAction(ctx context.Context, authContext *Context) error { +func (a *authorizer) isAdminActionAuthorizationRequired(ctx context.Context, authContext *Context) (bool, error) { // Builtin roles do not require MFA to perform admin actions. switch authContext.Identity.(type) { case BuiltinRole, RemoteBuiltinRole: - return nil + return false, nil } authpref, err := a.accessPoint.GetAuthPreference(ctx) if err != nil { - return trace.Wrap(err) + return false, trace.Wrap(err) } // Admin actions do not require MFA when Webauthn is not enabled. if authpref.GetPreferredLocalMFA() != constants.SecondFactorWebauthn { - return nil + return false, nil } // Skip MFA check if the user is a Bot. if user, err := a.accessPoint.GetUser(ctx, authContext.Identity.GetIdentity().Username, false); err == nil && user.IsBot() { a.logger.Debugf("Skipping admin action MFA check for bot identity: %v", authContext.Identity.GetIdentity()) - return nil + return false, nil } // Skip MFA if the identity is being impersonated by the Bot or Admin built in role. @@ -416,7 +452,7 @@ func (a *authorizer) authorizeAdminAction(ctx context.Context, authContext *Cont impersonatorUser, err := a.accessPoint.GetUser(ctx, impersonator, false) if err == nil && impersonatorUser.IsBot() { a.logger.Debugf("Skipping admin action MFA check for bot-impersonated identity: %v", authContext.Identity.GetIdentity()) - return nil + return false, nil } // If we don't find a user matching the impersonator, it may be the admin role impersonating. @@ -426,27 +462,46 @@ func (a *authorizer) authorizeAdminAction(ctx context.Context, authContext *Cont if hostFQDNParts[1] == a.clusterName { if _, err := uuid.Parse(hostFQDNParts[0]); err == nil { a.logger.Debugf("Skipping admin action MFA check for admin-impersonated identity: %v", authContext.Identity.GetIdentity()) - return nil + return false, nil } } } } + return true, nil +} + +func (a *authorizer) authorizeAdminAction(ctx context.Context, authContext *Context) error { // Certain hardware-key based private key policies require MFA for each request. if authContext.Identity.GetIdentity().PrivateKeyPolicy.MFAVerified() { + authContext.AdminActionAuthState = AdminActionAuthMFAVerified return nil } // MFA is required to be passed through the request context. mfaResp, err := mfa.CredentialsFromContext(ctx) if err != nil { + if trace.IsNotFound(err) { + // missing MFA verification should be a noop. + return nil + } return trace.Wrap(err) } - if _, _, err := a.accessPoint.ValidateMFAAuthResponse(ctx, mfaResp, authContext.User.GetName(), false); err != nil { + if a.mfaAuthentictor == nil { + return trace.AccessDenied("failed to validate MFA auth response, authorizer missing mfaAuthenticator field") + } + + mfaData, err := a.mfaAuthentictor.ValidateMFAAuthResponse(ctx, mfaResp, authContext.User.GetName(), webauthnpb.ChallengeScope_CHALLENGE_SCOPE_ADMIN_ACTION) + if err != nil { return trace.Wrap(err) } + authContext.AdminActionAuthState = AdminActionAuthMFAVerified + if mfaData.Reusable { + authContext.AdminActionAuthState = AdminActionAuthMFAVerifiedWithReuse + } + return nil } @@ -1100,8 +1155,8 @@ func ContextForBuiltinRole(r BuiltinRole, recConfig types.SessionRecordingConfig Checker: checker, Identity: r, UnmappedIdentity: r, - disableDeviceRoleMode: true, // Builtin roles skip device trust. - AdminActionAuthorized: true, // builtin roles skip mfa for admin actions. + disableDeviceRoleMode: true, // Builtin roles skip device trust. + AdminActionAuthState: AdminActionAuthNotRequired, // builtin roles skip mfa for admin actions. }, nil } @@ -1325,10 +1380,24 @@ func AuthorizeContextWithVerbs(ctx context.Context, log logrus.FieldLogger, auth // AuthorizeAdminAction will ensure that the user is authorized to perform admin actions. func AuthorizeAdminAction(ctx context.Context, authCtx *Context) error { - if !authCtx.AdminActionAuthorized { - return trace.Wrap(&mfa.ErrAdminActionMFARequired) + // TODO(Joerger): AdminActionAuthorized is deprecated in favor of AdminActionAuthState, remove once e is no longer dependent. + if authCtx.AdminActionAuthorized { + return nil } - return nil + switch authCtx.AdminActionAuthState { + case AdminActionAuthMFAVerified, AdminActionAuthNotRequired: + return nil + } + return trace.Wrap(&mfa.ErrAdminActionMFARequired) +} + +// AuthorizeAdminActionAllowReusedMFA will ensure that the user is authorized to perform +// admin actions. Additionally, MFA challenges that allow reuse will be accepted. +func AuthorizeAdminActionAllowReusedMFA(ctx context.Context, authCtx *Context) error { + if authCtx.AdminActionAuthState == AdminActionAuthMFAVerifiedWithReuse { + return nil + } + return AuthorizeAdminAction(ctx, authCtx) } // LocalUser is a local user diff --git a/lib/authz/permissions_test.go b/lib/authz/permissions_test.go index 8eec1a8691a43..eef892dffa183 100644 --- a/lib/authz/permissions_test.go +++ b/lib/authz/permissions_test.go @@ -40,6 +40,7 @@ import ( "github.com/gravitational/teleport/api/mfa" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/utils/keys" "github.com/gravitational/teleport/lib/backend/memory" "github.com/gravitational/teleport/lib/modules" @@ -50,8 +51,7 @@ import ( ) const ( - clusterName = "test-cluster" - validTOTPCode = "valid" + clusterName = "test-cluster" ) func TestContextLockTargets(t *testing.T) { @@ -444,6 +444,18 @@ func hostFQDN(hostUUID, clusterName string) string { return fmt.Sprintf("%v.%v", hostUUID, clusterName) } +type fakeMFAAuthentictor struct { + mfaData map[string]*MFAAuthData +} + +func (a *fakeMFAAuthentictor) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, requiredScope webauthnpb.ChallengeScope) (*MFAAuthData, error) { + mfaData, ok := a.mfaData[resp.GetTOTP().GetCode()] + if !ok { + return nil, trace.AccessDenied("invalid MFA") + } + return mfaData, nil +} + func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { ctx := context.Background() client, watcher, _ := newTestResources(t) @@ -479,20 +491,57 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { _, err = client.CreateUser(ctx, bot) require.NoError(t, err) + validTOTPCode := "valid" + validReusableTOTPCode := "valid-reusable" + fakeMFAAuthentictor := &fakeMFAAuthentictor{ + mfaData: map[string]*MFAAuthData{ + validTOTPCode: {}, + validReusableTOTPCode: { + Reusable: true, + }, + }, + } + // Create a new authorizer. authorizer, err := NewAuthorizer(AuthorizerOpts{ - ClusterName: clusterName, - AccessPoint: client, - LockWatcher: watcher, + ClusterName: clusterName, + AccessPoint: client, + LockWatcher: watcher, + MFAAuthenticator: fakeMFAAuthentictor, }) require.NoError(t, err, "NewAuthorizer failed") + validMFA := &proto.MFAAuthenticateResponse{ + Response: &proto.MFAAuthenticateResponse_TOTP{ + TOTP: &proto.TOTPResponse{ + Code: validTOTPCode, + }, + }, + } + + validMFAWithReuse := &proto.MFAAuthenticateResponse{ + Response: &proto.MFAAuthenticateResponse_TOTP{ + TOTP: &proto.TOTPResponse{ + Code: validReusableTOTPCode, + }, + }, + } + + invalidMFA := &proto.MFAAuthenticateResponse{ + Response: &proto.MFAAuthenticateResponse_TOTP{ + TOTP: &proto.TOTPResponse{ + Code: "invalid", + }, + }, + } + for _, tt := range []struct { name string user IdentityGetter - withTOTPInContext string + withMFA *proto.MFAAuthenticateResponse + allowedReusedMFA bool contextGetter func() context.Context - wantErr string + wantErrContains string wantAdminActionAuthorized bool }{ { @@ -503,10 +552,9 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Username: localUser.GetName(), }, }, - wantErr: "", wantAdminActionAuthorized: false, }, { - name: "NOK local user with mfa verified cert", + name: "NOK local user mfa verified cert", user: LocalUser{ Username: localUser.GetName(), Identity: tlsca.Identity{ @@ -514,7 +562,6 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { MFAVerified: "mfa-verified-test", }, }, - wantErr: "", wantAdminActionAuthorized: false, }, { // edge case for the admin role check. @@ -525,32 +572,51 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Username: userWithHostName.GetName(), }, }, - wantErr: "", wantAdminActionAuthorized: false, }, { - name: "NOK local user with invalid mfa from context", + name: "NOK local user invalid mfa", user: LocalUser{ Username: localUser.GetName(), Identity: tlsca.Identity{ Username: localUser.GetName(), }, }, - withTOTPInContext: "invalid", - wantErr: "invalid MFA", + withMFA: invalidMFA, + wantErrContains: "invalid MFA", wantAdminActionAuthorized: true, }, { - name: "OK local user with valid mfa from context", + name: "NOK local user reused mfa with reuse not allowed", user: LocalUser{ Username: localUser.GetName(), Identity: tlsca.Identity{ Username: localUser.GetName(), }, }, - withTOTPInContext: validTOTPCode, - wantErr: "", + withMFA: validMFAWithReuse, + wantAdminActionAuthorized: false, + }, { + name: "OK local user valid mfa", + user: LocalUser{ + Username: localUser.GetName(), + Identity: tlsca.Identity{ + Username: localUser.GetName(), + }, + }, + withMFA: validMFA, + wantAdminActionAuthorized: true, + }, { + name: "OK local user reused mfa with reuse allowed", + user: LocalUser{ + Username: localUser.GetName(), + Identity: tlsca.Identity{ + Username: localUser.GetName(), + }, + }, + withMFA: validMFAWithReuse, + allowedReusedMFA: true, wantAdminActionAuthorized: true, }, { - name: "OK local user with mfa verified private key policy", + name: "OK local user mfa verified private key policy", user: LocalUser{ Username: localUser.GetName(), Identity: tlsca.Identity{ @@ -558,7 +624,6 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { PrivateKeyPolicy: keys.PrivateKeyPolicyHardwareKeyTouch, }, }, - wantErr: "", wantAdminActionAuthorized: true, }, { name: "OK admin", @@ -566,7 +631,6 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Role: types.RoleAdmin, Username: hostFQDN(uuid.NewString(), clusterName), }, - wantErr: "", wantAdminActionAuthorized: true, }, { name: "OK bot", @@ -576,7 +640,6 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Username: bot.GetName(), }, }, - wantErr: "", wantAdminActionAuthorized: true, }, { name: "OK admin impersonating local user", @@ -587,7 +650,6 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Impersonator: hostFQDN(uuid.NewString(), clusterName), }, }, - wantErr: "", wantAdminActionAuthorized: true, }, { name: "OK bot impersonating local user", @@ -598,21 +660,13 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { Impersonator: bot.GetName(), }, }, - wantErr: "", wantAdminActionAuthorized: true, }, } { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - if tt.withTOTPInContext != "" { - mfaResp := &proto.MFAAuthenticateResponse{ - Response: &proto.MFAAuthenticateResponse_TOTP{ - TOTP: &proto.TOTPResponse{ - Code: tt.withTOTPInContext, - }, - }, - } - encodedMFAResp, err := mfa.EncodeMFAChallengeResponseCredentials(mfaResp) + if tt.withMFA != nil { + encodedMFAResp, err := mfa.EncodeMFAChallengeResponseCredentials(tt.withMFA) require.NoError(t, err) md := metadata.MD(map[string][]string{ mfa.ResponseMetadataKey: {encodedMFAResp}, @@ -621,13 +675,19 @@ func TestAuthorizer_AuthorizeAdminAction(t *testing.T) { } userCtx := context.WithValue(ctx, contextUser, tt.user) authCtx, err := authorizer.Authorize(userCtx) - if tt.wantErr != "" { - require.ErrorContains(t, err, tt.wantErr, "Expected matching Authorize error") + if tt.wantErrContains != "" { + require.ErrorContains(t, err, tt.wantErrContains, "Expected matching Authorize error") return } require.NoError(t, err) - authAdminActionErr := AuthorizeAdminAction(ctx, authCtx) + var authAdminActionErr error + if tt.allowedReusedMFA { + authAdminActionErr = AuthorizeAdminActionAllowReusedMFA(ctx, authCtx) + } else { + authAdminActionErr = AuthorizeAdminAction(ctx, authCtx) + } + if tt.wantAdminActionAuthorized { require.NoError(t, authAdminActionErr) } else { @@ -1083,14 +1143,6 @@ type testClient struct { types.Events } -func (c *testClient) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAuthenticateResponse, user string, passwordless bool) (*types.MFADevice, string, error) { - if resp.GetTOTP().Code == validTOTPCode { - return &types.MFADevice{}, "", nil - } - - return nil, "", trace.AccessDenied("invalid MFA") -} - func newTestResources(t *testing.T) (*testClient, *services.LockWatcher, Authorizer) { backend, err := memory.New(memory.Config{}) require.NoError(t, err) diff --git a/lib/client/api.go b/lib/client/api.go index 871b267b8293a..22f9ba749e113 100644 --- a/lib/client/api.go +++ b/lib/client/api.go @@ -64,6 +64,7 @@ import ( "github.com/gravitational/teleport/api/profile" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/grpc/interceptors" "github.com/gravitational/teleport/api/utils/keys" @@ -5236,6 +5237,7 @@ func (tc *TeleportClient) HeadlessApprove(ctx context.Context, headlessAuthentic Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_HEADLESS, }) if err != nil { return trace.Wrap(err) diff --git a/lib/client/cluster_client.go b/lib/client/cluster_client.go index 2aec602aa0f85..b28162b3ff8c0 100644 --- a/lib/client/cluster_client.go +++ b/lib/client/cluster_client.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" proxyclient "github.com/gravitational/teleport/api/client/proxy" "github.com/gravitational/teleport/api/mfa" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/services" ) @@ -312,6 +313,7 @@ func PerformMFACeremony(ctx context.Context, params PerformMFACeremonyParams) (* Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_SESSION, MFARequiredCheck: mfaRequiredReq, }) if err != nil { diff --git a/lib/service/service.go b/lib/service/service.go index 0c4cfc0dceb15..dbee0efb240bf 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -1966,10 +1966,11 @@ func (process *TeleportProcess) initAuthService() error { // each serving requests for a "role" which is assigned to every connected // client based on their certificate (user, server, admin, etc) authorizer, err := authz.NewAuthorizer(authz.AuthorizerOpts{ - ClusterName: clusterName, - AccessPoint: authServer, - LockWatcher: lockWatcher, - Logger: log, + ClusterName: clusterName, + AccessPoint: authServer, + MFAAuthenticator: authServer, + LockWatcher: lockWatcher, + Logger: log, // Auth Server does explicit device authorization. // Various Auth APIs must allow access to unauthorized devices, otherwise it // is not possible to acquire device-aware certificates in the first place. diff --git a/lib/teleterm/clusters/cluster_headless.go b/lib/teleterm/clusters/cluster_headless.go index 8897f0aa95700..e15804af62cff 100644 --- a/lib/teleterm/clusters/cluster_headless.go +++ b/lib/teleterm/clusters/cluster_headless.go @@ -25,6 +25,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" ) // WatchPendingHeadlessAuthentications watches the backend for pending headless authentication requests for the user. @@ -117,6 +118,7 @@ func (c *Cluster) UpdateHeadlessAuthenticationState(ctx context.Context, headles Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_HEADLESS, }) if err != nil { return trace.Wrap(err) diff --git a/lib/web/mfa.go b/lib/web/mfa.go index 85fa932a83082..43b8558576b25 100644 --- a/lib/web/mfa.go +++ b/lib/web/mfa.go @@ -26,6 +26,7 @@ import ( "github.com/julienschmidt/httprouter" "github.com/gravitational/teleport/api/client/proto" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" "github.com/gravitational/teleport/lib/client" "github.com/gravitational/teleport/lib/httplib" @@ -130,15 +131,31 @@ func (h *Handler) addMFADeviceHandle(w http.ResponseWriter, r *http.Request, par return OK(), nil } +type createAuthenticateChallengeRequest struct { + Scope int `json:"scope"` + AllowReuse bool `json:"allow_reuse"` +} + // createAuthenticateChallengeHandle creates and returns MFA authentication challenges for the user in context (logged in user). // Used when users need to re-authenticate their second factors. func (h *Handler) createAuthenticateChallengeHandle(w http.ResponseWriter, r *http.Request, p httprouter.Params, c *SessionContext) (interface{}, error) { + var req createAuthenticateChallengeRequest + if err := httplib.ReadJSON(r, &req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := c.GetClient() if err != nil { return nil, trace.Wrap(err) } - chal, err := clt.CreateAuthenticateChallenge(r.Context(), &proto.CreateAuthenticateChallengeRequest{}) + chal, err := clt.CreateAuthenticateChallenge(r.Context(), &proto.CreateAuthenticateChallengeRequest{ + Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ + ContextUser: &proto.ContextUser{}, + }, + Scope: webauthnpb.ChallengeScope(req.Scope), + AllowReuse: req.AllowReuse, + }) if err != nil { return nil, trace.Wrap(err) } @@ -291,7 +308,8 @@ func (r *isMFARequiredRequest) checkAndGetProtoRequest() (*proto.IsMFARequiredRe Protocol: r.Database.Protocol, Database: r.Database.DatabaseName, Username: r.Database.Username, - }}, + }, + }, } } @@ -322,7 +340,8 @@ func (r *isMFARequiredRequest) checkAndGetProtoRequest() (*proto.IsMFARequiredRe WindowsDesktop: &proto.RouteToWindowsDesktop{ WindowsDesktop: r.WindowsDesktop.DesktopName, Login: r.WindowsDesktop.Login, - }}, + }, + }, } } @@ -340,7 +359,8 @@ func (r *isMFARequiredRequest) checkAndGetProtoRequest() (*proto.IsMFARequiredRe Node: &proto.NodeLogin{ Login: r.Node.Login, Node: r.Node.NodeName, - }}, + }, + }, } } diff --git a/tool/tsh/common/mfa.go b/tool/tsh/common/mfa.go index 572e958c1da87..b89e631dc223f 100644 --- a/tool/tsh/common/mfa.go +++ b/tool/tsh/common/mfa.go @@ -37,6 +37,7 @@ import ( "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/mfa" "github.com/gravitational/teleport/api/types" + webauthnpb "github.com/gravitational/teleport/api/types/webauthn" "github.com/gravitational/teleport/api/utils/prompt" "github.com/gravitational/teleport/lib/asciitable" "github.com/gravitational/teleport/lib/auth/touchid" @@ -334,7 +335,9 @@ func (c *mfaAddCommand) addDeviceRPC(ctx context.Context, tc *client.TeleportCli // Issue the authn challenge. // Required for the registration challenge. - authChallenge, err := aci.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{}) + authChallenge, err := aci.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{ + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, + }) if err != nil { return trace.Wrap(err) } @@ -596,6 +599,7 @@ func (c *mfaRemoveCommand) run(cf *CLIConf) error { Request: &proto.CreateAuthenticateChallengeRequest_ContextUser{ ContextUser: &proto.ContextUser{}, }, + Scope: webauthnpb.ChallengeScope_CHALLENGE_SCOPE_MANAGE_DEVICES, }) if err != nil { return trace.Wrap(err) diff --git a/web/packages/teleport/src/Account/AccountNew.tsx b/web/packages/teleport/src/Account/AccountNew.tsx index 6c9c2cb561925..53e7d10171ee7 100644 --- a/web/packages/teleport/src/Account/AccountNew.tsx +++ b/web/packages/teleport/src/Account/AccountNew.tsx @@ -35,6 +35,7 @@ import useManageDevices, { import AddDevice from './ManageDevices/AddDevice'; import { ActionButton, Header } from './Header'; import { PasswordBox } from './PasswordBox'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; export interface EnterpriseComponentProps { // TODO(bl-nero): Consider moving the notifications to its own store and @@ -208,6 +209,7 @@ export function Account({ onAuthenticated={setToken} onClose={hideReAuthenticate} actionText="registering a new device" + challengeScope={WebAuthnChallengeScope.SESSION} /> )} {isAddDeviceVisible && ( diff --git a/web/packages/teleport/src/Account/ManageDevices/ManageDevices.tsx b/web/packages/teleport/src/Account/ManageDevices/ManageDevices.tsx index df23b323f9359..4a8f204e53a3d 100644 --- a/web/packages/teleport/src/Account/ManageDevices/ManageDevices.tsx +++ b/web/packages/teleport/src/Account/ManageDevices/ManageDevices.tsx @@ -32,6 +32,7 @@ import ReAuthenticate from 'teleport/components/ReAuthenticate'; import AddDevice from './AddDevice'; import useManageDevices, { State } from './useManageDevices'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; export default function Container() { const ctx = useTeleport(); @@ -104,6 +105,7 @@ export function ManageDevices({ onAuthenticated={setToken} onClose={hideReAuthenticate} actionText="registering a new device" + challengeScope={WebAuthnChallengeScope.SESSION} /> )} {isAddDeviceVisible && ( diff --git a/web/packages/teleport/src/Console/DocumentSsh/useGetScpUrl.ts b/web/packages/teleport/src/Console/DocumentSsh/useGetScpUrl.ts index 0757e16ce77ef..4d168bff31f64 100644 --- a/web/packages/teleport/src/Console/DocumentSsh/useGetScpUrl.ts +++ b/web/packages/teleport/src/Console/DocumentSsh/useGetScpUrl.ts @@ -20,7 +20,7 @@ import { useCallback } from 'react'; import useAttempt from 'shared/hooks/useAttemptNext'; import cfg, { UrlScpParams } from 'teleport/config'; -import auth from 'teleport/services/auth/auth'; +import auth, { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; export default function useGetScpUrl(addMfaToScpUrls: boolean) { const { setAttempt, attempt, handleError } = useAttempt(''); @@ -35,7 +35,7 @@ export default function useGetScpUrl(addMfaToScpUrls: boolean) { return cfg.getScpUrl(params); } try { - let webauthn = await auth.getWebauthnResponse(); + let webauthn = await auth.getWebauthnResponse(WebAuthnChallengeScope.SESSION); setAttempt({ status: 'success', statusText: '', diff --git a/web/packages/teleport/src/Discover/ConnectMyComputer/TestConnection/TestConnection.tsx b/web/packages/teleport/src/Discover/ConnectMyComputer/TestConnection/TestConnection.tsx index f9a85457ad23a..cb08b08df75eb 100644 --- a/web/packages/teleport/src/Discover/ConnectMyComputer/TestConnection/TestConnection.tsx +++ b/web/packages/teleport/src/Discover/ConnectMyComputer/TestConnection/TestConnection.tsx @@ -53,6 +53,7 @@ import type { Option } from 'shared/components/Select'; import type { AgentStepProps } from '../../types'; import type { MfaAuthnResponse } from 'teleport/services/mfa'; import type { ConnectionDiagnosticRequest } from 'teleport/services/agents'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; export function TestConnection(props: AgentStepProps) { const { userService, storeUser } = useTeleport(); @@ -172,6 +173,7 @@ export function TestConnection(props: AgentStepProps) { }) } onClose={cancelMfaDialog} + challengeScope={WebAuthnChallengeScope.SESSION} /> )}
diff --git a/web/packages/teleport/src/Discover/Database/TestConnection/TestConnection.tsx b/web/packages/teleport/src/Discover/Database/TestConnection/TestConnection.tsx index 10cb0d6b50a68..432f9d8f64b0d 100644 --- a/web/packages/teleport/src/Discover/Database/TestConnection/TestConnection.tsx +++ b/web/packages/teleport/src/Discover/Database/TestConnection/TestConnection.tsx @@ -37,6 +37,7 @@ import { DatabaseEngine } from '../../SelectResource'; import { useTestConnection, State } from './useTestConnection'; import type { AgentStepProps } from '../../types'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; /** * @deprecated Refactor Discover/Database/TestConnection away from the container component @@ -89,6 +90,7 @@ export function TestConnectionView({ testConnection(makeTestConnRequest(), res)} onClose={cancelMfaDialog} + challengeScope={WebAuthnChallengeScope.SESSION} /> )}
Test Connection
diff --git a/web/packages/teleport/src/Discover/Kubernetes/TestConnection/TestConnection.tsx b/web/packages/teleport/src/Discover/Kubernetes/TestConnection/TestConnection.tsx index 5edf97a0dccff..38bda6145ade6 100644 --- a/web/packages/teleport/src/Discover/Kubernetes/TestConnection/TestConnection.tsx +++ b/web/packages/teleport/src/Discover/Kubernetes/TestConnection/TestConnection.tsx @@ -40,6 +40,7 @@ import { useTestConnection, State } from './useTestConnection'; import type { AgentStepProps } from '../../types'; import type { KubeImpersonation } from 'teleport/services/agents'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; /** * @deprecated Refactor Discover/Kubernetes/TestConnection away from the container component @@ -101,6 +102,7 @@ export function TestConnection({ testConnection(makeTestConnRequest(), res)} onClose={cancelMfaDialog} + challengeScope={WebAuthnChallengeScope.SESSION} /> )}
Test Connection
diff --git a/web/packages/teleport/src/Discover/Server/TestConnection/TestConnection.tsx b/web/packages/teleport/src/Discover/Server/TestConnection/TestConnection.tsx index 5a596ab99fade..18407a7a8b3e3 100644 --- a/web/packages/teleport/src/Discover/Server/TestConnection/TestConnection.tsx +++ b/web/packages/teleport/src/Discover/Server/TestConnection/TestConnection.tsx @@ -38,6 +38,7 @@ import { NodeMeta } from '../../useDiscover'; import type { Option } from 'shared/components/Select'; import type { AgentStepProps } from '../../types'; import type { MfaAuthnResponse } from 'teleport/services/mfa'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; export function TestConnection(props: AgentStepProps) { const { @@ -87,6 +88,7 @@ export function TestConnection(props: AgentStepProps) { testConnection(selectedOpt.value, res)} onClose={cancelMfaDialog} + challengeScope={WebAuthnChallengeScope.SESSION} /> )}
Test Connection
diff --git a/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.story.tsx b/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.story.tsx index 088bedae810a2..6cb3c2c8a05ac 100644 --- a/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.story.tsx +++ b/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.story.tsx @@ -47,4 +47,5 @@ const props: State = { onClose: () => null, auth2faType: 'on', actionText: 'performing this action', + challengeScope: 'CHALLENGE_SCOPE_UNSPECIFIED', }; diff --git a/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.tsx b/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.tsx index 9c769393a970d..327f073cf16e7 100644 --- a/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.tsx +++ b/web/packages/teleport/src/components/ReAuthenticate/ReAuthenticate.tsx @@ -47,6 +47,7 @@ export function ReAuthenticate({ auth2faType, preferredMfaType, actionText, + challengeScope, }: State) { const [otpToken, setOtpToken] = useState(''); const mfaOptions = createMfaOptions({ @@ -60,7 +61,7 @@ export function ReAuthenticate({ e.preventDefault(); if (mfaOption?.value === 'webauthn') { - submitWithWebauthn(); + submitWithWebauthn(challengeScope); } if (mfaOption?.value === 'otp') { submitWithTotp(otpToken); diff --git a/web/packages/teleport/src/components/ReAuthenticate/useReAuthenticate.ts b/web/packages/teleport/src/components/ReAuthenticate/useReAuthenticate.ts index 3ad3116768fff..09928da494a96 100644 --- a/web/packages/teleport/src/components/ReAuthenticate/useReAuthenticate.ts +++ b/web/packages/teleport/src/components/ReAuthenticate/useReAuthenticate.ts @@ -20,6 +20,7 @@ import useAttempt from 'shared/hooks/useAttemptNext'; import cfg from 'teleport/config'; import auth from 'teleport/services/auth'; +import { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; import type { MfaAuthnResponse } from 'teleport/services/mfa'; @@ -31,7 +32,7 @@ import type { MfaAuthnResponse } from 'teleport/services/mfa'; // token, and after successfully obtaining the token, the function // `onAuthenticated` will be called with this token. export default function useReAuthenticate(props: Props) { - const { onClose, actionText = defaultActionText } = props; + const { onClose, actionText = defaultActionText, challengeScope } = props; // Note that attempt state "success" is not used or required. // After the user submits, the control is passed back @@ -52,12 +53,12 @@ export default function useReAuthenticate(props: Props) { .catch(handleError); } - function submitWithWebauthn() { + function submitWithWebauthn(scope: WebAuthnChallengeScope) { setAttempt({ status: 'processing' }); if ('onMfaResponse' in props) { auth - .getWebauthnResponse() + .getWebauthnResponse(scope) .then(webauthnResponse => props.onMfaResponse({ webauthn_response: webauthnResponse }) ) @@ -66,7 +67,7 @@ export default function useReAuthenticate(props: Props) { } auth - .createPrivilegeTokenWithWebauthn() + .createPrivilegeTokenWithWebauthn(scope) .then(props.onAuthenticated) .catch((err: Error) => { // This catches a webauthn frontend error that occurs on Firefox and replaces it with a more helpful error message. @@ -96,6 +97,7 @@ export default function useReAuthenticate(props: Props) { auth2faType: cfg.getAuth2faType(), preferredMfaType: cfg.getPreferredMfaType(), actionText, + challengeScope, onClose, }; } @@ -114,6 +116,11 @@ type BaseProps = { * * */ actionText?: string; + /** + * The MFA challenge scope of the action to perform, as defined in webauthn.proto. + * + * */ + challengeScope: WebAuthnChallengeScope; }; // MfaResponseProps defines a function diff --git a/web/packages/teleport/src/services/api/api.ts b/web/packages/teleport/src/services/api/api.ts index 09107e3d3a70a..fb56785b91ca7 100644 --- a/web/packages/teleport/src/services/api/api.ts +++ b/web/packages/teleport/src/services/api/api.ts @@ -17,7 +17,7 @@ */ import 'whatwg-fetch'; -import auth from 'teleport/services/auth/auth'; +import auth, { WebAuthnChallengeScope } from 'teleport/services/auth/auth'; import { storageService } from '../storageService'; import { WebauthnAssertionResponse } from '../auth'; @@ -117,7 +117,7 @@ const api = { let webauthnResponseForRetry; try { - webauthnResponseForRetry = await auth.getWebauthnResponse(); + webauthnResponseForRetry = await auth.getWebauthnResponse(WebAuthnChallengeScope.ADMIN_ACTION); } catch (err) { throw new Error( 'Failed to fetch webauthn credentials, please connect a registered hardware key and try again. If you do not have a hardware key registered, you can add one from your account settings page.' diff --git a/web/packages/teleport/src/services/auth/auth.ts b/web/packages/teleport/src/services/auth/auth.ts index a90e511d57c7e..d65fb3da72b15 100644 --- a/web/packages/teleport/src/services/auth/auth.ts +++ b/web/packages/teleport/src/services/auth/auth.ts @@ -245,7 +245,11 @@ const auth = { headlessSSOAccept(transactionId: string) { return auth .checkWebauthnSupport() - .then(() => api.post(cfg.api.mfaAuthnChallengePath)) + .then(() => + api.post(cfg.api.mfaAuthnChallengePath, { + scope: 'CHALLENGE_SCOPE_HEADLESS', + }) + ) .then(res => navigator.credentials.get({ publicKey: makeMfaAuthenticateChallenge(res).webauthnPublicKey, @@ -273,12 +277,12 @@ const auth = { return api.post(cfg.api.createPrivilegeTokenPath, { secondFactorToken }); }, - fetchWebauthnChallenge() { + fetchWebauthnChallenge(scope: WebAuthnChallengeScope) { return auth .checkWebauthnSupport() .then(() => api - .post(cfg.api.mfaAuthnChallengePath) + .post(cfg.api.mfaAuthnChallengePath, { scope: scope }) .then(makeMfaAuthenticateChallenge) ) .then(res => @@ -288,8 +292,8 @@ const auth = { ); }, - createPrivilegeTokenWithWebauthn() { - return auth.fetchWebauthnChallenge().then(res => + createPrivilegeTokenWithWebauthn(scope) { + return auth.fetchWebauthnChallenge(scope).then(res => api.post(cfg.api.createPrivilegeTokenPath, { webauthnAssertionResponse: makeWebauthnAssertionResponse(res), }) @@ -300,9 +304,9 @@ const auth = { return api.post(cfg.api.createPrivilegeTokenPath, {}); }, - getWebauthnResponse() { + getWebauthnResponse(scope: WebAuthnChallengeScope) { return auth - .fetchWebauthnChallenge() + .fetchWebauthnChallenge(scope) .then(res => makeWebauthnAssertionResponse(res)); }, }; @@ -361,3 +365,15 @@ export type IsMfaRequiredKube = { cluster_name: string; }; }; + +// WebAuthnChallengeScope is a challenge scope. Possible values are defined in webauthn.proto +export enum WebAuthnChallengeScope { + UNSPECIFIED = 0, + LOGIN = 1, + PASSWORDLESS_LOGIN = 2, + MANAGE_DEVICES = 3, + RECOVERY = 4, + SESSION = 5, + HEADLESS = 6, + ADMIN_ACTION = 7, +} \ No newline at end of file