зеркало из https://github.com/microsoft/docker.git
Bump SwarmKit to 831df679a0b8a21b4dccd5791667d030642de7ff
Changes included: - Ingress network should not be attachable - [manager/state] Add fernet as an option for raft encryption - Log GRPC server errors - Log leadership changes at manager level - [state/raft] Increase raft ElectionTick to 10xHeartbeatTick - Remove the containerd executor - agent: backoff session when no remotes are available - [ca/manager] Remove root CA key encryption support entirely - Fix agent logging race (fixes https://github.com/docker/swarmkit/issues/2576) - Adding logic to restore networks in order Also adds github.com/fernet/fernet-go as a new dependency Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Родитель
7410b04649
Коммит
27749659d5
|
@ -43,7 +43,7 @@ func TestServiceWithPredefinedNetwork(t *testing.T) {
|
|||
|
||||
const ingressNet = "ingress"
|
||||
|
||||
func TestServiceWithIngressNetwork(t *testing.T) {
|
||||
func TestServiceRemoveKeepsIngressNetwork(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
|
@ -54,9 +54,7 @@ func TestServiceWithIngressNetwork(t *testing.T) {
|
|||
poll.WaitOn(t, swarmIngressReady(client), swarm.NetworkPoll)
|
||||
|
||||
var instances uint64 = 1
|
||||
serviceName := "TestIngressService"
|
||||
serviceSpec := swarmServiceSpec(serviceName, instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: ingressNet})
|
||||
serviceSpec := swarmServiceSpec(t.Name()+"-service", instances)
|
||||
serviceSpec.EndpointSpec = &swarmtypes.EndpointSpec{
|
||||
Ports: []swarmtypes.PortConfig{
|
||||
{
|
||||
|
|
|
@ -119,9 +119,10 @@ github.com/dmcgowan/go-tar go1.10
|
|||
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
||||
|
||||
# cluster
|
||||
github.com/docker/swarmkit 49a9d7f6ba3c1925262641e694c18eb43575f74b
|
||||
github.com/docker/swarmkit 831df679a0b8a21b4dccd5791667d030642de7ff
|
||||
github.com/gogo/protobuf v0.4
|
||||
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
|
||||
github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
||||
github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e
|
||||
golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca
|
||||
golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
|
||||
|
|
|
@ -324,6 +324,8 @@ func (a *Agent) run(ctx context.Context) {
|
|||
registered = nil // we only care about this once per session
|
||||
backoff = 0 // reset backoff
|
||||
sessionq = a.sessionq
|
||||
// re-report all task statuses when re-establishing a session
|
||||
go a.worker.Report(ctx, reporter)
|
||||
case err := <-session.errs:
|
||||
// TODO(stevvooe): This may actually block if a session is closed
|
||||
// but no error was sent. This must be the only place
|
||||
|
|
|
@ -67,7 +67,14 @@ func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionI
|
|||
)
|
||||
|
||||
if err != nil {
|
||||
s.errs <- err
|
||||
// since we are returning without launching the session goroutine, we
|
||||
// need to provide the delay that is guaranteed by calling this
|
||||
// function. We launch a goroutine so that we only delay the retry and
|
||||
// avoid blocking the main loop.
|
||||
go func() {
|
||||
time.Sleep(delay)
|
||||
s.errs <- err
|
||||
}()
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ type Worker interface {
|
|||
// The listener will be removed if the context is cancelled.
|
||||
Listen(ctx context.Context, reporter StatusReporter)
|
||||
|
||||
// Report resends the status of all tasks controlled by this worker.
|
||||
Report(ctx context.Context, reporter StatusReporter)
|
||||
|
||||
// Subscribe to log messages matching the subscription.
|
||||
Subscribe(ctx context.Context, subscription *api.SubscriptionMessage) error
|
||||
|
||||
|
@ -416,12 +419,23 @@ func (w *worker) Listen(ctx context.Context, reporter StatusReporter) {
|
|||
}()
|
||||
|
||||
// report the current statuses to the new listener
|
||||
w.reportAllStatuses(ctx, reporter)
|
||||
}
|
||||
|
||||
func (w *worker) Report(ctx context.Context, reporter StatusReporter) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
w.reportAllStatuses(ctx, reporter)
|
||||
}
|
||||
|
||||
func (w *worker) reportAllStatuses(ctx context.Context, reporter StatusReporter) {
|
||||
if err := w.db.View(func(tx *bolt.Tx) error {
|
||||
return WalkTaskStatus(tx, func(id string, status *api.TaskStatus) error {
|
||||
return reporter.UpdateTaskStatus(ctx, id, status)
|
||||
})
|
||||
}); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("failed reporting initial statuses to registered listener %v", reporter)
|
||||
log.G(ctx).WithError(err).Errorf("failed reporting initial statuses")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -578,15 +578,18 @@ type MaybeEncryptedRecord_Algorithm int32
|
|||
const (
|
||||
MaybeEncryptedRecord_NotEncrypted MaybeEncryptedRecord_Algorithm = 0
|
||||
MaybeEncryptedRecord_NACLSecretboxSalsa20Poly1305 MaybeEncryptedRecord_Algorithm = 1
|
||||
MaybeEncryptedRecord_FernetAES128CBC MaybeEncryptedRecord_Algorithm = 2
|
||||
)
|
||||
|
||||
var MaybeEncryptedRecord_Algorithm_name = map[int32]string{
|
||||
0: "NONE",
|
||||
1: "SECRETBOX_SALSA20_POLY1305",
|
||||
2: "FERNET_AES_128_CBC",
|
||||
}
|
||||
var MaybeEncryptedRecord_Algorithm_value = map[string]int32{
|
||||
"NONE": 0,
|
||||
"SECRETBOX_SALSA20_POLY1305": 1,
|
||||
"FERNET_AES_128_CBC": 2,
|
||||
}
|
||||
|
||||
func (x MaybeEncryptedRecord_Algorithm) String() string {
|
||||
|
@ -17043,321 +17046,324 @@ var (
|
|||
func init() { proto.RegisterFile("github.com/docker/swarmkit/api/types.proto", fileDescriptorTypes) }
|
||||
|
||||
var fileDescriptorTypes = []byte{
|
||||
// 5054 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0x4d, 0x6c, 0x24, 0x49,
|
||||
0x56, 0x76, 0xfd, 0xba, 0xea, 0x55, 0xd9, 0x4e, 0x47, 0x7b, 0x7b, 0xdc, 0xb5, 0xdd, 0x76, 0x4d,
|
||||
0xce, 0xf4, 0xce, 0x6c, 0x6f, 0x53, 0xfd, 0xb7, 0xbb, 0xea, 0x99, 0x61, 0x77, 0xa6, 0xfe, 0x6c,
|
||||
0xd7, 0xb6, 0x5d, 0x55, 0x8a, 0x2a, 0x77, 0xef, 0x22, 0x41, 0x92, 0xce, 0x0c, 0x97, 0x73, 0x9c,
|
||||
0x95, 0x51, 0x64, 0x66, 0xd9, 0x5d, 0x2c, 0x88, 0x16, 0x07, 0x40, 0x3e, 0xc1, 0x89, 0x45, 0xc8,
|
||||
0x08, 0x09, 0x8e, 0x48, 0x1c, 0x40, 0x42, 0x70, 0x1a, 0x24, 0x84, 0xf6, 0x06, 0x0b, 0x12, 0x5a,
|
||||
0x81, 0x64, 0x58, 0x1f, 0xb8, 0xad, 0xe0, 0x82, 0xb8, 0x80, 0x84, 0xe2, 0x27, 0xb3, 0xd2, 0xd5,
|
||||
0x69, 0xbb, 0x87, 0xdd, 0x8b, 0x5d, 0xf1, 0xde, 0xf7, 0x5e, 0x44, 0xbc, 0x88, 0x78, 0xf1, 0xde,
|
||||
0x8b, 0x84, 0x7b, 0x03, 0xcb, 0x3f, 0x18, 0xef, 0x55, 0x0c, 0x3a, 0x7c, 0x60, 0x52, 0xe3, 0x90,
|
||||
0xb8, 0x0f, 0xbc, 0x63, 0xdd, 0x1d, 0x1e, 0x5a, 0xfe, 0x03, 0x7d, 0x64, 0x3d, 0xf0, 0x27, 0x23,
|
||||
0xe2, 0x55, 0x46, 0x2e, 0xf5, 0x29, 0x42, 0x02, 0x50, 0x09, 0x00, 0x95, 0xa3, 0x47, 0xa5, 0xf5,
|
||||
0x01, 0xa5, 0x03, 0x9b, 0x3c, 0xe0, 0x88, 0xbd, 0xf1, 0xfe, 0x03, 0xdf, 0x1a, 0x12, 0xcf, 0xd7,
|
||||
0x87, 0x23, 0x21, 0x54, 0x5a, 0x9b, 0x05, 0x98, 0x63, 0x57, 0xf7, 0x2d, 0xea, 0x48, 0xfe, 0xca,
|
||||
0x80, 0x0e, 0x28, 0xff, 0xf9, 0x80, 0xfd, 0x12, 0x54, 0x75, 0x1d, 0xe6, 0x9f, 0x13, 0xd7, 0xb3,
|
||||
0xa8, 0x83, 0x56, 0x20, 0x63, 0x39, 0x26, 0x79, 0xb9, 0x9a, 0x28, 0x27, 0xde, 0x4f, 0x63, 0xd1,
|
||||
0x50, 0x1f, 0x02, 0xb4, 0xd8, 0x8f, 0xa6, 0xe3, 0xbb, 0x13, 0xa4, 0x40, 0xea, 0x90, 0x4c, 0x38,
|
||||
0x22, 0x8f, 0xd9, 0x4f, 0x46, 0x39, 0xd2, 0xed, 0xd5, 0xa4, 0xa0, 0x1c, 0xe9, 0xb6, 0xfa, 0xa3,
|
||||
0x04, 0x14, 0xaa, 0x8e, 0x43, 0x7d, 0xde, 0xbb, 0x87, 0x10, 0xa4, 0x1d, 0x7d, 0x48, 0xa4, 0x10,
|
||||
0xff, 0x8d, 0xea, 0x90, 0xb5, 0xf5, 0x3d, 0x62, 0x7b, 0xab, 0xc9, 0x72, 0xea, 0xfd, 0xc2, 0xe3,
|
||||
0xaf, 0x54, 0x5e, 0x9f, 0x72, 0x25, 0xa2, 0xa4, 0xb2, 0xcd, 0xd1, 0x7c, 0x10, 0x58, 0x8a, 0xa2,
|
||||
0x6f, 0xc2, 0xbc, 0xe5, 0x98, 0x96, 0x41, 0xbc, 0xd5, 0x34, 0xd7, 0xb2, 0x16, 0xa7, 0x65, 0x3a,
|
||||
0xfa, 0x5a, 0xfa, 0xfb, 0x67, 0xeb, 0x73, 0x38, 0x10, 0x2a, 0x7d, 0x00, 0x85, 0x88, 0xda, 0x98,
|
||||
0xb9, 0xad, 0x40, 0xe6, 0x48, 0xb7, 0xc7, 0x44, 0xce, 0x4e, 0x34, 0x3e, 0x4c, 0x3e, 0x4d, 0xa8,
|
||||
0x9f, 0xc0, 0x4a, 0x5b, 0x1f, 0x12, 0x73, 0x93, 0x38, 0xc4, 0xb5, 0x0c, 0x4c, 0x3c, 0x3a, 0x76,
|
||||
0x0d, 0xc2, 0xe6, 0x7a, 0x68, 0x39, 0x66, 0x30, 0x57, 0xf6, 0x3b, 0x5e, 0x8b, 0x5a, 0x87, 0xb7,
|
||||
0x1a, 0x96, 0x67, 0xb8, 0xc4, 0x27, 0x9f, 0x5b, 0x49, 0x2a, 0x50, 0x72, 0x96, 0x80, 0xa5, 0x59,
|
||||
0xe9, 0x9f, 0x83, 0x1b, 0xcc, 0xc4, 0xa6, 0xe6, 0x4a, 0x8a, 0xe6, 0x8d, 0x88, 0xc1, 0x95, 0x15,
|
||||
0x1e, 0xbf, 0x1f, 0x67, 0xa1, 0xb8, 0x99, 0x6c, 0xcd, 0xe1, 0x65, 0xae, 0x26, 0x20, 0xf4, 0x46,
|
||||
0xc4, 0x40, 0x06, 0xdc, 0x34, 0xe5, 0xa0, 0x67, 0xd4, 0x27, 0xb9, 0xfa, 0xd8, 0x65, 0xbc, 0x64,
|
||||
0x9a, 0x5b, 0x73, 0x78, 0x25, 0x50, 0x16, 0xed, 0xa4, 0x06, 0x90, 0x0b, 0x74, 0xab, 0xdf, 0x4b,
|
||||
0x40, 0x3e, 0x60, 0x7a, 0xe8, 0xcb, 0x90, 0x77, 0x74, 0x87, 0x6a, 0xc6, 0x68, 0xec, 0xf1, 0x09,
|
||||
0xa5, 0x6a, 0xc5, 0xf3, 0xb3, 0xf5, 0x5c, 0x5b, 0x77, 0x68, 0xbd, 0xbb, 0xeb, 0xe1, 0x1c, 0x63,
|
||||
0xd7, 0x47, 0x63, 0x0f, 0xbd, 0x0d, 0xc5, 0x21, 0x19, 0x52, 0x77, 0xa2, 0xed, 0x4d, 0x7c, 0xe2,
|
||||
0x49, 0xb3, 0x15, 0x04, 0xad, 0xc6, 0x48, 0xe8, 0x1b, 0x30, 0x3f, 0x10, 0x43, 0x5a, 0x4d, 0xf1,
|
||||
0xed, 0xf3, 0x4e, 0xdc, 0xe8, 0x67, 0x46, 0x8d, 0x03, 0x19, 0xf5, 0xb7, 0x13, 0xb0, 0x12, 0x52,
|
||||
0xc9, 0x2f, 0x8d, 0x2d, 0x97, 0x0c, 0x89, 0xe3, 0x7b, 0xe8, 0x6b, 0x90, 0xb5, 0xad, 0xa1, 0xe5,
|
||||
0x7b, 0xd2, 0xe6, 0x77, 0xe2, 0xd4, 0x86, 0x93, 0xc2, 0x12, 0x8c, 0xaa, 0x50, 0x74, 0x89, 0x47,
|
||||
0xdc, 0x23, 0xb1, 0xe3, 0xa5, 0x45, 0xaf, 0x11, 0xbe, 0x20, 0xa2, 0x6e, 0x40, 0xae, 0x6b, 0xeb,
|
||||
0xfe, 0x3e, 0x75, 0x87, 0x48, 0x85, 0xa2, 0xee, 0x1a, 0x07, 0x96, 0x4f, 0x0c, 0x7f, 0xec, 0x06,
|
||||
0xa7, 0xef, 0x02, 0x0d, 0xdd, 0x84, 0x24, 0x15, 0x1d, 0xe5, 0x6b, 0xd9, 0xf3, 0xb3, 0xf5, 0x64,
|
||||
0xa7, 0x87, 0x93, 0xd4, 0x53, 0x3f, 0x82, 0xe5, 0xae, 0x3d, 0x1e, 0x58, 0x4e, 0x83, 0x78, 0x86,
|
||||
0x6b, 0x8d, 0x98, 0x76, 0xb6, 0x2b, 0x99, 0x8f, 0x0a, 0x76, 0x25, 0xfb, 0x1d, 0x1e, 0xed, 0xe4,
|
||||
0xf4, 0x68, 0xab, 0xbf, 0x99, 0x84, 0xe5, 0xa6, 0x33, 0xb0, 0x1c, 0x12, 0x95, 0xbe, 0x0b, 0x8b,
|
||||
0x84, 0x13, 0xb5, 0x23, 0xe1, 0x6e, 0xa4, 0x9e, 0x05, 0x41, 0x0d, 0x7c, 0x50, 0x6b, 0xc6, 0x2f,
|
||||
0x3c, 0x8a, 0x9b, 0xfe, 0x6b, 0xda, 0x63, 0xbd, 0x43, 0x13, 0xe6, 0x47, 0x7c, 0x12, 0x9e, 0x5c,
|
||||
0xde, 0xbb, 0x71, 0xba, 0x5e, 0x9b, 0x67, 0xe0, 0x24, 0xa4, 0xec, 0x4f, 0xe2, 0x24, 0xfe, 0x24,
|
||||
0x09, 0x4b, 0x6d, 0x6a, 0x5e, 0xb0, 0x43, 0x09, 0x72, 0x07, 0xd4, 0xf3, 0x23, 0x0e, 0x31, 0x6c,
|
||||
0xa3, 0xa7, 0x90, 0x1b, 0xc9, 0xe5, 0x93, 0xab, 0x7f, 0x3b, 0x7e, 0xc8, 0x02, 0x83, 0x43, 0x34,
|
||||
0xfa, 0x08, 0xf2, 0xc1, 0x91, 0x61, 0xb3, 0x7d, 0x83, 0x8d, 0x33, 0xc5, 0xa3, 0x6f, 0x40, 0x56,
|
||||
0x2c, 0xc2, 0x6a, 0x9a, 0x4b, 0xde, 0x7d, 0x23, 0x9b, 0x63, 0x29, 0x84, 0x36, 0x21, 0xe7, 0xdb,
|
||||
0x9e, 0x66, 0x39, 0xfb, 0x74, 0x35, 0xc3, 0x15, 0xac, 0xc7, 0x3a, 0x19, 0x6a, 0x92, 0xfe, 0x76,
|
||||
0xaf, 0xe5, 0xec, 0xd3, 0x5a, 0xe1, 0xfc, 0x6c, 0x7d, 0x5e, 0x36, 0xf0, 0xbc, 0x6f, 0x7b, 0xec,
|
||||
0x87, 0xfa, 0x3b, 0x09, 0x28, 0x44, 0x50, 0xe8, 0x0e, 0x80, 0xef, 0x8e, 0x3d, 0x5f, 0x73, 0x29,
|
||||
0xf5, 0xb9, 0xb1, 0x8a, 0x38, 0xcf, 0x29, 0x98, 0x52, 0x1f, 0x55, 0xe0, 0x86, 0x41, 0x5c, 0x5f,
|
||||
0xb3, 0x3c, 0x6f, 0x4c, 0x5c, 0xcd, 0x1b, 0xef, 0x7d, 0x4a, 0x0c, 0x9f, 0x1b, 0xae, 0x88, 0x97,
|
||||
0x19, 0xab, 0xc5, 0x39, 0x3d, 0xc1, 0x40, 0x4f, 0xe0, 0x66, 0x14, 0x3f, 0x1a, 0xef, 0xd9, 0x96,
|
||||
0xa1, 0xb1, 0xc5, 0x4c, 0x71, 0x91, 0x1b, 0x53, 0x91, 0x2e, 0xe7, 0x3d, 0x23, 0x13, 0xf5, 0x87,
|
||||
0x09, 0x50, 0xb0, 0xbe, 0xef, 0xef, 0x90, 0xe1, 0x1e, 0x71, 0x7b, 0xbe, 0xee, 0x8f, 0x3d, 0x74,
|
||||
0x13, 0xb2, 0x36, 0xd1, 0x4d, 0xe2, 0xf2, 0x41, 0xe5, 0xb0, 0x6c, 0xa1, 0x5d, 0x76, 0x82, 0x75,
|
||||
0xe3, 0x40, 0xdf, 0xb3, 0x6c, 0xcb, 0x9f, 0xf0, 0xa1, 0x2c, 0xc6, 0x6f, 0xe1, 0x59, 0x9d, 0x15,
|
||||
0x1c, 0x11, 0xc4, 0x17, 0xd4, 0xa0, 0x55, 0x98, 0x1f, 0x12, 0xcf, 0xd3, 0x07, 0x84, 0x8f, 0x34,
|
||||
0x8f, 0x83, 0xa6, 0xfa, 0x11, 0x14, 0xa3, 0x72, 0xa8, 0x00, 0xf3, 0xbb, 0xed, 0x67, 0xed, 0xce,
|
||||
0x8b, 0xb6, 0x32, 0x87, 0x96, 0xa0, 0xb0, 0xdb, 0xc6, 0xcd, 0x6a, 0x7d, 0xab, 0x5a, 0xdb, 0x6e,
|
||||
0x2a, 0x09, 0xb4, 0x00, 0xf9, 0x69, 0x33, 0xa9, 0xfe, 0x59, 0x02, 0x80, 0x99, 0x5b, 0x4e, 0xea,
|
||||
0x43, 0xc8, 0x78, 0xbe, 0xee, 0x8b, 0x5d, 0xb9, 0xf8, 0xf8, 0xdd, 0xcb, 0xd6, 0x50, 0x8e, 0x97,
|
||||
0xfd, 0x23, 0x58, 0x88, 0x44, 0x47, 0x98, 0xbc, 0x30, 0x42, 0xe6, 0x20, 0x74, 0xd3, 0x74, 0xe5,
|
||||
0xc0, 0xf9, 0x6f, 0xf5, 0x23, 0xc8, 0x70, 0xe9, 0x8b, 0xc3, 0xcd, 0x41, 0xba, 0xc1, 0x7e, 0x25,
|
||||
0x50, 0x1e, 0x32, 0xb8, 0x59, 0x6d, 0x7c, 0x47, 0x49, 0x22, 0x05, 0x8a, 0x8d, 0x56, 0xaf, 0xde,
|
||||
0x69, 0xb7, 0x9b, 0xf5, 0x7e, 0xb3, 0xa1, 0xa4, 0xd4, 0xbb, 0x90, 0x69, 0x0d, 0x99, 0xe6, 0xdb,
|
||||
0x6c, 0xcb, 0xef, 0x13, 0x97, 0x38, 0x46, 0x70, 0x92, 0xa6, 0x04, 0xf5, 0xc7, 0x05, 0xc8, 0xec,
|
||||
0xd0, 0xb1, 0xe3, 0xa3, 0xc7, 0x11, 0xb7, 0xb5, 0x18, 0x1f, 0x21, 0x70, 0x60, 0xa5, 0x3f, 0x19,
|
||||
0x11, 0xe9, 0xd6, 0x6e, 0x42, 0x56, 0x1c, 0x0e, 0x39, 0x1d, 0xd9, 0x62, 0x74, 0x5f, 0x77, 0x07,
|
||||
0xc4, 0x97, 0xf3, 0x91, 0x2d, 0xf4, 0x3e, 0xbb, 0xb1, 0x74, 0x93, 0x3a, 0xf6, 0x84, 0x9f, 0xa1,
|
||||
0x9c, 0xb8, 0x96, 0x30, 0xd1, 0xcd, 0x8e, 0x63, 0x4f, 0x70, 0xc8, 0x45, 0x5b, 0x50, 0xdc, 0xb3,
|
||||
0x1c, 0x53, 0xa3, 0x23, 0xe1, 0xe4, 0x33, 0x97, 0x9f, 0x38, 0x31, 0xaa, 0x9a, 0xe5, 0x98, 0x1d,
|
||||
0x01, 0xc6, 0x85, 0xbd, 0x69, 0x03, 0xb5, 0x61, 0xf1, 0x88, 0xda, 0xe3, 0x21, 0x09, 0x75, 0x65,
|
||||
0xb9, 0xae, 0xf7, 0x2e, 0xd7, 0xf5, 0x9c, 0xe3, 0x03, 0x6d, 0x0b, 0x47, 0xd1, 0x26, 0x7a, 0x06,
|
||||
0x0b, 0xfe, 0x70, 0xb4, 0xef, 0x85, 0xea, 0xe6, 0xb9, 0xba, 0x2f, 0x5d, 0x61, 0x30, 0x06, 0x0f,
|
||||
0xb4, 0x15, 0xfd, 0x48, 0x0b, 0x6d, 0x42, 0xc1, 0xa0, 0x8e, 0x67, 0x79, 0x3e, 0x71, 0x8c, 0xc9,
|
||||
0x6a, 0x8e, 0xdb, 0xfe, 0x8a, 0x59, 0xd6, 0xa7, 0x60, 0x1c, 0x95, 0x2c, 0xfd, 0x7a, 0x0a, 0x0a,
|
||||
0x11, 0x13, 0xa0, 0x1e, 0x14, 0x46, 0x2e, 0x1d, 0xe9, 0x03, 0x7e, 0xe3, 0xc9, 0x45, 0x7d, 0xf4,
|
||||
0x46, 0xe6, 0xab, 0x74, 0xa7, 0x82, 0x38, 0xaa, 0x45, 0x3d, 0x4d, 0x42, 0x21, 0xc2, 0x44, 0xf7,
|
||||
0x20, 0x87, 0xbb, 0xb8, 0xf5, 0xbc, 0xda, 0x6f, 0x2a, 0x73, 0xa5, 0xdb, 0x27, 0xa7, 0xe5, 0x55,
|
||||
0xae, 0x2d, 0xaa, 0xa0, 0xeb, 0x5a, 0x47, 0x6c, 0x0f, 0xbf, 0x0f, 0xf3, 0x01, 0x34, 0x51, 0xfa,
|
||||
0xe2, 0xc9, 0x69, 0xf9, 0xad, 0x59, 0x68, 0x04, 0x89, 0x7b, 0x5b, 0x55, 0xdc, 0x6c, 0x28, 0xc9,
|
||||
0x78, 0x24, 0xee, 0x1d, 0xe8, 0x2e, 0x31, 0xd1, 0x97, 0x20, 0x2b, 0x81, 0xa9, 0x52, 0xe9, 0xe4,
|
||||
0xb4, 0x7c, 0x73, 0x16, 0x38, 0xc5, 0xe1, 0xde, 0x76, 0xf5, 0x79, 0x53, 0x49, 0xc7, 0xe3, 0x70,
|
||||
0xcf, 0xd6, 0x8f, 0x08, 0x7a, 0x17, 0x32, 0x02, 0x96, 0x29, 0xdd, 0x3a, 0x39, 0x2d, 0x7f, 0xe1,
|
||||
0x35, 0x75, 0x0c, 0x55, 0x5a, 0xfd, 0xad, 0x3f, 0x5a, 0x9b, 0xfb, 0xab, 0x3f, 0x5e, 0x53, 0x66,
|
||||
0xd9, 0xa5, 0xff, 0x49, 0xc0, 0xc2, 0x85, 0xbd, 0x83, 0x54, 0xc8, 0x3a, 0xd4, 0xa0, 0x23, 0x71,
|
||||
0x11, 0xe6, 0x6a, 0x70, 0x7e, 0xb6, 0x9e, 0x6d, 0xd3, 0x3a, 0x1d, 0x4d, 0xb0, 0xe4, 0xa0, 0x67,
|
||||
0x33, 0x57, 0xf9, 0x93, 0x37, 0xdc, 0x98, 0xb1, 0x97, 0xf9, 0xc7, 0xb0, 0x60, 0xba, 0xd6, 0x11,
|
||||
0x71, 0x35, 0x83, 0x3a, 0xfb, 0xd6, 0x40, 0x5e, 0x72, 0xa5, 0xd8, 0x78, 0x93, 0x03, 0x71, 0x51,
|
||||
0x08, 0xd4, 0x39, 0xfe, 0x27, 0xb8, 0xc6, 0x4b, 0xcf, 0xa1, 0x18, 0xdd, 0xea, 0xec, 0x5e, 0xf2,
|
||||
0xac, 0x5f, 0x26, 0x32, 0xb0, 0xe4, 0x61, 0x28, 0xce, 0x33, 0x8a, 0x08, 0x2b, 0xdf, 0x83, 0xf4,
|
||||
0x90, 0x9a, 0x42, 0xcf, 0x42, 0xed, 0x06, 0x8b, 0x26, 0xfe, 0xf9, 0x6c, 0xbd, 0x40, 0xbd, 0xca,
|
||||
0x86, 0x65, 0x93, 0x1d, 0x6a, 0x12, 0xcc, 0x01, 0xea, 0x11, 0xa4, 0x99, 0xcf, 0x41, 0x5f, 0x84,
|
||||
0x74, 0xad, 0xd5, 0x6e, 0x28, 0x73, 0xa5, 0xe5, 0x93, 0xd3, 0xf2, 0x02, 0x37, 0x09, 0x63, 0xb0,
|
||||
0xbd, 0x8b, 0xd6, 0x21, 0xfb, 0xbc, 0xb3, 0xbd, 0xbb, 0xc3, 0xb6, 0xd7, 0x8d, 0x93, 0xd3, 0xf2,
|
||||
0x52, 0xc8, 0x16, 0x46, 0x43, 0x77, 0x20, 0xd3, 0xdf, 0xe9, 0x6e, 0xf4, 0x94, 0x64, 0x09, 0x9d,
|
||||
0x9c, 0x96, 0x17, 0x43, 0x3e, 0x1f, 0x73, 0x69, 0x59, 0xae, 0x6a, 0x3e, 0xa4, 0xab, 0x3f, 0x48,
|
||||
0x40, 0x21, 0x72, 0xe0, 0xd8, 0xc6, 0x6c, 0x34, 0x37, 0xaa, 0xbb, 0xdb, 0x7d, 0x65, 0x2e, 0xb2,
|
||||
0x31, 0x23, 0x90, 0x06, 0xd9, 0xd7, 0xc7, 0x36, 0xf3, 0x73, 0x50, 0xef, 0xb4, 0x7b, 0xad, 0x5e,
|
||||
0xbf, 0xd9, 0xee, 0x2b, 0x89, 0xd2, 0xea, 0xc9, 0x69, 0x79, 0x65, 0x16, 0xbc, 0x31, 0xb6, 0x6d,
|
||||
0xb6, 0x35, 0xeb, 0xd5, 0xfa, 0x16, 0xdf, 0xeb, 0xd3, 0xad, 0x19, 0x41, 0xd5, 0x75, 0xe3, 0x80,
|
||||
0x98, 0xe8, 0x3e, 0xe4, 0x1b, 0xcd, 0xed, 0xe6, 0x66, 0x95, 0x7b, 0xf7, 0xd2, 0x9d, 0x93, 0xd3,
|
||||
0xf2, 0xad, 0xd7, 0x7b, 0xb7, 0xc9, 0x40, 0xf7, 0x89, 0x39, 0xb3, 0x45, 0x23, 0x10, 0xf5, 0xbf,
|
||||
0x92, 0xb0, 0x80, 0x59, 0x3a, 0xec, 0xfa, 0x5d, 0x6a, 0x5b, 0xc6, 0x04, 0x75, 0x21, 0x6f, 0x50,
|
||||
0xc7, 0xb4, 0x22, 0x7e, 0xe2, 0xf1, 0x25, 0x21, 0xd1, 0x54, 0x2a, 0x68, 0xd5, 0x03, 0x49, 0x3c,
|
||||
0x55, 0x82, 0x1e, 0x40, 0xc6, 0x24, 0xb6, 0x3e, 0x91, 0xb1, 0xd9, 0xad, 0x8a, 0x48, 0xb8, 0x2b,
|
||||
0x41, 0xc2, 0x5d, 0x69, 0xc8, 0x84, 0x1b, 0x0b, 0x1c, 0xcf, 0x41, 0xf4, 0x97, 0x9a, 0xee, 0xfb,
|
||||
0x64, 0x38, 0xf2, 0x45, 0x60, 0x96, 0xc6, 0x85, 0xa1, 0xfe, 0xb2, 0x2a, 0x49, 0xe8, 0x11, 0x64,
|
||||
0x8f, 0x2d, 0xc7, 0xa4, 0xc7, 0x32, 0xf6, 0xba, 0x42, 0xa9, 0x04, 0xaa, 0x27, 0x2c, 0x24, 0x99,
|
||||
0x19, 0x26, 0xdb, 0x43, 0xed, 0x4e, 0xbb, 0x19, 0xec, 0x21, 0xc9, 0xef, 0x38, 0x6d, 0xea, 0xb0,
|
||||
0xf3, 0x0f, 0x9d, 0xb6, 0xb6, 0x51, 0x6d, 0x6d, 0xef, 0x62, 0xb6, 0x8f, 0x56, 0x4e, 0x4e, 0xcb,
|
||||
0x4a, 0x08, 0xd9, 0xd0, 0x2d, 0x9b, 0x25, 0x03, 0xb7, 0x20, 0x55, 0x6d, 0x7f, 0x47, 0x49, 0x96,
|
||||
0x94, 0x93, 0xd3, 0x72, 0x31, 0x64, 0x57, 0x9d, 0xc9, 0xd4, 0xee, 0xb3, 0xfd, 0xaa, 0x7f, 0x97,
|
||||
0x82, 0xe2, 0xee, 0xc8, 0xd4, 0x7d, 0x22, 0xce, 0x19, 0x2a, 0x43, 0x61, 0xa4, 0xbb, 0xba, 0x6d,
|
||||
0x13, 0xdb, 0xf2, 0x86, 0xb2, 0x94, 0x10, 0x25, 0xa1, 0x0f, 0xde, 0xd4, 0x8c, 0xb5, 0x1c, 0x3b,
|
||||
0x3b, 0xdf, 0xfb, 0xd7, 0xf5, 0x44, 0x60, 0xd0, 0x5d, 0x58, 0xdc, 0x17, 0xa3, 0xd5, 0x74, 0x83,
|
||||
0x2f, 0x6c, 0x8a, 0x2f, 0x6c, 0x25, 0x6e, 0x61, 0xa3, 0xc3, 0xaa, 0xc8, 0x49, 0x56, 0xb9, 0x14,
|
||||
0x5e, 0xd8, 0x8f, 0x36, 0xd1, 0x13, 0x98, 0x1f, 0x52, 0xc7, 0xf2, 0xa9, 0x7b, 0xfd, 0x2a, 0x04,
|
||||
0x48, 0x74, 0x0f, 0x96, 0xd9, 0xe2, 0x06, 0xe3, 0xe1, 0x6c, 0x7e, 0x9d, 0x27, 0xf1, 0xd2, 0x50,
|
||||
0x7f, 0x29, 0x3b, 0xc4, 0x8c, 0x8c, 0x6a, 0x90, 0xa1, 0x2e, 0x8b, 0x17, 0xb3, 0x7c, 0xb8, 0xf7,
|
||||
0xaf, 0x1d, 0xae, 0x68, 0x74, 0x98, 0x0c, 0x16, 0xa2, 0xea, 0xd7, 0x61, 0xe1, 0xc2, 0x24, 0x58,
|
||||
0x98, 0xd4, 0xad, 0xee, 0xf6, 0x9a, 0xca, 0x1c, 0x2a, 0x42, 0xae, 0xde, 0x69, 0xf7, 0x5b, 0xed,
|
||||
0x5d, 0x16, 0xe7, 0x15, 0x21, 0x87, 0x3b, 0xdb, 0xdb, 0xb5, 0x6a, 0xfd, 0x99, 0x92, 0x54, 0x2b,
|
||||
0x50, 0x88, 0x68, 0x43, 0x8b, 0x00, 0xbd, 0x7e, 0xa7, 0xab, 0x6d, 0xb4, 0x70, 0xaf, 0x2f, 0xa2,
|
||||
0xc4, 0x5e, 0xbf, 0x8a, 0xfb, 0x92, 0x90, 0x50, 0xff, 0x23, 0x19, 0xac, 0xa8, 0x0c, 0x0c, 0x6b,
|
||||
0x17, 0x03, 0xc3, 0x2b, 0x06, 0x2f, 0x43, 0xc3, 0x69, 0x23, 0x0c, 0x10, 0x3f, 0x00, 0xe0, 0x1b,
|
||||
0x87, 0x98, 0x9a, 0xee, 0xcb, 0x85, 0x2f, 0xbd, 0x66, 0xe4, 0x7e, 0x50, 0xd1, 0xc2, 0x79, 0x89,
|
||||
0xae, 0xfa, 0xe8, 0x1b, 0x50, 0x34, 0xe8, 0x70, 0x64, 0x13, 0x29, 0x9c, 0xba, 0x56, 0xb8, 0x10,
|
||||
0xe2, 0xab, 0x7e, 0x34, 0x34, 0x4d, 0x5f, 0x0c, 0x9e, 0x7f, 0x23, 0x11, 0x58, 0x26, 0x26, 0x1a,
|
||||
0x2d, 0x42, 0x6e, 0xb7, 0xdb, 0xa8, 0xf6, 0x5b, 0xed, 0x4d, 0x25, 0x81, 0x00, 0xb2, 0xdc, 0xd4,
|
||||
0x0d, 0x25, 0xc9, 0xa2, 0xe8, 0x7a, 0x67, 0xa7, 0xbb, 0xdd, 0xe4, 0x1e, 0x0b, 0xad, 0x80, 0x12,
|
||||
0x18, 0x5b, 0xe3, 0x86, 0x6c, 0x36, 0x94, 0x34, 0xba, 0x01, 0x4b, 0x21, 0x55, 0x4a, 0x66, 0xd0,
|
||||
0x4d, 0x40, 0x21, 0x71, 0xaa, 0x22, 0xab, 0xfe, 0x2a, 0x2c, 0xd5, 0xa9, 0xe3, 0xeb, 0x96, 0x13,
|
||||
0x66, 0x18, 0x8f, 0xd9, 0xa4, 0x25, 0x49, 0xb3, 0x64, 0x25, 0xa8, 0xb6, 0x74, 0x7e, 0xb6, 0x5e,
|
||||
0x08, 0xa1, 0xad, 0x06, 0x0f, 0x95, 0x64, 0xc3, 0x64, 0xe7, 0x77, 0x64, 0x99, 0xdc, 0xb8, 0x99,
|
||||
0xda, 0xfc, 0xf9, 0xd9, 0x7a, 0xaa, 0xdb, 0x6a, 0x60, 0x46, 0x43, 0x5f, 0x84, 0x3c, 0x79, 0x69,
|
||||
0xf9, 0x9a, 0xc1, 0xee, 0x25, 0x66, 0xc0, 0x0c, 0xce, 0x31, 0x42, 0x9d, 0x5d, 0x43, 0x35, 0x80,
|
||||
0x2e, 0x75, 0x7d, 0xd9, 0xf3, 0x57, 0x21, 0x33, 0xa2, 0x2e, 0xaf, 0x5d, 0x5c, 0x5a, 0x51, 0x63,
|
||||
0x70, 0xb1, 0x51, 0xb1, 0x00, 0xab, 0xbf, 0x97, 0x02, 0xe8, 0xeb, 0xde, 0xa1, 0x54, 0xf2, 0x14,
|
||||
0xf2, 0x61, 0x75, 0x52, 0x16, 0x41, 0xae, 0x5c, 0xed, 0x10, 0x8c, 0x9e, 0x04, 0x9b, 0x4d, 0xe4,
|
||||
0x4e, 0xb1, 0x49, 0x6c, 0xd0, 0x51, 0x5c, 0xfa, 0x71, 0x31, 0x41, 0x62, 0xd7, 0x3c, 0x71, 0x5d,
|
||||
0xb9, 0xf2, 0xec, 0x27, 0xaa, 0xf3, 0x6b, 0x41, 0x18, 0x4d, 0x46, 0xdf, 0xb1, 0x65, 0x9f, 0x99,
|
||||
0x15, 0xd9, 0x9a, 0xc3, 0x53, 0x39, 0xf4, 0x31, 0x14, 0xd8, 0xbc, 0x35, 0x8f, 0xf3, 0x64, 0xe0,
|
||||
0x7d, 0xa9, 0xa9, 0x84, 0x06, 0x0c, 0xa3, 0xa9, 0x95, 0xef, 0x00, 0xe8, 0xa3, 0x91, 0x6d, 0x11,
|
||||
0x53, 0xdb, 0x9b, 0xf0, 0x48, 0x3b, 0x8f, 0xf3, 0x92, 0x52, 0x9b, 0xb0, 0xe3, 0x12, 0xb0, 0x75,
|
||||
0x9f, 0x47, 0xcf, 0xd7, 0x18, 0x50, 0xa2, 0xab, 0x7e, 0x4d, 0x81, 0x45, 0x77, 0xec, 0x30, 0x83,
|
||||
0xca, 0xd1, 0xa9, 0x7f, 0x9a, 0x84, 0xb7, 0xda, 0xc4, 0x3f, 0xa6, 0xee, 0x61, 0xd5, 0xf7, 0x75,
|
||||
0xe3, 0x60, 0x48, 0x1c, 0xb9, 0x7c, 0x91, 0x84, 0x26, 0x71, 0x21, 0xa1, 0x59, 0x85, 0x79, 0xdd,
|
||||
0xb6, 0x74, 0x8f, 0x88, 0xe0, 0x2d, 0x8f, 0x83, 0x26, 0x4b, 0xbb, 0x58, 0x12, 0x47, 0x3c, 0x8f,
|
||||
0x88, 0xba, 0x0a, 0x1b, 0x78, 0x40, 0x40, 0xdf, 0x85, 0x9b, 0x32, 0x4c, 0xd3, 0xc3, 0xae, 0x58,
|
||||
0x42, 0x11, 0x14, 0x68, 0x9b, 0xb1, 0x59, 0x65, 0xfc, 0xe0, 0x64, 0x1c, 0x37, 0x25, 0x77, 0x46,
|
||||
0xbe, 0x8c, 0x0a, 0x57, 0xcc, 0x18, 0x56, 0x69, 0x13, 0x6e, 0x5d, 0x2a, 0xf2, 0xb9, 0xea, 0x36,
|
||||
0xff, 0x98, 0x04, 0x68, 0x75, 0xab, 0x3b, 0xd2, 0x48, 0x0d, 0xc8, 0xee, 0xeb, 0x43, 0xcb, 0x9e,
|
||||
0x5c, 0xe5, 0x01, 0xa7, 0xf8, 0x4a, 0x55, 0x98, 0x63, 0x83, 0xcb, 0x60, 0x29, 0xcb, 0x73, 0xca,
|
||||
0xf1, 0x9e, 0x43, 0xfc, 0x30, 0xa7, 0xe4, 0x2d, 0x36, 0x0c, 0x57, 0x77, 0xc2, 0xad, 0x2b, 0x1a,
|
||||
0x6c, 0x01, 0x58, 0xc8, 0x73, 0xac, 0x4f, 0x02, 0xb7, 0x25, 0x9b, 0x68, 0x8b, 0x57, 0x47, 0x89,
|
||||
0x7b, 0x44, 0xcc, 0xd5, 0x0c, 0x37, 0xea, 0x75, 0xe3, 0xc1, 0x12, 0x2e, 0x6c, 0x17, 0x4a, 0x97,
|
||||
0x3e, 0xe2, 0x21, 0xd3, 0x94, 0xf5, 0xb9, 0x6c, 0xf4, 0x10, 0x16, 0x2e, 0xcc, 0xf3, 0xb5, 0x64,
|
||||
0xbe, 0xd5, 0x7d, 0xfe, 0x55, 0x25, 0x2d, 0x7f, 0x7d, 0x5d, 0xc9, 0xaa, 0x7f, 0x9b, 0x12, 0x8e,
|
||||
0x46, 0x5a, 0x35, 0xfe, 0x55, 0x20, 0xc7, 0x77, 0xb7, 0x41, 0x6d, 0xe9, 0x00, 0xde, 0xbb, 0xda,
|
||||
0xff, 0xb0, 0x9c, 0x8e, 0xc3, 0x71, 0x28, 0x88, 0xd6, 0xa1, 0x20, 0x76, 0xb1, 0xc6, 0x0e, 0x1c,
|
||||
0x37, 0xeb, 0x02, 0x06, 0x41, 0x62, 0x92, 0xe8, 0x2e, 0x2c, 0xf2, 0xe2, 0x8f, 0x77, 0x40, 0x4c,
|
||||
0x81, 0x49, 0x73, 0xcc, 0x42, 0x48, 0xe5, 0xb0, 0x1d, 0x28, 0x4a, 0x82, 0xc6, 0xe3, 0xf9, 0x0c,
|
||||
0x1f, 0xd0, 0xbd, 0xeb, 0x06, 0x24, 0x44, 0x78, 0x98, 0x5f, 0x18, 0x4d, 0x1b, 0xea, 0x2f, 0x42,
|
||||
0x2e, 0x18, 0x2c, 0x5a, 0x85, 0x54, 0xbf, 0xde, 0x55, 0xe6, 0x4a, 0x4b, 0x27, 0xa7, 0xe5, 0x42,
|
||||
0x40, 0xee, 0xd7, 0xbb, 0x8c, 0xb3, 0xdb, 0xe8, 0x2a, 0x89, 0x8b, 0x9c, 0xdd, 0x46, 0x17, 0x95,
|
||||
0x20, 0xdd, 0xab, 0xf7, 0xbb, 0x41, 0x7c, 0x16, 0xb0, 0x18, 0xad, 0x94, 0x66, 0xf1, 0x99, 0xba,
|
||||
0x0f, 0x85, 0x48, 0xef, 0xe8, 0x1d, 0x98, 0x6f, 0xb5, 0x37, 0x71, 0xb3, 0xd7, 0x53, 0xe6, 0x4a,
|
||||
0x37, 0x4f, 0x4e, 0xcb, 0x28, 0xc2, 0x6d, 0x39, 0x03, 0xb6, 0x76, 0xe8, 0x0e, 0xa4, 0xb7, 0x3a,
|
||||
0xec, 0xde, 0x17, 0xc9, 0x45, 0x04, 0xb1, 0x45, 0x3d, 0xbf, 0x74, 0x43, 0x06, 0x7e, 0x51, 0xc5,
|
||||
0xea, 0xef, 0x27, 0x20, 0x2b, 0x0e, 0x5a, 0xec, 0x22, 0x56, 0x61, 0x3e, 0x28, 0x21, 0x88, 0xc4,
|
||||
0xef, 0xbd, 0xcb, 0x93, 0xb4, 0x8a, 0xcc, 0xa9, 0xc4, 0xd6, 0x0c, 0xe4, 0x4a, 0x1f, 0x42, 0x31,
|
||||
0xca, 0xf8, 0x5c, 0x1b, 0xf3, 0xbb, 0x50, 0x60, 0x7b, 0x3f, 0x48, 0xd6, 0x1e, 0x43, 0x56, 0x38,
|
||||
0x8b, 0xf0, 0x1e, 0xba, 0x3c, 0x63, 0x94, 0x48, 0xf4, 0x14, 0xe6, 0x45, 0x96, 0x19, 0x54, 0x8e,
|
||||
0xd7, 0xae, 0x3e, 0x61, 0x38, 0x80, 0xab, 0x1f, 0x43, 0xba, 0x4b, 0x88, 0xcb, 0x6c, 0xef, 0x50,
|
||||
0x93, 0x4c, 0xaf, 0x6e, 0x99, 0x20, 0x9b, 0xa4, 0xd5, 0x60, 0x09, 0xb2, 0x49, 0x5a, 0x66, 0x58,
|
||||
0x1b, 0x4b, 0x46, 0x6a, 0x63, 0x7d, 0x28, 0xbe, 0x20, 0xd6, 0xe0, 0xc0, 0x27, 0x26, 0x57, 0x74,
|
||||
0x1f, 0xd2, 0x23, 0x12, 0x0e, 0x7e, 0x35, 0x76, 0xf3, 0x11, 0xe2, 0x62, 0x8e, 0x62, 0x3e, 0xe6,
|
||||
0x98, 0x4b, 0xcb, 0xe7, 0x0e, 0xd9, 0x52, 0xff, 0x21, 0x09, 0x8b, 0x2d, 0xcf, 0x1b, 0xeb, 0x8e,
|
||||
0x11, 0x44, 0x75, 0xdf, 0xbc, 0x18, 0xd5, 0xc5, 0xbe, 0x0b, 0x5d, 0x14, 0xb9, 0x58, 0xf2, 0x93,
|
||||
0x37, 0x6b, 0x32, 0xbc, 0x59, 0xd5, 0x1f, 0x27, 0x82, 0xba, 0xde, 0xdd, 0x88, 0x2b, 0x10, 0x39,
|
||||
0x62, 0x54, 0x13, 0xd9, 0x75, 0x0e, 0x1d, 0x7a, 0xec, 0xa0, 0xb7, 0x21, 0x83, 0x9b, 0xed, 0xe6,
|
||||
0x0b, 0x25, 0x21, 0xb6, 0xe7, 0x05, 0x10, 0x26, 0x0e, 0x39, 0x66, 0x9a, 0xba, 0xcd, 0x76, 0x83,
|
||||
0x45, 0x61, 0xc9, 0x18, 0x4d, 0x5d, 0xe2, 0x98, 0x96, 0x33, 0x40, 0xef, 0x40, 0xb6, 0xd5, 0xeb,
|
||||
0xed, 0xf2, 0x14, 0xf2, 0xad, 0x93, 0xd3, 0xf2, 0x8d, 0x0b, 0x28, 0x5e, 0xd3, 0x35, 0x19, 0x88,
|
||||
0xa5, 0x40, 0x2c, 0x3e, 0x8b, 0x01, 0xb1, 0xd8, 0x5a, 0x80, 0x70, 0xa7, 0x5f, 0xed, 0x37, 0x95,
|
||||
0x4c, 0x0c, 0x08, 0x53, 0xf6, 0x57, 0x1e, 0xb7, 0x7f, 0x49, 0x82, 0x52, 0x35, 0x0c, 0x32, 0xf2,
|
||||
0x19, 0x5f, 0x66, 0x9d, 0x7d, 0xc8, 0x8d, 0xd8, 0x2f, 0x8b, 0x04, 0x11, 0xd4, 0xd3, 0xd8, 0x97,
|
||||
0xcd, 0x19, 0xb9, 0x0a, 0xa6, 0x36, 0xa9, 0x9a, 0x43, 0xcb, 0xf3, 0x2c, 0xea, 0x08, 0x1a, 0x0e,
|
||||
0x35, 0x95, 0xfe, 0x33, 0x01, 0x37, 0x62, 0x10, 0xe8, 0x21, 0xa4, 0x5d, 0x6a, 0x07, 0x6b, 0x78,
|
||||
0xfb, 0xb2, 0x92, 0x2d, 0x13, 0xc5, 0x1c, 0x89, 0xd6, 0x00, 0xf4, 0xb1, 0x4f, 0x75, 0xde, 0x3f,
|
||||
0x5f, 0xbd, 0x1c, 0x8e, 0x50, 0xd0, 0x0b, 0xc8, 0x7a, 0xc4, 0x70, 0x49, 0x10, 0x67, 0x7f, 0xfc,
|
||||
0xff, 0x1d, 0x7d, 0xa5, 0xc7, 0xd5, 0x60, 0xa9, 0xae, 0x54, 0x81, 0xac, 0xa0, 0xb0, 0x6d, 0x6f,
|
||||
0xea, 0xbe, 0x2e, 0x0b, 0xfa, 0xfc, 0x37, 0xdb, 0x4d, 0xba, 0x3d, 0x08, 0x76, 0x93, 0x6e, 0x0f,
|
||||
0xd4, 0xbf, 0x49, 0x02, 0x34, 0x5f, 0xfa, 0xc4, 0x75, 0x74, 0xbb, 0x5e, 0x45, 0xcd, 0xc8, 0xcd,
|
||||
0x20, 0x66, 0xfb, 0xe5, 0xd8, 0x57, 0x8a, 0x50, 0xa2, 0x52, 0xaf, 0xc6, 0xdc, 0x0d, 0xb7, 0x20,
|
||||
0x35, 0x76, 0xe5, 0x63, 0xb5, 0x88, 0x91, 0x77, 0xf1, 0x36, 0x66, 0x34, 0xd4, 0x9c, 0xba, 0xad,
|
||||
0xd4, 0xe5, 0x4f, 0xd2, 0x91, 0x0e, 0x62, 0x5d, 0x17, 0x3b, 0xf9, 0x86, 0xae, 0x19, 0x44, 0xde,
|
||||
0x2a, 0x45, 0x71, 0xf2, 0xeb, 0xd5, 0x3a, 0x71, 0x7d, 0x9c, 0x35, 0x74, 0xf6, 0xff, 0x27, 0xf2,
|
||||
0x6f, 0xf7, 0x01, 0xa6, 0x53, 0x43, 0x6b, 0x90, 0xa9, 0x6f, 0xf4, 0x7a, 0xdb, 0xca, 0x9c, 0x70,
|
||||
0xe0, 0x53, 0x16, 0x27, 0xab, 0x7f, 0x99, 0x84, 0x5c, 0xbd, 0x2a, 0xaf, 0xdc, 0x3a, 0x28, 0xdc,
|
||||
0x2b, 0xf1, 0x67, 0x10, 0xf2, 0x72, 0x64, 0xb9, 0x13, 0xe9, 0x58, 0xae, 0x48, 0x78, 0x17, 0x99,
|
||||
0x08, 0x1b, 0x75, 0x93, 0x0b, 0x20, 0x0c, 0x45, 0x22, 0x8d, 0xa0, 0x19, 0x7a, 0xe0, 0xe3, 0xd7,
|
||||
0xae, 0x36, 0x96, 0x48, 0x5d, 0xa6, 0x6d, 0x0f, 0x17, 0x02, 0x25, 0x75, 0xdd, 0x43, 0x1f, 0xc0,
|
||||
0x92, 0x67, 0x0d, 0x1c, 0xcb, 0x19, 0x68, 0x81, 0xf1, 0xf8, 0x9b, 0x4c, 0x6d, 0xf9, 0xfc, 0x6c,
|
||||
0x7d, 0xa1, 0x27, 0x58, 0xd2, 0x86, 0x0b, 0x12, 0x59, 0xe7, 0xa6, 0x44, 0x5f, 0x87, 0xc5, 0x88,
|
||||
0x28, 0xb3, 0xa2, 0x30, 0xbb, 0x72, 0x7e, 0xb6, 0x5e, 0x0c, 0x25, 0x9f, 0x91, 0x09, 0x2e, 0x86,
|
||||
0x82, 0xcf, 0x08, 0xaf, 0xcd, 0xec, 0x53, 0xd7, 0x20, 0x9a, 0xcb, 0xcf, 0x34, 0xbf, 0xdd, 0xd3,
|
||||
0xb8, 0xc0, 0x69, 0xe2, 0x98, 0xab, 0xcf, 0xe1, 0x46, 0xc7, 0x35, 0x0e, 0x88, 0xe7, 0x0b, 0x53,
|
||||
0x48, 0x2b, 0x7e, 0x0c, 0xb7, 0x7d, 0xdd, 0x3b, 0xd4, 0x0e, 0x2c, 0xcf, 0xa7, 0xee, 0x44, 0x73,
|
||||
0x89, 0x4f, 0x1c, 0xc6, 0xd7, 0xf8, 0x43, 0xae, 0x2c, 0x08, 0xde, 0x62, 0x98, 0x2d, 0x01, 0xc1,
|
||||
0x01, 0x62, 0x9b, 0x01, 0xd4, 0x16, 0x14, 0x59, 0x0a, 0x23, 0x8b, 0x6a, 0x6c, 0xf6, 0x60, 0xd3,
|
||||
0x81, 0xf6, 0xc6, 0xd7, 0x54, 0xde, 0xa6, 0x03, 0xf1, 0x53, 0xfd, 0x36, 0x28, 0x0d, 0xcb, 0x1b,
|
||||
0xe9, 0xbe, 0x71, 0x10, 0x54, 0x3a, 0x51, 0x03, 0x94, 0x03, 0xa2, 0xbb, 0xfe, 0x1e, 0xd1, 0x7d,
|
||||
0x6d, 0x44, 0x5c, 0x8b, 0x9a, 0xd7, 0xaf, 0xf2, 0x52, 0x28, 0xd2, 0xe5, 0x12, 0xea, 0x7f, 0x27,
|
||||
0x00, 0xb0, 0xbe, 0x1f, 0x44, 0x6b, 0x5f, 0x81, 0x65, 0xcf, 0xd1, 0x47, 0xde, 0x01, 0xf5, 0x35,
|
||||
0xcb, 0xf1, 0x89, 0x7b, 0xa4, 0xdb, 0xb2, 0xb8, 0xa3, 0x04, 0x8c, 0x96, 0xa4, 0xa3, 0xfb, 0x80,
|
||||
0x0e, 0x09, 0x19, 0x69, 0xd4, 0x36, 0xb5, 0x80, 0x29, 0x9e, 0x99, 0xd3, 0x58, 0x61, 0x9c, 0x8e,
|
||||
0x6d, 0xf6, 0x02, 0x3a, 0xaa, 0xc1, 0x1a, 0x9b, 0x3e, 0x71, 0x7c, 0xd7, 0x22, 0x9e, 0xb6, 0x4f,
|
||||
0x5d, 0xcd, 0xb3, 0xe9, 0xb1, 0xb6, 0x4f, 0x6d, 0x9b, 0x1e, 0x13, 0x37, 0xa8, 0x9b, 0x95, 0x6c,
|
||||
0x3a, 0x68, 0x0a, 0xd0, 0x06, 0x75, 0x7b, 0x36, 0x3d, 0xde, 0x08, 0x10, 0x2c, 0xa4, 0x9b, 0xce,
|
||||
0xd9, 0xb7, 0x8c, 0xc3, 0x20, 0xa4, 0x0b, 0xa9, 0x7d, 0xcb, 0x38, 0x44, 0xef, 0xc0, 0x02, 0xb1,
|
||||
0x09, 0x2f, 0x9f, 0x08, 0x54, 0x86, 0xa3, 0x8a, 0x01, 0x91, 0x81, 0xd4, 0x4f, 0x40, 0x69, 0x3a,
|
||||
0x86, 0x3b, 0x19, 0x45, 0xd6, 0xfc, 0x3e, 0x20, 0xe6, 0x24, 0x35, 0x9b, 0x1a, 0x87, 0xda, 0x50,
|
||||
0x77, 0xf4, 0x01, 0x1b, 0x97, 0x78, 0xfd, 0x53, 0x18, 0x67, 0x9b, 0x1a, 0x87, 0x3b, 0x92, 0xae,
|
||||
0x7e, 0x00, 0xd0, 0x1b, 0xb9, 0x44, 0x37, 0x3b, 0x2c, 0x9a, 0x60, 0xa6, 0xe3, 0x2d, 0xcd, 0x94,
|
||||
0xaf, 0xa7, 0xd4, 0x95, 0x47, 0x5d, 0x11, 0x8c, 0x46, 0x48, 0x57, 0x7f, 0x1e, 0x6e, 0x74, 0x6d,
|
||||
0xdd, 0xe0, 0x5f, 0x12, 0x74, 0xc3, 0xe7, 0x2c, 0xf4, 0x14, 0xb2, 0x02, 0x2a, 0x57, 0x32, 0xf6,
|
||||
0xb8, 0x4d, 0xfb, 0xdc, 0x9a, 0xc3, 0x12, 0x5f, 0x2b, 0x02, 0x4c, 0xf5, 0xa8, 0x7f, 0x9e, 0x80,
|
||||
0x7c, 0xa8, 0x1f, 0x95, 0xc5, 0x2b, 0x8d, 0xef, 0xea, 0x96, 0x23, 0x33, 0xfe, 0x3c, 0x8e, 0x92,
|
||||
0x50, 0x0b, 0x0a, 0xa3, 0x50, 0xfa, 0xca, 0x78, 0x2e, 0x66, 0xd4, 0x38, 0x2a, 0x8b, 0x3e, 0x84,
|
||||
0x7c, 0xf0, 0x5c, 0x1d, 0x78, 0xd8, 0xab, 0x5f, 0xb7, 0xa7, 0x70, 0xf5, 0x9b, 0x00, 0xdf, 0xa2,
|
||||
0x96, 0xd3, 0xa7, 0x87, 0xc4, 0xe1, 0xcf, 0xaf, 0x2c, 0x5f, 0x24, 0x81, 0x15, 0x65, 0x8b, 0x97,
|
||||
0x01, 0xc4, 0x12, 0x84, 0xaf, 0x90, 0xa2, 0xa9, 0xfe, 0x75, 0x12, 0xb2, 0x98, 0x52, 0xbf, 0x5e,
|
||||
0x45, 0x65, 0xc8, 0x4a, 0x3f, 0xc1, 0xef, 0x9f, 0x5a, 0xfe, 0xfc, 0x6c, 0x3d, 0x23, 0x1c, 0x44,
|
||||
0xc6, 0xe0, 0x9e, 0x21, 0xe2, 0xc1, 0x93, 0x97, 0x79, 0x70, 0xf4, 0x10, 0x8a, 0x12, 0xa4, 0x1d,
|
||||
0xe8, 0xde, 0x81, 0x48, 0xde, 0x6a, 0x8b, 0xe7, 0x67, 0xeb, 0x20, 0x90, 0x5b, 0xba, 0x77, 0x80,
|
||||
0x41, 0xa0, 0xd9, 0x6f, 0xd4, 0x84, 0xc2, 0xa7, 0xd4, 0x72, 0x34, 0x9f, 0x4f, 0x42, 0x16, 0x1a,
|
||||
0x63, 0xd7, 0x71, 0x3a, 0x55, 0xf9, 0x2d, 0x02, 0x7c, 0x3a, 0x9d, 0x7c, 0x13, 0x16, 0x5c, 0x4a,
|
||||
0x7d, 0xe1, 0xb6, 0x2c, 0xea, 0xc8, 0x1a, 0x46, 0x39, 0xb6, 0xb4, 0x4d, 0xa9, 0x8f, 0x25, 0x0e,
|
||||
0x17, 0xdd, 0x48, 0x0b, 0x3d, 0x84, 0x15, 0x5b, 0xf7, 0x7c, 0x8d, 0xfb, 0x3b, 0x73, 0xaa, 0x2d,
|
||||
0xcb, 0x8f, 0x1a, 0x62, 0xbc, 0x0d, 0xce, 0x0a, 0x24, 0xd4, 0x7f, 0x4a, 0x40, 0x81, 0x4d, 0xc6,
|
||||
0xda, 0xb7, 0x0c, 0x16, 0xe4, 0x7d, 0xfe, 0xd8, 0xe3, 0x16, 0xa4, 0x0c, 0xcf, 0x95, 0x46, 0xe5,
|
||||
0x97, 0x6f, 0xbd, 0x87, 0x31, 0xa3, 0xa1, 0x4f, 0x20, 0x2b, 0x6b, 0x29, 0x22, 0xec, 0x50, 0xaf,
|
||||
0x0f, 0x47, 0xa5, 0x6d, 0xa4, 0x1c, 0xdf, 0xcb, 0xd3, 0xd1, 0x89, 0x4b, 0x00, 0x47, 0x49, 0xe8,
|
||||
0x26, 0x24, 0x0d, 0x61, 0x2e, 0xf9, 0xb1, 0x4b, 0xbd, 0x8d, 0x93, 0x86, 0xa3, 0xfe, 0x20, 0x01,
|
||||
0x0b, 0xd3, 0x03, 0xcf, 0x76, 0xc0, 0x6d, 0xc8, 0x7b, 0xe3, 0x3d, 0x6f, 0xe2, 0xf9, 0x64, 0x18,
|
||||
0x3c, 0x2d, 0x87, 0x04, 0xd4, 0x82, 0xbc, 0x6e, 0x0f, 0xa8, 0x6b, 0xf9, 0x07, 0x43, 0x99, 0xa5,
|
||||
0xc6, 0x87, 0x0a, 0x51, 0x9d, 0x95, 0x6a, 0x20, 0x82, 0xa7, 0xd2, 0xc1, 0xbd, 0x2f, 0xbe, 0x3f,
|
||||
0xe0, 0xf7, 0xfe, 0xdb, 0x50, 0xb4, 0xf5, 0x21, 0x2f, 0x2e, 0xf9, 0xd6, 0x50, 0xcc, 0x23, 0x8d,
|
||||
0x0b, 0x92, 0xd6, 0xb7, 0x86, 0x44, 0x55, 0x21, 0x1f, 0x2a, 0x43, 0x4b, 0x50, 0xa8, 0x36, 0x7b,
|
||||
0xda, 0xa3, 0xc7, 0x4f, 0xb5, 0xcd, 0xfa, 0x8e, 0x32, 0x27, 0x63, 0xd3, 0xbf, 0x48, 0xc0, 0x82,
|
||||
0x74, 0x47, 0x32, 0xde, 0x7f, 0x07, 0xe6, 0x5d, 0x7d, 0xdf, 0x0f, 0x32, 0x92, 0xb4, 0xd8, 0xd5,
|
||||
0xcc, 0xc3, 0xb3, 0x8c, 0x84, 0xb1, 0xe2, 0x33, 0x92, 0xc8, 0xc7, 0x0e, 0xa9, 0x2b, 0x3f, 0x76,
|
||||
0x48, 0xff, 0x54, 0x3e, 0x76, 0x50, 0x7f, 0x0d, 0x60, 0xc3, 0xb2, 0x49, 0x5f, 0xd4, 0xa1, 0xe2,
|
||||
0xf2, 0x4b, 0x16, 0xc3, 0xc9, 0x3a, 0x67, 0x10, 0xc3, 0xb5, 0x1a, 0x98, 0xd1, 0x18, 0x6b, 0x60,
|
||||
0x99, 0xf2, 0x30, 0x72, 0xd6, 0x26, 0x63, 0x0d, 0x2c, 0x33, 0x7c, 0x95, 0x4b, 0x5f, 0xf7, 0x2a,
|
||||
0x77, 0x9a, 0x80, 0x25, 0x19, 0xbb, 0x86, 0xee, 0xf7, 0xcb, 0x90, 0x17, 0x61, 0xec, 0x34, 0xa1,
|
||||
0xe3, 0x0f, 0xfc, 0x02, 0xd7, 0x6a, 0xe0, 0x9c, 0x60, 0xb7, 0x4c, 0xb4, 0x0e, 0x05, 0x09, 0x8d,
|
||||
0x7c, 0x18, 0x05, 0x82, 0xd4, 0x66, 0xc3, 0xff, 0x2a, 0xa4, 0xf7, 0x2d, 0x9b, 0xc8, 0x8d, 0x1e,
|
||||
0xeb, 0x00, 0xa6, 0x06, 0xd8, 0x9a, 0xc3, 0x1c, 0x5d, 0xcb, 0x05, 0x85, 0x3a, 0x3e, 0x3e, 0x99,
|
||||
0x76, 0x46, 0xc7, 0x27, 0x32, 0xd0, 0x99, 0xf1, 0x09, 0x1c, 0x1b, 0x9f, 0x60, 0x8b, 0xf1, 0x49,
|
||||
0x68, 0x74, 0x7c, 0x82, 0xf4, 0x53, 0x19, 0xdf, 0x36, 0xdc, 0xac, 0xd9, 0xba, 0x71, 0x68, 0x5b,
|
||||
0x9e, 0x4f, 0xcc, 0xa8, 0xc7, 0x78, 0x0c, 0xd9, 0x0b, 0x41, 0xe7, 0x55, 0x15, 0x4d, 0x89, 0x54,
|
||||
0xff, 0x3d, 0x01, 0xc5, 0x2d, 0xa2, 0xdb, 0xfe, 0xc1, 0xb4, 0x6c, 0xe4, 0x13, 0xcf, 0x97, 0x97,
|
||||
0x15, 0xff, 0x8d, 0xbe, 0x06, 0xb9, 0x30, 0x26, 0xb9, 0xf6, 0x6d, 0x2e, 0x84, 0xa2, 0x27, 0x30,
|
||||
0xcf, 0xce, 0x18, 0x1d, 0x07, 0xc9, 0xce, 0x55, 0xcf, 0x3e, 0x12, 0xc9, 0x2e, 0x19, 0x97, 0xf0,
|
||||
0x20, 0x84, 0x6f, 0xa5, 0x0c, 0x0e, 0x9a, 0xe8, 0x67, 0xa1, 0xc8, 0x5f, 0x2d, 0x82, 0x98, 0x2b,
|
||||
0x73, 0x9d, 0xce, 0x82, 0x78, 0x78, 0x14, 0xf1, 0xd6, 0xff, 0x26, 0x60, 0x65, 0x47, 0x9f, 0xec,
|
||||
0x11, 0xe9, 0x36, 0x88, 0x89, 0x89, 0x41, 0x5d, 0x13, 0x75, 0xa3, 0xee, 0xe6, 0x8a, 0x77, 0xcc,
|
||||
0x38, 0xe1, 0x78, 0xaf, 0x13, 0x24, 0x60, 0xc9, 0x48, 0x02, 0xb6, 0x02, 0x19, 0x87, 0x3a, 0x06,
|
||||
0x91, 0xbe, 0x48, 0x34, 0x54, 0x2b, 0xea, 0x6a, 0x4a, 0xe1, 0x13, 0x23, 0x2f, 0x40, 0xb5, 0xa9,
|
||||
0x1f, 0xf6, 0x86, 0x3e, 0x81, 0x52, 0xaf, 0x59, 0xc7, 0xcd, 0x7e, 0xad, 0xf3, 0x6d, 0xad, 0x57,
|
||||
0xdd, 0xee, 0x55, 0x1f, 0x3f, 0xd4, 0xba, 0x9d, 0xed, 0xef, 0x3c, 0x7a, 0xf2, 0xf0, 0x6b, 0x4a,
|
||||
0xa2, 0x54, 0x3e, 0x39, 0x2d, 0xdf, 0x6e, 0x57, 0xeb, 0xdb, 0xe2, 0xc4, 0xec, 0xd1, 0x97, 0x3d,
|
||||
0xdd, 0xf6, 0xf4, 0xc7, 0x0f, 0xbb, 0xd4, 0x9e, 0x30, 0x0c, 0xdb, 0xd6, 0xc5, 0xe8, 0x7d, 0x15,
|
||||
0xbd, 0x86, 0x13, 0x97, 0x5e, 0xc3, 0xd3, 0xdb, 0x3c, 0x79, 0xc9, 0x6d, 0xbe, 0x01, 0x2b, 0x86,
|
||||
0x4b, 0x3d, 0x4f, 0x63, 0xd1, 0x3f, 0x31, 0x67, 0xf2, 0x8b, 0x2f, 0x9c, 0x9f, 0xad, 0x2f, 0xd7,
|
||||
0x19, 0xbf, 0xc7, 0xd9, 0x52, 0xfd, 0xb2, 0x11, 0x21, 0xf1, 0x9e, 0xd4, 0x3f, 0x48, 0xb1, 0x40,
|
||||
0xca, 0x3a, 0xb2, 0x6c, 0x32, 0x20, 0x1e, 0x7a, 0x0e, 0x4b, 0x86, 0x4b, 0x4c, 0x16, 0xd6, 0xeb,
|
||||
0x76, 0xf4, 0x03, 0xdb, 0x9f, 0x89, 0x8d, 0x69, 0x42, 0xc1, 0x4a, 0x3d, 0x94, 0xea, 0x8d, 0x88,
|
||||
0x81, 0x17, 0x8d, 0x0b, 0x6d, 0xf4, 0x29, 0x2c, 0x79, 0xc4, 0xb6, 0x9c, 0xf1, 0x4b, 0xcd, 0xa0,
|
||||
0x8e, 0x4f, 0x5e, 0x06, 0xaf, 0x65, 0xd7, 0xe9, 0xed, 0x35, 0xb7, 0x99, 0x54, 0x5d, 0x08, 0xd5,
|
||||
0xd0, 0xf9, 0xd9, 0xfa, 0xe2, 0x45, 0x1a, 0x5e, 0x94, 0x9a, 0x65, 0xbb, 0xd4, 0x86, 0xc5, 0x8b,
|
||||
0xa3, 0x41, 0x2b, 0xf2, 0xec, 0x73, 0x17, 0x12, 0x9c, 0x6d, 0x74, 0x1b, 0x72, 0x2e, 0x19, 0x58,
|
||||
0x9e, 0xef, 0x0a, 0x33, 0x33, 0x4e, 0x48, 0x61, 0x27, 0x5f, 0x7c, 0x1d, 0x55, 0xfa, 0x15, 0x98,
|
||||
0xe9, 0x91, 0x1d, 0x16, 0xd3, 0xf2, 0xf4, 0x3d, 0xa9, 0x32, 0x87, 0x83, 0x26, 0xdb, 0x83, 0x63,
|
||||
0x2f, 0x0c, 0xd4, 0xf8, 0x6f, 0x46, 0xe3, 0x11, 0x85, 0xfc, 0x56, 0x8c, 0xc7, 0x0c, 0xc1, 0x47,
|
||||
0xa7, 0xe9, 0xc8, 0x47, 0xa7, 0x2b, 0x90, 0xb1, 0xc9, 0x11, 0xb1, 0xc5, 0x5d, 0x8e, 0x45, 0xe3,
|
||||
0xde, 0x43, 0x28, 0x06, 0x5f, 0x37, 0xf2, 0xaf, 0x2a, 0x72, 0x90, 0xee, 0x57, 0x7b, 0xcf, 0x94,
|
||||
0x39, 0x04, 0x90, 0x15, 0x9b, 0x53, 0xbc, 0xe4, 0xd5, 0x3b, 0xed, 0x8d, 0xd6, 0xa6, 0x92, 0xbc,
|
||||
0xf7, 0xbb, 0x69, 0xc8, 0x87, 0x6f, 0x49, 0xec, 0xee, 0x68, 0x37, 0x5f, 0x04, 0xbb, 0x3b, 0xa4,
|
||||
0xb7, 0xc9, 0x31, 0x7a, 0x7b, 0x5a, 0x85, 0xfa, 0x44, 0x3c, 0x9e, 0x87, 0xec, 0xa0, 0x02, 0xf5,
|
||||
0x2e, 0xe4, 0xaa, 0xbd, 0x5e, 0x6b, 0xb3, 0xdd, 0x6c, 0x28, 0x9f, 0x25, 0x4a, 0x5f, 0x38, 0x39,
|
||||
0x2d, 0x2f, 0x87, 0xa0, 0xaa, 0x27, 0x36, 0x1f, 0x47, 0xd5, 0xeb, 0xcd, 0x6e, 0xbf, 0xd9, 0x50,
|
||||
0x5e, 0x25, 0x67, 0x51, 0xbc, 0xaa, 0xc2, 0x3f, 0xeb, 0xc9, 0x77, 0x71, 0xb3, 0x5b, 0xc5, 0xac,
|
||||
0xc3, 0xcf, 0x92, 0xa2, 0x38, 0x36, 0xed, 0xd1, 0x25, 0x23, 0xdd, 0x65, 0x7d, 0xae, 0x05, 0xdf,
|
||||
0xc9, 0xbd, 0x4a, 0x89, 0x4f, 0x3f, 0xa6, 0x0f, 0x63, 0x44, 0x37, 0x27, 0xac, 0x37, 0xfe, 0x22,
|
||||
0xc9, 0xd5, 0xa4, 0x66, 0x7a, 0xeb, 0x31, 0xdf, 0xc3, 0xb4, 0xa8, 0x30, 0x8f, 0x77, 0xdb, 0x6d,
|
||||
0x06, 0x7a, 0x95, 0x9e, 0x99, 0x1d, 0x1e, 0x3b, 0x2c, 0x63, 0x46, 0x77, 0x21, 0x17, 0x3c, 0x58,
|
||||
0x2a, 0x9f, 0xa5, 0x67, 0x06, 0x54, 0x0f, 0x5e, 0x5b, 0x79, 0x87, 0x5b, 0xbb, 0x7d, 0xfe, 0x19,
|
||||
0xdf, 0xab, 0xcc, 0x6c, 0x87, 0x07, 0x63, 0xdf, 0xa4, 0xc7, 0x0e, 0x3b, 0xb3, 0xb2, 0x0e, 0xf7,
|
||||
0x59, 0x46, 0x14, 0x2d, 0x42, 0x8c, 0x2c, 0xc2, 0xbd, 0x0b, 0x39, 0xdc, 0xfc, 0x96, 0xf8, 0xe2,
|
||||
0xef, 0x55, 0x76, 0x46, 0x0f, 0x26, 0x9f, 0x12, 0x83, 0xf5, 0x56, 0x86, 0x2c, 0x6e, 0xee, 0x74,
|
||||
0x9e, 0x37, 0x95, 0x3f, 0xcc, 0xce, 0xe8, 0xc1, 0x64, 0x48, 0xf9, 0x77, 0x4f, 0xb9, 0x0e, 0xee,
|
||||
0x6e, 0x55, 0xf9, 0xa2, 0xcc, 0xea, 0xe9, 0xb8, 0xa3, 0x03, 0xdd, 0x21, 0xe6, 0xf4, 0x0b, 0x99,
|
||||
0x90, 0x75, 0xef, 0x17, 0x20, 0x17, 0xc4, 0xae, 0x68, 0x0d, 0xb2, 0x2f, 0x3a, 0xf8, 0x59, 0x13,
|
||||
0x2b, 0x73, 0xc2, 0xca, 0x01, 0xe7, 0x85, 0xc8, 0x3a, 0xca, 0x30, 0xbf, 0x53, 0x6d, 0x57, 0x37,
|
||||
0x9b, 0x38, 0x28, 0xa2, 0x07, 0x00, 0x19, 0x80, 0x95, 0x14, 0xd9, 0x41, 0xa8, 0xb3, 0xb6, 0xfa,
|
||||
0xfd, 0x1f, 0xad, 0xcd, 0xfd, 0xf0, 0x47, 0x6b, 0x73, 0xaf, 0xce, 0xd7, 0x12, 0xdf, 0x3f, 0x5f,
|
||||
0x4b, 0xfc, 0xfd, 0xf9, 0x5a, 0xe2, 0xdf, 0xce, 0xd7, 0x12, 0x7b, 0x59, 0x7e, 0x4d, 0x3c, 0xf9,
|
||||
0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x9b, 0x2e, 0x8d, 0x2e, 0x32, 0x00, 0x00,
|
||||
// 5091 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x7a, 0x5d, 0x6c, 0x23, 0x59,
|
||||
0x56, 0x7f, 0xec, 0xd8, 0x8e, 0x7d, 0xec, 0x24, 0xd5, 0xb7, 0xb3, 0x3d, 0x69, 0x6f, 0x4f, 0x92,
|
||||
0xa9, 0x99, 0xde, 0x99, 0xed, 0x9d, 0xbf, 0xfb, 0x6b, 0x77, 0xd5, 0x33, 0xf3, 0xdf, 0x9d, 0xb1,
|
||||
0xcb, 0x95, 0x8e, 0xb7, 0x13, 0xdb, 0xba, 0x76, 0xba, 0x77, 0x91, 0xa0, 0xa8, 0x54, 0xdd, 0x38,
|
||||
0x35, 0x29, 0xd7, 0x35, 0x55, 0xe5, 0xa4, 0xcd, 0x82, 0x18, 0xf1, 0x00, 0x28, 0x4f, 0xf0, 0x02,
|
||||
0x8b, 0x50, 0x10, 0x12, 0xbc, 0x81, 0xc4, 0x03, 0x48, 0x08, 0x9e, 0x06, 0x09, 0xa1, 0x7d, 0x83,
|
||||
0x05, 0x09, 0xad, 0x40, 0x0a, 0x6c, 0x1e, 0x78, 0x5b, 0xc1, 0x0b, 0xe2, 0x85, 0x07, 0x74, 0x3f,
|
||||
0xaa, 0x5c, 0x71, 0x57, 0x92, 0x19, 0x76, 0x5f, 0x12, 0xdf, 0x73, 0x7e, 0xe7, 0xdc, 0x7b, 0xcf,
|
||||
0xbd, 0xf7, 0xdc, 0x73, 0xce, 0x2d, 0xb8, 0x37, 0x70, 0xc2, 0x83, 0xf1, 0x5e, 0xcd, 0xa2, 0xc3,
|
||||
0xfb, 0x36, 0xb5, 0x0e, 0x89, 0x7f, 0x3f, 0x38, 0x36, 0xfd, 0xe1, 0xa1, 0x13, 0xde, 0x37, 0x47,
|
||||
0xce, 0xfd, 0x70, 0x32, 0x22, 0x41, 0x6d, 0xe4, 0xd3, 0x90, 0x22, 0x24, 0x00, 0xb5, 0x08, 0x50,
|
||||
0x3b, 0x7a, 0x58, 0x5d, 0x1f, 0x50, 0x3a, 0x70, 0xc9, 0x7d, 0x8e, 0xd8, 0x1b, 0xef, 0xdf, 0x0f,
|
||||
0x9d, 0x21, 0x09, 0x42, 0x73, 0x38, 0x12, 0x42, 0xd5, 0xb5, 0x59, 0x80, 0x3d, 0xf6, 0xcd, 0xd0,
|
||||
0xa1, 0x9e, 0xe4, 0xaf, 0x0c, 0xe8, 0x80, 0xf2, 0x9f, 0xf7, 0xd9, 0x2f, 0x41, 0x55, 0xd7, 0x61,
|
||||
0xe1, 0x39, 0xf1, 0x03, 0x87, 0x7a, 0x68, 0x05, 0xf2, 0x8e, 0x67, 0x93, 0x97, 0xab, 0x99, 0x8d,
|
||||
0xcc, 0x3b, 0x39, 0x2c, 0x1a, 0xea, 0x03, 0x80, 0x16, 0xfb, 0xa1, 0x7b, 0xa1, 0x3f, 0x41, 0x0a,
|
||||
0xcc, 0x1f, 0x92, 0x09, 0x47, 0x94, 0x30, 0xfb, 0xc9, 0x28, 0x47, 0xa6, 0xbb, 0x9a, 0x15, 0x94,
|
||||
0x23, 0xd3, 0x55, 0x7f, 0x94, 0x81, 0x72, 0xdd, 0xf3, 0x68, 0xc8, 0x7b, 0x0f, 0x10, 0x82, 0x9c,
|
||||
0x67, 0x0e, 0x89, 0x14, 0xe2, 0xbf, 0x91, 0x06, 0x05, 0xd7, 0xdc, 0x23, 0x6e, 0xb0, 0x9a, 0xdd,
|
||||
0x98, 0x7f, 0xa7, 0xfc, 0xe8, 0x2b, 0xb5, 0x57, 0xa7, 0x5c, 0x4b, 0x28, 0xa9, 0x6d, 0x73, 0x34,
|
||||
0x1f, 0x04, 0x96, 0xa2, 0xe8, 0x9b, 0xb0, 0xe0, 0x78, 0xb6, 0x63, 0x91, 0x60, 0x35, 0xc7, 0xb5,
|
||||
0xac, 0xa5, 0x69, 0x99, 0x8e, 0xbe, 0x91, 0xfb, 0xfe, 0xd9, 0xfa, 0x1c, 0x8e, 0x84, 0xaa, 0xef,
|
||||
0x41, 0x39, 0xa1, 0x36, 0x65, 0x6e, 0x2b, 0x90, 0x3f, 0x32, 0xdd, 0x31, 0x91, 0xb3, 0x13, 0x8d,
|
||||
0xf7, 0xb3, 0x4f, 0x32, 0xea, 0x47, 0xb0, 0xd2, 0x36, 0x87, 0xc4, 0x7e, 0x4a, 0x3c, 0xe2, 0x3b,
|
||||
0x16, 0x26, 0x01, 0x1d, 0xfb, 0x16, 0x61, 0x73, 0x3d, 0x74, 0x3c, 0x3b, 0x9a, 0x2b, 0xfb, 0x9d,
|
||||
0xae, 0x45, 0xd5, 0xe0, 0xb5, 0xa6, 0x13, 0x58, 0x3e, 0x09, 0xc9, 0xe7, 0x56, 0x32, 0x1f, 0x29,
|
||||
0x39, 0xcb, 0xc0, 0xf2, 0xac, 0xf4, 0xcf, 0xc0, 0x4d, 0x66, 0x62, 0xdb, 0xf0, 0x25, 0xc5, 0x08,
|
||||
0x46, 0xc4, 0xe2, 0xca, 0xca, 0x8f, 0xde, 0x49, 0xb3, 0x50, 0xda, 0x4c, 0xb6, 0xe6, 0xf0, 0x0d,
|
||||
0xae, 0x26, 0x22, 0xf4, 0x46, 0xc4, 0x42, 0x16, 0xdc, 0xb2, 0xe5, 0xa0, 0x67, 0xd4, 0x67, 0xb9,
|
||||
0xfa, 0xd4, 0x65, 0xbc, 0x64, 0x9a, 0x5b, 0x73, 0x78, 0x25, 0x52, 0x96, 0xec, 0xa4, 0x01, 0x50,
|
||||
0x8c, 0x74, 0xab, 0xdf, 0xcb, 0x40, 0x29, 0x62, 0x06, 0xe8, 0xcb, 0x50, 0xf2, 0x4c, 0x8f, 0x1a,
|
||||
0xd6, 0x68, 0x1c, 0xf0, 0x09, 0xcd, 0x37, 0x2a, 0xe7, 0x67, 0xeb, 0xc5, 0xb6, 0xe9, 0x51, 0xad,
|
||||
0xbb, 0x1b, 0xe0, 0x22, 0x63, 0x6b, 0xa3, 0x71, 0x80, 0xde, 0x80, 0xca, 0x90, 0x0c, 0xa9, 0x3f,
|
||||
0x31, 0xf6, 0x26, 0x21, 0x09, 0xa4, 0xd9, 0xca, 0x82, 0xd6, 0x60, 0x24, 0xf4, 0x0d, 0x58, 0x18,
|
||||
0x88, 0x21, 0xad, 0xce, 0xf3, 0xed, 0xf3, 0x66, 0xda, 0xe8, 0x67, 0x46, 0x8d, 0x23, 0x19, 0xf5,
|
||||
0x37, 0x33, 0xb0, 0x12, 0x53, 0xc9, 0x2f, 0x8c, 0x1d, 0x9f, 0x0c, 0x89, 0x17, 0x06, 0xe8, 0x6b,
|
||||
0x50, 0x70, 0x9d, 0xa1, 0x13, 0x06, 0xd2, 0xe6, 0xaf, 0xa7, 0xa9, 0x8d, 0x27, 0x85, 0x25, 0x18,
|
||||
0xd5, 0xa1, 0xe2, 0x93, 0x80, 0xf8, 0x47, 0x62, 0xc7, 0x4b, 0x8b, 0x5e, 0x23, 0x7c, 0x41, 0x44,
|
||||
0xdd, 0x84, 0x62, 0xd7, 0x35, 0xc3, 0x7d, 0xea, 0x0f, 0x91, 0x0a, 0x15, 0xd3, 0xb7, 0x0e, 0x9c,
|
||||
0x90, 0x58, 0xe1, 0xd8, 0x8f, 0x4e, 0xdf, 0x05, 0x1a, 0xba, 0x05, 0x59, 0x2a, 0x3a, 0x2a, 0x35,
|
||||
0x0a, 0xe7, 0x67, 0xeb, 0xd9, 0x4e, 0x0f, 0x67, 0x69, 0xa0, 0x7e, 0x00, 0x37, 0xba, 0xee, 0x78,
|
||||
0xe0, 0x78, 0x4d, 0x12, 0x58, 0xbe, 0x33, 0x62, 0xda, 0xd9, 0xae, 0x64, 0x3e, 0x2a, 0xda, 0x95,
|
||||
0xec, 0x77, 0x7c, 0xb4, 0xb3, 0xd3, 0xa3, 0xad, 0xfe, 0x7a, 0x16, 0x6e, 0xe8, 0xde, 0xc0, 0xf1,
|
||||
0x48, 0x52, 0xfa, 0x2e, 0x2c, 0x11, 0x4e, 0x34, 0x8e, 0x84, 0xbb, 0x91, 0x7a, 0x16, 0x05, 0x35,
|
||||
0xf2, 0x41, 0xad, 0x19, 0xbf, 0xf0, 0x30, 0x6d, 0xfa, 0xaf, 0x68, 0x4f, 0xf5, 0x0e, 0x3a, 0x2c,
|
||||
0x8c, 0xf8, 0x24, 0x02, 0xb9, 0xbc, 0x77, 0xd3, 0x74, 0xbd, 0x32, 0xcf, 0xc8, 0x49, 0x48, 0xd9,
|
||||
0x9f, 0xc4, 0x49, 0xfc, 0x49, 0x16, 0x96, 0xdb, 0xd4, 0xbe, 0x60, 0x87, 0x2a, 0x14, 0x0f, 0x68,
|
||||
0x10, 0x26, 0x1c, 0x62, 0xdc, 0x46, 0x4f, 0xa0, 0x38, 0x92, 0xcb, 0x27, 0x57, 0xff, 0x4e, 0xfa,
|
||||
0x90, 0x05, 0x06, 0xc7, 0x68, 0xf4, 0x01, 0x94, 0xa2, 0x23, 0xc3, 0x66, 0xfb, 0x19, 0x36, 0xce,
|
||||
0x14, 0x8f, 0xbe, 0x01, 0x05, 0xb1, 0x08, 0xab, 0x39, 0x2e, 0x79, 0xf7, 0x33, 0xd9, 0x1c, 0x4b,
|
||||
0x21, 0xf4, 0x14, 0x8a, 0xa1, 0x1b, 0x18, 0x8e, 0xb7, 0x4f, 0x57, 0xf3, 0x5c, 0xc1, 0x7a, 0xaa,
|
||||
0x93, 0xa1, 0x36, 0xe9, 0x6f, 0xf7, 0x5a, 0xde, 0x3e, 0x6d, 0x94, 0xcf, 0xcf, 0xd6, 0x17, 0x64,
|
||||
0x03, 0x2f, 0x84, 0x6e, 0xc0, 0x7e, 0xa8, 0xbf, 0x95, 0x81, 0x72, 0x02, 0x85, 0x5e, 0x07, 0x08,
|
||||
0xfd, 0x71, 0x10, 0x1a, 0x3e, 0xa5, 0x21, 0x37, 0x56, 0x05, 0x97, 0x38, 0x05, 0x53, 0x1a, 0xa2,
|
||||
0x1a, 0xdc, 0xb4, 0x88, 0x1f, 0x1a, 0x4e, 0x10, 0x8c, 0x89, 0x6f, 0x04, 0xe3, 0xbd, 0x8f, 0x89,
|
||||
0x15, 0x72, 0xc3, 0x55, 0xf0, 0x0d, 0xc6, 0x6a, 0x71, 0x4e, 0x4f, 0x30, 0xd0, 0x63, 0xb8, 0x95,
|
||||
0xc4, 0x8f, 0xc6, 0x7b, 0xae, 0x63, 0x19, 0x6c, 0x31, 0xe7, 0xb9, 0xc8, 0xcd, 0xa9, 0x48, 0x97,
|
||||
0xf3, 0x9e, 0x91, 0x89, 0xfa, 0xc3, 0x0c, 0x28, 0xd8, 0xdc, 0x0f, 0x77, 0xc8, 0x70, 0x8f, 0xf8,
|
||||
0xbd, 0xd0, 0x0c, 0xc7, 0x01, 0xba, 0x05, 0x05, 0x97, 0x98, 0x36, 0xf1, 0xf9, 0xa0, 0x8a, 0x58,
|
||||
0xb6, 0xd0, 0x2e, 0x3b, 0xc1, 0xa6, 0x75, 0x60, 0xee, 0x39, 0xae, 0x13, 0x4e, 0xf8, 0x50, 0x96,
|
||||
0xd2, 0xb7, 0xf0, 0xac, 0xce, 0x1a, 0x4e, 0x08, 0xe2, 0x0b, 0x6a, 0xd0, 0x2a, 0x2c, 0x0c, 0x49,
|
||||
0x10, 0x98, 0x03, 0xc2, 0x47, 0x5a, 0xc2, 0x51, 0x53, 0xfd, 0x00, 0x2a, 0x49, 0x39, 0x54, 0x86,
|
||||
0x85, 0xdd, 0xf6, 0xb3, 0x76, 0xe7, 0x45, 0x5b, 0x99, 0x43, 0xcb, 0x50, 0xde, 0x6d, 0x63, 0xbd,
|
||||
0xae, 0x6d, 0xd5, 0x1b, 0xdb, 0xba, 0x92, 0x41, 0x8b, 0x50, 0x9a, 0x36, 0xb3, 0xea, 0x9f, 0x65,
|
||||
0x00, 0x98, 0xb9, 0xe5, 0xa4, 0xde, 0x87, 0x7c, 0x10, 0x9a, 0xa1, 0xd8, 0x95, 0x4b, 0x8f, 0xde,
|
||||
0xba, 0x6c, 0x0d, 0xe5, 0x78, 0xd9, 0x3f, 0x82, 0x85, 0x48, 0x72, 0x84, 0xd9, 0x0b, 0x23, 0x64,
|
||||
0x0e, 0xc2, 0xb4, 0x6d, 0x5f, 0x0e, 0x9c, 0xff, 0x56, 0x3f, 0x80, 0x3c, 0x97, 0xbe, 0x38, 0xdc,
|
||||
0x22, 0xe4, 0x9a, 0xec, 0x57, 0x06, 0x95, 0x20, 0x8f, 0xf5, 0x7a, 0xf3, 0x3b, 0x4a, 0x16, 0x29,
|
||||
0x50, 0x69, 0xb6, 0x7a, 0x5a, 0xa7, 0xdd, 0xd6, 0xb5, 0xbe, 0xde, 0x54, 0xe6, 0xd5, 0xbb, 0x90,
|
||||
0x6f, 0x0d, 0x99, 0xe6, 0x3b, 0x6c, 0xcb, 0xef, 0x13, 0x9f, 0x78, 0x56, 0x74, 0x92, 0xa6, 0x04,
|
||||
0xf5, 0xc7, 0x65, 0xc8, 0xef, 0xd0, 0xb1, 0x17, 0xa2, 0x47, 0x09, 0xb7, 0xb5, 0x94, 0x1e, 0x21,
|
||||
0x70, 0x60, 0xad, 0x3f, 0x19, 0x11, 0xe9, 0xd6, 0x6e, 0x41, 0x41, 0x1c, 0x0e, 0x39, 0x1d, 0xd9,
|
||||
0x62, 0xf4, 0xd0, 0xf4, 0x07, 0x24, 0x94, 0xf3, 0x91, 0x2d, 0xf4, 0x0e, 0xbb, 0xb1, 0x4c, 0x9b,
|
||||
0x7a, 0xee, 0x84, 0x9f, 0xa1, 0xa2, 0xb8, 0x96, 0x30, 0x31, 0xed, 0x8e, 0xe7, 0x4e, 0x70, 0xcc,
|
||||
0x45, 0x5b, 0x50, 0xd9, 0x73, 0x3c, 0xdb, 0xa0, 0x23, 0xe1, 0xe4, 0xf3, 0x97, 0x9f, 0x38, 0x31,
|
||||
0xaa, 0x86, 0xe3, 0xd9, 0x1d, 0x01, 0xc6, 0xe5, 0xbd, 0x69, 0x03, 0xb5, 0x61, 0xe9, 0x88, 0xba,
|
||||
0xe3, 0x21, 0x89, 0x75, 0x15, 0xb8, 0xae, 0xb7, 0x2f, 0xd7, 0xf5, 0x9c, 0xe3, 0x23, 0x6d, 0x8b,
|
||||
0x47, 0xc9, 0x26, 0x7a, 0x06, 0x8b, 0xe1, 0x70, 0xb4, 0x1f, 0xc4, 0xea, 0x16, 0xb8, 0xba, 0x2f,
|
||||
0x5d, 0x61, 0x30, 0x06, 0x8f, 0xb4, 0x55, 0xc2, 0x44, 0x0b, 0x3d, 0x85, 0xb2, 0x45, 0xbd, 0xc0,
|
||||
0x09, 0x42, 0xe2, 0x59, 0x93, 0xd5, 0x22, 0xb7, 0xfd, 0x15, 0xb3, 0xd4, 0xa6, 0x60, 0x9c, 0x94,
|
||||
0xac, 0xfe, 0xea, 0x3c, 0x94, 0x13, 0x26, 0x40, 0x3d, 0x28, 0x8f, 0x7c, 0x3a, 0x32, 0x07, 0xfc,
|
||||
0xc6, 0x93, 0x8b, 0xfa, 0xf0, 0x33, 0x99, 0xaf, 0xd6, 0x9d, 0x0a, 0xe2, 0xa4, 0x16, 0xf5, 0x34,
|
||||
0x0b, 0xe5, 0x04, 0x13, 0xdd, 0x83, 0x22, 0xee, 0xe2, 0xd6, 0xf3, 0x7a, 0x5f, 0x57, 0xe6, 0xaa,
|
||||
0x77, 0x4e, 0x4e, 0x37, 0x56, 0xb9, 0xb6, 0xa4, 0x82, 0xae, 0xef, 0x1c, 0xb1, 0x3d, 0xfc, 0x0e,
|
||||
0x2c, 0x44, 0xd0, 0x4c, 0xf5, 0x8b, 0x27, 0xa7, 0x1b, 0xaf, 0xcd, 0x42, 0x13, 0x48, 0xdc, 0xdb,
|
||||
0xaa, 0x63, 0xbd, 0xa9, 0x64, 0xd3, 0x91, 0xb8, 0x77, 0x60, 0xfa, 0xc4, 0x46, 0x5f, 0x82, 0x82,
|
||||
0x04, 0xce, 0x57, 0xab, 0x27, 0xa7, 0x1b, 0xb7, 0x66, 0x81, 0x53, 0x1c, 0xee, 0x6d, 0xd7, 0x9f,
|
||||
0xeb, 0x4a, 0x2e, 0x1d, 0x87, 0x7b, 0xae, 0x79, 0x44, 0xd0, 0x5b, 0x90, 0x17, 0xb0, 0x7c, 0xf5,
|
||||
0xf6, 0xc9, 0xe9, 0xc6, 0x17, 0x5e, 0x51, 0xc7, 0x50, 0xd5, 0xd5, 0xdf, 0xf8, 0xc3, 0xb5, 0xb9,
|
||||
0xbf, 0xfa, 0xa3, 0x35, 0x65, 0x96, 0x5d, 0xfd, 0x9f, 0x0c, 0x2c, 0x5e, 0xd8, 0x3b, 0x48, 0x85,
|
||||
0x82, 0x47, 0x2d, 0x3a, 0x12, 0x17, 0x61, 0xb1, 0x01, 0xe7, 0x67, 0xeb, 0x85, 0x36, 0xd5, 0xe8,
|
||||
0x68, 0x82, 0x25, 0x07, 0x3d, 0x9b, 0xb9, 0xca, 0x1f, 0x7f, 0xc6, 0x8d, 0x99, 0x7a, 0x99, 0x7f,
|
||||
0x08, 0x8b, 0xb6, 0xef, 0x1c, 0x11, 0xdf, 0xb0, 0xa8, 0xb7, 0xef, 0x0c, 0xe4, 0x25, 0x57, 0x4d,
|
||||
0x8d, 0x37, 0x39, 0x10, 0x57, 0x84, 0x80, 0xc6, 0xf1, 0x3f, 0xc1, 0x35, 0x5e, 0x7d, 0x0e, 0x95,
|
||||
0xe4, 0x56, 0x67, 0xf7, 0x52, 0xe0, 0xfc, 0x22, 0x91, 0x81, 0x25, 0x0f, 0x43, 0x71, 0x89, 0x51,
|
||||
0x44, 0x58, 0xf9, 0x36, 0xe4, 0x86, 0xd4, 0x16, 0x7a, 0x16, 0x1b, 0x37, 0x59, 0x34, 0xf1, 0xcf,
|
||||
0x67, 0xeb, 0x65, 0x1a, 0xd4, 0x36, 0x1d, 0x97, 0xec, 0x50, 0x9b, 0x60, 0x0e, 0x50, 0x8f, 0x20,
|
||||
0xc7, 0x7c, 0x0e, 0xfa, 0x22, 0xe4, 0x1a, 0xad, 0x76, 0x53, 0x99, 0xab, 0xde, 0x38, 0x39, 0xdd,
|
||||
0x58, 0xe4, 0x26, 0x61, 0x0c, 0xb6, 0x77, 0xd1, 0x3a, 0x14, 0x9e, 0x77, 0xb6, 0x77, 0x77, 0xd8,
|
||||
0xf6, 0xba, 0x79, 0x72, 0xba, 0xb1, 0x1c, 0xb3, 0x85, 0xd1, 0xd0, 0xeb, 0x90, 0xef, 0xef, 0x74,
|
||||
0x37, 0x7b, 0x4a, 0xb6, 0x8a, 0x4e, 0x4e, 0x37, 0x96, 0x62, 0x3e, 0x1f, 0x73, 0xf5, 0x86, 0x5c,
|
||||
0xd5, 0x52, 0x4c, 0x57, 0x7f, 0x90, 0x81, 0x72, 0xe2, 0xc0, 0xb1, 0x8d, 0xd9, 0xd4, 0x37, 0xeb,
|
||||
0xbb, 0xdb, 0x7d, 0x65, 0x2e, 0xb1, 0x31, 0x13, 0x90, 0x26, 0xd9, 0x37, 0xc7, 0x2e, 0xf3, 0x73,
|
||||
0xa0, 0x75, 0xda, 0xbd, 0x56, 0xaf, 0xaf, 0xb7, 0xfb, 0x4a, 0xa6, 0xba, 0x7a, 0x72, 0xba, 0xb1,
|
||||
0x32, 0x0b, 0xde, 0x1c, 0xbb, 0x2e, 0xdb, 0x9a, 0x5a, 0x5d, 0xdb, 0xe2, 0x7b, 0x7d, 0xba, 0x35,
|
||||
0x13, 0x28, 0xcd, 0xb4, 0x0e, 0x88, 0x8d, 0xde, 0x85, 0x52, 0x53, 0xdf, 0xd6, 0x9f, 0xd6, 0xb9,
|
||||
0x77, 0xaf, 0xbe, 0x7e, 0x72, 0xba, 0x71, 0xfb, 0xd5, 0xde, 0x5d, 0x32, 0x30, 0x43, 0x62, 0xcf,
|
||||
0x6c, 0xd1, 0x04, 0x44, 0xfd, 0xaf, 0x2c, 0x2c, 0x62, 0x96, 0x0e, 0xfb, 0x61, 0x97, 0xba, 0x8e,
|
||||
0x35, 0x41, 0x5d, 0x28, 0x59, 0xd4, 0xb3, 0x9d, 0x84, 0x9f, 0x78, 0x74, 0x49, 0x48, 0x34, 0x95,
|
||||
0x8a, 0x5a, 0x5a, 0x24, 0x89, 0xa7, 0x4a, 0xd0, 0x7d, 0xc8, 0xdb, 0xc4, 0x35, 0x27, 0x32, 0x36,
|
||||
0xbb, 0x5d, 0x13, 0x09, 0x77, 0x2d, 0x4a, 0xb8, 0x6b, 0x4d, 0x99, 0x70, 0x63, 0x81, 0xe3, 0x39,
|
||||
0x88, 0xf9, 0xd2, 0x30, 0xc3, 0x90, 0x0c, 0x47, 0xa1, 0x08, 0xcc, 0x72, 0xb8, 0x3c, 0x34, 0x5f,
|
||||
0xd6, 0x25, 0x09, 0x3d, 0x84, 0xc2, 0xb1, 0xe3, 0xd9, 0xf4, 0x58, 0xc6, 0x5e, 0x57, 0x28, 0x95,
|
||||
0x40, 0xf5, 0x84, 0x85, 0x24, 0x33, 0xc3, 0x64, 0x7b, 0xa8, 0xdd, 0x69, 0xeb, 0xd1, 0x1e, 0x92,
|
||||
0xfc, 0x8e, 0xd7, 0xa6, 0x1e, 0x3b, 0xff, 0xd0, 0x69, 0x1b, 0x9b, 0xf5, 0xd6, 0xf6, 0x2e, 0x66,
|
||||
0xfb, 0x68, 0xe5, 0xe4, 0x74, 0x43, 0x89, 0x21, 0x9b, 0xa6, 0xe3, 0xb2, 0x64, 0xe0, 0x36, 0xcc,
|
||||
0xd7, 0xdb, 0xdf, 0x51, 0xb2, 0x55, 0xe5, 0xe4, 0x74, 0xa3, 0x12, 0xb3, 0xeb, 0xde, 0x64, 0x6a,
|
||||
0xf7, 0xd9, 0x7e, 0xd5, 0xbf, 0x9b, 0x87, 0xca, 0xee, 0xc8, 0x36, 0x43, 0x22, 0xce, 0x19, 0xda,
|
||||
0x80, 0xf2, 0xc8, 0xf4, 0x4d, 0xd7, 0x25, 0xae, 0x13, 0x0c, 0x65, 0x29, 0x21, 0x49, 0x42, 0xef,
|
||||
0x7d, 0x56, 0x33, 0x36, 0x8a, 0xec, 0xec, 0x7c, 0xef, 0x5f, 0xd7, 0x33, 0x91, 0x41, 0x77, 0x61,
|
||||
0x69, 0x5f, 0x8c, 0xd6, 0x30, 0x2d, 0xbe, 0xb0, 0xf3, 0x7c, 0x61, 0x6b, 0x69, 0x0b, 0x9b, 0x1c,
|
||||
0x56, 0x4d, 0x4e, 0xb2, 0xce, 0xa5, 0xf0, 0xe2, 0x7e, 0xb2, 0x89, 0x1e, 0xc3, 0xc2, 0x90, 0x7a,
|
||||
0x4e, 0x48, 0xfd, 0xeb, 0x57, 0x21, 0x42, 0xa2, 0x7b, 0x70, 0x83, 0x2d, 0x6e, 0x34, 0x1e, 0xce,
|
||||
0xe6, 0xd7, 0x79, 0x16, 0x2f, 0x0f, 0xcd, 0x97, 0xb2, 0x43, 0xcc, 0xc8, 0xa8, 0x01, 0x79, 0xea,
|
||||
0xb3, 0x78, 0xb1, 0xc0, 0x87, 0xfb, 0xee, 0xb5, 0xc3, 0x15, 0x8d, 0x0e, 0x93, 0xc1, 0x42, 0x54,
|
||||
0xfd, 0x3a, 0x2c, 0x5e, 0x98, 0x04, 0x0b, 0x93, 0xba, 0xf5, 0xdd, 0x9e, 0xae, 0xcc, 0xa1, 0x0a,
|
||||
0x14, 0xb5, 0x4e, 0xbb, 0xdf, 0x6a, 0xef, 0xb2, 0x38, 0xaf, 0x02, 0x45, 0xdc, 0xd9, 0xde, 0x6e,
|
||||
0xd4, 0xb5, 0x67, 0x4a, 0x56, 0xad, 0x41, 0x39, 0xa1, 0x0d, 0x2d, 0x01, 0xf4, 0xfa, 0x9d, 0xae,
|
||||
0xb1, 0xd9, 0xc2, 0xbd, 0xbe, 0x88, 0x12, 0x7b, 0xfd, 0x3a, 0xee, 0x4b, 0x42, 0x46, 0xfd, 0x8f,
|
||||
0x6c, 0xb4, 0xa2, 0x32, 0x30, 0x6c, 0x5c, 0x0c, 0x0c, 0xaf, 0x18, 0xbc, 0x0c, 0x0d, 0xa7, 0x8d,
|
||||
0x38, 0x40, 0x7c, 0x0f, 0x80, 0x6f, 0x1c, 0x62, 0x1b, 0x66, 0x28, 0x17, 0xbe, 0xfa, 0x8a, 0x91,
|
||||
0xfb, 0x51, 0x45, 0x0b, 0x97, 0x24, 0xba, 0x1e, 0xa2, 0x6f, 0x40, 0xc5, 0xa2, 0xc3, 0x91, 0x4b,
|
||||
0xa4, 0xf0, 0xfc, 0xb5, 0xc2, 0xe5, 0x18, 0x5f, 0x0f, 0x93, 0xa1, 0x69, 0xee, 0x62, 0xf0, 0xfc,
|
||||
0x6b, 0x99, 0xc8, 0x32, 0x29, 0xd1, 0x68, 0x05, 0x8a, 0xbb, 0xdd, 0x66, 0xbd, 0xdf, 0x6a, 0x3f,
|
||||
0x55, 0x32, 0x08, 0xa0, 0xc0, 0x4d, 0xdd, 0x54, 0xb2, 0x2c, 0x8a, 0xd6, 0x3a, 0x3b, 0xdd, 0x6d,
|
||||
0x9d, 0x7b, 0x2c, 0xb4, 0x02, 0x4a, 0x64, 0x6c, 0x83, 0x1b, 0x52, 0x6f, 0x2a, 0x39, 0x74, 0x13,
|
||||
0x96, 0x63, 0xaa, 0x94, 0xcc, 0xa3, 0x5b, 0x80, 0x62, 0xe2, 0x54, 0x45, 0x41, 0xfd, 0x65, 0x58,
|
||||
0xd6, 0xa8, 0x17, 0x9a, 0x8e, 0x17, 0x67, 0x18, 0x8f, 0xd8, 0xa4, 0x25, 0xc9, 0x70, 0x64, 0x25,
|
||||
0xa8, 0xb1, 0x7c, 0x7e, 0xb6, 0x5e, 0x8e, 0xa1, 0xad, 0x26, 0x0f, 0x95, 0x64, 0xc3, 0x66, 0xe7,
|
||||
0x77, 0xe4, 0xd8, 0xdc, 0xb8, 0xf9, 0xc6, 0xc2, 0xf9, 0xd9, 0xfa, 0x7c, 0xb7, 0xd5, 0xc4, 0x8c,
|
||||
0x86, 0xbe, 0x08, 0x25, 0xf2, 0xd2, 0x09, 0x0d, 0x8b, 0xdd, 0x4b, 0xcc, 0x80, 0x79, 0x5c, 0x64,
|
||||
0x04, 0x8d, 0x5d, 0x43, 0x0d, 0x80, 0x2e, 0xf5, 0x43, 0xd9, 0xf3, 0x57, 0x21, 0x3f, 0xa2, 0x3e,
|
||||
0xaf, 0x5d, 0x5c, 0x5a, 0x51, 0x63, 0x70, 0xb1, 0x51, 0xb1, 0x00, 0xab, 0xbf, 0x3b, 0x0f, 0xd0,
|
||||
0x37, 0x83, 0x43, 0xa9, 0xe4, 0x09, 0x94, 0xe2, 0xea, 0xa4, 0x2c, 0x82, 0x5c, 0xb9, 0xda, 0x31,
|
||||
0x18, 0x3d, 0x8e, 0x36, 0x9b, 0xc8, 0x9d, 0x52, 0x93, 0xd8, 0xa8, 0xa3, 0xb4, 0xf4, 0xe3, 0x62,
|
||||
0x82, 0xc4, 0xae, 0x79, 0xe2, 0xfb, 0x72, 0xe5, 0xd9, 0x4f, 0xa4, 0xf1, 0x6b, 0x41, 0x18, 0x4d,
|
||||
0x46, 0xdf, 0xa9, 0x65, 0x9f, 0x99, 0x15, 0xd9, 0x9a, 0xc3, 0x53, 0x39, 0xf4, 0x21, 0x94, 0xd9,
|
||||
0xbc, 0x8d, 0x80, 0xf3, 0x64, 0xe0, 0x7d, 0xa9, 0xa9, 0x84, 0x06, 0x0c, 0xa3, 0xa9, 0x95, 0x5f,
|
||||
0x07, 0x30, 0x47, 0x23, 0xd7, 0x21, 0xb6, 0xb1, 0x37, 0xe1, 0x91, 0x76, 0x09, 0x97, 0x24, 0xa5,
|
||||
0x31, 0x61, 0xc7, 0x25, 0x62, 0x9b, 0x21, 0x8f, 0x9e, 0xaf, 0x31, 0xa0, 0x44, 0xd7, 0xc3, 0x86,
|
||||
0x02, 0x4b, 0xfe, 0xd8, 0x63, 0x06, 0x95, 0xa3, 0x53, 0xff, 0x34, 0x0b, 0xaf, 0xb5, 0x49, 0x78,
|
||||
0x4c, 0xfd, 0xc3, 0x7a, 0x18, 0x9a, 0xd6, 0xc1, 0x90, 0x78, 0x72, 0xf9, 0x12, 0x09, 0x4d, 0xe6,
|
||||
0x42, 0x42, 0xb3, 0x0a, 0x0b, 0xa6, 0xeb, 0x98, 0x01, 0x11, 0xc1, 0x5b, 0x09, 0x47, 0x4d, 0x96,
|
||||
0x76, 0xb1, 0x24, 0x8e, 0x04, 0x01, 0x11, 0x75, 0x15, 0x36, 0xf0, 0x88, 0x80, 0xbe, 0x0b, 0xb7,
|
||||
0x64, 0x98, 0x66, 0xc6, 0x5d, 0xb1, 0x84, 0x22, 0x2a, 0xd0, 0xea, 0xa9, 0x59, 0x65, 0xfa, 0xe0,
|
||||
0x64, 0x1c, 0x37, 0x25, 0x77, 0x46, 0xa1, 0x8c, 0x0a, 0x57, 0xec, 0x14, 0x56, 0xf5, 0x29, 0xdc,
|
||||
0xbe, 0x54, 0xe4, 0x73, 0xd5, 0x6d, 0xfe, 0x31, 0x0b, 0xd0, 0xea, 0xd6, 0x77, 0xa4, 0x91, 0x9a,
|
||||
0x50, 0xd8, 0x37, 0x87, 0x8e, 0x3b, 0xb9, 0xca, 0x03, 0x4e, 0xf1, 0xb5, 0xba, 0x30, 0xc7, 0x26,
|
||||
0x97, 0xc1, 0x52, 0x96, 0xe7, 0x94, 0xe3, 0x3d, 0x8f, 0x84, 0x71, 0x4e, 0xc9, 0x5b, 0x6c, 0x18,
|
||||
0xbe, 0xe9, 0xc5, 0x5b, 0x57, 0x34, 0xd8, 0x02, 0xb0, 0x90, 0xe7, 0xd8, 0x9c, 0x44, 0x6e, 0x4b,
|
||||
0x36, 0xd1, 0x16, 0xaf, 0x8e, 0x12, 0xff, 0x88, 0xd8, 0xab, 0x79, 0x6e, 0xd4, 0xeb, 0xc6, 0x83,
|
||||
0x25, 0x5c, 0xd8, 0x2e, 0x96, 0xae, 0x7e, 0xc0, 0x43, 0xa6, 0x29, 0xeb, 0x73, 0xd9, 0xe8, 0x01,
|
||||
0x2c, 0x5e, 0x98, 0xe7, 0x2b, 0xc9, 0x7c, 0xab, 0xfb, 0xfc, 0xab, 0x4a, 0x4e, 0xfe, 0xfa, 0xba,
|
||||
0x52, 0x50, 0xff, 0x76, 0x5e, 0x38, 0x1a, 0x69, 0xd5, 0xf4, 0x57, 0x81, 0x22, 0xdf, 0xdd, 0x16,
|
||||
0x75, 0xa5, 0x03, 0x78, 0xfb, 0x6a, 0xff, 0xc3, 0x72, 0x3a, 0x0e, 0xc7, 0xb1, 0x20, 0x5a, 0x87,
|
||||
0xb2, 0xd8, 0xc5, 0x06, 0x3b, 0x70, 0xdc, 0xac, 0x8b, 0x18, 0x04, 0x89, 0x49, 0xa2, 0xbb, 0xb0,
|
||||
0xc4, 0x8b, 0x3f, 0xc1, 0x01, 0xb1, 0x05, 0x26, 0xc7, 0x31, 0x8b, 0x31, 0x95, 0xc3, 0x76, 0xa0,
|
||||
0x22, 0x09, 0x06, 0x8f, 0xe7, 0xf3, 0x7c, 0x40, 0xf7, 0xae, 0x1b, 0x90, 0x10, 0xe1, 0x61, 0x7e,
|
||||
0x79, 0x34, 0x6d, 0xa8, 0x3f, 0x0f, 0xc5, 0x68, 0xb0, 0x68, 0x15, 0xe6, 0xfb, 0x5a, 0x57, 0x99,
|
||||
0xab, 0x2e, 0x9f, 0x9c, 0x6e, 0x94, 0x23, 0x72, 0x5f, 0xeb, 0x32, 0xce, 0x6e, 0xb3, 0xab, 0x64,
|
||||
0x2e, 0x72, 0x76, 0x9b, 0x5d, 0x54, 0x85, 0x5c, 0x4f, 0xeb, 0x77, 0xa3, 0xf8, 0x2c, 0x62, 0x31,
|
||||
0x5a, 0x35, 0xc7, 0xe2, 0x33, 0x75, 0x1f, 0xca, 0x89, 0xde, 0xd1, 0x9b, 0xb0, 0xd0, 0x6a, 0x3f,
|
||||
0xc5, 0x7a, 0xaf, 0xa7, 0xcc, 0x55, 0x6f, 0x9d, 0x9c, 0x6e, 0xa0, 0x04, 0xb7, 0xe5, 0x0d, 0xd8,
|
||||
0xda, 0xa1, 0xd7, 0x21, 0xb7, 0xd5, 0x61, 0xf7, 0xbe, 0x48, 0x2e, 0x12, 0x88, 0x2d, 0x1a, 0x84,
|
||||
0xd5, 0x9b, 0x32, 0xf0, 0x4b, 0x2a, 0x56, 0x7f, 0x2f, 0x03, 0x05, 0x71, 0xd0, 0x52, 0x17, 0xb1,
|
||||
0x0e, 0x0b, 0x51, 0x09, 0x41, 0x24, 0x7e, 0x6f, 0x5f, 0x9e, 0xa4, 0xd5, 0x64, 0x4e, 0x25, 0xb6,
|
||||
0x66, 0x24, 0x57, 0x7d, 0x1f, 0x2a, 0x49, 0xc6, 0xe7, 0xda, 0x98, 0xdf, 0x85, 0x32, 0xdb, 0xfb,
|
||||
0x51, 0xb2, 0xf6, 0x08, 0x0a, 0xc2, 0x59, 0xc4, 0xf7, 0xd0, 0xe5, 0x19, 0xa3, 0x44, 0xa2, 0x27,
|
||||
0xb0, 0x20, 0xb2, 0xcc, 0xa8, 0x72, 0xbc, 0x76, 0xf5, 0x09, 0xc3, 0x11, 0x5c, 0xfd, 0x10, 0x72,
|
||||
0x5d, 0x42, 0x7c, 0x66, 0x7b, 0x8f, 0xda, 0x64, 0x7a, 0x75, 0xcb, 0x04, 0xd9, 0x26, 0xad, 0x26,
|
||||
0x4b, 0x90, 0x6d, 0xd2, 0xb2, 0xe3, 0xda, 0x58, 0x36, 0x51, 0x1b, 0xeb, 0x43, 0xe5, 0x05, 0x71,
|
||||
0x06, 0x07, 0x21, 0xb1, 0xb9, 0xa2, 0x77, 0x21, 0x37, 0x22, 0xf1, 0xe0, 0x57, 0x53, 0x37, 0x1f,
|
||||
0x21, 0x3e, 0xe6, 0x28, 0xe6, 0x63, 0x8e, 0xb9, 0xb4, 0x7c, 0xee, 0x90, 0x2d, 0xf5, 0x1f, 0xb2,
|
||||
0xb0, 0xd4, 0x0a, 0x82, 0xb1, 0xe9, 0x59, 0x51, 0x54, 0xf7, 0xcd, 0x8b, 0x51, 0x5d, 0xea, 0xbb,
|
||||
0xd0, 0x45, 0x91, 0x8b, 0x25, 0x3f, 0x79, 0xb3, 0x66, 0xe3, 0x9b, 0x55, 0xfd, 0x71, 0x26, 0xaa,
|
||||
0xeb, 0xdd, 0x4d, 0xb8, 0x02, 0x91, 0x23, 0x26, 0x35, 0x91, 0x5d, 0xef, 0xd0, 0xa3, 0xc7, 0x1e,
|
||||
0x7a, 0x03, 0xf2, 0x58, 0x6f, 0xeb, 0x2f, 0x94, 0x8c, 0xd8, 0x9e, 0x17, 0x40, 0x98, 0x78, 0xe4,
|
||||
0x98, 0x69, 0xea, 0xea, 0xed, 0x26, 0x8b, 0xc2, 0xb2, 0x29, 0x9a, 0xba, 0xc4, 0xb3, 0x1d, 0x6f,
|
||||
0x80, 0xde, 0x84, 0x42, 0xab, 0xd7, 0xdb, 0xe5, 0x29, 0xe4, 0x6b, 0x27, 0xa7, 0x1b, 0x37, 0x2f,
|
||||
0xa0, 0x78, 0x4d, 0xd7, 0x66, 0x20, 0x96, 0x02, 0xb1, 0xf8, 0x2c, 0x05, 0xc4, 0x62, 0x6b, 0x01,
|
||||
0xc2, 0x9d, 0x7e, 0xbd, 0xaf, 0x2b, 0xf9, 0x14, 0x10, 0xa6, 0xec, 0xaf, 0x3c, 0x6e, 0xff, 0x92,
|
||||
0x05, 0xa5, 0x6e, 0x59, 0x64, 0x14, 0x32, 0xbe, 0xcc, 0x3a, 0xfb, 0x50, 0x1c, 0xb1, 0x5f, 0x0e,
|
||||
0x89, 0x22, 0xa8, 0x27, 0xa9, 0x2f, 0x9b, 0x33, 0x72, 0x35, 0x4c, 0x5d, 0x52, 0xb7, 0x87, 0x4e,
|
||||
0x10, 0x38, 0xd4, 0x13, 0x34, 0x1c, 0x6b, 0xaa, 0xfe, 0x67, 0x06, 0x6e, 0xa6, 0x20, 0xd0, 0x03,
|
||||
0xc8, 0xf9, 0xd4, 0x8d, 0xd6, 0xf0, 0xce, 0x65, 0x25, 0x5b, 0x26, 0x8a, 0x39, 0x12, 0xad, 0x01,
|
||||
0x98, 0xe3, 0x90, 0x9a, 0xbc, 0x7f, 0xbe, 0x7a, 0x45, 0x9c, 0xa0, 0xa0, 0x17, 0x50, 0x08, 0x88,
|
||||
0xe5, 0x93, 0x28, 0xce, 0xfe, 0xf0, 0xff, 0x3a, 0xfa, 0x5a, 0x8f, 0xab, 0xc1, 0x52, 0x5d, 0xb5,
|
||||
0x06, 0x05, 0x41, 0x61, 0xdb, 0xde, 0x36, 0x43, 0x53, 0x16, 0xf4, 0xf9, 0x6f, 0xb6, 0x9b, 0x4c,
|
||||
0x77, 0x10, 0xed, 0x26, 0xd3, 0x1d, 0xa8, 0x7f, 0x93, 0x05, 0xd0, 0x5f, 0x86, 0xc4, 0xf7, 0x4c,
|
||||
0x57, 0xab, 0x23, 0x3d, 0x71, 0x33, 0x88, 0xd9, 0x7e, 0x39, 0xf5, 0x95, 0x22, 0x96, 0xa8, 0x69,
|
||||
0xf5, 0x94, 0xbb, 0xe1, 0x36, 0xcc, 0x8f, 0x7d, 0xf9, 0x58, 0x2d, 0x62, 0xe4, 0x5d, 0xbc, 0x8d,
|
||||
0x19, 0x0d, 0xe9, 0x53, 0xb7, 0x35, 0x7f, 0xf9, 0x93, 0x74, 0xa2, 0x83, 0x54, 0xd7, 0xc5, 0x4e,
|
||||
0xbe, 0x65, 0x1a, 0x16, 0x91, 0xb7, 0x4a, 0x45, 0x9c, 0x7c, 0xad, 0xae, 0x11, 0x3f, 0xc4, 0x05,
|
||||
0xcb, 0x64, 0xff, 0x7f, 0x22, 0xff, 0xf6, 0x2e, 0xc0, 0x74, 0x6a, 0x68, 0x0d, 0xf2, 0xda, 0x66,
|
||||
0xaf, 0xb7, 0xad, 0xcc, 0x09, 0x07, 0x3e, 0x65, 0x71, 0xb2, 0xfa, 0x97, 0x59, 0x28, 0x6a, 0x75,
|
||||
0x79, 0xe5, 0x6a, 0xa0, 0x70, 0xaf, 0xc4, 0x9f, 0x41, 0xc8, 0xcb, 0x91, 0xe3, 0x4f, 0xa4, 0x63,
|
||||
0xb9, 0x22, 0xe1, 0x5d, 0x62, 0x22, 0x6c, 0xd4, 0x3a, 0x17, 0x40, 0x18, 0x2a, 0x44, 0x1a, 0xc1,
|
||||
0xb0, 0xcc, 0xc8, 0xc7, 0xaf, 0x5d, 0x6d, 0x2c, 0x91, 0xba, 0x4c, 0xdb, 0x01, 0x2e, 0x47, 0x4a,
|
||||
0x34, 0x33, 0x40, 0xef, 0xc1, 0x72, 0xe0, 0x0c, 0x3c, 0xc7, 0x1b, 0x18, 0x91, 0xf1, 0xf8, 0x9b,
|
||||
0x4c, 0xe3, 0xc6, 0xf9, 0xd9, 0xfa, 0x62, 0x4f, 0xb0, 0xa4, 0x0d, 0x17, 0x25, 0x52, 0xe3, 0xa6,
|
||||
0x44, 0x5f, 0x87, 0xa5, 0x84, 0x28, 0xb3, 0xa2, 0x30, 0xbb, 0x72, 0x7e, 0xb6, 0x5e, 0x89, 0x25,
|
||||
0x9f, 0x91, 0x09, 0xae, 0xc4, 0x82, 0xcf, 0x08, 0xaf, 0xcd, 0xec, 0x53, 0xdf, 0x22, 0x86, 0xcf,
|
||||
0xcf, 0x34, 0xbf, 0xdd, 0x73, 0xb8, 0xcc, 0x69, 0xe2, 0x98, 0xab, 0xcf, 0xe1, 0x66, 0xc7, 0xb7,
|
||||
0x0e, 0x48, 0x10, 0x0a, 0x53, 0x48, 0x2b, 0x7e, 0x08, 0x77, 0x42, 0x33, 0x38, 0x34, 0x0e, 0x9c,
|
||||
0x20, 0xa4, 0xfe, 0xc4, 0xf0, 0x49, 0x48, 0x3c, 0xc6, 0x37, 0xf8, 0x43, 0xae, 0x2c, 0x08, 0xde,
|
||||
0x66, 0x98, 0x2d, 0x01, 0xc1, 0x11, 0x62, 0x9b, 0x01, 0xd4, 0x16, 0x54, 0x58, 0x0a, 0x23, 0x8b,
|
||||
0x6a, 0x6c, 0xf6, 0xe0, 0xd2, 0x81, 0xf1, 0x99, 0xaf, 0xa9, 0x92, 0x4b, 0x07, 0xe2, 0xa7, 0xfa,
|
||||
0x6d, 0x50, 0x9a, 0x4e, 0x30, 0x32, 0x43, 0xeb, 0x20, 0xaa, 0x74, 0xa2, 0x26, 0x28, 0x07, 0xc4,
|
||||
0xf4, 0xc3, 0x3d, 0x62, 0x86, 0xc6, 0x88, 0xf8, 0x0e, 0xb5, 0xaf, 0x5f, 0xe5, 0xe5, 0x58, 0xa4,
|
||||
0xcb, 0x25, 0xd4, 0xff, 0xce, 0x00, 0x60, 0x73, 0x3f, 0x8a, 0xd6, 0xbe, 0x02, 0x37, 0x02, 0xcf,
|
||||
0x1c, 0x05, 0x07, 0x34, 0x34, 0x1c, 0x2f, 0x24, 0xfe, 0x91, 0xe9, 0xca, 0xe2, 0x8e, 0x12, 0x31,
|
||||
0x5a, 0x92, 0x8e, 0xde, 0x05, 0x74, 0x48, 0xc8, 0xc8, 0xa0, 0xae, 0x6d, 0x44, 0x4c, 0xf1, 0xcc,
|
||||
0x9c, 0xc3, 0x0a, 0xe3, 0x74, 0x5c, 0xbb, 0x17, 0xd1, 0x51, 0x03, 0xd6, 0xd8, 0xf4, 0x89, 0x17,
|
||||
0xfa, 0x0e, 0x09, 0x8c, 0x7d, 0xea, 0x1b, 0x81, 0x4b, 0x8f, 0x8d, 0x7d, 0xea, 0xba, 0xf4, 0x98,
|
||||
0xf8, 0x51, 0xdd, 0xac, 0xea, 0xd2, 0x81, 0x2e, 0x40, 0x9b, 0xd4, 0xef, 0xb9, 0xf4, 0x78, 0x33,
|
||||
0x42, 0xb0, 0x90, 0x6e, 0x3a, 0xe7, 0xd0, 0xb1, 0x0e, 0xa3, 0x90, 0x2e, 0xa6, 0xf6, 0x1d, 0xeb,
|
||||
0x10, 0xbd, 0x09, 0x8b, 0xc4, 0x25, 0xbc, 0x7c, 0x22, 0x50, 0x79, 0x8e, 0xaa, 0x44, 0x44, 0x06,
|
||||
0x52, 0x3f, 0x02, 0x45, 0xf7, 0x2c, 0x7f, 0x32, 0x4a, 0xac, 0xf9, 0xbb, 0x80, 0x98, 0x93, 0x34,
|
||||
0x5c, 0x6a, 0x1d, 0x1a, 0x43, 0xd3, 0x33, 0x07, 0x6c, 0x5c, 0xe2, 0xf5, 0x4f, 0x61, 0x9c, 0x6d,
|
||||
0x6a, 0x1d, 0xee, 0x48, 0xba, 0xfa, 0x1e, 0x40, 0x6f, 0xe4, 0x13, 0xd3, 0xee, 0xb0, 0x68, 0x82,
|
||||
0x99, 0x8e, 0xb7, 0x0c, 0x5b, 0xbe, 0x9e, 0x52, 0x5f, 0x1e, 0x75, 0x45, 0x30, 0x9a, 0x31, 0x5d,
|
||||
0xfd, 0x59, 0xb8, 0xd9, 0x75, 0x4d, 0x8b, 0x7f, 0x49, 0xd0, 0x8d, 0x9f, 0xb3, 0xd0, 0x13, 0x28,
|
||||
0x08, 0xa8, 0x5c, 0xc9, 0xd4, 0xe3, 0x36, 0xed, 0x73, 0x6b, 0x0e, 0x4b, 0x7c, 0xa3, 0x02, 0x30,
|
||||
0xd5, 0xa3, 0xfe, 0x79, 0x06, 0x4a, 0xb1, 0x7e, 0xb4, 0x21, 0x5e, 0x69, 0x42, 0xdf, 0x74, 0x3c,
|
||||
0x99, 0xf1, 0x97, 0x70, 0x92, 0x84, 0x5a, 0x50, 0x1e, 0xc5, 0xd2, 0x57, 0xc6, 0x73, 0x29, 0xa3,
|
||||
0xc6, 0x49, 0x59, 0xf4, 0x3e, 0x94, 0xa2, 0xe7, 0xea, 0xc8, 0xc3, 0x5e, 0xfd, 0xba, 0x3d, 0x85,
|
||||
0xab, 0xdf, 0x04, 0xf8, 0x16, 0x75, 0xbc, 0x3e, 0x3d, 0x24, 0x1e, 0x7f, 0x7e, 0x65, 0xf9, 0x22,
|
||||
0x89, 0xac, 0x28, 0x5b, 0xbc, 0x0c, 0x20, 0x96, 0x20, 0x7e, 0x85, 0x14, 0x4d, 0xf5, 0xaf, 0xb3,
|
||||
0x50, 0xc0, 0x94, 0x86, 0x5a, 0x1d, 0x6d, 0x40, 0x41, 0xfa, 0x09, 0x7e, 0xff, 0x34, 0x4a, 0xe7,
|
||||
0x67, 0xeb, 0x79, 0xe1, 0x20, 0xf2, 0x16, 0xf7, 0x0c, 0x09, 0x0f, 0x9e, 0xbd, 0xcc, 0x83, 0xa3,
|
||||
0x07, 0x50, 0x91, 0x20, 0xe3, 0xc0, 0x0c, 0x0e, 0x44, 0xf2, 0xd6, 0x58, 0x3a, 0x3f, 0x5b, 0x07,
|
||||
0x81, 0xdc, 0x32, 0x83, 0x03, 0x0c, 0x02, 0xcd, 0x7e, 0x23, 0x1d, 0xca, 0x1f, 0x53, 0xc7, 0x33,
|
||||
0x42, 0x3e, 0x09, 0x59, 0x68, 0x4c, 0x5d, 0xc7, 0xe9, 0x54, 0xe5, 0xb7, 0x08, 0xf0, 0xf1, 0x74,
|
||||
0xf2, 0x3a, 0x2c, 0xfa, 0x94, 0x86, 0xc2, 0x6d, 0x39, 0xd4, 0x93, 0x35, 0x8c, 0x8d, 0xd4, 0xd2,
|
||||
0x36, 0xa5, 0x21, 0x96, 0x38, 0x5c, 0xf1, 0x13, 0x2d, 0xf4, 0x00, 0x56, 0x5c, 0x33, 0x08, 0x0d,
|
||||
0xee, 0xef, 0xec, 0xa9, 0xb6, 0x02, 0x3f, 0x6a, 0x88, 0xf1, 0x36, 0x39, 0x2b, 0x92, 0x50, 0xff,
|
||||
0x29, 0x03, 0x65, 0x36, 0x19, 0x67, 0xdf, 0xb1, 0x58, 0x90, 0xf7, 0xf9, 0x63, 0x8f, 0xdb, 0x30,
|
||||
0x6f, 0x05, 0xbe, 0x34, 0x2a, 0xbf, 0x7c, 0xb5, 0x1e, 0xc6, 0x8c, 0x86, 0x3e, 0x82, 0x82, 0xac,
|
||||
0xa5, 0x88, 0xb0, 0x43, 0xbd, 0x3e, 0x1c, 0x95, 0xb6, 0x91, 0x72, 0x7c, 0x2f, 0x4f, 0x47, 0x27,
|
||||
0x2e, 0x01, 0x9c, 0x24, 0xa1, 0x5b, 0x90, 0xb5, 0x84, 0xb9, 0xe4, 0xc7, 0x2e, 0x5a, 0x1b, 0x67,
|
||||
0x2d, 0x4f, 0xfd, 0x41, 0x06, 0x16, 0xa7, 0x07, 0x9e, 0xed, 0x80, 0x3b, 0x50, 0x0a, 0xc6, 0x7b,
|
||||
0xc1, 0x24, 0x08, 0xc9, 0x30, 0x7a, 0x5a, 0x8e, 0x09, 0xa8, 0x05, 0x25, 0xd3, 0x1d, 0x50, 0xdf,
|
||||
0x09, 0x0f, 0x86, 0x32, 0x4b, 0x4d, 0x0f, 0x15, 0x92, 0x3a, 0x6b, 0xf5, 0x48, 0x04, 0x4f, 0xa5,
|
||||
0xa3, 0x7b, 0x5f, 0x7c, 0x7f, 0xc0, 0xef, 0xfd, 0x37, 0xa0, 0xe2, 0x9a, 0x43, 0x5e, 0x5c, 0x0a,
|
||||
0x9d, 0xa1, 0x98, 0x47, 0x0e, 0x97, 0x25, 0xad, 0xef, 0x0c, 0x89, 0xaa, 0x42, 0x29, 0x56, 0x86,
|
||||
0x96, 0xa1, 0x5c, 0xd7, 0x7b, 0xc6, 0xc3, 0x47, 0x4f, 0x8c, 0xa7, 0xda, 0x8e, 0x32, 0x27, 0x63,
|
||||
0xd3, 0xbf, 0xc8, 0xc0, 0xa2, 0x74, 0x47, 0x32, 0xde, 0x7f, 0x13, 0x16, 0x7c, 0x73, 0x3f, 0x8c,
|
||||
0x32, 0x92, 0x9c, 0xd8, 0xd5, 0xcc, 0xc3, 0xb3, 0x8c, 0x84, 0xb1, 0xd2, 0x33, 0x92, 0xc4, 0xc7,
|
||||
0x0e, 0xf3, 0x57, 0x7e, 0xec, 0x90, 0xfb, 0xa9, 0x7c, 0xec, 0xa0, 0xfe, 0x0a, 0xc0, 0xa6, 0xe3,
|
||||
0x92, 0xbe, 0xa8, 0x43, 0xa5, 0xe5, 0x97, 0x2c, 0x86, 0x93, 0x75, 0xce, 0x28, 0x86, 0x6b, 0x35,
|
||||
0x31, 0xa3, 0x31, 0xd6, 0xc0, 0xb1, 0xe5, 0x61, 0xe4, 0xac, 0xa7, 0x8c, 0x35, 0x70, 0xec, 0xf8,
|
||||
0x55, 0x2e, 0x77, 0xdd, 0xab, 0xdc, 0x69, 0x06, 0x96, 0x65, 0xec, 0x1a, 0xbb, 0xdf, 0x2f, 0x43,
|
||||
0x49, 0x84, 0xb1, 0xd3, 0x84, 0x8e, 0x3f, 0xf0, 0x0b, 0x5c, 0xab, 0x89, 0x8b, 0x82, 0xdd, 0xb2,
|
||||
0xd1, 0x3a, 0x94, 0x25, 0x34, 0xf1, 0x61, 0x14, 0x08, 0x52, 0x9b, 0x0d, 0xff, 0xab, 0x90, 0xdb,
|
||||
0x77, 0x5c, 0x22, 0x37, 0x7a, 0xaa, 0x03, 0x98, 0x1a, 0x60, 0x6b, 0x0e, 0x73, 0x74, 0xa3, 0x18,
|
||||
0x15, 0xea, 0xf8, 0xf8, 0x64, 0xda, 0x99, 0x1c, 0x9f, 0xc8, 0x40, 0x67, 0xc6, 0x27, 0x70, 0x6c,
|
||||
0x7c, 0x82, 0x2d, 0xc6, 0x27, 0xa1, 0xc9, 0xf1, 0x09, 0xd2, 0x4f, 0x65, 0x7c, 0xdb, 0x70, 0xab,
|
||||
0xe1, 0x9a, 0xd6, 0xa1, 0xeb, 0x04, 0x21, 0xb1, 0x93, 0x1e, 0xe3, 0x11, 0x14, 0x2e, 0x04, 0x9d,
|
||||
0x57, 0x55, 0x34, 0x25, 0x52, 0xfd, 0xf7, 0x0c, 0x54, 0xb6, 0x88, 0xe9, 0x86, 0x07, 0xd3, 0xb2,
|
||||
0x51, 0x48, 0x82, 0x50, 0x5e, 0x56, 0xfc, 0x37, 0xfa, 0x1a, 0x14, 0xe3, 0x98, 0xe4, 0xda, 0xb7,
|
||||
0xb9, 0x18, 0x8a, 0x1e, 0xc3, 0x02, 0x3b, 0x63, 0x74, 0x1c, 0x25, 0x3b, 0x57, 0x3d, 0xfb, 0x48,
|
||||
0x24, 0xbb, 0x64, 0x7c, 0xc2, 0x83, 0x10, 0xbe, 0x95, 0xf2, 0x38, 0x6a, 0xa2, 0xff, 0x0f, 0x15,
|
||||
0xfe, 0x6a, 0x11, 0xc5, 0x5c, 0xf9, 0xeb, 0x74, 0x96, 0xc5, 0xc3, 0xa3, 0x88, 0xb7, 0xfe, 0x38,
|
||||
0x0b, 0x2b, 0x3b, 0xe6, 0x64, 0x8f, 0x48, 0xb7, 0x41, 0x6c, 0x4c, 0x2c, 0xea, 0xdb, 0xa8, 0x9b,
|
||||
0x74, 0x37, 0x57, 0xbc, 0x63, 0xa6, 0x09, 0xa7, 0x7b, 0x9d, 0x28, 0x01, 0xcb, 0x26, 0x12, 0xb0,
|
||||
0x15, 0xc8, 0x7b, 0xd4, 0xb3, 0x88, 0xf4, 0x45, 0xa2, 0xa1, 0xfe, 0x76, 0x26, 0xe9, 0x6b, 0xaa,
|
||||
0xf1, 0x1b, 0x23, 0xaf, 0x40, 0xb5, 0x69, 0x18, 0x77, 0x87, 0x3e, 0x82, 0x6a, 0x4f, 0xd7, 0xb0,
|
||||
0xde, 0x6f, 0x74, 0xbe, 0x6d, 0xf4, 0xea, 0xdb, 0xbd, 0xfa, 0xa3, 0x07, 0x46, 0xb7, 0xb3, 0xfd,
|
||||
0x9d, 0x87, 0x8f, 0x1f, 0x7c, 0x4d, 0xc9, 0x54, 0x37, 0x4e, 0x4e, 0x37, 0xee, 0xb4, 0xeb, 0xda,
|
||||
0xb6, 0x38, 0x32, 0x7b, 0xf4, 0x65, 0xcf, 0x74, 0x03, 0xf3, 0xd1, 0x83, 0x2e, 0x75, 0x27, 0x0c,
|
||||
0x83, 0xbe, 0x02, 0x68, 0x53, 0xc7, 0x6d, 0xbd, 0x6f, 0x44, 0x0e, 0x4d, 0x6b, 0x68, 0x4a, 0x56,
|
||||
0xa4, 0x35, 0x9b, 0xc4, 0xf7, 0x48, 0x58, 0xd7, 0x7b, 0x0f, 0x1f, 0x3d, 0xd1, 0x1a, 0x1a, 0x3b,
|
||||
0x04, 0x95, 0xe4, 0xed, 0x96, 0xbc, 0xb4, 0x33, 0x97, 0x5e, 0xda, 0xd3, 0xbb, 0x3f, 0x7b, 0xc9,
|
||||
0xdd, 0xbf, 0x09, 0x2b, 0x96, 0x4f, 0x83, 0xc0, 0x60, 0xb9, 0x02, 0xb1, 0x67, 0xb2, 0x91, 0x2f,
|
||||
0x9c, 0x9f, 0xad, 0xdf, 0xd0, 0x18, 0xbf, 0xc7, 0xd9, 0x52, 0xfd, 0x0d, 0x2b, 0x41, 0xe2, 0x3d,
|
||||
0xa9, 0xbf, 0x3f, 0xcf, 0xc2, 0x2e, 0xe7, 0xc8, 0x71, 0xc9, 0x80, 0x04, 0xe8, 0x39, 0x2c, 0x5b,
|
||||
0x3e, 0xb1, 0x59, 0x12, 0x60, 0xba, 0xc9, 0xcf, 0x71, 0xff, 0x5f, 0x6a, 0x04, 0x14, 0x0b, 0xd6,
|
||||
0xb4, 0x58, 0xaa, 0x37, 0x22, 0x16, 0x5e, 0xb2, 0x2e, 0xb4, 0xd1, 0xc7, 0xb0, 0x1c, 0x10, 0xd7,
|
||||
0xf1, 0xc6, 0x2f, 0x0d, 0x8b, 0x7a, 0x21, 0x79, 0x19, 0xbd, 0xad, 0x5d, 0xa7, 0xb7, 0xa7, 0x6f,
|
||||
0x33, 0x29, 0x4d, 0x08, 0x35, 0xd0, 0xf9, 0xd9, 0xfa, 0xd2, 0x45, 0x1a, 0x5e, 0x92, 0x9a, 0x65,
|
||||
0xbb, 0xda, 0x86, 0xa5, 0x8b, 0xa3, 0x41, 0x2b, 0xd2, 0x53, 0x70, 0x87, 0x13, 0x79, 0x02, 0x74,
|
||||
0x07, 0x8a, 0x3e, 0x19, 0x38, 0x41, 0xe8, 0x0b, 0x33, 0x33, 0x4e, 0x4c, 0x61, 0x7e, 0x42, 0x7c,
|
||||
0x4b, 0x55, 0xfd, 0x25, 0x98, 0xe9, 0x91, 0x1d, 0x2d, 0xdb, 0x09, 0xcc, 0x3d, 0xa9, 0xb2, 0x88,
|
||||
0xa3, 0x26, 0xdb, 0xb1, 0xe3, 0x20, 0x0e, 0xeb, 0xf8, 0x6f, 0x46, 0xe3, 0xf1, 0x87, 0xfc, 0xb2,
|
||||
0x8c, 0x47, 0x18, 0xd1, 0x27, 0xaa, 0xb9, 0xc4, 0x27, 0xaa, 0x2b, 0x90, 0x77, 0xc9, 0x11, 0x71,
|
||||
0xc5, 0xcd, 0x8f, 0x45, 0xe3, 0xde, 0x03, 0xa8, 0x44, 0xdf, 0x42, 0xf2, 0x6f, 0x30, 0x8a, 0x90,
|
||||
0xeb, 0xd7, 0x7b, 0xcf, 0x94, 0x39, 0x04, 0x50, 0x10, 0x3b, 0x59, 0xbc, 0xfb, 0x69, 0x9d, 0xf6,
|
||||
0x66, 0xeb, 0xa9, 0x92, 0xbd, 0xf7, 0x3b, 0x39, 0x28, 0xc5, 0x2f, 0x4f, 0xec, 0xa6, 0x69, 0xeb,
|
||||
0x2f, 0xa2, 0xa3, 0x10, 0xd3, 0xdb, 0xe4, 0x18, 0xbd, 0x31, 0xad, 0x59, 0x7d, 0x24, 0x9e, 0xda,
|
||||
0x63, 0x76, 0x54, 0xaf, 0x7a, 0x0b, 0x8a, 0xf5, 0x5e, 0xaf, 0xf5, 0xb4, 0xad, 0x37, 0x95, 0x4f,
|
||||
0x33, 0xd5, 0x2f, 0x9c, 0x9c, 0x6e, 0xdc, 0x88, 0x41, 0xf5, 0x40, 0x6c, 0x3e, 0x8e, 0xd2, 0x34,
|
||||
0xbd, 0xdb, 0xd7, 0x9b, 0xca, 0x27, 0xd9, 0x59, 0x14, 0xaf, 0xc1, 0xf0, 0x8f, 0x80, 0x4a, 0x5d,
|
||||
0xac, 0x77, 0xeb, 0x98, 0x75, 0xf8, 0x69, 0x56, 0x94, 0xd2, 0xa6, 0x3d, 0xfa, 0x64, 0x64, 0xfa,
|
||||
0xac, 0xcf, 0xb5, 0xe8, 0xab, 0xba, 0x4f, 0xe6, 0xc5, 0x87, 0x22, 0xd3, 0x67, 0x34, 0x62, 0xda,
|
||||
0x13, 0xd6, 0x1b, 0x7f, 0xbf, 0xe4, 0x6a, 0xe6, 0x67, 0x7a, 0xeb, 0x31, 0x4f, 0xc5, 0xb4, 0xa8,
|
||||
0xb0, 0x80, 0x77, 0xdb, 0x6d, 0x06, 0xfa, 0x24, 0x37, 0x33, 0x3b, 0x3c, 0xf6, 0x58, 0x7e, 0x8d,
|
||||
0xee, 0x42, 0x31, 0x7a, 0xde, 0x54, 0x3e, 0xcd, 0xcd, 0x0c, 0x48, 0x8b, 0xde, 0x66, 0x79, 0x87,
|
||||
0x5b, 0xbb, 0x7d, 0xfe, 0xd1, 0xdf, 0x27, 0xf9, 0xd9, 0x0e, 0x0f, 0xc6, 0xa1, 0x4d, 0x8f, 0x3d,
|
||||
0x76, 0x66, 0x65, 0xd5, 0xee, 0xd3, 0xbc, 0xf0, 0x05, 0x31, 0x46, 0x96, 0xec, 0xde, 0x82, 0x22,
|
||||
0xd6, 0xbf, 0x25, 0xbe, 0x0f, 0xfc, 0xa4, 0x30, 0xa3, 0x07, 0x93, 0x8f, 0x89, 0xc5, 0x7a, 0xdb,
|
||||
0x80, 0x02, 0xd6, 0x77, 0x3a, 0xcf, 0x75, 0xe5, 0x0f, 0x0a, 0x33, 0x7a, 0x30, 0x19, 0x52, 0xfe,
|
||||
0x95, 0x54, 0xb1, 0x83, 0xbb, 0x5b, 0x75, 0xbe, 0x28, 0xb3, 0x7a, 0x3a, 0xfe, 0xe8, 0xc0, 0xf4,
|
||||
0x88, 0x3d, 0xfd, 0x9e, 0x26, 0x66, 0xdd, 0xfb, 0x39, 0x28, 0x46, 0x91, 0x2e, 0x5a, 0x83, 0xc2,
|
||||
0x8b, 0x0e, 0x7e, 0xa6, 0x63, 0x65, 0x4e, 0x58, 0x39, 0xe2, 0xbc, 0x10, 0x39, 0xca, 0x06, 0x2c,
|
||||
0xec, 0xd4, 0xdb, 0xf5, 0xa7, 0x3a, 0x8e, 0x4a, 0xee, 0x11, 0x40, 0x86, 0x6b, 0x55, 0x45, 0x76,
|
||||
0x10, 0xeb, 0x6c, 0xac, 0x7e, 0xff, 0x47, 0x6b, 0x73, 0x3f, 0xfc, 0xd1, 0xda, 0xdc, 0x27, 0xe7,
|
||||
0x6b, 0x99, 0xef, 0x9f, 0xaf, 0x65, 0xfe, 0xfe, 0x7c, 0x2d, 0xf3, 0x6f, 0xe7, 0x6b, 0x99, 0xbd,
|
||||
0x02, 0xbf, 0x54, 0x1e, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x92, 0xe0, 0x5d, 0x4a, 0x5c,
|
||||
0x32, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -1035,6 +1035,7 @@ message MaybeEncryptedRecord {
|
|||
enum Algorithm {
|
||||
NONE = 0 [(gogoproto.enumvalue_customname) = "NotEncrypted"];
|
||||
SECRETBOX_SALSA20_POLY1305 = 1 [(gogoproto.enumvalue_customname) = "NACLSecretboxSalsa20Poly1305"];
|
||||
FERNET_AES_128_CBC = 2 [(gogoproto.enumvalue_customname) = "FernetAES128CBC"];
|
||||
}
|
||||
|
||||
Algorithm algorithm = 1;
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/docker/swarmkit/ca/keyutils"
|
||||
"github.com/docker/swarmkit/ca/pkcs8"
|
||||
"github.com/docker/swarmkit/connectionbroker"
|
||||
"github.com/docker/swarmkit/fips"
|
||||
"github.com/docker/swarmkit/ioutils"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -51,13 +52,6 @@ const (
|
|||
RootKeySize = 256
|
||||
// RootKeyAlgo defines the default algorithm for the root CA Key
|
||||
RootKeyAlgo = "ecdsa"
|
||||
// PassphraseENVVar defines the environment variable to look for the
|
||||
// root CA private key material encryption key
|
||||
PassphraseENVVar = "SWARM_ROOT_CA_PASSPHRASE"
|
||||
// PassphraseENVVarPrev defines the alternate environment variable to look for the
|
||||
// root CA private key material encryption key. It can be used for seamless
|
||||
// KEK rotations.
|
||||
PassphraseENVVarPrev = "SWARM_ROOT_CA_PASSPHRASE_PREV"
|
||||
// RootCAExpiration represents the default expiration for the root CA in seconds (20 years)
|
||||
RootCAExpiration = "630720000s"
|
||||
// DefaultNodeCertExpiration represents the default expiration for node certificates (3 months)
|
||||
|
@ -641,28 +635,10 @@ func newLocalSigner(keyBytes, certBytes []byte, certExpiry time.Duration, rootPo
|
|||
return nil, errors.Wrap(err, "error while validating signing CA certificate against roots and intermediates")
|
||||
}
|
||||
|
||||
var (
|
||||
passphraseStr string
|
||||
passphrase, passphrasePrev []byte
|
||||
priv crypto.Signer
|
||||
)
|
||||
|
||||
// Attempt two distinct passphrases, so we can do a hitless passphrase rotation
|
||||
if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
|
||||
passphrase = []byte(passphraseStr)
|
||||
}
|
||||
|
||||
if p := os.Getenv(PassphraseENVVarPrev); p != "" {
|
||||
passphrasePrev = []byte(p)
|
||||
}
|
||||
|
||||
// Attempt to decrypt the current private-key with the passphrases provided
|
||||
priv, err = keyutils.ParsePrivateKeyPEMWithPassword(keyBytes, passphrase)
|
||||
// The key should not be encrypted, but it could be in PKCS8 format rather than PKCS1
|
||||
priv, err := keyutils.ParsePrivateKeyPEMWithPassword(keyBytes, nil)
|
||||
if err != nil {
|
||||
priv, err = keyutils.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "malformed private key")
|
||||
}
|
||||
return nil, errors.Wrap(err, "malformed private key")
|
||||
}
|
||||
|
||||
// We will always use the first certificate inside of the root bundle as the active one
|
||||
|
@ -675,17 +651,6 @@ func newLocalSigner(keyBytes, certBytes []byte, certExpiry time.Duration, rootPo
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// If the key was loaded from disk unencrypted, but there is a passphrase set,
|
||||
// ensure it is encrypted, so it doesn't hit raft in plain-text
|
||||
// we don't have to check for nil, because if we couldn't pem-decode the bytes, then parsing above would have failed
|
||||
keyBlock, _ := pem.Decode(keyBytes)
|
||||
if passphraseStr != "" && !keyutils.IsEncryptedPEMBlock(keyBlock) {
|
||||
keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to encrypt signing CA key material")
|
||||
}
|
||||
}
|
||||
|
||||
return &LocalSigner{Cert: certBytes, Key: keyBytes, Signer: signer, parsedCert: parsedCerts[0], cryptoSigner: priv}, nil
|
||||
}
|
||||
|
||||
|
@ -818,7 +783,7 @@ func CreateRootCA(rootCN string) (RootCA, error) {
|
|||
}
|
||||
|
||||
// Convert key to PKCS#8 in FIPS mode
|
||||
if keyutils.FIPSEnabled() {
|
||||
if fips.Enabled() {
|
||||
key, err = pkcs8.ConvertECPrivateKeyPEM(key)
|
||||
if err != nil {
|
||||
return RootCA{}, err
|
||||
|
@ -976,30 +941,6 @@ func GenerateNewCSR() ([]byte, []byte, error) {
|
|||
return csr, key, err
|
||||
}
|
||||
|
||||
// EncryptECPrivateKey receives a PEM encoded private key and returns an encrypted
|
||||
// AES256 version using a passphrase
|
||||
// TODO: Make this method generic to handle RSA keys
|
||||
func EncryptECPrivateKey(key []byte, passphraseStr string) ([]byte, error) {
|
||||
passphrase := []byte(passphraseStr)
|
||||
|
||||
keyBlock, _ := pem.Decode(key)
|
||||
if keyBlock == nil {
|
||||
// This RootCA does not have a valid signer.
|
||||
return nil, errors.New("error while decoding PEM key")
|
||||
}
|
||||
|
||||
encryptedPEMBlock, err := keyutils.EncryptPEMBlock(keyBlock.Bytes, passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if encryptedPEMBlock.Headers == nil {
|
||||
return nil, errors.New("unable to encrypt key - invalid PEM file produced")
|
||||
}
|
||||
|
||||
return pem.EncodeToMemory(encryptedPEMBlock), nil
|
||||
}
|
||||
|
||||
// NormalizePEMs takes a bundle of PEM-encoded certificates in a certificate bundle,
|
||||
// decodes them, removes headers, and re-encodes them to make sure that they have
|
||||
// consistent whitespace. Note that this is intended to normalize x509 certificates
|
||||
|
|
|
@ -10,22 +10,14 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/docker/swarmkit/ca/pkcs8"
|
||||
"github.com/docker/swarmkit/fips"
|
||||
)
|
||||
|
||||
var errFIPSUnsupportedKeyFormat = errors.New("unsupported key format due to FIPS compliance")
|
||||
|
||||
// FIPSEnvVar is the environment variable which stores FIPS mode state
|
||||
const FIPSEnvVar = "GOFIPS"
|
||||
|
||||
// FIPSEnabled returns true when FIPS mode is enabled
|
||||
func FIPSEnabled() bool {
|
||||
return os.Getenv(FIPSEnvVar) != ""
|
||||
}
|
||||
|
||||
// IsPKCS8 returns true if the provided der bytes is encrypted/unencrypted PKCS#8 key
|
||||
func IsPKCS8(derBytes []byte) bool {
|
||||
if _, err := x509.ParsePKCS8PrivateKey(derBytes); err == nil {
|
||||
|
@ -49,7 +41,7 @@ func ParsePrivateKeyPEMWithPassword(pemBytes, password []byte) (crypto.Signer, e
|
|||
|
||||
if IsPKCS8(block.Bytes) {
|
||||
return pkcs8.ParsePrivateKeyPEMWithPassword(pemBytes, password)
|
||||
} else if FIPSEnabled() {
|
||||
} else if fips.Enabled() {
|
||||
return nil, errFIPSUnsupportedKeyFormat
|
||||
}
|
||||
|
||||
|
@ -59,7 +51,7 @@ func ParsePrivateKeyPEMWithPassword(pemBytes, password []byte) (crypto.Signer, e
|
|||
// IsEncryptedPEMBlock checks if a PKCS#1 or PKCS#8 PEM-block is encrypted or not
|
||||
// It returns false in FIPS mode even if PKCS#1 is encrypted
|
||||
func IsEncryptedPEMBlock(block *pem.Block) bool {
|
||||
return pkcs8.IsEncryptedPEMBlock(block) || (!FIPSEnabled() && x509.IsEncryptedPEMBlock(block))
|
||||
return pkcs8.IsEncryptedPEMBlock(block) || (!fips.Enabled() && x509.IsEncryptedPEMBlock(block))
|
||||
}
|
||||
|
||||
// DecryptPEMBlock requires PKCS#1 or PKCS#8 PEM Block and password to decrypt and return unencrypted der []byte
|
||||
|
@ -67,7 +59,7 @@ func IsEncryptedPEMBlock(block *pem.Block) bool {
|
|||
func DecryptPEMBlock(block *pem.Block, password []byte) ([]byte, error) {
|
||||
if IsPKCS8(block.Bytes) {
|
||||
return pkcs8.DecryptPEMBlock(block, password)
|
||||
} else if FIPSEnabled() {
|
||||
} else if fips.Enabled() {
|
||||
return nil, errFIPSUnsupportedKeyFormat
|
||||
}
|
||||
|
||||
|
@ -79,7 +71,7 @@ func DecryptPEMBlock(block *pem.Block, password []byte) ([]byte, error) {
|
|||
func EncryptPEMBlock(data, password []byte) (*pem.Block, error) {
|
||||
if IsPKCS8(data) {
|
||||
return pkcs8.EncryptPEMBlock(data, password)
|
||||
} else if FIPSEnabled() {
|
||||
} else if fips.Enabled() {
|
||||
return nil, errFIPSUnsupportedKeyFormat
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package fips
|
||||
|
||||
import "os"
|
||||
|
||||
// EnvVar is the environment variable which stores FIPS mode state
|
||||
const EnvVar = "GOFIPS"
|
||||
|
||||
// Enabled returns true when FIPS mode is enabled
|
||||
func Enabled() bool {
|
||||
return os.Getenv(EnvVar) != ""
|
||||
}
|
|
@ -118,42 +118,15 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
|
|||
return errors.Wrap(err, "failure while looking for ingress network during init")
|
||||
}
|
||||
|
||||
// Allocate networks in the store so far before we started
|
||||
// watching.
|
||||
var networks []*api.Network
|
||||
a.store.View(func(tx store.ReadTx) {
|
||||
networks, err = store.FindNetworks(tx, store.All)
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error listing all networks in store while trying to allocate during init")
|
||||
// First, allocate (read it as restore) objects likes network,nodes,serives
|
||||
// and tasks that were already allocated. Then go on the allocate objects
|
||||
// that are in raft and were previously not allocated. The reason being, during
|
||||
// restore, we make sure that we populate the allocated states of
|
||||
// the objects in the raft onto our in memory state.
|
||||
if err := a.allocateNetworks(ctx, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var allocatedNetworks []*api.Network
|
||||
for _, n := range networks {
|
||||
if na.IsAllocated(n) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := a.allocateNetwork(ctx, n); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("failed allocating network %s during init", n.ID)
|
||||
continue
|
||||
}
|
||||
allocatedNetworks = append(allocatedNetworks, n)
|
||||
}
|
||||
|
||||
if err := a.store.Batch(func(batch *store.Batch) error {
|
||||
for _, n := range allocatedNetworks {
|
||||
if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("failed committing allocation of network %s during init", n.ID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.G(ctx).WithError(err).Error("failed committing allocation of networks during init")
|
||||
}
|
||||
|
||||
// First, allocate objects that already have addresses associated with
|
||||
// them, to reserve these IP addresses in internal state.
|
||||
if err := a.allocateNodes(ctx, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -164,6 +137,11 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
|
|||
if err := a.allocateTasks(ctx, true); err != nil {
|
||||
return err
|
||||
}
|
||||
// Now allocate objects that were not previously allocated
|
||||
// but were present in the raft.
|
||||
if err := a.allocateNetworks(ctx, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := a.allocateNodes(ctx, false); err != nil {
|
||||
return err
|
||||
|
@ -184,7 +162,6 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
|
|||
if nc.nwkAllocator.IsAllocated(n) {
|
||||
break
|
||||
}
|
||||
|
||||
if IsIngressNetwork(n) && nc.ingressNetwork != nil {
|
||||
log.G(ctx).Errorf("Cannot allocate ingress network %s (%s) because another ingress network is already present: %s (%s)",
|
||||
n.ID, n.Spec.Annotations.Name, nc.ingressNetwork.ID, nc.ingressNetwork.Spec.Annotations)
|
||||
|
@ -560,6 +537,60 @@ func (a *Allocator) deallocateNode(node *api.Node) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// allocateNetworks allocates (restores) networks in the store so far before we process
|
||||
// watched events. existingOnly flags is set to true to specify if only allocated
|
||||
// networks need to be restored.
|
||||
func (a *Allocator) allocateNetworks(ctx context.Context, existingOnly bool) error {
|
||||
var (
|
||||
nc = a.netCtx
|
||||
networks []*api.Network
|
||||
err error
|
||||
)
|
||||
a.store.View(func(tx store.ReadTx) {
|
||||
networks, err = store.FindNetworks(tx, store.All)
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error listing all networks in store while trying to allocate during init")
|
||||
}
|
||||
|
||||
var allocatedNetworks []*api.Network
|
||||
for _, n := range networks {
|
||||
if nc.nwkAllocator.IsAllocated(n) {
|
||||
continue
|
||||
}
|
||||
// Network is considered allocated only if the DriverState and IPAM are NOT nil.
|
||||
// During initial restore (existingOnly being true), check the network state in
|
||||
// raft store. If it is allocated, then restore the same in the in memory allocator
|
||||
// state. If it is not allocated, then skip allocating the network at this step.
|
||||
// This is to avoid allocating an in-use network IP, subnet pool or vxlan id to
|
||||
// another network.
|
||||
if existingOnly &&
|
||||
(n.DriverState == nil ||
|
||||
n.IPAM == nil) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := a.allocateNetwork(ctx, n); err != nil {
|
||||
log.G(ctx).WithField("existingOnly", existingOnly).WithError(err).Errorf("failed allocating network %s during init", n.ID)
|
||||
continue
|
||||
}
|
||||
allocatedNetworks = append(allocatedNetworks, n)
|
||||
}
|
||||
|
||||
if err := a.store.Batch(func(batch *store.Batch) error {
|
||||
for _, n := range allocatedNetworks {
|
||||
if err := a.commitAllocatedNetwork(ctx, batch, n); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("failed committing allocation of network %s during init", n.ID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.G(ctx).WithError(err).Error("failed committing allocation of networks during init")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// allocateServices allocates services in the store so far before we process
|
||||
// watched events.
|
||||
func (a *Allocator) allocateServices(ctx context.Context, existingAddressesOnly bool) error {
|
||||
|
@ -580,7 +611,6 @@ func (a *Allocator) allocateServices(ctx context.Context, existingAddressesOnly
|
|||
if nc.nwkAllocator.IsServiceAllocated(s, networkallocator.OnInit) {
|
||||
continue
|
||||
}
|
||||
|
||||
if existingAddressesOnly &&
|
||||
(s.Endpoint == nil ||
|
||||
len(s.Endpoint.VirtualIPs) == 0) {
|
||||
|
|
|
@ -644,7 +644,7 @@ func (s *Server) CreateService(ctx context.Context, request *api.CreateServiceRe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.validateNetworks(request.Spec.Networks); err != nil {
|
||||
if err := s.validateNetworks(request.Spec.Task.Networks); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -727,6 +727,10 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.validateNetworks(request.Spec.Task.Networks); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var service *api.Service
|
||||
s.store.View(func(tx store.ReadTx) {
|
||||
service = store.GetService(tx, request.ServiceID)
|
||||
|
|
|
@ -165,16 +165,10 @@ type Dispatcher struct {
|
|||
}
|
||||
|
||||
// New returns Dispatcher with cluster interface(usually raft.Node).
|
||||
func New(cluster Cluster, c *Config, dp *drivers.DriverProvider, securityConfig *ca.SecurityConfig) *Dispatcher {
|
||||
func New() *Dispatcher {
|
||||
d := &Dispatcher{
|
||||
dp: dp,
|
||||
nodes: newNodeStore(c.HeartbeatPeriod, c.HeartbeatEpsilon, c.GracePeriodMultiplier, c.RateLimitPeriod),
|
||||
downNodes: newNodeStore(defaultNodeDownPeriod, 0, 1, 0),
|
||||
store: cluster.MemoryStore(),
|
||||
cluster: cluster,
|
||||
processUpdatesTrigger: make(chan struct{}, 1),
|
||||
config: c,
|
||||
securityConfig: securityConfig,
|
||||
}
|
||||
|
||||
d.processUpdatesCond = sync.NewCond(&d.processUpdatesLock)
|
||||
|
@ -182,6 +176,21 @@ func New(cluster Cluster, c *Config, dp *drivers.DriverProvider, securityConfig
|
|||
return d
|
||||
}
|
||||
|
||||
// Init is used to initialize the dispatcher and
|
||||
// is typically called before starting the dispatcher
|
||||
// when a manager becomes a leader.
|
||||
// The dispatcher is a grpc server, and unlike other components,
|
||||
// it can't simply be recreated on becoming a leader.
|
||||
// This function ensures the dispatcher restarts with a clean slate.
|
||||
func (d *Dispatcher) Init(cluster Cluster, c *Config, dp *drivers.DriverProvider, securityConfig *ca.SecurityConfig) {
|
||||
d.cluster = cluster
|
||||
d.config = c
|
||||
d.securityConfig = securityConfig
|
||||
d.dp = dp
|
||||
d.store = cluster.MemoryStore()
|
||||
d.nodes = newNodeStore(c.HeartbeatPeriod, c.HeartbeatEpsilon, c.GracePeriodMultiplier, c.RateLimitPeriod)
|
||||
}
|
||||
|
||||
func getWeightedPeers(cluster Cluster) []*api.WeightedPeer {
|
||||
members := cluster.GetMemberlist()
|
||||
var mgrs []*api.WeightedPeer
|
||||
|
@ -333,6 +342,7 @@ func (d *Dispatcher) Stop() error {
|
|||
// cancelled and should fail organically.
|
||||
d.rpcRW.Lock()
|
||||
d.nodes.Clean()
|
||||
d.downNodes.Clean()
|
||||
d.rpcRW.Unlock()
|
||||
|
||||
d.processUpdatesLock.Lock()
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/docker/swarmkit/api"
|
||||
"github.com/docker/swarmkit/fips"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -59,6 +60,60 @@ func (n noopCrypter) Algorithm() api.MaybeEncryptedRecord_Algorithm {
|
|||
// decrypt any data
|
||||
var NoopCrypter = noopCrypter{}
|
||||
|
||||
// specificDecryptor represents a specific type of Decrypter, like NaclSecretbox or Fernet.
|
||||
// It does not apply to a more general decrypter like MultiDecrypter.
|
||||
type specificDecrypter interface {
|
||||
Decrypter
|
||||
Algorithm() api.MaybeEncryptedRecord_Algorithm
|
||||
}
|
||||
|
||||
// MultiDecrypter is a decrypter that will attempt to decrypt with multiple decrypters. It
|
||||
// references them by algorithm, so that only the relevant decrypters are checked instead of
|
||||
// every single one. The reason for multiple decrypters per algorithm is to support hitless
|
||||
// encryption key rotation.
|
||||
//
|
||||
// For raft encryption for instance, during an encryption key rotation, it's possible to have
|
||||
// some raft logs encrypted with the old key and some encrypted with the new key, so we need a
|
||||
// decrypter that can decrypt both.
|
||||
type MultiDecrypter struct {
|
||||
decrypters map[api.MaybeEncryptedRecord_Algorithm][]Decrypter
|
||||
}
|
||||
|
||||
// Decrypt tries to decrypt using any decrypters that match the given algorithm.
|
||||
func (m MultiDecrypter) Decrypt(r api.MaybeEncryptedRecord) (result []byte, err error) {
|
||||
decrypters, ok := m.decrypters[r.Algorithm]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot decrypt record encrypted using %s",
|
||||
api.MaybeEncryptedRecord_Algorithm_name[int32(r.Algorithm)])
|
||||
}
|
||||
for _, d := range decrypters {
|
||||
result, err = d.Decrypt(r)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewMultiDecrypter returns a new MultiDecrypter given multiple Decrypters. If any of
|
||||
// the Decrypters are also MultiDecrypters, they are flattened into a single map, but
|
||||
// it does not deduplicate any decrypters.
|
||||
// Note that if something is neither a MultiDecrypter nor a specificDecrypter, it is
|
||||
// ignored.
|
||||
func NewMultiDecrypter(decrypters ...Decrypter) MultiDecrypter {
|
||||
m := MultiDecrypter{decrypters: make(map[api.MaybeEncryptedRecord_Algorithm][]Decrypter)}
|
||||
for _, d := range decrypters {
|
||||
if md, ok := d.(MultiDecrypter); ok {
|
||||
for algo, dec := range md.decrypters {
|
||||
m.decrypters[algo] = append(m.decrypters[algo], dec...)
|
||||
}
|
||||
} else if sd, ok := d.(specificDecrypter); ok {
|
||||
m.decrypters[sd.Algorithm()] = append(m.decrypters[sd.Algorithm()], sd)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Decrypt turns a slice of bytes serialized as an MaybeEncryptedRecord into a slice of plaintext bytes
|
||||
func Decrypt(encryptd []byte, decrypter Decrypter) ([]byte, error) {
|
||||
if decrypter == nil {
|
||||
|
@ -97,8 +152,12 @@ func Encrypt(plaintext []byte, encrypter Encrypter) ([]byte, error) {
|
|||
|
||||
// Defaults returns a default encrypter and decrypter
|
||||
func Defaults(key []byte) (Encrypter, Decrypter) {
|
||||
f := NewFernet(key)
|
||||
if fips.Enabled() {
|
||||
return f, f
|
||||
}
|
||||
n := NewNACLSecretbox(key)
|
||||
return n, n
|
||||
return n, NewMultiDecrypter(n, f)
|
||||
}
|
||||
|
||||
// GenerateSecretKey generates a secret key that can be used for encrypting data
|
||||
|
|
54
vendor/github.com/docker/swarmkit/manager/encryption/fernet.go
сгенерированный
поставляемый
Normal file
54
vendor/github.com/docker/swarmkit/manager/encryption/fernet.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,54 @@
|
|||
package encryption
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/swarmkit/api"
|
||||
|
||||
"github.com/fernet/fernet-go"
|
||||
)
|
||||
|
||||
// Fernet wraps the `fernet` library as an implementation of encrypter/decrypter.
|
||||
type Fernet struct {
|
||||
key fernet.Key
|
||||
}
|
||||
|
||||
// NewFernet returns a new Fernet encrypter/decrypter with the given key
|
||||
func NewFernet(key []byte) Fernet {
|
||||
frnt := Fernet{}
|
||||
copy(frnt.key[:], key)
|
||||
return frnt
|
||||
}
|
||||
|
||||
// Algorithm returns the type of algorithm this is (Fernet, which uses AES128-CBC)
|
||||
func (f Fernet) Algorithm() api.MaybeEncryptedRecord_Algorithm {
|
||||
return api.MaybeEncryptedRecord_FernetAES128CBC
|
||||
}
|
||||
|
||||
// Encrypt encrypts some bytes and returns an encrypted record
|
||||
func (f Fernet) Encrypt(data []byte) (*api.MaybeEncryptedRecord, error) {
|
||||
out, err := fernet.EncryptAndSign(data, &f.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// fernet generates its own IVs, so nonce is empty
|
||||
return &api.MaybeEncryptedRecord{
|
||||
Algorithm: f.Algorithm(),
|
||||
Data: out,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts a MaybeEncryptedRecord and returns some bytes
|
||||
func (f Fernet) Decrypt(record api.MaybeEncryptedRecord) ([]byte, error) {
|
||||
if record.Algorithm != f.Algorithm() {
|
||||
return nil, fmt.Errorf("record is not a Fernet message")
|
||||
}
|
||||
|
||||
// -1 skips the TTL check, since we don't care about message expiry
|
||||
out := fernet.VerifyAndDecrypt(record.Data, -1, []*fernet.Key{&f.key})
|
||||
// VerifyandDecrypt returns a nil message if it can't be verified and decrypted
|
||||
if out == nil {
|
||||
return nil, fmt.Errorf("decryption error using Fernet")
|
||||
}
|
||||
return out, nil
|
||||
}
|
|
@ -2,7 +2,6 @@ package manager
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
@ -17,7 +16,6 @@ import (
|
|||
gmetrics "github.com/docker/go-metrics"
|
||||
"github.com/docker/swarmkit/api"
|
||||
"github.com/docker/swarmkit/ca"
|
||||
"github.com/docker/swarmkit/ca/keyutils"
|
||||
"github.com/docker/swarmkit/connectionbroker"
|
||||
"github.com/docker/swarmkit/identity"
|
||||
"github.com/docker/swarmkit/log"
|
||||
|
@ -227,17 +225,51 @@ func New(config *Config) (*Manager, error) {
|
|||
}
|
||||
raftNode := raft.NewNode(newNodeOpts)
|
||||
|
||||
// the interceptorWrappers are functions that wrap the prometheus grpc
|
||||
// interceptor, and add some of code to log errors locally. one for stream
|
||||
// and one for unary. this is needed because the grpc unary interceptor
|
||||
// doesn't natively do chaining, you have to implement it in the caller.
|
||||
// note that even though these are logging errors, we're still using
|
||||
// debug level. returning errors from GRPC methods is common and expected,
|
||||
// and logging an ERROR every time a user mistypes a service name would
|
||||
// pollute the logs really fast.
|
||||
//
|
||||
// NOTE(dperny): Because of the fact that these functions are very simple
|
||||
// in their operation and have no side effects other than the log output,
|
||||
// they are not automatically tested. If you modify them later, make _sure_
|
||||
// that they are correct. If you add substantial side effects, abstract
|
||||
// these out and test them!
|
||||
unaryInterceptorWrapper := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
// pass the call down into the grpc_prometheus interceptor
|
||||
resp, err := grpc_prometheus.UnaryServerInterceptor(ctx, req, info, handler)
|
||||
if err != nil {
|
||||
log.G(ctx).WithField("rpc", info.FullMethod).WithError(err).Debug("error handling rpc")
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
streamInterceptorWrapper := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
// we can't re-write a stream context, so don't bother creating a
|
||||
// sub-context like in unary methods
|
||||
// pass the call down into the grpc_prometheus interceptor
|
||||
err := grpc_prometheus.StreamServerInterceptor(srv, ss, info, handler)
|
||||
if err != nil {
|
||||
log.G(ss.Context()).WithField("rpc", info.FullMethod).WithError(err).Debug("error handling streaming rpc")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
opts := []grpc.ServerOption{
|
||||
grpc.Creds(config.SecurityConfig.ServerTLSCreds),
|
||||
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
|
||||
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
|
||||
grpc.StreamInterceptor(streamInterceptorWrapper),
|
||||
grpc.UnaryInterceptor(unaryInterceptorWrapper),
|
||||
grpc.MaxMsgSize(transport.GRPCMaxMsgSize),
|
||||
}
|
||||
|
||||
m := &Manager{
|
||||
config: *config,
|
||||
caserver: ca.NewServer(raftNode.MemoryStore(), config.SecurityConfig),
|
||||
dispatcher: dispatcher.New(raftNode, dispatcher.DefaultConfig(), drivers.New(config.PluginGetter), config.SecurityConfig),
|
||||
dispatcher: dispatcher.New(),
|
||||
logbroker: logbroker.New(raftNode.MemoryStore()),
|
||||
watchServer: watchapi.NewServer(raftNode.MemoryStore()),
|
||||
server: grpc.NewServer(opts...),
|
||||
|
@ -620,6 +652,10 @@ func (m *Manager) Stop(ctx context.Context, clearData bool) {
|
|||
m.collector.Stop()
|
||||
}
|
||||
|
||||
// The following components are gRPC services that are
|
||||
// registered when creating the manager and will need
|
||||
// to be re-registered if they are recreated.
|
||||
// For simplicity, they are not nilled out.
|
||||
m.dispatcher.Stop()
|
||||
m.logbroker.Stop()
|
||||
m.watchServer.Stop()
|
||||
|
@ -768,111 +804,39 @@ func (m *Manager) watchForClusterChanges(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// rotateRootCAKEK will attempt to rotate the key-encryption-key for root CA key-material in raft.
|
||||
// If there is no passphrase set in ENV, it returns.
|
||||
// If there is plain-text root key-material, and a passphrase set, it encrypts it.
|
||||
// If there is encrypted root key-material and it is using the current passphrase, it returns.
|
||||
// If there is encrypted root key-material, and it is using the previous passphrase, it
|
||||
// re-encrypts it with the current passphrase.
|
||||
func (m *Manager) rotateRootCAKEK(ctx context.Context, clusterID string) error {
|
||||
// If we don't have a KEK, we won't ever be rotating anything
|
||||
strPassphrase := os.Getenv(ca.PassphraseENVVar)
|
||||
strPassphrasePrev := os.Getenv(ca.PassphraseENVVarPrev)
|
||||
if strPassphrase == "" && strPassphrasePrev == "" {
|
||||
return nil
|
||||
// getLeaderNodeID is a small helper function returning a string with the
|
||||
// leader's node ID. it is only used for logging, and should not be relied on
|
||||
// to give a node ID for actual operational purposes (because it returns errors
|
||||
// as nicely decorated strings)
|
||||
func (m *Manager) getLeaderNodeID() string {
|
||||
// get the current leader ID. this variable tracks the leader *only* for
|
||||
// the purposes of logging leadership changes, and should not be relied on
|
||||
// for other purposes
|
||||
leader, leaderErr := m.raftNode.Leader()
|
||||
switch leaderErr {
|
||||
case raft.ErrNoRaftMember:
|
||||
// this is an unlikely case, but we have to handle it. this means this
|
||||
// node is not a member of the raft quorum. this won't look very pretty
|
||||
// in logs ("leadership changed from aslkdjfa to ErrNoRaftMember") but
|
||||
// it also won't be very common
|
||||
return "not yet part of a raft cluster"
|
||||
case raft.ErrNoClusterLeader:
|
||||
return "no cluster leader"
|
||||
default:
|
||||
id, err := m.raftNode.GetNodeIDByRaftID(leader)
|
||||
// the only possible error here is "ErrMemberUnknown"
|
||||
if err != nil {
|
||||
return "an unknown node"
|
||||
}
|
||||
return id
|
||||
}
|
||||
if strPassphrase != "" {
|
||||
log.G(ctx).Warn("Encrypting the root CA key in swarm using environment variables is deprecated. " +
|
||||
"Support for decrypting or rotating the key will be removed in the future.")
|
||||
}
|
||||
|
||||
passphrase := []byte(strPassphrase)
|
||||
passphrasePrev := []byte(strPassphrasePrev)
|
||||
|
||||
s := m.raftNode.MemoryStore()
|
||||
var (
|
||||
cluster *api.Cluster
|
||||
err error
|
||||
finalKey []byte
|
||||
)
|
||||
// Retrieve the cluster identified by ClusterID
|
||||
return s.Update(func(tx store.Tx) error {
|
||||
cluster = store.GetCluster(tx, clusterID)
|
||||
if cluster == nil {
|
||||
return fmt.Errorf("cluster not found: %s", clusterID)
|
||||
}
|
||||
|
||||
// Try to get the private key from the cluster
|
||||
privKeyPEM := cluster.RootCA.CAKey
|
||||
if len(privKeyPEM) == 0 {
|
||||
// We have no PEM root private key in this cluster.
|
||||
log.G(ctx).Warnf("cluster %s does not have private key material", clusterID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decode the PEM private key
|
||||
keyBlock, _ := pem.Decode(privKeyPEM)
|
||||
if keyBlock == nil {
|
||||
return fmt.Errorf("invalid PEM-encoded private key inside of cluster %s", clusterID)
|
||||
}
|
||||
|
||||
if keyutils.IsEncryptedPEMBlock(keyBlock) {
|
||||
// PEM encryption does not have a digest, so sometimes decryption doesn't
|
||||
// error even with the wrong passphrase. So actually try to parse it into a valid key.
|
||||
_, err := keyutils.ParsePrivateKeyPEMWithPassword(privKeyPEM, []byte(passphrase))
|
||||
if err == nil {
|
||||
// This key is already correctly encrypted with the correct KEK, nothing to do here
|
||||
return nil
|
||||
}
|
||||
|
||||
// This key is already encrypted, but failed with current main passphrase.
|
||||
// Let's try to decrypt with the previous passphrase, and parse into a valid key, for the
|
||||
// same reason as above.
|
||||
_, err = keyutils.ParsePrivateKeyPEMWithPassword(privKeyPEM, []byte(passphrasePrev))
|
||||
if err != nil {
|
||||
// We were not able to decrypt either with the main or backup passphrase, error
|
||||
return err
|
||||
}
|
||||
// ok the above passphrase is correct, so decrypt the PEM block so we can re-encrypt -
|
||||
// since the key was successfully decrypted above, there will be no error doing PEM
|
||||
// decryption
|
||||
unencryptedDER, _ := keyutils.DecryptPEMBlock(keyBlock, []byte(passphrasePrev))
|
||||
unencryptedKeyBlock := &pem.Block{
|
||||
Type: keyBlock.Type,
|
||||
Bytes: unencryptedDER,
|
||||
}
|
||||
|
||||
// we were able to decrypt the key with the previous passphrase - if the current passphrase is empty,
|
||||
// the we store the decrypted key in raft
|
||||
finalKey = pem.EncodeToMemory(unencryptedKeyBlock)
|
||||
|
||||
// the current passphrase is not empty, so let's encrypt with the new one and store it in raft
|
||||
if strPassphrase != "" {
|
||||
finalKey, err = ca.EncryptECPrivateKey(finalKey, strPassphrase)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Debugf("failed to rotate the key-encrypting-key for the root key material of cluster %s", clusterID)
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if strPassphrase != "" {
|
||||
// If this key is not encrypted, and the passphrase is not nil, then we have to encrypt it
|
||||
finalKey, err = ca.EncryptECPrivateKey(privKeyPEM, strPassphrase)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Debugf("failed to rotate the key-encrypting-key for the root key material of cluster %s", clusterID)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return nil // don't update if it's not encrypted and we don't want it encrypted
|
||||
}
|
||||
|
||||
log.G(ctx).Infof("Updating the encryption on the root key material of cluster %s", clusterID)
|
||||
cluster.RootCA.CAKey = finalKey
|
||||
return store.UpdateCluster(tx, cluster)
|
||||
})
|
||||
}
|
||||
|
||||
// handleLeadershipEvents handles the is leader event or is follower event.
|
||||
func (m *Manager) handleLeadershipEvents(ctx context.Context, leadershipCh chan events.Event) {
|
||||
// get the current leader and save it for logging leadership changes in
|
||||
// this loop
|
||||
oldLeader := m.getLeaderNodeID()
|
||||
for {
|
||||
select {
|
||||
case leadershipEvent := <-leadershipCh:
|
||||
|
@ -891,6 +855,12 @@ func (m *Manager) handleLeadershipEvents(ctx context.Context, leadershipCh chan
|
|||
leaderMetric.Set(0)
|
||||
}
|
||||
m.mu.Unlock()
|
||||
|
||||
newLeader := m.getLeaderNodeID()
|
||||
// maybe we should use logrus fields for old and new leader, so
|
||||
// that users are better able to ingest leadership changes into log
|
||||
// aggregators?
|
||||
log.G(ctx).Infof("leadership changed from %v to %v", oldLeader, newLeader)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
@ -938,7 +908,10 @@ func (m *Manager) becomeLeader(ctx context.Context) {
|
|||
initialCAConfig := ca.DefaultCAConfig()
|
||||
initialCAConfig.ExternalCAs = m.config.ExternalCAs
|
||||
|
||||
var unlockKeys []*api.EncryptionKey
|
||||
var (
|
||||
unlockKeys []*api.EncryptionKey
|
||||
err error
|
||||
)
|
||||
if m.config.AutoLockManagers {
|
||||
unlockKeys = []*api.EncryptionKey{{
|
||||
Subsystem: ca.ManagerRole,
|
||||
|
@ -991,12 +964,6 @@ func (m *Manager) becomeLeader(ctx context.Context) {
|
|||
return nil
|
||||
})
|
||||
|
||||
// Attempt to rotate the key-encrypting-key of the root CA key-material
|
||||
err := m.rotateRootCAKEK(ctx, clusterID)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("root key-encrypting-key rotation failed")
|
||||
}
|
||||
|
||||
m.replicatedOrchestrator = replicated.NewReplicatedOrchestrator(s)
|
||||
m.constraintEnforcer = constraintenforcer.New(s)
|
||||
m.globalOrchestrator = global.NewGlobalOrchestrator(s)
|
||||
|
@ -1025,6 +992,8 @@ func (m *Manager) becomeLeader(ctx context.Context) {
|
|||
}
|
||||
|
||||
go func(d *dispatcher.Dispatcher) {
|
||||
// Initialize the dispatcher.
|
||||
d.Init(m.raftNode, dispatcher.DefaultConfig(), drivers.New(m.config.PluginGetter), m.config.SecurityConfig)
|
||||
if err := d.Run(ctx); err != nil {
|
||||
log.G(ctx).WithError(err).Error("Dispatcher exited with an error")
|
||||
}
|
||||
|
@ -1084,6 +1053,10 @@ func (m *Manager) becomeLeader(ctx context.Context) {
|
|||
|
||||
// becomeFollower shuts down the subsystems that are only run by the leader.
|
||||
func (m *Manager) becomeFollower() {
|
||||
// The following components are gRPC services that are
|
||||
// registered when creating the manager and will need
|
||||
// to be re-registered if they are recreated.
|
||||
// For simplicity, they are not nilled out.
|
||||
m.dispatcher.Stop()
|
||||
m.logbroker.Stop()
|
||||
m.caserver.Stop()
|
||||
|
|
|
@ -474,8 +474,11 @@ func (n *Node) joinCluster(ctx context.Context) error {
|
|||
// raft node that can be modified and customized
|
||||
func DefaultNodeConfig() *raft.Config {
|
||||
return &raft.Config{
|
||||
HeartbeatTick: 1,
|
||||
ElectionTick: 3,
|
||||
HeartbeatTick: 1,
|
||||
// Recommended value in etcd/raft is 10 x (HeartbeatTick).
|
||||
// Lower values were seen to have caused instability because of
|
||||
// frequent leader elections when running on flakey networks.
|
||||
ElectionTick: 10,
|
||||
MaxSizePerMsg: math.MaxUint16,
|
||||
MaxInflightMsgs: 256,
|
||||
Logger: log.L,
|
||||
|
@ -489,8 +492,11 @@ func DefaultRaftConfig() api.RaftConfig {
|
|||
KeepOldSnapshots: 0,
|
||||
SnapshotInterval: 10000,
|
||||
LogEntriesForSlowFollowers: 500,
|
||||
ElectionTick: 3,
|
||||
HeartbeatTick: 1,
|
||||
// Recommended value in etcd/raft is 10 x (HeartbeatTick).
|
||||
// Lower values were seen to have caused instability because of
|
||||
// frequent leader elections when running on flakey networks.
|
||||
HeartbeatTick: 1,
|
||||
ElectionTick: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1703,6 +1709,18 @@ func (n *Node) GetMemberByNodeID(nodeID string) *membership.Member {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetNodeIDByRaftID returns the generic Node ID of a member given its raft ID.
|
||||
// It returns ErrMemberUnknown if the raft ID is unknown.
|
||||
func (n *Node) GetNodeIDByRaftID(raftID uint64) (string, error) {
|
||||
if member, ok := n.cluster.Members()[raftID]; ok {
|
||||
return member.NodeID, nil
|
||||
}
|
||||
// this is the only possible error value that should be returned; the
|
||||
// manager code depends on this. if you need to add more errors later, make
|
||||
// sure that you update the callers of this method accordingly
|
||||
return "", ErrMemberUnknown
|
||||
}
|
||||
|
||||
// IsMember checks if the raft node has effectively joined
|
||||
// a cluster of existing members.
|
||||
func (n *Node) IsMember() bool {
|
||||
|
|
17
vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go
сгенерированный
поставляемый
17
vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go
сгенерированный
поставляемый
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/coreos/etcd/snap"
|
||||
"github.com/coreos/etcd/wal"
|
||||
"github.com/coreos/etcd/wal/walpb"
|
||||
"github.com/docker/swarmkit/api"
|
||||
"github.com/docker/swarmkit/log"
|
||||
"github.com/docker/swarmkit/manager/encryption"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -34,20 +33,6 @@ var versionedWALSnapDirs = []walSnapDirs{
|
|||
{wal: "wal", snap: "snap"},
|
||||
}
|
||||
|
||||
// MultiDecrypter attempts to decrypt with a list of decrypters
|
||||
type MultiDecrypter []encryption.Decrypter
|
||||
|
||||
// Decrypt tries to decrypt using all the decrypters
|
||||
func (m MultiDecrypter) Decrypt(r api.MaybeEncryptedRecord) (result []byte, err error) {
|
||||
for _, d := range m {
|
||||
result, err = d.Decrypt(r)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncryptedRaftLogger saves raft data to disk
|
||||
type EncryptedRaftLogger struct {
|
||||
StateDir string
|
||||
|
@ -75,7 +60,7 @@ func (e *EncryptedRaftLogger) BootstrapFromDisk(ctx context.Context, oldEncrypti
|
|||
_, d := encryption.Defaults(key)
|
||||
decrypters = append(decrypters, d)
|
||||
}
|
||||
decrypter = MultiDecrypter(decrypters)
|
||||
decrypter = encryption.NewMultiDecrypter(decrypters...)
|
||||
}
|
||||
|
||||
snapFactory := NewSnapFactory(encrypter, decrypter)
|
||||
|
|
|
@ -260,12 +260,16 @@ func (n *Node) currentRole() api.NodeRole {
|
|||
func (n *Node) run(ctx context.Context) (err error) {
|
||||
defer func() {
|
||||
n.err = err
|
||||
// close the n.closed channel to indicate that the Node has completely
|
||||
// terminated
|
||||
close(n.closed)
|
||||
}()
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
ctx = log.WithModule(ctx, "node")
|
||||
|
||||
// set up a goroutine to monitor the stop channel, and cancel the run
|
||||
// context when the node is stopped
|
||||
go func(ctx context.Context) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
@ -274,6 +278,17 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
}
|
||||
}(ctx)
|
||||
|
||||
// First thing's first: get the SecurityConfig for this node. This includes
|
||||
// the certificate information, and the root CA. It also returns a cancel
|
||||
// function. This is needed because the SecurityConfig is a live object,
|
||||
// and provides a watch queue so that caller can observe changes to the
|
||||
// security config. This watch queue has to be closed, which is done by the
|
||||
// secConfigCancel function.
|
||||
//
|
||||
// It's also noteworthy that loading the security config with the node's
|
||||
// loadSecurityConfig method has the side effect of setting the node's ID
|
||||
// and role fields, meaning it isn't until after that point that node knows
|
||||
// its ID
|
||||
paths := ca.NewConfigPaths(filepath.Join(n.config.StateDir, certDirectory))
|
||||
securityConfig, secConfigCancel, err := n.loadSecurityConfig(ctx, paths)
|
||||
if err != nil {
|
||||
|
@ -281,11 +296,23 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
}
|
||||
defer secConfigCancel()
|
||||
|
||||
// Now that we have the security config, we can get a TLSRenewer, which is
|
||||
// a live component handling certificate rotation.
|
||||
renewer := ca.NewTLSRenewer(securityConfig, n.connBroker, paths.RootCA)
|
||||
|
||||
// Now that we have the security goop all loaded, we know the Node's ID and
|
||||
// can add that to our logging context.
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("node.id", n.NodeID()))
|
||||
|
||||
// Next, set up the task database. The task database is used by the agent
|
||||
// to keep a persistent local record of its tasks. Since every manager also
|
||||
// has an agent, every node needs a task database, so we do this regardless
|
||||
// of role.
|
||||
taskDBPath := filepath.Join(n.config.StateDir, "worker", "tasks.db")
|
||||
// Doing os.MkdirAll will create the necessary directory path for the task
|
||||
// database if it doesn't already exist, and if it does already exist, no
|
||||
// error will be returned, so we use this regardless of whether this node
|
||||
// is new or not.
|
||||
if err := os.MkdirAll(filepath.Dir(taskDBPath), 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -296,8 +323,18 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
// agentDone is a channel that represents the agent having exited. We start
|
||||
// the agent in a goroutine a few blocks down, and before that goroutine
|
||||
// exits, it closes this channel to signal to the goroutine just below to
|
||||
// terminate.
|
||||
agentDone := make(chan struct{})
|
||||
|
||||
// This goroutine is the node changes loop. The n.notifyNodeChange
|
||||
// channel is passed to the agent. When an new node object gets sent down
|
||||
// to the agent, it gets passed back up to this node object, so that we can
|
||||
// check if a role update or a root certificate rotation is required. This
|
||||
// handles root rotation, but the renewer handles regular certification
|
||||
// rotation.
|
||||
go func() {
|
||||
// lastNodeDesiredRole is the last-seen value of Node.Spec.DesiredRole,
|
||||
// used to make role changes "edge triggered" and avoid renewal loops.
|
||||
|
@ -354,9 +391,14 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
}
|
||||
}()
|
||||
|
||||
// Now we're going to launch the main component goroutines, the Agent, the
|
||||
// Manager (maybe) and the certificate updates loop. We shouldn't exit
|
||||
// the node object until all 3 of these components have terminated, so we
|
||||
// create a waitgroup to block termination of the node until then
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
|
||||
// These two blocks update some of the metrics settings.
|
||||
nodeInfo.WithValues(
|
||||
securityConfig.ClientTLSCreds.Organization(),
|
||||
securityConfig.ClientTLSCreds.NodeID(),
|
||||
|
@ -368,6 +410,10 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
nodeManager.Set(0)
|
||||
}
|
||||
|
||||
// We created the renewer way up when we were creating the SecurityConfig
|
||||
// at the beginning of run, but now we're ready to start receiving
|
||||
// CertificateUpdates, and launch a goroutine to handle this. Updates is a
|
||||
// channel we iterate containing the results of certificate renewals.
|
||||
updates := renewer.Start(ctx)
|
||||
go func() {
|
||||
for certUpdate := range updates {
|
||||
|
@ -375,12 +421,14 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
logrus.Warnf("error renewing TLS certificate: %v", certUpdate.Err)
|
||||
continue
|
||||
}
|
||||
// Set the new role, and notify our waiting role changing logic
|
||||
// that the role has changed.
|
||||
n.Lock()
|
||||
n.role = certUpdate.Role
|
||||
n.roleCond.Broadcast()
|
||||
n.Unlock()
|
||||
|
||||
// Export the new role.
|
||||
// Export the new role for metrics
|
||||
if n.currentRole() == api.NodeRoleManager {
|
||||
nodeManager.Set(1)
|
||||
} else {
|
||||
|
@ -391,13 +439,19 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
wg.Done()
|
||||
}()
|
||||
|
||||
// and, finally, start the two main components: the manager and the agent
|
||||
role := n.role
|
||||
|
||||
// Channels to signal when these respective components are up and ready to
|
||||
// go.
|
||||
managerReady := make(chan struct{})
|
||||
agentReady := make(chan struct{})
|
||||
// these variables are defined in this scope so that they're closed on by
|
||||
// respective goroutines below.
|
||||
var managerErr error
|
||||
var agentErr error
|
||||
go func() {
|
||||
// superviseManager is a routine that watches our manager role
|
||||
managerErr = n.superviseManager(ctx, securityConfig, paths.RootCA, managerReady, renewer) // store err and loop
|
||||
wg.Done()
|
||||
cancel()
|
||||
|
@ -409,6 +463,11 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
close(agentDone)
|
||||
}()
|
||||
|
||||
// This goroutine is what signals that the node has fully started by
|
||||
// closing the n.ready channel. First, it waits for the agent to start.
|
||||
// Then, if this node is a manager, it will wait on either the manager
|
||||
// starting, or the node role changing. This ensures that if the node is
|
||||
// demoted before the manager starts, it doesn't get stuck.
|
||||
go func() {
|
||||
<-agentReady
|
||||
if role == ca.ManagerRole {
|
||||
|
@ -428,6 +487,8 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
close(n.ready)
|
||||
}()
|
||||
|
||||
// And, finally, we park and wait for the node to close up. If we get any
|
||||
// error other than context canceled, we return it.
|
||||
wg.Wait()
|
||||
if managerErr != nil && errors.Cause(managerErr) != context.Canceled {
|
||||
return managerErr
|
||||
|
@ -435,6 +496,9 @@ func (n *Node) run(ctx context.Context) (err error) {
|
|||
if agentErr != nil && errors.Cause(agentErr) != context.Canceled {
|
||||
return agentErr
|
||||
}
|
||||
// NOTE(dperny): we return err here, but the last time I can see err being
|
||||
// set is when we open the boltdb way up in this method, so I don't know
|
||||
// what returning err is supposed to do.
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -477,11 +541,25 @@ func (n *Node) Err(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
// runAgent starts the node's agent. When the agent has started, the provided
|
||||
// ready channel is closed. When the agent exits, this will return the error
|
||||
// that caused it.
|
||||
func (n *Node) runAgent(ctx context.Context, db *bolt.DB, securityConfig *ca.SecurityConfig, ready chan<- struct{}) error {
|
||||
waitCtx, waitCancel := context.WithCancel(ctx)
|
||||
// First, get a channel for knowing when a remote peer has been selected.
|
||||
// The value returned from the remotesCh is ignored, we just need to know
|
||||
// when the peer is selected
|
||||
remotesCh := n.remotes.WaitSelect(ctx)
|
||||
// then, we set up a new context to pass specifically to
|
||||
// ListenControlSocket, and start that method to wait on a connection on
|
||||
// the cluster control API.
|
||||
waitCtx, waitCancel := context.WithCancel(ctx)
|
||||
controlCh := n.ListenControlSocket(waitCtx)
|
||||
|
||||
// The goal here to wait either until we have a remote peer selected, or
|
||||
// connection to the control
|
||||
// socket. These are both ways to connect the
|
||||
// agent to a manager, and we need to wait until one or the other is
|
||||
// available to start the agent
|
||||
waitPeer:
|
||||
for {
|
||||
select {
|
||||
|
@ -490,20 +568,28 @@ waitPeer:
|
|||
case <-remotesCh:
|
||||
break waitPeer
|
||||
case conn := <-controlCh:
|
||||
// conn will probably be nil the first time we call this, probably,
|
||||
// but only a non-nil conn represent an actual connection.
|
||||
if conn != nil {
|
||||
break waitPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can stop listening for new control socket connections once we're
|
||||
// ready
|
||||
waitCancel()
|
||||
|
||||
// NOTE(dperny): not sure why we need to recheck the context here. I guess
|
||||
// it avoids a race if the context was canceled at the same time that a
|
||||
// connection or peer was available. I think it's just an optimization.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
// Now we can go ahead and configure, create, and start the agent.
|
||||
secChangesCh, secChangesCancel := securityConfig.Watch()
|
||||
defer secChangesCancel()
|
||||
|
||||
|
@ -524,8 +610,8 @@ waitPeer:
|
|||
CertIssuerSubject: issuer.Subject,
|
||||
},
|
||||
}
|
||||
// if a join address has been specified, then if the agent fails to connect due to a TLS error, fail fast - don't
|
||||
// keep re-trying to join
|
||||
// if a join address has been specified, then if the agent fails to connect
|
||||
// due to a TLS error, fail fast - don't keep re-trying to join
|
||||
if n.config.JoinAddr != "" {
|
||||
agentConfig.SessionTracker = &firstSessionErrorTracker{}
|
||||
}
|
||||
|
@ -548,6 +634,7 @@ waitPeer:
|
|||
n.Unlock()
|
||||
}()
|
||||
|
||||
// when the agent indicates that it is ready, we close the ready channel.
|
||||
go func() {
|
||||
<-a.Ready()
|
||||
close(ready)
|
||||
|
@ -785,6 +872,10 @@ func (n *Node) initManagerConnection(ctx context.Context, ready chan<- struct{})
|
|||
return nil
|
||||
}
|
||||
|
||||
// waitRole takes a context and a role. it the blocks until the context is
|
||||
// canceled or the node's role updates to the provided role. returns nil when
|
||||
// the node has acquired the provided role, or ctx.Err() if the context is
|
||||
// canceled
|
||||
func (n *Node) waitRole(ctx context.Context, role string) error {
|
||||
n.roleCond.L.Lock()
|
||||
if role == n.role {
|
||||
|
@ -814,7 +905,13 @@ func (n *Node) waitRole(ctx context.Context, role string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// runManager runs the manager on this node. It returns a boolean indicating if
|
||||
// the stoppage was due to a role change, and an error indicating why the
|
||||
// manager stopped
|
||||
func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig, rootPaths ca.CertPaths, ready chan struct{}, workerRole <-chan struct{}) (bool, error) {
|
||||
// First, set up this manager's advertise and listen addresses, if
|
||||
// provided. they might not be provided if this node is joining the cluster
|
||||
// instead of creating a new one.
|
||||
var remoteAPI *manager.RemoteAddrs
|
||||
if n.config.ListenRemoteAPI != "" {
|
||||
remoteAPI = &manager.RemoteAddrs{
|
||||
|
@ -851,8 +948,15 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// The done channel is used to signal that the manager has exited.
|
||||
done := make(chan struct{})
|
||||
// runErr is an error value set by the goroutine that runs the manager
|
||||
var runErr error
|
||||
|
||||
// The context used to start this might have a logger associated with it
|
||||
// that we'd like to reuse, but we don't want to use that context, so we
|
||||
// pass to the goroutine only the logger, and create a new context with
|
||||
//that logger.
|
||||
go func(logger *logrus.Entry) {
|
||||
if err := m.Run(log.WithLogger(context.Background(), logger)); err != nil {
|
||||
runErr = err
|
||||
|
@ -860,6 +964,9 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
|
|||
close(done)
|
||||
}(log.G(ctx))
|
||||
|
||||
// clearData is set in the select below, and is used to signal why the
|
||||
// manager is stopping, and indicate whether or not to delete raft data and
|
||||
// keys when stopping the manager.
|
||||
var clearData bool
|
||||
defer func() {
|
||||
n.Lock()
|
||||
|
@ -877,9 +984,26 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
|
|||
connCtx, connCancel := context.WithCancel(ctx)
|
||||
defer connCancel()
|
||||
|
||||
// launch a goroutine that will manage our local connection to the manager
|
||||
// from the agent. Remember the managerReady channel created way back in
|
||||
// run? This is actually where we close it. Not when the manager starts,
|
||||
// but when a connection to the control socket has been established.
|
||||
go n.initManagerConnection(connCtx, ready)
|
||||
|
||||
// wait for manager stop or for role change
|
||||
// The manager can be stopped one of 4 ways:
|
||||
// 1. The manager may have errored out and returned an error, closing the
|
||||
// done channel in the process
|
||||
// 2. The node may have been demoted to a worker. In this case, we're gonna
|
||||
// have to stop the manager ourselves, setting clearData to true so the
|
||||
// local raft data, certs, keys, etc, are nuked.
|
||||
// 3. The manager may have been booted from raft. This could happen if it's
|
||||
// removed from the raft quorum but the role update hasn't registered
|
||||
// yet. The fact that there is more than 1 code path to cause the
|
||||
// manager to exit is a possible source of bugs.
|
||||
// 4. The context may have been canceled from above, in which case we
|
||||
// should stop the manager ourselves, but indicate that this is NOT a
|
||||
// demotion.
|
||||
select {
|
||||
case <-done:
|
||||
return false, runErr
|
||||
|
@ -895,12 +1019,22 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig
|
|||
return clearData, nil
|
||||
}
|
||||
|
||||
// superviseManager controls whether or not we are running a manager on this
|
||||
// node
|
||||
func (n *Node) superviseManager(ctx context.Context, securityConfig *ca.SecurityConfig, rootPaths ca.CertPaths, ready chan struct{}, renewer *ca.TLSRenewer) error {
|
||||
// superviseManager is a loop, because we can come in and out of being a
|
||||
// manager, and need to appropriately handle that without disrupting the
|
||||
// node functionality.
|
||||
for {
|
||||
// if we're not a manager, we're just gonna park here and wait until we
|
||||
// are. For normal agent nodes, we'll stay here forever, as intended.
|
||||
if err := n.waitRole(ctx, ca.ManagerRole); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Once we know we are a manager, we get ourselves ready for when we
|
||||
// lose that role. we create a channel to signal that we've become a
|
||||
// worker, and close it when n.waitRole completes.
|
||||
workerRole := make(chan struct{})
|
||||
waitRoleCtx, waitRoleCancel := context.WithCancel(ctx)
|
||||
go func() {
|
||||
|
@ -909,6 +1043,9 @@ func (n *Node) superviseManager(ctx context.Context, securityConfig *ca.Security
|
|||
}
|
||||
}()
|
||||
|
||||
// the ready channel passed to superviseManager is in turn passed down
|
||||
// to the runManager function. It's used to signal to the caller that
|
||||
// the manager has started.
|
||||
wasRemoved, err := n.runManager(ctx, securityConfig, rootPaths, ready, workerRole)
|
||||
if err != nil {
|
||||
waitRoleCancel()
|
||||
|
@ -967,6 +1104,8 @@ func (n *Node) superviseManager(ctx context.Context, securityConfig *ca.Security
|
|||
return err
|
||||
}
|
||||
|
||||
// set ready to nil after the first time we've gone through this, as we
|
||||
// don't need to signal after the first time that the manager is ready.
|
||||
ready = nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,40 +11,34 @@ github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18
|
|||
|
||||
# etcd/raft
|
||||
github.com/coreos/etcd v3.2.1
|
||||
github.com/coreos/go-systemd v12
|
||||
github.com/coreos/go-systemd v15
|
||||
github.com/coreos/pkg v3
|
||||
github.com/prometheus/client_golang 52437c81da6b127a9925d17eb3a382a2e5fd395e
|
||||
github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6
|
||||
github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8
|
||||
github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
|
||||
|
||||
github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621
|
||||
github.com/docker/docker 8af4db6f002ac907b6ef8610b237879dfcaa5b7a
|
||||
github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d
|
||||
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
|
||||
github.com/docker/docker 3d14173a2900b60200d9b1475abd5138f4315981
|
||||
github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6
|
||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
github.com/docker/go-units 954fed01cc617c55d838fa2230073f2cb17386c8
|
||||
github.com/docker/libkv 9fd56606e928ff1f309808f5d5a0b7a2ef73f9a8
|
||||
github.com/docker/libnetwork 21544598c53fa36a3c771a8725c643dd2340f845
|
||||
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
github.com/opencontainers/runc d40db12e72a40109dfcf28539f5ee0930d2f0277
|
||||
github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448
|
||||
github.com/opencontainers/image-spec v1.0.0
|
||||
github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
|
||||
github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
|
||||
github.com/docker/libnetwork 1b91bc94094ecfdae41daa465cc0c8df37dfb3dd
|
||||
github.com/opencontainers/runc 4fc53a81fb7c994640722ac585fa9ca548971871
|
||||
github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb
|
||||
|
||||
# containerd executor
|
||||
github.com/containerd/containerd 29a4dd7f46e0780d0bff2a237dc600a5b90a4dd5
|
||||
github.com/containerd/fifo 69b99525e472735860a5269b75af1970142b3062
|
||||
github.com/opencontainers/runtime-spec v1.0.0
|
||||
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
||||
github.com/containerd/continuity cf279e6ac893682272b4479d4c67fd3abf878b4e
|
||||
|
||||
github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||
github.com/Microsoft/go-winio v0.4.2
|
||||
github.com/sirupsen/logrus v1.0.1
|
||||
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 # v1.1.0
|
||||
github.com/Microsoft/go-winio v0.4.6
|
||||
github.com/sirupsen/logrus v1.0.3
|
||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||
github.com/boltdb/bolt e72f08ddb5a52992c0a44c7dda9316c7333938b2
|
||||
github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904
|
||||
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
|
||||
github.com/dustin/go-humanize 8929fe90cee4b2cb9deb468b51fb34eba64d1bf0
|
||||
github.com/google/certificate-transparency 0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341
|
||||
github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
||||
github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e
|
||||
github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990
|
||||
github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad
|
||||
github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
|
||||
|
@ -57,8 +51,8 @@ github.com/rcrowley/go-metrics 51425a2415d21afadfd55cd93432c0bc69e9598d
|
|||
github.com/spf13/cobra 8e91712f174ced10270cf66615e0a9127e7c4de5
|
||||
github.com/spf13/pflag 7f60f83a2c81bc3c3c0d5297f61ddfa68da9d3b7
|
||||
github.com/stretchr/testify v1.1.4
|
||||
golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2
|
||||
golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca
|
||||
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
|
||||
golang.org/x/sys 739734461d1c916b6c72a63d7efda2b27edb369f
|
||||
golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd
|
||||
golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756
|
||||
golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
Copyright © 2013 Keith Rarick
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,22 @@
|
|||
Fernet takes a user-provided *message* (an arbitrary sequence of
|
||||
bytes), a *key* (256 bits), and the current time, and produces a
|
||||
*token*, which contains the message in a form that can't be read
|
||||
or altered without the key.
|
||||
|
||||
This package is compatible with the other implementations at
|
||||
https://github.com/fernet. They can exchange tokens freely among
|
||||
each other.
|
||||
|
||||
Documentation: http://godoc.org/github.com/fernet/fernet-go
|
||||
|
||||
|
||||
INSTALL
|
||||
|
||||
$ go get github.com/fernet/fernet-go
|
||||
|
||||
|
||||
For more information and background, see the Fernet spec at
|
||||
https://github.com/fernet/spec.
|
||||
|
||||
Fernet is distributed under the terms of the MIT license.
|
||||
See the License file for details.
|
|
@ -0,0 +1,168 @@
|
|||
// Package fernet takes a user-provided message (an arbitrary
|
||||
// sequence of bytes), a key (256 bits), and the current time,
|
||||
// and produces a token, which contains the message in a form
|
||||
// that can't be read or altered without the key.
|
||||
//
|
||||
// For more information and background, see the Fernet spec
|
||||
// at https://github.com/fernet/spec.
|
||||
//
|
||||
// Subdirectories in this package provide command-line tools
|
||||
// for working with Fernet keys and tokens.
|
||||
package fernet
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
version byte = 0x80
|
||||
tsOffset = 1
|
||||
ivOffset = tsOffset + 8
|
||||
payOffset = ivOffset + aes.BlockSize
|
||||
overhead = 1 + 8 + aes.BlockSize + sha256.Size // ver + ts + iv + hmac
|
||||
maxClockSkew = 60 * time.Second
|
||||
)
|
||||
|
||||
var encoding = base64.URLEncoding
|
||||
|
||||
// generates a token from msg, writes it into tok, and returns the
|
||||
// number of bytes generated, which is encodedLen(msg).
|
||||
// len(tok) must be >= encodedLen(len(msg))
|
||||
func gen(tok, msg, iv []byte, ts time.Time, k *Key) int {
|
||||
tok[0] = version
|
||||
binary.BigEndian.PutUint64(tok[tsOffset:], uint64(ts.Unix()))
|
||||
copy(tok[ivOffset:], iv)
|
||||
p := tok[payOffset:]
|
||||
n := pad(p, msg, aes.BlockSize)
|
||||
bc, _ := aes.NewCipher(k.cryptBytes())
|
||||
cipher.NewCBCEncrypter(bc, iv).CryptBlocks(p[:n], p[:n])
|
||||
genhmac(p[n:n], tok[:payOffset+n], k.signBytes())
|
||||
return payOffset + n + sha256.Size
|
||||
}
|
||||
|
||||
// token length for input msg of length n, not including base64
|
||||
func encodedLen(n int) int {
|
||||
const k = aes.BlockSize
|
||||
return n/k*k + k + overhead
|
||||
}
|
||||
|
||||
// max msg length for tok of length n, for binary token (no base64)
|
||||
// upper bound; not exact
|
||||
func decodedLen(n int) int {
|
||||
return n - overhead
|
||||
}
|
||||
|
||||
// if msg is nil, decrypts in place and returns a slice of tok.
|
||||
func verify(msg, tok []byte, ttl time.Duration, now time.Time, k *Key) []byte {
|
||||
if len(tok) < 1 || tok[0] != version {
|
||||
return nil
|
||||
}
|
||||
ts := time.Unix(int64(binary.BigEndian.Uint64(tok[1:])), 0)
|
||||
if ttl >= 0 && (now.After(ts.Add(ttl)) || ts.After(now.Add(maxClockSkew))) {
|
||||
return nil
|
||||
}
|
||||
n := len(tok) - sha256.Size
|
||||
var hmac [sha256.Size]byte
|
||||
genhmac(hmac[:0], tok[:n], k.signBytes())
|
||||
if subtle.ConstantTimeCompare(tok[n:], hmac[:]) != 1 {
|
||||
return nil
|
||||
}
|
||||
pay := tok[payOffset : len(tok)-sha256.Size]
|
||||
if len(pay)%aes.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
if msg != nil {
|
||||
copy(msg, pay)
|
||||
pay = msg
|
||||
}
|
||||
bc, _ := aes.NewCipher(k.cryptBytes())
|
||||
iv := tok[9:][:aes.BlockSize]
|
||||
cipher.NewCBCDecrypter(bc, iv).CryptBlocks(pay, pay)
|
||||
return unpad(pay)
|
||||
}
|
||||
|
||||
// Pads p to a multiple of k using PKCS #7 standard block padding.
|
||||
// See http://tools.ietf.org/html/rfc5652#section-6.3.
|
||||
func pad(q, p []byte, k int) int {
|
||||
n := len(p)/k*k + k
|
||||
copy(q, p)
|
||||
c := byte(n - len(p))
|
||||
for i := len(p); i < n; i++ {
|
||||
q[i] = c
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Removes PKCS #7 standard block padding from p.
|
||||
// See http://tools.ietf.org/html/rfc5652#section-6.3.
|
||||
// This function is the inverse of pad.
|
||||
// If the padding is not well-formed, unpad returns nil.
|
||||
func unpad(p []byte) []byte {
|
||||
c := p[len(p)-1]
|
||||
for i := len(p) - int(c); i < len(p); i++ {
|
||||
if i < 0 || p[i] != c {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return p[:len(p)-int(c)]
|
||||
}
|
||||
|
||||
func b64enc(src []byte) []byte {
|
||||
dst := make([]byte, encoding.EncodedLen(len(src)))
|
||||
encoding.Encode(dst, src)
|
||||
return dst
|
||||
}
|
||||
|
||||
func b64dec(src []byte) []byte {
|
||||
dst := make([]byte, encoding.DecodedLen(len(src)))
|
||||
n, err := encoding.Decode(dst, src)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return dst[:n]
|
||||
}
|
||||
|
||||
func genhmac(q, p, k []byte) {
|
||||
h := hmac.New(sha256.New, k)
|
||||
h.Write(p)
|
||||
h.Sum(q)
|
||||
}
|
||||
|
||||
// EncryptAndSign encrypts and signs msg with key k and returns the resulting
|
||||
// fernet token. If msg contains text, the text should be encoded
|
||||
// with UTF-8 to follow fernet convention.
|
||||
func EncryptAndSign(msg []byte, k *Key) (tok []byte, err error) {
|
||||
iv := make([]byte, aes.BlockSize)
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := make([]byte, encodedLen(len(msg)))
|
||||
n := gen(b, msg, iv, time.Now(), k)
|
||||
tok = make([]byte, encoding.EncodedLen(n))
|
||||
encoding.Encode(tok, b[:n])
|
||||
return tok, nil
|
||||
}
|
||||
|
||||
// VerifyAndDecrypt verifies that tok is a valid fernet token that was signed
|
||||
// with a key in k at most ttl time ago only if ttl is greater than zero.
|
||||
// Returns the message contained in tok if tok is valid, otherwise nil.
|
||||
func VerifyAndDecrypt(tok []byte, ttl time.Duration, k []*Key) (msg []byte) {
|
||||
b := make([]byte, encoding.DecodedLen(len(tok)))
|
||||
n, _ := encoding.Decode(b, tok)
|
||||
for _, k1 := range k {
|
||||
msg = verify(nil, b[:n], ttl, time.Now(), k1)
|
||||
if msg != nil {
|
||||
return msg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package fernet
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
errKeyLen = errors.New("fernet: key decodes to wrong size")
|
||||
errNoKeys = errors.New("fernet: no keys provided")
|
||||
)
|
||||
|
||||
// Key represents a key.
|
||||
type Key [32]byte
|
||||
|
||||
func (k *Key) cryptBytes() []byte {
|
||||
return k[len(k)/2:]
|
||||
}
|
||||
|
||||
func (k *Key) signBytes() []byte {
|
||||
return k[:len(k)/2]
|
||||
}
|
||||
|
||||
// Generate initializes k with pseudorandom data from package crypto/rand.
|
||||
func (k *Key) Generate() error {
|
||||
_, err := io.ReadFull(rand.Reader, k[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// Encode returns the URL-safe base64 encoding of k.
|
||||
func (k *Key) Encode() string {
|
||||
return encoding.EncodeToString(k[:])
|
||||
}
|
||||
|
||||
// DecodeKey decodes a key from s and returns it. The key can be in
|
||||
// hexadecimal, standard base64, or URL-safe base64.
|
||||
func DecodeKey(s string) (*Key, error) {
|
||||
var b []byte
|
||||
var err error
|
||||
if s == "" {
|
||||
return nil, errors.New("empty key")
|
||||
}
|
||||
if len(s) == hex.EncodedLen(len(Key{})) {
|
||||
b, err = hex.DecodeString(s)
|
||||
} else {
|
||||
b, err = base64.StdEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
b, err = base64.URLEncoding.DecodeString(s)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) != len(Key{}) {
|
||||
return nil, errKeyLen
|
||||
}
|
||||
k := new(Key)
|
||||
copy(k[:], b)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// DecodeKeys decodes each element of a using DecodeKey and returns the
|
||||
// resulting keys. Requires at least one key.
|
||||
func DecodeKeys(a ...string) ([]*Key, error) {
|
||||
if len(a) == 0 {
|
||||
return nil, errNoKeys
|
||||
}
|
||||
var err error
|
||||
ks := make([]*Key, len(a))
|
||||
for i, s := range a {
|
||||
ks[i], err = DecodeKey(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ks, nil
|
||||
}
|
||||
|
||||
// MustDecodeKeys is like DecodeKeys, but panics if an error occurs.
|
||||
// It simplifies safe initialization of global variables holding
|
||||
// keys.
|
||||
func MustDecodeKeys(a ...string) []*Key {
|
||||
k, err := DecodeKeys(a...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return k
|
||||
}
|
Загрузка…
Ссылка в новой задаче