From 4a084fad645af919a79e559cd7c820e124d95541 Mon Sep 17 00:00:00 2001 From: Eugene Fryntov Date: Tue, 16 Jul 2019 17:46:32 -0400 Subject: [PATCH 01/23] Added seamless VPN and tunnel restart helper method to Android library. --- .../Android/PsiphonTunnel/PsiphonTunnel.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java index d6235447f..e21a7c627 100644 --- a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java +++ b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java @@ -190,6 +190,25 @@ public synchronized void restartPsiphon() throws Exception { startPsiphon(""); } + // Creates a temporary dummy VPN interface in order to prevent traffic leaking while performing + // complete VPN and tunnel restart, for example, caused by host app settings change. + // Note: same deadlock note as stop(). + public synchronized void seamlessVpnRestart(VpnService.Builder vpnServiceBuilder) throws Exception { + ParcelFileDescriptor dummyVpnFd = startDummyVpn(vpnServiceBuilder); + try { + stopVpn(); + startVpn(); + } finally { + if (dummyVpnFd != null) { + try { + dummyVpnFd.close(); + } catch (IOException e) { + } + } + } + restartPsiphon(); + } + public void setClientPlatformAffixes(String prefix, String suffix) { mClientPlatformPrefix.set(prefix); mClientPlatformSuffix.set(suffix); @@ -279,6 +298,37 @@ private boolean startVpn() throws Exception { return true; } + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private ParcelFileDescriptor startDummyVpn(VpnService.Builder vpnServiceBuilder) throws Exception { + PrivateAddress privateAddress = selectPrivateAddress(); + + Locale previousLocale = Locale.getDefault(); + + final String errorMessage = "startDummyVpn failed"; + final ParcelFileDescriptor tunFd; + try { + // Workaround for https://code.google.com/p/android/issues/detail?id=61096 + Locale.setDefault(new Locale("en")); + tunFd = vpnServiceBuilder + .setSession(mHostService.getAppName()) + .addAddress(mPrivateAddress.mIpAddress, mPrivateAddress.mPrefixLength) + .addRoute("0.0.0.0", 0) + .addRoute(mPrivateAddress.mSubnet, mPrivateAddress.mPrefixLength) + .establish(); + } catch(IllegalArgumentException e) { + throw new Exception(errorMessage, e); + } catch(IllegalStateException e) { + throw new Exception(errorMessage, e); + } catch(SecurityException e) { + throw new Exception(errorMessage, e); + } finally { + // Restore the original locale. + Locale.setDefault(previousLocale); + } + + return tunFd; + } + private boolean isVpnMode() { return mVpnMode.get(); } From a3dbd69651308e921bfdd22f270f01fd97fdb26f Mon Sep 17 00:00:00 2001 From: Eugene Fryntov Date: Wed, 17 Jul 2019 11:52:38 -0400 Subject: [PATCH 02/23] Addded seamless VPN handover comments. --- .../Android/PsiphonTunnel/PsiphonTunnel.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java index e21a7c627..70d4af974 100644 --- a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java +++ b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java @@ -194,11 +194,21 @@ public synchronized void restartPsiphon() throws Exception { // complete VPN and tunnel restart, for example, caused by host app settings change. // Note: same deadlock note as stop(). public synchronized void seamlessVpnRestart(VpnService.Builder vpnServiceBuilder) throws Exception { + // Perform seamless VPN interface swap Psiphon VPN -> dummy VPN + // + // From https://developer.android.com/reference/android/net/VpnService.Builder.html#establish() + // "However, it is rare but not impossible to have two interfaces while performing a seamless handover. + // In this case, the old interface will be deactivated when the new one is created successfully. Both + // file descriptors are valid but now outgoing packets will be routed to the new interface. Therefore, + // after draining the old file descriptor, the application MUST close it and start using the new file + // descriptor." ParcelFileDescriptor dummyVpnFd = startDummyVpn(vpnServiceBuilder); try { + // Clean up and restart Psiphon VPN interface, which will also do the swap dummy VPN -> Psiphon VPN stopVpn(); startVpn(); } finally { + // Close dummy VPN file descriptor as per documentation. if (dummyVpnFd != null) { try { dummyVpnFd.close(); @@ -206,6 +216,7 @@ public synchronized void seamlessVpnRestart(VpnService.Builder vpnServiceBuilder } } } + // Restart the tunnel. restartPsiphon(); } From 57a38f6f5d919b666574a5195e0ab60ef2bbd029 Mon Sep 17 00:00:00 2001 From: Eugene Fryntov Date: Wed, 17 Jul 2019 16:41:12 -0400 Subject: [PATCH 03/23] Added TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) annotation. --- MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java index 70d4af974..41ab0427a 100644 --- a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java +++ b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java @@ -193,6 +193,7 @@ public synchronized void restartPsiphon() throws Exception { // Creates a temporary dummy VPN interface in order to prevent traffic leaking while performing // complete VPN and tunnel restart, for example, caused by host app settings change. // Note: same deadlock note as stop(). + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public synchronized void seamlessVpnRestart(VpnService.Builder vpnServiceBuilder) throws Exception { // Perform seamless VPN interface swap Psiphon VPN -> dummy VPN // From ea7024ebb73e81a709af5a05849554a50cea1b54 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Thu, 18 Jul 2019 22:14:51 -0400 Subject: [PATCH 04/23] Prevent excessive notice noise from multiple GetSLOK failures --- psiphon/remoteServerList.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/psiphon/remoteServerList.go b/psiphon/remoteServerList.go index c451ff8c2..03ff7173e 100644 --- a/psiphon/remoteServerList.go +++ b/psiphon/remoteServerList.go @@ -25,6 +25,7 @@ import ( "errors" "fmt" "os" + "sync/atomic" "time" "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" @@ -188,10 +189,14 @@ func FetchObfuscatedServerLists( registryFilename = downloadFilename } + // Prevent excessive notice noise in cases such as a general database + // failure, as GetSLOK may be called thousands of times per fetch. + emittedGetSLOKAlert := int32(0) + lookupSLOKs := func(slokID []byte) []byte { // Lookup SLOKs in local datastore key, err := GetSLOK(slokID) - if err != nil { + if err != nil && atomic.CompareAndSwapInt32(&emittedGetSLOKAlert, 0, 1) { NoticeAlert("GetSLOK failed: %s", err) } return key From b01998f4e17f55d4fb9688a2d97b1f4fc7b7cec7 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Thu, 18 Jul 2019 23:03:56 -0400 Subject: [PATCH 05/23] Update vendored bolt - Backport panic/crash fixes from bbolt --- vendor/github.com/Psiphon-Labs/bolt/db.go | 36 +++++++++++++++++-- vendor/github.com/Psiphon-Labs/bolt/errors.go | 10 ++++++ vendor/github.com/Psiphon-Labs/bolt/tx.go | 9 +++++ vendor/vendor.json | 6 ++-- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/vendor/github.com/Psiphon-Labs/bolt/db.go b/vendor/github.com/Psiphon-Labs/bolt/db.go index f352ff14f..03eac4060 100644 --- a/vendor/github.com/Psiphon-Labs/bolt/db.go +++ b/vendor/github.com/Psiphon-Labs/bolt/db.go @@ -110,6 +110,10 @@ type DB struct { freelist *freelist stats Stats + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + mmapErr error // set on mmap failure; subsequently returned by all methods + pagePool sync.Pool batchMu sync.Mutex @@ -275,7 +279,13 @@ func (db *DB) mmap(minsz int) error { // Memory-map the data file as a byte slice. if err := mmap(db, size); err != nil { - return err + + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + // If mmap fails, we cannot safely continue. Mark the db as unusable, + // causing all future calls to return the mmap error. + db.mmapErr = MmapError(err.Error()) + return db.mmapErr } // Save references to the meta pages. @@ -395,8 +405,11 @@ func (db *DB) Close() error { db.metalock.Lock() defer db.metalock.Unlock() - db.mmaplock.RLock() - defer db.mmaplock.RUnlock() + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/e06ec0a754bc30c2e17ad871962e71635bf94d45 + // "Fix Close() to wait for view transactions by getting a full lock on mmaplock" + db.mmaplock.Lock() + defer db.mmaplock.Unlock() return db.close() } @@ -481,6 +494,15 @@ func (db *DB) beginTx() (*Tx, error) { return nil, ErrDatabaseNotOpen } + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + // Return mmap error if a previous mmap failed. + if db.mmapErr != nil { + db.mmaplock.RUnlock() + db.metalock.Unlock() + return nil, db.mmapErr + } + // Create a transaction associated with the database. t := &Tx{} t.init(db) @@ -522,6 +544,14 @@ func (db *DB) beginRWTx() (*Tx, error) { return nil, ErrDatabaseNotOpen } + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + // Return mmap error if a previous mmap failed. + if db.mmapErr != nil { + db.rwlock.Unlock() + return nil, db.mmapErr + } + // Create a transaction associated with the database. t := &Tx{writable: true} t.init(db) diff --git a/vendor/github.com/Psiphon-Labs/bolt/errors.go b/vendor/github.com/Psiphon-Labs/bolt/errors.go index a3620a3eb..ea49f1348 100644 --- a/vendor/github.com/Psiphon-Labs/bolt/errors.go +++ b/vendor/github.com/Psiphon-Labs/bolt/errors.go @@ -69,3 +69,13 @@ var ( // non-bucket key on an existing bucket key. ErrIncompatibleValue = errors.New("incompatible value") ) + +// [Psiphon] +// https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + +// MmapError represents an error resulting from a failed mmap call. Typically, +// this error means that no further database writes will be possible. The most +// common cause is insufficient disk space. +type MmapError string + +func (e MmapError) Error() string { return string(e) } diff --git a/vendor/github.com/Psiphon-Labs/bolt/tx.go b/vendor/github.com/Psiphon-Labs/bolt/tx.go index 3b37e6b69..3d2912a9c 100644 --- a/vendor/github.com/Psiphon-Labs/bolt/tx.go +++ b/vendor/github.com/Psiphon-Labs/bolt/tx.go @@ -250,6 +250,15 @@ func (tx *Tx) rollback() { if tx.db == nil { return } + + // [Psiphon] + // https://github.com/etcd-io/bbolt/commit/b3e98dcb3752e0a8d5db6503b80fe19e462fdb73 + // If the transaction failed due to mmap, rollback is futile. + if tx.db.mmapErr != nil { + tx.close() + return + } + if tx.writable { tx.db.freelist.rollback(tx.meta.txid) tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist)) diff --git a/vendor/vendor.json b/vendor/vendor.json index 5af57def7..7972c0b94 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -33,10 +33,10 @@ "revisionTime": "2017-02-28T16:03:01Z" }, { - "checksumSHA1": "3dYPdIMg6hc6whNAEXrMm09WFW0=", + "checksumSHA1": "ijTqnpkvC8IM47rIKnK0L4QSqmk=", "path": "github.com/Psiphon-Labs/bolt", - "revision": "c6e046a80d4b4c6c87b9563b9dd92098f4f6f50a", - "revisionTime": "2017-08-14T17:37:24Z" + "revision": "6667eecf83b5dbd480cdb6265d95efc92c0623a6", + "revisionTime": "2019-07-19T02:57:58Z" }, { "checksumSHA1": "d3DwsdacdFn1/KCG/2uPV1PwR3s=", From d2abe8315cffb9325270d7f5151bbdc8b8d362dd Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Fri, 19 Jul 2019 13:57:02 -0400 Subject: [PATCH 06/23] Recover from SIGSEGV and SIGBUS signals raised by boltdb mmap accesses --- psiphon/dataStore_bolt.go | 323 +++++++++++++++++++--- vendor/github.com/Psiphon-Labs/bolt/tx.go | 14 +- vendor/vendor.json | 6 +- 3 files changed, 289 insertions(+), 54 deletions(-) diff --git a/psiphon/dataStore_bolt.go b/psiphon/dataStore_bolt.go index fc5c9f013..2d9a5ff59 100644 --- a/psiphon/dataStore_bolt.go +++ b/psiphon/dataStore_bolt.go @@ -22,8 +22,12 @@ package psiphon import ( + "errors" + "fmt" "os" "path/filepath" + "runtime/debug" + "sync/atomic" "time" "github.com/Psiphon-Labs/bolt" @@ -31,60 +35,86 @@ import ( ) type datastoreDB struct { - boltDB *bolt.DB + boltDB *bolt.DB + isFailed int32 } type datastoreTx struct { + db *datastoreDB boltTx *bolt.Tx } type datastoreBucket struct { + db *datastoreDB boltBucket *bolt.Bucket } type datastoreCursor struct { + db *datastoreDB boltCursor *bolt.Cursor } func datastoreOpenDB(rootDataDirectory string) (*datastoreDB, error) { - filename := filepath.Join(rootDataDirectory, "psiphon.boltdb") - - var newDB *bolt.DB + var db *datastoreDB var err error for retry := 0; retry < 3; retry++ { - if retry > 0 { - NoticeAlert("datastoreOpenDB retry: %d", retry) + db, err = tryDatastoreOpenDB(rootDataDirectory, retry > 0) + if err == nil { + break } - newDB, err = bolt.Open(filename, 0600, &bolt.Options{Timeout: 1 * time.Second}) + NoticeAlert("tryDatastoreOpenDB failed: %s", err) - // The datastore file may be corrupt, so attempt to delete and try again - if err != nil { - NoticeAlert("bolt.Open error: %s", err) - os.Remove(filename) - continue - } + // The datastore file may be corrupt, so, in subsequent iterations, set the + // "reset" flag and attempt to delete the file and try again. + } - // Run consistency checks on datastore and emit errors for diagnostics purposes - // We assume this will complete quickly for typical size Psiphon datastores. - err = newDB.View(func(tx *bolt.Tx) error { - return tx.SynchronousCheck() - }) + return db, err +} + +func tryDatastoreOpenDB(rootDataDirectory string, reset bool) (retdb *datastoreDB, reterr error) { + + // Testing indicates that the bolt Check function can raise SIGSEGV due to + // invalid mmap buffer accesses in cases such as opening a valid but + // truncated datastore file. + // + // To handle this, we temporarily set SetPanicOnFault in order to treat the + // fault as a panic, recover any panic, and return an error which will result + // in a retry with reset. - // The datastore file may be corrupt, so attempt to delete and try again - if err != nil { - NoticeAlert("bolt.SynchronousCheck error: %s", err) - newDB.Close() - os.Remove(filename) - continue + // Begin recovery preamble + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + + defer func() { + if r := recover(); r != nil { + retdb = nil + reterr = common.ContextError(fmt.Errorf("panic: %v", r)) } + }() + // End recovery preamble - break + filename := filepath.Join(rootDataDirectory, "psiphon.boltdb") + + if reset { + NoticeAlert("tryDatastoreOpenDB: reset") + os.Remove(filename) } + newDB, err := bolt.Open(filename, 0600, &bolt.Options{Timeout: 1 * time.Second}) + if err != nil { + return nil, common.ContextError(err) + } + + // Run consistency checks on datastore and emit errors for diagnostics + // purposes. We assume this will complete quickly for typical size Psiphon + // datastores and wait for the check to complete before proceeding. + err = newDB.View(func(tx *bolt.Tx) error { + return tx.SynchronousCheck() + }) if err != nil { return nil, common.ContextError(err) } @@ -142,14 +172,58 @@ func datastoreOpenDB(rootDataDirectory string) (*datastoreDB, error) { return &datastoreDB{boltDB: newDB}, nil } +var errDatastoreFailed = errors.New("datastore has failed") + +func (db *datastoreDB) isDatastoreFailed() bool { + return atomic.LoadInt32(&db.isFailed) == 1 +} + +func (db *datastoreDB) setDatastoreFailed(r interface{}) { + atomic.StoreInt32(&db.isFailed, 1) + NoticeAlert("Datastore failed: %s", + common.ContextError(fmt.Errorf("panic: %v", r))) +} + func (db *datastoreDB) close() error { + + // Limitation: there is no panic recover in this case. We assume boltDB.Close + // does not make mmap accesses and prefer to not continue with the datastore + // file in a locked or open state. We also assume that any locks aquired by + // boltDB.Close, held by transactions, will be released even if the + // transaction panics and the database is in the failed state. + return db.boltDB.Close() } -func (db *datastoreDB) view(fn func(tx *datastoreTx) error) error { +func (db *datastoreDB) view(fn func(tx *datastoreTx) error) (reterr error) { + + // Any bolt function that performs mmap buffer accesses can raise SIGBUS due + // to underlying storage changes, such as a truncation of the datastore file + // or removal or network attached storage, etc. + // + // To handle this, we temporarily set SetPanicOnFault in order to treat the + // fault as a panic, recover any panic to avoid crashing the process, and + // putting this datastoreDB instance into a failed state. All subsequent + // calls to this datastoreDBinstance or its related datastoreTx and + // datastoreBucket instances will fail. + + // Begin recovery preamble + if db.isDatastoreFailed() { + return errDatastoreFailed + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + db.setDatastoreFailed(r) + reterr = errDatastoreFailed + } + }() + // End recovery preamble + return db.boltDB.View( func(tx *bolt.Tx) error { - err := fn(&datastoreTx{boltTx: tx}) + err := fn(&datastoreTx{db: db, boltTx: tx}) if err != nil { return common.ContextError(err) } @@ -157,10 +231,25 @@ func (db *datastoreDB) view(fn func(tx *datastoreTx) error) error { }) } -func (db *datastoreDB) update(fn func(tx *datastoreTx) error) error { +func (db *datastoreDB) update(fn func(tx *datastoreTx) error) (reterr error) { + + // Begin recovery preamble + if db.isDatastoreFailed() { + return errDatastoreFailed + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + db.setDatastoreFailed(r) + reterr = errDatastoreFailed + } + }() + // End recovery preamble + return db.boltDB.Update( func(tx *bolt.Tx) error { - err := fn(&datastoreTx{boltTx: tx}) + err := fn(&datastoreTx{db: db, boltTx: tx}) if err != nil { return common.ContextError(err) } @@ -168,11 +257,41 @@ func (db *datastoreDB) update(fn func(tx *datastoreTx) error) error { }) } -func (tx *datastoreTx) bucket(name []byte) *datastoreBucket { - return &datastoreBucket{boltBucket: tx.boltTx.Bucket(name)} +func (tx *datastoreTx) bucket(name []byte) (retbucket *datastoreBucket) { + + // Begin recovery preamble + if tx.db.isDatastoreFailed() { + return &datastoreBucket{db: tx.db, boltBucket: nil} + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + tx.db.setDatastoreFailed(r) + retbucket = &datastoreBucket{db: tx.db, boltBucket: nil} + } + }() + // End recovery preamble + + return &datastoreBucket{db: tx.db, boltBucket: tx.boltTx.Bucket(name)} } -func (tx *datastoreTx) clearBucket(name []byte) error { +func (tx *datastoreTx) clearBucket(name []byte) (reterr error) { + + // Begin recovery preamble + if tx.db.isDatastoreFailed() { + return errDatastoreFailed + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + tx.db.setDatastoreFailed(r) + reterr = errDatastoreFailed + } + }() + // End recovery preamble + err := tx.boltTx.DeleteBucket(name) if err != nil { return common.ContextError(err) @@ -184,11 +303,41 @@ func (tx *datastoreTx) clearBucket(name []byte) error { return nil } -func (b *datastoreBucket) get(key []byte) []byte { +func (b *datastoreBucket) get(key []byte) (retvalue []byte) { + + // Begin recovery preamble + if b.db.isDatastoreFailed() { + return nil + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + b.db.setDatastoreFailed(r) + retvalue = nil + } + }() + // End recovery preamble + return b.boltBucket.Get(key) } -func (b *datastoreBucket) put(key, value []byte) error { +func (b *datastoreBucket) put(key, value []byte) (reterr error) { + + // Begin recovery preamble + if b.db.isDatastoreFailed() { + return errDatastoreFailed + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + b.db.setDatastoreFailed(r) + reterr = errDatastoreFailed + } + }() + // End recovery preamble + err := b.boltBucket.Put(key, value) if err != nil { return common.ContextError(err) @@ -196,7 +345,22 @@ func (b *datastoreBucket) put(key, value []byte) error { return nil } -func (b *datastoreBucket) delete(key []byte) error { +func (b *datastoreBucket) delete(key []byte) (reterr error) { + + // Begin recovery preamble + if b.db.isDatastoreFailed() { + return errDatastoreFailed + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + b.db.setDatastoreFailed(r) + reterr = errDatastoreFailed + } + }() + // End recovery preamble + err := b.boltBucket.Delete(key) if err != nil { return common.ContextError(err) @@ -204,25 +368,102 @@ func (b *datastoreBucket) delete(key []byte) error { return nil } -func (b *datastoreBucket) cursor() datastoreCursor { - return datastoreCursor{boltCursor: b.boltBucket.Cursor()} +func (b *datastoreBucket) cursor() (retcursor datastoreCursor) { + + // Begin recovery preamble + if b.db.isDatastoreFailed() { + return datastoreCursor{db: b.db, boltCursor: nil} + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + b.db.setDatastoreFailed(r) + retcursor = datastoreCursor{db: b.db, boltCursor: nil} + } + }() + // End recovery preamble + + return datastoreCursor{db: b.db, boltCursor: b.boltBucket.Cursor()} } -func (c *datastoreCursor) firstKey() []byte { +func (c *datastoreCursor) firstKey() (retkey []byte) { + + // Begin recovery preamble + if c.db.isDatastoreFailed() { + return nil + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + c.db.setDatastoreFailed(r) + retkey = nil + } + }() + // End recovery preamble + key, _ := c.boltCursor.First() return key } -func (c *datastoreCursor) nextKey() []byte { +func (c *datastoreCursor) nextKey() (retkey []byte) { + + // Begin recovery preamble + if c.db.isDatastoreFailed() { + return nil + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + c.db.setDatastoreFailed(r) + retkey = nil + } + }() + // End recovery preamble + key, _ := c.boltCursor.Next() return key } -func (c *datastoreCursor) first() ([]byte, []byte) { +func (c *datastoreCursor) first() (retkey, retvalue []byte) { + + // Begin recovery preamble + if c.db.isDatastoreFailed() { + return nil, nil + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + c.db.setDatastoreFailed(r) + retkey = nil + retvalue = nil + } + }() + // End recovery preamble + return c.boltCursor.First() } -func (c *datastoreCursor) next() ([]byte, []byte) { +func (c *datastoreCursor) next() (retkey, retvalue []byte) { + + // Begin recovery preamble + if c.db.isDatastoreFailed() { + return nil, nil + } + panicOnFault := debug.SetPanicOnFault(true) + defer debug.SetPanicOnFault(panicOnFault) + defer func() { + if r := recover(); r != nil { + c.db.setDatastoreFailed(r) + retkey = nil + retvalue = nil + } + }() + // End recovery preamble + return c.boltCursor.Next() } diff --git a/vendor/github.com/Psiphon-Labs/bolt/tx.go b/vendor/github.com/Psiphon-Labs/bolt/tx.go index 3d2912a9c..ec902a5cc 100644 --- a/vendor/github.com/Psiphon-Labs/bolt/tx.go +++ b/vendor/github.com/Psiphon-Labs/bolt/tx.go @@ -388,18 +388,12 @@ func (tx *Tx) Check() <-chan error { } // [Psiphon] -// SynchronousCheck performs the Check function in the current goroutine and recovers -// from any panics, such as the panic in Cursor.search(). -func (tx *Tx) SynchronousCheck() (reterr error) { - defer func() { - if e := recover(); e != nil { - reterr = fmt.Errorf("SynchronousCheck panic: %s", e) - } - }() +// SynchronousCheck performs the Check function in the current goroutine, +// allowing the caller to recover from any panics or faults. +func (tx *Tx) SynchronousCheck() error { ch := make(chan error) tx.check(ch) - reterr = <-ch - return + return <-ch } func (tx *Tx) check(ch chan error) { diff --git a/vendor/vendor.json b/vendor/vendor.json index 7972c0b94..f42e21279 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -33,10 +33,10 @@ "revisionTime": "2017-02-28T16:03:01Z" }, { - "checksumSHA1": "ijTqnpkvC8IM47rIKnK0L4QSqmk=", + "checksumSHA1": "dVfefYjTFuN1AKIJyCcqNrlLEJo=", "path": "github.com/Psiphon-Labs/bolt", - "revision": "6667eecf83b5dbd480cdb6265d95efc92c0623a6", - "revisionTime": "2019-07-19T02:57:58Z" + "revision": "b7c055003ce9d8a1bddb9416648cb7d955a3148d", + "revisionTime": "2019-07-19T17:53:53Z" }, { "checksumSHA1": "d3DwsdacdFn1/KCG/2uPV1PwR3s=", From 0499a8bec13c2e0084cdbe63aa7c83ea01037af0 Mon Sep 17 00:00:00 2001 From: Eugene Fryntov Date: Fri, 19 Jul 2019 17:43:14 -0400 Subject: [PATCH 07/23] Removed org.apache.http dependency because of Apache client deprecation on Android 9.0, see https://developer.android.com/about/versions/pie/android-9.0-changes-all#apache-nonp --- MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java index 41ab0427a..70c6a42ff 100644 --- a/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java +++ b/MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java @@ -22,17 +22,16 @@ import android.annotation.TargetApi; import android.content.Context; import android.net.ConnectivityManager; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiInfo; import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.VpnService; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.os.Build; import android.os.ParcelFileDescriptor; import android.telephony.TelephonyManager; import android.util.Base64; -import org.apache.http.conn.util.InetAddressUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -44,6 +43,7 @@ import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -964,8 +964,8 @@ private static PrivateAddress selectPrivateAddress() throws Exception { for (NetworkInterface netInterface : netInterfaces) { for (InetAddress inetAddress : Collections.list(netInterface.getInetAddresses())) { - String ipAddress = inetAddress.getHostAddress(); - if (InetAddressUtils.isIPv4Address(ipAddress)) { + if (inetAddress instanceof Inet4Address) { + String ipAddress = inetAddress.getHostAddress(); if (ipAddress.startsWith("10.")) { candidates.remove("10"); } From fa53cdfb89a7b4c822f9b9f7df13dc6db9666368 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 22 Jul 2019 12:33:01 -0400 Subject: [PATCH 08/23] Redact sensitive data from diagnostic notices - Never log server IP addresses. Servers are now identified by a short ID derived from the server entry tag. - A regex is used to strip any remaining IP addresses from notice text. This covers cases such as "net" package error messages containing addresses. - EmitDiagnosticNetworkParameters introduces a second level of detail for EmitDiagnosticNotices. By default, EmitDiagnosticNotices will not log dial parameters or resource URLs and error messages that may contain domain names are redacted. This data may be logged by enabling the new flag. --- ConsoleClient/main.go | 12 +- psiphon/LookupIP.go | 13 +- psiphon/LookupIP_nobind.go | 5 + psiphon/TCPConn.go | 4 +- psiphon/TCPConn_bind.go | 4 +- psiphon/TCPConn_nobind.go | 5 + psiphon/common/fragmentor/fragmentor.go | 9 +- psiphon/common/protocol/serverEntry.go | 28 ++++ psiphon/config.go | 17 ++- psiphon/controller.go | 18 +-- psiphon/dataStore.go | 8 +- psiphon/dialParameters.go | 6 +- psiphon/meekConn.go | 5 +- psiphon/memory_test/memory_test.go | 2 +- psiphon/net.go | 3 + psiphon/notice.go | 194 ++++++++++++++---------- psiphon/server/server_test.go | 2 +- psiphon/serverApi.go | 16 +- psiphon/tunnel.go | 18 +-- psiphon/utils.go | 52 +++++++ 20 files changed, 280 insertions(+), 141 deletions(-) diff --git a/ConsoleClient/main.go b/ConsoleClient/main.go index 8f12ccef6..bb5be7f37 100644 --- a/ConsoleClient/main.go +++ b/ConsoleClient/main.go @@ -161,22 +161,22 @@ func main() { // Handle required config file parameter // EmitDiagnosticNotices is set by LoadConfig; force to true - // an emit diagnostics when LoadConfig-related errors occur. + // and emit diagnostics when LoadConfig-related errors occur. if configFilename == "" { - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, false) psiphon.NoticeError("configuration file is required") os.Exit(1) } configFileContents, err := ioutil.ReadFile(configFilename) if err != nil { - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, false) psiphon.NoticeError("error loading configuration file: %s", err) os.Exit(1) } config, err := psiphon.LoadConfig(configFileContents) if err != nil { - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, false) psiphon.NoticeError("error processing configuration file: %s", err) os.Exit(1) } @@ -191,7 +191,7 @@ func main() { tunDeviceFile, err := configurePacketTunnel( config, tunDevice, tunBindInterface, tunPrimaryDNS, tunSecondaryDNS) if err != nil { - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, false) psiphon.NoticeError("error configuring packet tunnel: %s", err) os.Exit(1) } @@ -202,7 +202,7 @@ func main() { err = config.Commit() if err != nil { - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, false) psiphon.NoticeError("error loading configuration file: %s", err) os.Exit(1) } diff --git a/psiphon/LookupIP.go b/psiphon/LookupIP.go index 7aaa2b700..4e387444a 100644 --- a/psiphon/LookupIP.go +++ b/psiphon/LookupIP.go @@ -62,7 +62,9 @@ func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, e return ips, err } - NoticeAlert("retry resolve host %s: %s", host, err) + if GetEmitNetworkParameters() { + NoticeAlert("retry resolve host %s: %s", host, err) + } return bindLookupIP(ctx, host, dnsServer, config) } @@ -72,6 +74,11 @@ func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, e return nil, common.ContextError(err) } + // Remove domain names from "net" error messages. + if !GetEmitNetworkParameters() { + err = RedactNetError(err) + } + ips := make([]net.IP, len(addrs)) for i, addr := range addrs { ips[i] = addr.IP @@ -116,7 +123,7 @@ func bindLookupIP( copy(ipv6[:], ipAddr.To16()) domain = syscall.AF_INET6 } else { - return nil, common.ContextError(fmt.Errorf("invalid IP address for dns server: %s", ipAddr.String())) + return nil, common.ContextError(errors.New("invalid IP address for DNS server")) } socketFd, err := syscall.Socket(domain, syscall.SOCK_DGRAM, 0) @@ -127,7 +134,7 @@ func bindLookupIP( _, err = config.DeviceBinder.BindToDevice(socketFd) if err != nil { syscall.Close(socketFd) - return nil, common.ContextError(fmt.Errorf("BindToDevice failed: %s", err)) + return nil, common.ContextError(fmt.Errorf("BindToDevice failed with %s", err)) } // Connect socket to the server's IP address diff --git a/psiphon/LookupIP_nobind.go b/psiphon/LookupIP_nobind.go index 47ae894d4..663b6f5c6 100644 --- a/psiphon/LookupIP_nobind.go +++ b/psiphon/LookupIP_nobind.go @@ -41,6 +41,11 @@ func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, e return nil, common.ContextError(err) } + // Remove domain names from "net" error messages. + if !GetEmitNetworkParameters() { + err = RedactNetError(err) + } + ips := make([]net.IP, len(addrs)) for i, addr := range addrs { ips[i] = addr.IP diff --git a/psiphon/TCPConn.go b/psiphon/TCPConn.go index 0a361b833..e965ac805 100644 --- a/psiphon/TCPConn.go +++ b/psiphon/TCPConn.go @@ -84,7 +84,9 @@ func DialTCP( if config.FragmentorConfig.MayFragment() { conn = fragmentor.NewConn( config.FragmentorConfig, - func(message string) { NoticeInfo(message) }, + func(message string) { + NoticeFragmentor(config.DiagnosticID, message) + }, conn) } diff --git a/psiphon/TCPConn_bind.go b/psiphon/TCPConn_bind.go index d3aaa8510..499a40ba4 100644 --- a/psiphon/TCPConn_bind.go +++ b/psiphon/TCPConn_bind.go @@ -117,7 +117,7 @@ func tcpDial(ctx context.Context, addr string, config *DialConfig) (net.Conn, er copy(ipv6[:], ipAddr.To16()) domain = syscall.AF_INET6 } else { - lastErr = common.ContextError(fmt.Errorf("invalid IP address: %s", ipAddr.String())) + lastErr = common.ContextError(errors.New("invalid IP address")) continue } if domain == syscall.AF_INET { @@ -142,7 +142,7 @@ func tcpDial(ctx context.Context, addr string, config *DialConfig) (net.Conn, er _, err = config.DeviceBinder.BindToDevice(socketFD) if err != nil { syscall.Close(socketFD) - lastErr = common.ContextError(fmt.Errorf("BindToDevice failed: %s", err)) + lastErr = common.ContextError(fmt.Errorf("BindToDevice failed with %s", err)) continue } } diff --git a/psiphon/TCPConn_nobind.go b/psiphon/TCPConn_nobind.go index b124ecad4..5bfee501b 100644 --- a/psiphon/TCPConn_nobind.go +++ b/psiphon/TCPConn_nobind.go @@ -40,6 +40,11 @@ func tcpDial(ctx context.Context, addr string, config *DialConfig) (net.Conn, er conn, err := dialer.DialContext(ctx, "tcp", addr) + // Remove domain names from "net" error messages. + if !GetEmitNetworkParameters() { + err = RedactNetError(err) + } + if err != nil { return nil, common.ContextError(err) } diff --git a/psiphon/common/fragmentor/fragmentor.go b/psiphon/common/fragmentor/fragmentor.go index e979405c8..17644488b 100644 --- a/psiphon/common/fragmentor/fragmentor.go +++ b/psiphon/common/fragmentor/fragmentor.go @@ -259,14 +259,7 @@ func (c *Conn) Write(buffer []byte) (int, error) { var notice bytes.Buffer if emitNotice { - remoteAddrStr := "(nil)" - remoteAddr := c.Conn.RemoteAddr() - if remoteAddr != nil { - remoteAddrStr = remoteAddr.String() - } - fmt.Fprintf(¬ice, - "fragment %s %d bytes:", - remoteAddrStr, len(buffer)) + fmt.Fprintf(¬ice, "fragment %d bytes:", len(buffer)) } for iterations := 0; len(buffer) > 0; iterations += 1 { diff --git a/psiphon/common/protocol/serverEntry.go b/psiphon/common/protocol/serverEntry.go index 748c2b11e..1007aeb36 100644 --- a/psiphon/common/protocol/serverEntry.go +++ b/psiphon/common/protocol/serverEntry.go @@ -155,6 +155,18 @@ func (fields ServerEntryFields) SetTag(tag string) { fields["isLocalDerivedTag"] = true } +func (fields ServerEntryFields) GetDiagnosticID() string { + tag, ok := fields["tag"] + if !ok { + return "" + } + tagStr, ok := tag.(string) + if !ok { + return "" + } + return TagToDiagnosticID(tagStr) +} + func (fields ServerEntryFields) GetIPAddress() string { ipAddress, ok := fields["ipAddress"] if !ok { @@ -507,6 +519,10 @@ func (serverEntry *ServerEntry) HasSignature() bool { return serverEntry.Signature != "" } +func (serverEntry *ServerEntry) GetDiagnosticID() string { + return TagToDiagnosticID(serverEntry.Tag) +} + // GenerateServerEntryTag creates a server entry tag value that is // cryptographically derived from the IP address and web server secret in a // way that is difficult to reverse the IP address value from the tag or @@ -521,6 +537,18 @@ func GenerateServerEntryTag(ipAddress, webServerSecret string) string { return base64.StdEncoding.EncodeToString(h.Sum(nil)) } +// TagToDiagnosticID returns a prefix of the server entry tag that should be +// sufficient to uniquely identify servers in diagnostics, while also being +// more human readable than emitting the full tag. The tag is used as the base +// of the diagnostic ID as it doesn't leak the server IP address in diagnostic +// output. +func TagToDiagnosticID(tag string) string { + if len(tag) < 8 { + return "" + } + return tag[:8] +} + // EncodeServerEntry returns a string containing the encoding of // a ServerEntry following Psiphon conventions. func EncodeServerEntry(serverEntry *ServerEntry) (string, error) { diff --git a/psiphon/config.go b/psiphon/config.go index 79193faf6..84ae2a318 100755 --- a/psiphon/config.go +++ b/psiphon/config.go @@ -447,10 +447,16 @@ type Config struct { // EmitDiagnosticNotices indicates whether to output notices containing // detailed information about the Psiphon session. As these notices may - // contain sensitive network information, they should not be insecurely - // distributed or displayed to users. Default is off. + // contain sensitive information, they should not be insecurely distributed + // or displayed to users. Default is off. EmitDiagnosticNotices bool + // EmitDiagnosticNetworkParameters indicates whether to include network + // parameters in diagnostic notices. As these parameters are sensitive + // circumvention network information, they should not be insecurely + // distributed or displayed to users. Default is off. + EmitDiagnosticNetworkParameters bool + // RateLimits specify throttling configuration for the tunnel. RateLimits common.RateLimits @@ -596,10 +602,11 @@ func (config *Config) IsCommitted() bool { // not be reflected in internal data structures. func (config *Config) Commit() error { - // Do SetEmitDiagnosticNotices first, to ensure config file errors are emitted. - + // Do SetEmitDiagnosticNotices first, to ensure config file errors are + // emitted. if config.EmitDiagnosticNotices { - SetEmitDiagnosticNotices(true) + SetEmitDiagnosticNotices( + true, config.EmitDiagnosticNetworkParameters) } // Promote legacy fields. diff --git a/psiphon/controller.go b/psiphon/controller.go index a04e37b77..802d0bc8c 100755 --- a/psiphon/controller.go +++ b/psiphon/controller.go @@ -292,7 +292,7 @@ func (controller *Controller) TerminateNextActiveTunnel() { tunnel := controller.getNextActiveTunnel() if tunnel != nil { controller.SignalTunnelFailure(tunnel) - NoticeInfo("terminated tunnel: %s", tunnel.dialParams.ServerEntry.IpAddress) + NoticeInfo("terminated tunnel: %s", tunnel.dialParams.ServerEntry.GetDiagnosticID()) } } @@ -643,7 +643,7 @@ loop: } case failedTunnel := <-controller.failedTunnels: - NoticeAlert("tunnel failed: %s", failedTunnel.dialParams.ServerEntry.IpAddress) + NoticeAlert("tunnel failed: %s", failedTunnel.dialParams.ServerEntry.GetDiagnosticID()) controller.terminateTunnel(failedTunnel) // Clear the reference to this tunnel before calling startEstablishing, @@ -699,7 +699,7 @@ loop: if err != nil { NoticeAlert("failed to activate %s: %s", - connectedTunnel.dialParams.ServerEntry.IpAddress, err) + connectedTunnel.dialParams.ServerEntry.GetDiagnosticID(), err) discardTunnel = true } else { // It's unlikely that registerTunnel will fail, since only this goroutine @@ -707,7 +707,7 @@ loop: // expected. if !controller.registerTunnel(connectedTunnel) { NoticeAlert("failed to register %s: %s", - connectedTunnel.dialParams.ServerEntry.IpAddress, err) + connectedTunnel.dialParams.ServerEntry.GetDiagnosticID(), err) discardTunnel = true } } @@ -732,7 +732,7 @@ loop: } NoticeActiveTunnel( - connectedTunnel.dialParams.ServerEntry.IpAddress, + connectedTunnel.dialParams.ServerEntry.GetDiagnosticID(), connectedTunnel.dialParams.TunnelProtocol, connectedTunnel.dialParams.ServerEntry.SupportsSSHAPIRequests()) @@ -843,7 +843,7 @@ func (controller *Controller) SignalTunnelFailure(tunnel *Tunnel) { // discardTunnel disposes of a successful connection that is no longer required. func (controller *Controller) discardTunnel(tunnel *Tunnel) { - NoticeInfo("discard tunnel: %s", tunnel.dialParams.ServerEntry.IpAddress) + NoticeInfo("discard tunnel: %s", tunnel.dialParams.ServerEntry.GetDiagnosticID()) // TODO: not calling PromoteServerEntry, since that would rank the // discarded tunnel before fully active tunnels. Can a discarded tunnel // be promoted (since it connects), but with lower rank than all active @@ -866,7 +866,7 @@ func (controller *Controller) registerTunnel(tunnel *Tunnel) bool { if activeTunnel.dialParams.ServerEntry.IpAddress == tunnel.dialParams.ServerEntry.IpAddress { - NoticeAlert("duplicate tunnel: %s", tunnel.dialParams.ServerEntry.IpAddress) + NoticeAlert("duplicate tunnel: %s", tunnel.dialParams.ServerEntry.GetDiagnosticID()) return false } } @@ -1901,7 +1901,7 @@ loop: // Silently skip the candidate in this case. Otherwise, emit error. if err != nil { NoticeInfo("failed to select protocol for %s: %s", - candidateServerEntry.serverEntry.IpAddress, err) + candidateServerEntry.serverEntry.GetDiagnosticID(), err) } // Unblock other candidates immediately when server affinity @@ -2008,7 +2008,7 @@ loop: } NoticeInfo("failed to connect to %s: %s", - candidateServerEntry.serverEntry.IpAddress, err) + candidateServerEntry.serverEntry.GetDiagnosticID(), err) continue } diff --git a/psiphon/dataStore.go b/psiphon/dataStore.go index e8b98a78d..35da2462f 100644 --- a/psiphon/dataStore.go +++ b/psiphon/dataStore.go @@ -192,10 +192,6 @@ func StoreServerEntry(serverEntryFields protocol.ServerEntryFields, replaceIfExi update := !exists || replaceIfExists || newer if !update { - // Disabling this notice, for now, as it generates too much noise - // in diagnostics with clients that always submit embedded servers - // to the core on each run. - // NoticeInfo("ignored update for server %s", serverEntry.IpAddress) return nil } @@ -242,7 +238,7 @@ func StoreServerEntry(serverEntryFields protocol.ServerEntryFields, replaceIfExi return common.ContextError(err) } - NoticeInfo("updated server %s", serverEntryFields.GetIPAddress()) + NoticeInfo("updated server %s", serverEntryFields.GetDiagnosticID()) return nil }) @@ -506,7 +502,7 @@ func newTargetServerEntryIterator(config *Config, isTactics bool) (bool, *Server targetServerEntry: serverEntry, } - NoticeInfo("using TargetServerEntry: %s", serverEntry.IpAddress) + NoticeInfo("using TargetServerEntry: %s", serverEntry.GetDiagnosticID()) return false, iterator, nil } diff --git a/psiphon/dialParameters.go b/psiphon/dialParameters.go index 213ce54a0..7f2f9b9b1 100644 --- a/psiphon/dialParameters.go +++ b/psiphon/dialParameters.go @@ -558,6 +558,7 @@ func MakeDialParameters( // Initialize Dial/MeekConfigs to be passed to the corresponding dialers. dialParams.dialConfig = &DialConfig{ + DiagnosticID: serverEntry.GetDiagnosticID(), UpstreamProxyURL: config.UpstreamProxyURL, CustomHeaders: dialCustomHeaders, DeviceBinder: config.deviceBinder, @@ -574,6 +575,7 @@ func MakeDialParameters( if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) { dialParams.meekConfig = &MeekConfig{ + DiagnosticID: serverEntry.GetDiagnosticID(), ClientParameters: config.clientParameters, DialAddress: dialParams.MeekDialAddress, UseQUIC: protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol), @@ -623,7 +625,7 @@ func (dialParams *DialParameters) Succeeded() { return } - NoticeInfo("Set dial parameters for %s", dialParams.ServerEntry.IpAddress) + NoticeInfo("Set dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID()) err := SetDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID, dialParams) if err != nil { NoticeAlert("SetDialParameters failed: %s", err) @@ -648,7 +650,7 @@ func (dialParams *DialParameters) Failed(config *Config) { !config.GetClientParametersSnapshot().WeightedCoinFlip( parameters.ReplayRetainFailedProbability) { - NoticeInfo("Delete dial parameters for %s", dialParams.ServerEntry.IpAddress) + NoticeInfo("Delete dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID()) err := DeleteDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID) if err != nil { NoticeAlert("DeleteDialParameters failed: %s", err) diff --git a/psiphon/meekConn.go b/psiphon/meekConn.go index 66f6c6452..1fdb2e631 100644 --- a/psiphon/meekConn.go +++ b/psiphon/meekConn.go @@ -65,6 +65,9 @@ const ( // MeekConfig specifies the behavior of a MeekConn type MeekConfig struct { + // DiagnosticID is the server ID to record in any diagnostics notices. + DiagnosticID string + // ClientParameters is the active set of client parameters to use // for the meek dial. ClientParameters *parameters.ClientParameters @@ -348,7 +351,7 @@ func DialMeek( cachedTLSDialer = newCachedTLSDialer(preConn, tlsDialer) if IsTLSConnUsingHTTP2(preConn) { - NoticeInfo("negotiated HTTP/2 for %s", meekConfig.DialAddress) + NoticeInfo("negotiated HTTP/2 for %s", meekConfig.DiagnosticID) transport = &http2.Transport{ DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { return cachedTLSDialer.dial(network, addr) diff --git a/psiphon/memory_test/memory_test.go b/psiphon/memory_test/memory_test.go index a17e0cec6..7974fe9b2 100644 --- a/psiphon/memory_test/memory_test.go +++ b/psiphon/memory_test/memory_test.go @@ -85,7 +85,7 @@ func runMemoryTest(t *testing.T, testMode int) { } defer os.RemoveAll(testDataDirName) - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, true) configJSON, err := ioutil.ReadFile("../controller_test.config") if err != nil { diff --git a/psiphon/net.go b/psiphon/net.go index 6ab8b8a43..b4b1e0774 100644 --- a/psiphon/net.go +++ b/psiphon/net.go @@ -45,6 +45,9 @@ const DNS_PORT = 53 // of a Psiphon dialer (TCPDial, UDPDial, MeekDial, etc.) type DialConfig struct { + // DiagnosticID is the server ID to record in any diagnostics notices. + DiagnosticID string + // UpstreamProxyURL specifies a proxy to connect through. // E.g., "http://proxyhost:8080" // "socks5://user:password@proxyhost:1080" diff --git a/psiphon/notice.go b/psiphon/notice.go index 8bfcead3e..f65fdcbd7 100644 --- a/psiphon/notice.go +++ b/psiphon/notice.go @@ -35,7 +35,8 @@ import ( ) type noticeLogger struct { - logDiagnostics int32 + emitDiagnostics int32 + emitNetworkParameters int32 mutex sync.Mutex writer io.Writer homepageFilename string @@ -53,23 +54,40 @@ var singletonNoticeLogger = noticeLogger{ writer: os.Stderr, } -// SetEmitDiagnosticNotices toggles whether diagnostic notices -// are emitted. Diagnostic notices contain potentially sensitive -// circumvention network information; only enable this in environments -// where notices are handled securely (for example, don't include these -// notices in log files which users could post to public forums). -func SetEmitDiagnosticNotices(enable bool) { - if enable { - atomic.StoreInt32(&singletonNoticeLogger.logDiagnostics, 1) +// SetEmitDiagnosticNotices toggles whether diagnostic notices are emitted; +// and whether to include circumvention network parameters in diagnostics. +// +// Diagnostic notices contain potentially sensitive user information; and +// sensitive circumvention network parameters, when enabled. Only enable this +// in environments where notices are handled securely (for example, don't +// include these notices in log files which users could post to public +// forums). +func SetEmitDiagnosticNotices( + emitDiagnostics bool, emitNetworkParameters bool) { + + if emitDiagnostics { + atomic.StoreInt32(&singletonNoticeLogger.emitDiagnostics, 1) + } else { + atomic.StoreInt32(&singletonNoticeLogger.emitDiagnostics, 0) + } + + if emitNetworkParameters { + atomic.StoreInt32(&singletonNoticeLogger.emitNetworkParameters, 1) } else { - atomic.StoreInt32(&singletonNoticeLogger.logDiagnostics, 0) + atomic.StoreInt32(&singletonNoticeLogger.emitNetworkParameters, 0) } } // GetEmitDiagnoticNotices returns the current state // of emitting diagnostic notices. func GetEmitDiagnoticNotices() bool { - return atomic.LoadInt32(&singletonNoticeLogger.logDiagnostics) == 1 + return atomic.LoadInt32(&singletonNoticeLogger.emitDiagnostics) == 1 +} + +// GetEmitNetworkParameters returns the current state +// of emitting network parameters. +func GetEmitNetworkParameters() bool { + return atomic.LoadInt32(&singletonNoticeLogger.emitNetworkParameters) == 1 } // SetNoticeWriter sets a target writer to receive notices. By default, @@ -188,7 +206,7 @@ const ( // outputNotice encodes a notice in JSON and writes it to the output writer. func (nl *noticeLogger) outputNotice(noticeType string, noticeFlags uint32, args ...interface{}) { - if (noticeFlags¬iceIsDiagnostic != 0) && atomic.LoadInt32(&nl.logDiagnostics) != 1 { + if (noticeFlags¬iceIsDiagnostic != 0) && !GetEmitDiagnoticNotices() { return } @@ -218,6 +236,11 @@ func (nl *noticeLogger) outputNotice(noticeType string, noticeFlags uint32, args fmt.Sprintf("marshal notice failed: %s", common.ContextError(err))) } + // Ensure direct server IPs are not exposed in notices. The "net" package, + // and possibly other 3rd party packages, will include destination addresses + // in I/O error messages. + output = StripIPAddresses(output) + nl.mutex.Lock() defer nl.mutex.Unlock() @@ -404,78 +427,81 @@ func NoticeAvailableEgressRegions(regions []string) { func noticeWithDialParameters(noticeType string, dialParams *DialParameters) { args := []interface{}{ - "ipAddress", dialParams.ServerEntry.IpAddress, + "serverID", dialParams.ServerEntry.GetDiagnosticID(), "region", dialParams.ServerEntry.Region, "protocol", dialParams.TunnelProtocol, "isReplay", dialParams.IsReplay, } - if dialParams.SelectedSSHClientVersion { - args = append(args, "SSHClientVersion", dialParams.SSHClientVersion) - } + if GetEmitNetworkParameters() { - if dialParams.UpstreamProxyType != "" { - args = append(args, "upstreamProxyType", dialParams.UpstreamProxyType) - } + if dialParams.SelectedSSHClientVersion { + args = append(args, "SSHClientVersion", dialParams.SSHClientVersion) + } - if dialParams.UpstreamProxyCustomHeaderNames != nil { - args = append(args, "upstreamProxyCustomHeaderNames", strings.Join(dialParams.UpstreamProxyCustomHeaderNames, ",")) - } + if dialParams.UpstreamProxyType != "" { + args = append(args, "upstreamProxyType", dialParams.UpstreamProxyType) + } - if dialParams.MeekDialAddress != "" { - args = append(args, "meekDialAddress", dialParams.MeekDialAddress) - } + if dialParams.UpstreamProxyCustomHeaderNames != nil { + args = append(args, "upstreamProxyCustomHeaderNames", strings.Join(dialParams.UpstreamProxyCustomHeaderNames, ",")) + } - meekResolvedIPAddress := dialParams.MeekResolvedIPAddress.Load().(string) - if meekResolvedIPAddress != "" { - args = append(args, "meekResolvedIPAddress", meekResolvedIPAddress) - } + if dialParams.MeekDialAddress != "" { + args = append(args, "meekDialAddress", dialParams.MeekDialAddress) + } - if dialParams.MeekSNIServerName != "" { - args = append(args, "meekSNIServerName", dialParams.MeekSNIServerName) - } + meekResolvedIPAddress := dialParams.MeekResolvedIPAddress.Load().(string) + if meekResolvedIPAddress != "" { + args = append(args, "meekResolvedIPAddress", meekResolvedIPAddress) + } - if dialParams.MeekHostHeader != "" { - args = append(args, "meekHostHeader", dialParams.MeekHostHeader) - } + if dialParams.MeekSNIServerName != "" { + args = append(args, "meekSNIServerName", dialParams.MeekSNIServerName) + } - // MeekTransformedHostName is meaningful when meek is used, which is when MeekDialAddress != "" - if dialParams.MeekDialAddress != "" { - args = append(args, "meekTransformedHostName", dialParams.MeekTransformedHostName) - } + if dialParams.MeekHostHeader != "" { + args = append(args, "meekHostHeader", dialParams.MeekHostHeader) + } - if dialParams.SelectedUserAgent { - args = append(args, "userAgent", dialParams.UserAgent) - } + // MeekTransformedHostName is meaningful when meek is used, which is when MeekDialAddress != "" + if dialParams.MeekDialAddress != "" { + args = append(args, "meekTransformedHostName", dialParams.MeekTransformedHostName) + } - if dialParams.SelectedTLSProfile { - args = append(args, "TLSProfile", dialParams.TLSProfile) - args = append(args, "TLSVersion", dialParams.TLSVersion) - } + if dialParams.SelectedUserAgent { + args = append(args, "userAgent", dialParams.UserAgent) + } - if dialParams.DialPortNumber != "" { - args = append(args, "dialPortNumber", dialParams.DialPortNumber) - } + if dialParams.SelectedTLSProfile { + args = append(args, "TLSProfile", dialParams.TLSProfile) + args = append(args, "TLSVersion", dialParams.TLSVersion) + } - if dialParams.QUICVersion != "" { - args = append(args, "QUICVersion", dialParams.QUICVersion) - } + if dialParams.DialPortNumber != "" { + args = append(args, "dialPortNumber", dialParams.DialPortNumber) + } - if dialParams.QUICDialSNIAddress != "" { - args = append(args, "QUICDialSNIAddress", dialParams.QUICDialSNIAddress) - } + if dialParams.QUICVersion != "" { + args = append(args, "QUICVersion", dialParams.QUICVersion) + } - if dialParams.DialConnMetrics != nil { - metrics := dialParams.DialConnMetrics.GetMetrics() - for name, value := range metrics { - args = append(args, name, value) + if dialParams.QUICDialSNIAddress != "" { + args = append(args, "QUICDialSNIAddress", dialParams.QUICDialSNIAddress) } - } - if dialParams.ObfuscatedSSHConnMetrics != nil { - metrics := dialParams.ObfuscatedSSHConnMetrics.GetMetrics() - for name, value := range metrics { - args = append(args, name, value) + if dialParams.DialConnMetrics != nil { + metrics := dialParams.DialConnMetrics.GetMetrics() + for name, value := range metrics { + args = append(args, name, value) + } + } + + if dialParams.ObfuscatedSSHConnMetrics != nil { + metrics := dialParams.ObfuscatedSSHConnMetrics.GetMetrics() + for name, value := range metrics { + args = append(args, name, value) + } } } @@ -505,10 +531,10 @@ func NoticeRequestedTactics(dialParams *DialParameters) { } // NoticeActiveTunnel is a successful connection that is used as an active tunnel for port forwarding -func NoticeActiveTunnel(ipAddress, protocol string, isTCS bool) { +func NoticeActiveTunnel(serverID, protocol string, isTCS bool) { singletonNoticeLogger.outputNotice( "ActiveTunnel", noticeIsDiagnostic, - "ipAddress", ipAddress, + "serverID", serverID, "protocol", protocol, "isTCS", isTCS) } @@ -642,25 +668,24 @@ func NoticeClientUpgradeDownloaded(filename string) { } // NoticeBytesTransferred reports how many tunneled bytes have been -// transferred since the last NoticeBytesTransferred, for the tunnel -// to the server at ipAddress. This is not a diagnostic notice: the -// user app has requested this notice with EmitBytesTransferred for -// functionality such as traffic display; and this frequent notice -// is not intended to be included with feedback. -func NoticeBytesTransferred(ipAddress string, sent, received int64) { +// transferred since the last NoticeBytesTransferred. This is not a diagnostic +// notice: the user app has requested this notice with EmitBytesTransferred +// for functionality such as traffic display; and this frequent notice is not +// intended to be included with feedback. +func NoticeBytesTransferred(serverID string, sent, received int64) { singletonNoticeLogger.outputNotice( "BytesTransferred", 0, + "serverID", serverID, "sent", sent, "received", received) } // NoticeTotalBytesTransferred reports how many tunneled bytes have been -// transferred in total up to this point, for the tunnel to the server -// at ipAddress. This is a diagnostic notice. -func NoticeTotalBytesTransferred(ipAddress string, sent, received int64) { +// transferred in total up to this point. This is a diagnostic notice. +func NoticeTotalBytesTransferred(serverID string, sent, received int64) { singletonNoticeLogger.outputNotice( "TotalBytesTransferred", noticeIsDiagnostic, - "ipAddress", ipAddress, + "serverID", serverID, "sent", sent, "received", received) } @@ -701,6 +726,9 @@ func NoticeExiting() { // NoticeRemoteServerListResourceDownloadedBytes reports remote server list download progress. func NoticeRemoteServerListResourceDownloadedBytes(url string, bytes int64) { + if !GetEmitNetworkParameters() { + url = "" + } singletonNoticeLogger.outputNotice( "RemoteServerListResourceDownloadedBytes", noticeIsDiagnostic, "url", url, @@ -710,6 +738,9 @@ func NoticeRemoteServerListResourceDownloadedBytes(url string, bytes int64) { // NoticeRemoteServerListResourceDownloaded indicates that a remote server list download // completed successfully. func NoticeRemoteServerListResourceDownloaded(url string) { + if !GetEmitNetworkParameters() { + url = "" + } singletonNoticeLogger.outputNotice( "RemoteServerListResourceDownloaded", noticeIsDiagnostic, "url", url) @@ -757,10 +788,10 @@ func NoticeNetworkID(networkID string) { "NetworkID", 0, "ID", networkID) } -func NoticeLivenessTest(ipAddress string, metrics *livenessTestMetrics, success bool) { +func NoticeLivenessTest(serverID string, metrics *livenessTestMetrics, success bool) { singletonNoticeLogger.outputNotice( "LivenessTest", noticeIsDiagnostic, - "ipAddress", ipAddress, + "serverID", serverID, "metrics", metrics, "success", success) } @@ -779,6 +810,13 @@ func NoticeEstablishTunnelTimeout(timeout time.Duration) { "timeout", timeout) } +func NoticeFragmentor(serverID string, message string) { + singletonNoticeLogger.outputNotice( + "Fragmentor", noticeIsDiagnostic, + "serverID", serverID, + "message", message) +} + type repetitiveNoticeState struct { message string repeats int diff --git a/psiphon/server/server_test.go b/psiphon/server/server_test.go index 7b078a79c..e9396860a 100644 --- a/psiphon/server/server_test.go +++ b/psiphon/server/server_test.go @@ -80,7 +80,7 @@ func TestMain(m *testing.M) { } defer os.RemoveAll(testDataDirName) - psiphon.SetEmitDiagnosticNotices(true) + psiphon.SetEmitDiagnosticNotices(true, true) mockWebServerURL, mockWebServerExpectedResponse = runMockWebServer() diff --git a/psiphon/serverApi.go b/psiphon/serverApi.go index 977853988..fa5d34d51 100644 --- a/psiphon/serverApi.go +++ b/psiphon/serverApi.go @@ -32,7 +32,6 @@ import ( "net" "net/http" "net/url" - "regexp" "strconv" "strings" @@ -616,13 +615,6 @@ func RecordRemoteServerListStat( config, datastorePersistentStatTypeRemoteServerList, remoteServerListStatJson) } -// failedTunnelErrStripAddressRegex strips IPv4 address [and optional port] -// strings from "net" package I/O error messages. This is to avoid -// inadvertently recording direct server IPs via error message logs, and to -// reduce the error space due to superfluous source port data. -var failedTunnelErrStripAddressRegex = regexp.MustCompile( - `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}(:(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3}))?`) - // RecordFailedTunnelStat records metrics for a failed tunnel dial, including // dial parameters and error condition (tunnelErr). // @@ -647,7 +639,13 @@ func RecordFailedTunnelStat( params["server_entry_tag"] = dialParams.ServerEntry.Tag params["last_connected"] = lastConnected params["client_failed_timestamp"] = common.TruncateTimestampToHour(common.GetCurrentTimestamp()) - params["tunnel_error"] = failedTunnelErrStripAddressRegex.ReplaceAllString(tunnelErr.Error(), "
") + + // Ensure direct server IPs are not exposed in logs. The "net" package, and + // possibly other 3rd party packages, will include destination addresses in + // I/O error messages. + tunnelError := StripIPAddressesString(tunnelErr.Error()) + + params["tunnel_error"] = tunnelError failedTunnelStatJson, err := json.Marshal(params) if err != nil { diff --git a/psiphon/tunnel.go b/psiphon/tunnel.go index f71b9b3e4..445904f25 100644 --- a/psiphon/tunnel.go +++ b/psiphon/tunnel.go @@ -174,7 +174,7 @@ func (tunnel *Tunnel) Activate( if !tunnel.config.DisableApi { NoticeInfo( "starting server context for %s", - tunnel.dialParams.ServerEntry.IpAddress) + tunnel.dialParams.ServerEntry.GetDiagnosticID()) // Call NewServerContext in a goroutine, as it blocks on a network operation, // the handshake request, and would block shutdown. If the shutdown signal is @@ -224,7 +224,7 @@ func (tunnel *Tunnel) Activate( if result.err != nil { return common.ContextError( fmt.Errorf("error starting server context for %s: %s", - tunnel.dialParams.ServerEntry.IpAddress, result.err)) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), result.err)) } serverContext = result.serverContext @@ -829,7 +829,7 @@ func dialTunnel( // Skip notice when cancelling. if baseCtx.Err() == nil { NoticeLivenessTest( - dialParams.ServerEntry.IpAddress, metrics, err == nil) + dialParams.ServerEntry.GetDiagnosticID(), metrics, err == nil) } } } @@ -1101,14 +1101,14 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) { if lastTotalBytesTransferedTime.Add(noticePeriod).Before(monotime.Now()) { NoticeTotalBytesTransferred( - tunnel.dialParams.ServerEntry.IpAddress, totalSent, totalReceived) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), totalSent, totalReceived) lastTotalBytesTransferedTime = monotime.Now() } // Only emit the frequent BytesTransferred notice when tunnel is not idle. if tunnel.config.EmitBytesTransferred && (sent > 0 || received > 0) { NoticeBytesTransferred( - tunnel.dialParams.ServerEntry.IpAddress, sent, received) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), sent, received) } // Once the tunnel has connected, activated, and successfully @@ -1147,7 +1147,7 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) { // Note: no mutex on portForwardFailureTotal; only referenced here tunnel.totalPortForwardFailures++ NoticeInfo("port forward failures for %s: %d", - tunnel.dialParams.ServerEntry.IpAddress, + tunnel.dialParams.ServerEntry.GetDiagnosticID(), tunnel.totalPortForwardFailures) // If the underlying Conn has closed (meek and other plugin protocols may close @@ -1202,7 +1202,7 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) { // Always emit a final NoticeTotalBytesTransferred NoticeTotalBytesTransferred( - tunnel.dialParams.ServerEntry.IpAddress, totalSent, totalReceived) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), totalSent, totalReceived) if err == nil { NoticeInfo("shutdown operate tunnel") @@ -1216,7 +1216,7 @@ func (tunnel *Tunnel) operateTunnel(tunnelOwner TunnelOwner) { } else { NoticeAlert("operate tunnel error for %s: %s", - tunnel.dialParams.ServerEntry.IpAddress, err) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), err) tunnelOwner.SignalTunnelFailure(tunnel) } } @@ -1312,7 +1312,7 @@ func sendStats(tunnel *Tunnel) bool { err := tunnel.serverContext.DoStatusRequest(tunnel) if err != nil { NoticeAlert("DoStatusRequest failed for %s: %s", - tunnel.dialParams.ServerEntry.IpAddress, err) + tunnel.dialParams.ServerEntry.GetDiagnosticID(), err) } return err == nil diff --git a/psiphon/utils.go b/psiphon/utils.go index bf03d3935..7a9fa3fa5 100755 --- a/psiphon/utils.go +++ b/psiphon/utils.go @@ -27,8 +27,10 @@ import ( "net" "net/url" "os" + "regexp" "runtime" "runtime/debug" + "strings" "syscall" "time" @@ -111,6 +113,56 @@ func IsAddressInUseError(err error) bool { return false } +var stripIPv4AddressRegex = regexp.MustCompile( + `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}(:(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3}))?`) + +// StripIPAddresses returns a copy of the input with all IP addresses [and +// optional ports] replaced by "
". This is intended to be used to +// strip addresses from "net" package I/O error messages and otherwise avoid +// inadvertently recording direct server IPs via error message logs; and, in +// metrics, to reduce the error space due to superfluous source port data. +// +// Limitation: only strips IPv4 addresses. +func StripIPAddresses(b []byte) []byte { + // TODO: IPv6 support + return stripIPv4AddressRegex.ReplaceAll(b, []byte("
")) +} + +// StripIPAddressesString is StripIPAddresses for strings. +func StripIPAddressesString(s string) string { + // TODO: IPv6 support + return stripIPv4AddressRegex.ReplaceAllString(s, "
") +} + +// RedactNetError removes network address information from a "net" package +// error message. Addresses may be domains or IP addresses. +// +// Limitations: some non-address error context can be lost; this function +// makes assumptions about how the Go "net" package error messages are +// formatted and will fail to redact network addresses if this assumptions +// become untrue. +func RedactNetError(err error) error { + + // Example "net" package error messages: + // + // - lookup : no such host + // - lookup : No address associated with hostname + // - dial tcp
: connectex: No connection could be made because the target machine actively refused it + // - write tcp
->
: write: connection refused + + if err == nil { + return err + } + + errstr := err.Error() + index := strings.Index(errstr, ":") + if index == -1 { + return err + } + + return errors.New(errstr[index:]) +} + // SyncFileWriter wraps a file and exposes an io.Writer. At predefined // steps, the file is synced (flushed to disk) while writing. type SyncFileWriter struct { From 5772b854b3d6ae668f03c4e9d54698396305003f Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 22 Jul 2019 14:29:39 -0400 Subject: [PATCH 09/23] Fix: comment typos --- psiphon/server/tunnelServer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/psiphon/server/tunnelServer.go b/psiphon/server/tunnelServer.go index 6d7209a17..f2a8382f4 100644 --- a/psiphon/server/tunnelServer.go +++ b/psiphon/server/tunnelServer.go @@ -297,7 +297,7 @@ func (server *TunnelServer) GetClientHandshaked( return server.sshServer.getClientHandshaked(sessionID) } -// UpdateClientAPIParameters updates the recorded handhake API parameters for +// UpdateClientAPIParameters updates the recorded handshake API parameters for // the client corresponding to sessionID. func (server *TunnelServer) UpdateClientAPIParameters( sessionID string, @@ -431,7 +431,7 @@ func (sshServer *sshServer) runListener( handleClient := func(clientTunnelProtocol string, clientConn net.Conn) { // Note: establish tunnel limiter cannot simply stop TCP - // listeners in all cases (e.g., meek) since SSH tunnel can + // listeners in all cases (e.g., meek) since SSH tunnels can // span multiple TCP connections. if !sshServer.getEstablishTunnels() { From 4bb96f0b2babc93ae2553cfab375c4e11a5ddada Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 22 Jul 2019 15:07:25 -0400 Subject: [PATCH 10/23] Redact URL from "net/http" error message - Fix LookupIP redaction - Use common stub string value --- psiphon/LookupIP.go | 9 +++++---- psiphon/LookupIP_nobind.go | 9 +++++---- psiphon/TCPConn_nobind.go | 2 +- psiphon/config.go | 2 +- psiphon/net.go | 8 ++++++++ psiphon/notice.go | 4 ++-- psiphon/utils.go | 10 +++++----- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/psiphon/LookupIP.go b/psiphon/LookupIP.go index 4e387444a..4e0648607 100644 --- a/psiphon/LookupIP.go +++ b/psiphon/LookupIP.go @@ -70,15 +70,16 @@ func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, e } addrs, err := net.DefaultResolver.LookupIPAddr(ctx, host) - if err != nil { - return nil, common.ContextError(err) - } // Remove domain names from "net" error messages. - if !GetEmitNetworkParameters() { + if err != nil && !GetEmitNetworkParameters() { err = RedactNetError(err) } + if err != nil { + return nil, common.ContextError(err) + } + ips := make([]net.IP, len(addrs)) for i, addr := range addrs { ips[i] = addr.IP diff --git a/psiphon/LookupIP_nobind.go b/psiphon/LookupIP_nobind.go index 663b6f5c6..1765fc805 100644 --- a/psiphon/LookupIP_nobind.go +++ b/psiphon/LookupIP_nobind.go @@ -37,15 +37,16 @@ func LookupIP(ctx context.Context, host string, config *DialConfig) ([]net.IP, e } addrs, err := net.DefaultResolver.LookupIPAddr(ctx, host) - if err != nil { - return nil, common.ContextError(err) - } // Remove domain names from "net" error messages. - if !GetEmitNetworkParameters() { + if err != nil && !GetEmitNetworkParameters() { err = RedactNetError(err) } + if err != nil { + return nil, common.ContextError(err) + } + ips := make([]net.IP, len(addrs)) for i, addr := range addrs { ips[i] = addr.IP diff --git a/psiphon/TCPConn_nobind.go b/psiphon/TCPConn_nobind.go index 5bfee501b..da5b88cbf 100644 --- a/psiphon/TCPConn_nobind.go +++ b/psiphon/TCPConn_nobind.go @@ -41,7 +41,7 @@ func tcpDial(ctx context.Context, addr string, config *DialConfig) (net.Conn, er conn, err := dialer.DialContext(ctx, "tcp", addr) // Remove domain names from "net" error messages. - if !GetEmitNetworkParameters() { + if err != nil && !GetEmitNetworkParameters() { err = RedactNetError(err) } diff --git a/psiphon/config.go b/psiphon/config.go index 84ae2a318..9d6d5b645 100755 --- a/psiphon/config.go +++ b/psiphon/config.go @@ -1272,7 +1272,7 @@ func (n *loggingNetworkIDGetter) GetNetworkID() string { } if len(logNetworkID)+1 < len(networkID) { // Indicate when additional network info was present after the first "-". - logNetworkID += "+" + logNetworkID += "+[redacted]" } NoticeNetworkID(logNetworkID) diff --git a/psiphon/net.go b/psiphon/net.go index b4b1e0774..764b94846 100644 --- a/psiphon/net.go +++ b/psiphon/net.go @@ -30,6 +30,7 @@ import ( "net" "net/http" "os" + "strings" "sync" "sync/atomic" "time" @@ -530,6 +531,13 @@ func ResumeDownload( err = fmt.Errorf("unexpected response status code: %d", response.StatusCode) } if err != nil { + + // Redact URL from "net/http" error message. + if !GetEmitNetworkParameters() { + errStr := err.Error() + err = errors.New(strings.ReplaceAll(errStr, downloadURL, "[redacted]")) + } + return 0, "", common.ContextError(err) } defer response.Body.Close() diff --git a/psiphon/notice.go b/psiphon/notice.go index f65fdcbd7..f9373dad2 100644 --- a/psiphon/notice.go +++ b/psiphon/notice.go @@ -727,7 +727,7 @@ func NoticeExiting() { // NoticeRemoteServerListResourceDownloadedBytes reports remote server list download progress. func NoticeRemoteServerListResourceDownloadedBytes(url string, bytes int64) { if !GetEmitNetworkParameters() { - url = "" + url = "[redacted]" } singletonNoticeLogger.outputNotice( "RemoteServerListResourceDownloadedBytes", noticeIsDiagnostic, @@ -739,7 +739,7 @@ func NoticeRemoteServerListResourceDownloadedBytes(url string, bytes int64) { // completed successfully. func NoticeRemoteServerListResourceDownloaded(url string) { if !GetEmitNetworkParameters() { - url = "" + url = "[redacted]" } singletonNoticeLogger.outputNotice( "RemoteServerListResourceDownloaded", noticeIsDiagnostic, diff --git a/psiphon/utils.go b/psiphon/utils.go index 7a9fa3fa5..b4e1779f6 100755 --- a/psiphon/utils.go +++ b/psiphon/utils.go @@ -117,7 +117,7 @@ var stripIPv4AddressRegex = regexp.MustCompile( `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}(:(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3}))?`) // StripIPAddresses returns a copy of the input with all IP addresses [and -// optional ports] replaced by "
". This is intended to be used to +// optional ports] replaced by "[address]". This is intended to be used to // strip addresses from "net" package I/O error messages and otherwise avoid // inadvertently recording direct server IPs via error message logs; and, in // metrics, to reduce the error space due to superfluous source port data. @@ -125,13 +125,13 @@ var stripIPv4AddressRegex = regexp.MustCompile( // Limitation: only strips IPv4 addresses. func StripIPAddresses(b []byte) []byte { // TODO: IPv6 support - return stripIPv4AddressRegex.ReplaceAll(b, []byte("
")) + return stripIPv4AddressRegex.ReplaceAll(b, []byte("[redacted]")) } // StripIPAddressesString is StripIPAddresses for strings. func StripIPAddressesString(s string) string { // TODO: IPv6 support - return stripIPv4AddressRegex.ReplaceAllString(s, "
") + return stripIPv4AddressRegex.ReplaceAllString(s, "[redacted]") } // RedactNetError removes network address information from a "net" package @@ -155,12 +155,12 @@ func RedactNetError(err error) error { } errstr := err.Error() - index := strings.Index(errstr, ":") + index := strings.Index(errstr, ": ") if index == -1 { return err } - return errors.New(errstr[index:]) + return errors.New("[redacted]" + errstr[index:]) } // SyncFileWriter wraps a file and exposes an io.Writer. At predefined From 389fa8a0a19d4f4fcd69c259b63e6ea7d540e4a1 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 22 Jul 2019 19:23:04 -0400 Subject: [PATCH 11/23] Rename serverID to diagnosticID - In other contexts, "serverID" is synonymous with server IP address. --- psiphon/notice.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/psiphon/notice.go b/psiphon/notice.go index f9373dad2..39af4e262 100644 --- a/psiphon/notice.go +++ b/psiphon/notice.go @@ -427,7 +427,7 @@ func NoticeAvailableEgressRegions(regions []string) { func noticeWithDialParameters(noticeType string, dialParams *DialParameters) { args := []interface{}{ - "serverID", dialParams.ServerEntry.GetDiagnosticID(), + "diagnosticID", dialParams.ServerEntry.GetDiagnosticID(), "region", dialParams.ServerEntry.Region, "protocol", dialParams.TunnelProtocol, "isReplay", dialParams.IsReplay, @@ -531,10 +531,10 @@ func NoticeRequestedTactics(dialParams *DialParameters) { } // NoticeActiveTunnel is a successful connection that is used as an active tunnel for port forwarding -func NoticeActiveTunnel(serverID, protocol string, isTCS bool) { +func NoticeActiveTunnel(diagnosticID, protocol string, isTCS bool) { singletonNoticeLogger.outputNotice( "ActiveTunnel", noticeIsDiagnostic, - "serverID", serverID, + "diagnosticID", diagnosticID, "protocol", protocol, "isTCS", isTCS) } @@ -672,20 +672,20 @@ func NoticeClientUpgradeDownloaded(filename string) { // notice: the user app has requested this notice with EmitBytesTransferred // for functionality such as traffic display; and this frequent notice is not // intended to be included with feedback. -func NoticeBytesTransferred(serverID string, sent, received int64) { +func NoticeBytesTransferred(diagnosticID string, sent, received int64) { singletonNoticeLogger.outputNotice( "BytesTransferred", 0, - "serverID", serverID, + "diagnosticID", diagnosticID, "sent", sent, "received", received) } // NoticeTotalBytesTransferred reports how many tunneled bytes have been // transferred in total up to this point. This is a diagnostic notice. -func NoticeTotalBytesTransferred(serverID string, sent, received int64) { +func NoticeTotalBytesTransferred(diagnosticID string, sent, received int64) { singletonNoticeLogger.outputNotice( "TotalBytesTransferred", noticeIsDiagnostic, - "serverID", serverID, + "diagnosticID", diagnosticID, "sent", sent, "received", received) } @@ -788,10 +788,10 @@ func NoticeNetworkID(networkID string) { "NetworkID", 0, "ID", networkID) } -func NoticeLivenessTest(serverID string, metrics *livenessTestMetrics, success bool) { +func NoticeLivenessTest(diagnosticID string, metrics *livenessTestMetrics, success bool) { singletonNoticeLogger.outputNotice( "LivenessTest", noticeIsDiagnostic, - "serverID", serverID, + "diagnosticID", diagnosticID, "metrics", metrics, "success", success) } @@ -810,10 +810,10 @@ func NoticeEstablishTunnelTimeout(timeout time.Duration) { "timeout", timeout) } -func NoticeFragmentor(serverID string, message string) { +func NoticeFragmentor(diagnosticID string, message string) { singletonNoticeLogger.outputNotice( "Fragmentor", noticeIsDiagnostic, - "serverID", serverID, + "diagnosticID", diagnosticID, "message", message) } From e668f1a72342c1cacae57ea869311552d8dafab6 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 22 Jul 2019 21:05:10 -0400 Subject: [PATCH 12/23] Fix: GetEmitDiagnosticNotices name typo --- psiphon/notice.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/psiphon/notice.go b/psiphon/notice.go index 39af4e262..bfc319363 100644 --- a/psiphon/notice.go +++ b/psiphon/notice.go @@ -78,9 +78,9 @@ func SetEmitDiagnosticNotices( } } -// GetEmitDiagnoticNotices returns the current state +// GetEmitDiagnosticNotices returns the current state // of emitting diagnostic notices. -func GetEmitDiagnoticNotices() bool { +func GetEmitDiagnosticNotices() bool { return atomic.LoadInt32(&singletonNoticeLogger.emitDiagnostics) == 1 } @@ -206,7 +206,7 @@ const ( // outputNotice encodes a notice in JSON and writes it to the output writer. func (nl *noticeLogger) outputNotice(noticeType string, noticeFlags uint32, args ...interface{}) { - if (noticeFlags¬iceIsDiagnostic != 0) && !GetEmitDiagnoticNotices() { + if (noticeFlags¬iceIsDiagnostic != 0) && !GetEmitDiagnosticNotices() { return } From c6c265d4a64918643dca1465c4afb44f91823c62 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Tue, 23 Jul 2019 12:57:07 -0400 Subject: [PATCH 13/23] Fix: missing argument for SetEmitDiagnosticNotices --- psiphon/controller_test.go | 2 +- psiphon/remoteServerList_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/psiphon/controller_test.go b/psiphon/controller_test.go index 51e645bee..7f653697c 100644 --- a/psiphon/controller_test.go +++ b/psiphon/controller_test.go @@ -47,7 +47,7 @@ import ( func TestMain(m *testing.M) { flag.Parse() - SetEmitDiagnosticNotices(true) + SetEmitDiagnosticNotices(true, true) initDisruptor() initUpstreamProxy() diff --git a/psiphon/remoteServerList_test.go b/psiphon/remoteServerList_test.go index 9659bdf9a..573ccdd4c 100644 --- a/psiphon/remoteServerList_test.go +++ b/psiphon/remoteServerList_test.go @@ -372,7 +372,7 @@ func testObfuscatedRemoteServerLists(t *testing.T, omitMD5Sums bool) { // connect to Psiphon server with Psiphon client // - SetEmitDiagnosticNotices(true) + SetEmitDiagnosticNotices(true, true) // Note: calling LoadConfig ensures all *int config fields are initialized clientConfigJSONTemplate := ` From 893d139eed01909ca3502e085fea871705701361 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Tue, 23 Jul 2019 15:12:15 -0400 Subject: [PATCH 14/23] Fix: strings.ReplaceAll requires Go 1.12 --- psiphon/net.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psiphon/net.go b/psiphon/net.go index 764b94846..3c0dfea90 100644 --- a/psiphon/net.go +++ b/psiphon/net.go @@ -535,7 +535,7 @@ func ResumeDownload( // Redact URL from "net/http" error message. if !GetEmitNetworkParameters() { errStr := err.Error() - err = errors.New(strings.ReplaceAll(errStr, downloadURL, "[redacted]")) + err = errors.New(strings.Replace(errStr, downloadURL, "[redacted]", -1)) } return 0, "", common.ContextError(err) From e930c7bceb786470349895f37766b99bd6eff3db Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Thu, 25 Jul 2019 16:50:25 -0400 Subject: [PATCH 15/23] Add JSON encoder/signing protocol comment --- psiphon/common/protocol/serverEntry.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/psiphon/common/protocol/serverEntry.go b/psiphon/common/protocol/serverEntry.go index 1007aeb36..85c81284b 100644 --- a/psiphon/common/protocol/serverEntry.go +++ b/psiphon/common/protocol/serverEntry.go @@ -291,6 +291,15 @@ func (fields ServerEntryFields) AddSignature(publicKey, privateKey string) error delete(copyFields, "signature") + // Limitation: since the verifyier must remarshal its server entry before + // verifying, the JSON produced there must be a byte-for-byte match to the + // JSON signed here. The precise output of the JSON encoder that is used, + // "encoding/json", with default formatting, as of Go 1.11.5, is therefore + // part of the signature protocol. + // + // TODO: use a stadard, canonical encoding, such as JCS: + // https://tools.ietf.org/id/draft-rundgren-json-canonicalization-scheme-05.html + marshaledFields, err := json.Marshal(copyFields) if err != nil { return common.ContextError(err) From 52a15df7b9b7fd6b3e47759a717f404b17dfca3f Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Fri, 26 Jul 2019 10:30:52 -0400 Subject: [PATCH 16/23] Fix: duplicate session ID handling flaw - Failing to await full termination of an existing client, allowed a scenario where the existing client set the handshake state of the new client, causing invalid server_tunnel records to be logged and causing the new client handshake to fail. --- psiphon/server/tunnelServer.go | 99 +++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 18 deletions(-) diff --git a/psiphon/server/tunnelServer.go b/psiphon/server/tunnelServer.go index f2a8382f4..81acb60a7 100644 --- a/psiphon/server/tunnelServer.go +++ b/psiphon/server/tunnelServer.go @@ -572,26 +572,74 @@ func (sshServer *sshServer) registerEstablishedClient(client *sshClient) bool { // and reestablished. In this case, when the same server is selected, this logic // will be hit; closing the old, dangling client is desirable. // - Multi-tunnel clients should not normally use one server for multiple tunnels. - existingClient := sshServer.clients[client.sessionID] - sshServer.clients[client.sessionID] = client + existingClient := sshServer.clients[client.sessionID] sshServer.clientsMutex.Unlock() - // Call stop() outside the mutex to avoid deadlock. if existingClient != nil { + + // This case is expected to be common, and so logged at the lowest severity + // level. + log.WithContext().Debug( + "stopping existing client with duplicate session ID") + existingClient.stop() - // Since existingClient.run() isn't guaranteed to have terminated at - // this point, synchronously release authorizations for the previous - // client here. This ensures that the authorization IDs are not in - // use when the reconnecting client submits its authorizations. - existingClient.cleanupAuthorizations() + // Block until the existingClient is fully terminated. This is necessary to + // avoid this scenario: + // - existingClient is invoking handshakeAPIRequestHandler + // - sshServer.clients[client.sessionID] is updated to point to new client + // - existingClient's handshakeAPIRequestHandler invokes + // SetClientHandshakeState but sets the handshake parameters for new + // client + // - as a result, the new client handshake will fail (only a single handshake + // is permitted) and the new client server_tunnel log will contain an + // invalid mix of existing/new client fields + // + // Once existingClient.awaitStopped returns, all existingClient port + // forwards and request handlers have terminated, so no API handler, either + // tunneled web API or SSH API, will remain and it is safe to point + // sshServer.clients[client.sessionID] to the new client. + // Limitation: this scenario remains possible with _untunneled_ web API + // requests. + // + // Blocking also ensures existingClient.releaseAuthorizations is invoked before + // the new client attempts to submit the same authorizations. + // + // Perform blocking awaitStopped operation outside the + // sshServer.clientsMutex mutex to avoid blocking all other clients for the + // duration. We still expect and require that the stop process completes + // rapidly, e.g., does not block on network I/O, allowing the new client + // connection to proceed without delay. + // + // In addition, operations triggered by stop, and which must complete before + // awaitStopped returns, will attempt to lock sshServer.clientsMutex, + // including unregisterEstablishedClient. - log.WithContext().Debug( - "stopped existing client with duplicate session ID") + existingClient.awaitStopped() } + sshServer.clientsMutex.Lock() + defer sshServer.clientsMutex.Unlock() + + // existingClient's stop will have removed it from sshServer.clients via + // unregisterEstablishedClient, so sshServer.clients[client.sessionID] should + // be nil -- unless yet another client instance using the same sessionID has + // connected in the meantime while awaiting existingClient stop. In this + // case, it's not clear which is the most recent connection from the client, + // so instead of this connection terminating more peers, it aborts. + + if sshServer.clients[client.sessionID] != nil { + // As this is expected to be rare case, it's logged at a higher severity + // level. + log.WithContext().Warning( + "aborting new client with duplicate session ID") + return false + } + + sshServer.clients[client.sessionID] = client + return true } @@ -601,17 +649,15 @@ func (sshServer *sshServer) unregisterEstablishedClient(client *sshClient) { registeredClient := sshServer.clients[client.sessionID] - // registeredClient will differ from client when client - // is the existingClient terminated in registerEstablishedClient. - // In that case, registeredClient remains connected, and - // the sshServer.clients entry should be retained. + // registeredClient will differ from client when client is the existingClient + // terminated in registerEstablishedClient. In that case, registeredClient + // remains connected, and the sshServer.clients entry should be retained. if registeredClient == client { delete(sshServer.clients, client.sessionID) } sshServer.clientsMutex.Unlock() - // Call stop() outside the mutex to avoid deadlock. client.stop() } @@ -984,6 +1030,7 @@ type sshClient struct { signalIssueSLOKs chan struct{} runCtx context.Context stopRunning context.CancelFunc + stopped chan struct{} tcpPortForwardDialingAvailableSignal context.CancelFunc releaseAuthorizations func() stopTimer *time.Timer @@ -1050,6 +1097,7 @@ func newSshClient( signalIssueSLOKs: make(chan struct{}, 1), runCtx: runCtx, stopRunning: stopRunning, + stopped: make(chan struct{}), } client.tcpTrafficState.availablePortForwardCond = sync.NewCond(new(sync.Mutex)) @@ -1061,6 +1109,10 @@ func newSshClient( func (sshClient *sshClient) run( baseConn net.Conn, onSSHHandshakeFinished func()) { + // When run returns, the client has fully stopped, with all SSH state torn + // down and no port forwards or API requests in progress. + defer close(sshClient.stopped) + // onSSHHandshakeFinished must be called even if the SSH handshake is aborted. defer func() { if onSSHHandshakeFinished != nil { @@ -1410,14 +1462,25 @@ func (sshClient *sshClient) authLogCallback(conn ssh.ConnMetadata, method string } } -// stop signals the ssh connection to shutdown. After sshConn() returns, -// the connection has terminated but sshClient.run() may still be -// running and in the process of exiting. +// stop signals the ssh connection to shutdown. After sshConn.Wait returns, +// the SSH connection has terminated but sshClient.run may still be running and +// in the process of exiting. +// +// The shutdown process must complete rapidly and not, e.g., block on network +// I/O, as newly connecting clients need to await stop completion of any +// existing connection that shares the same session ID. func (sshClient *sshClient) stop() { sshClient.sshConn.Close() sshClient.sshConn.Wait() } +// awaitStopped will block until sshClient.run has exited, at which point all +// worker goroutines associated with the sshClient, including any in-flight +// API handlers, will have exited. +func (sshClient *sshClient) awaitStopped() { + <-sshClient.stopped +} + // runTunnel handles/dispatches new channels and new requests from the client. // When the SSH client connection closes, both the channels and requests channels // will close and runTunnel will exit. From 0e0ea7104761eb7c57968c2596e9c396e9a04e4e Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Sun, 28 Jul 2019 14:01:32 -0400 Subject: [PATCH 17/23] Add tests to exercise Bolt DB resiliency --- psiphon/dataStore_recovery_test.go | 293 +++++++++++++++++++++++++++++ psiphon/exchange_test.go | 6 +- 2 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 psiphon/dataStore_recovery_test.go diff --git a/psiphon/dataStore_recovery_test.go b/psiphon/dataStore_recovery_test.go new file mode 100644 index 000000000..de8e69f88 --- /dev/null +++ b/psiphon/dataStore_recovery_test.go @@ -0,0 +1,293 @@ +// +build !BADGER_DB,!FILES_DB + +/* + * Copyright (c) 2019, Psiphon Inc. + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package psiphon + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "testing" + + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng" + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol" +) + +func TestBoltResiliency(t *testing.T) { + + testDataDirName, err := ioutil.TempDir("", "psiphon-bolt-recovery-test") + if err != nil { + t.Fatalf("TempDir failed: %s", err) + } + defer os.RemoveAll(testDataDirName) + + SetEmitDiagnosticNotices(true, true) + + clientConfigJSONTemplate := ` + { + "DataStoreDirectory" : "%s", + "ClientPlatform" : "", + "ClientVersion" : "0", + "SponsorId" : "0", + "PropagationChannelId" : "0", + "ConnectionPoolSize" : 10, + "EstablishTunnelTimeoutSeconds" : 1, + "EstablishTunnelPausePeriodSeconds" : 1 + }` + + clientConfigJSON := fmt.Sprintf( + clientConfigJSONTemplate, + testDataDirName) + + clientConfig, err := LoadConfig([]byte(clientConfigJSON)) + if err != nil { + t.Fatalf("LoadConfig failed: %s", err) + } + err = clientConfig.Commit() + if err != nil { + t.Fatalf("Commit failed: %s", err) + } + + serverEntryCount := 100 + + noticeCandidateServers := make(chan struct{}, 1) + noticeExiting := make(chan struct{}, 1) + noticeResetDatastore := make(chan struct{}, 1) + noticeDatastoreFailed := make(chan struct{}, 1) + + SetNoticeWriter(NewNoticeReceiver( + func(notice []byte) { + + noticeType, payload, err := GetNotice(notice) + if err != nil { + return + } + + printNotice := false + + switch noticeType { + case "CandidateServers": + count := int(payload["count"].(float64)) + if count != serverEntryCount { + t.Fatalf("unexpected server entry count: %d", count) + } + select { + case noticeCandidateServers <- *new(struct{}): + default: + } + case "Exiting": + select { + case noticeExiting <- *new(struct{}): + default: + } + case "Alert": + message := payload["message"].(string) + var channel chan struct{} + if strings.Contains(message, "tryDatastoreOpenDB: reset") { + channel = noticeResetDatastore + } else if strings.Contains(message, "datastore has failed") { + channel = noticeDatastoreFailed + } + if channel != nil { + select { + case channel <- *new(struct{}): + default: + } + } + } + + if printNotice { + fmt.Printf("%s\n", string(notice)) + } + })) + + drainNoticeChannel := func(channel chan struct{}) { + for { + select { + case channel <- *new(struct{}): + default: + return + } + } + } + + drainNoticeChannels := func() { + drainNoticeChannel(noticeCandidateServers) + drainNoticeChannel(noticeExiting) + drainNoticeChannel(noticeResetDatastore) + drainNoticeChannel(noticeDatastoreFailed) + } + + // Paving sufficient server entries, then truncating the datastore file to + // remove some server entry data, then iterating over all server entries (to + // produce the CandidateServers output) triggers datastore corruption + // detection and, at start up, reset/recovery. + + paveServerEntries := func() { + for i := 0; i < serverEntryCount; i++ { + + n := 16 + fields := make(protocol.ServerEntryFields) + fields["ipAddress"] = fmt.Sprintf("127.0.0.%d", i+1) + fields["sshPort"] = 2222 + fields["sshUsername"] = prng.HexString(n) + fields["sshPassword"] = prng.HexString(n) + fields["sshHostKey"] = prng.HexString(n) + fields["capabilities"] = []string{"SSH", "ssh-api-requests"} + fields["region"] = "US" + fields["configurationVersion"] = 1 + + fields.SetLocalSource(protocol.SERVER_ENTRY_SOURCE_EMBEDDED) + fields.SetLocalTimestamp( + common.TruncateTimestampToHour(common.GetCurrentTimestamp())) + + err = StoreServerEntry(fields, true) + if err != nil { + t.Fatalf("StoreServerEntry failed: %s", err) + } + } + } + + startController := func() func() { + controller, err := NewController(clientConfig) + if err != nil { + t.Fatalf("NewController failed: %s", err) + } + ctx, cancelFunc := context.WithCancel(context.Background()) + controllerWaitGroup := new(sync.WaitGroup) + controllerWaitGroup.Add(1) + go func() { + defer controllerWaitGroup.Done() + controller.Run(ctx) + }() + return func() { + cancelFunc() + controllerWaitGroup.Wait() + } + } + + truncateDataStore := func() { + filename := filepath.Join(testDataDirName, "psiphon.boltdb") + configFile, err := os.OpenFile(filename, os.O_RDWR, 0666) + if err != nil { + t.Fatalf("OpenFile failed: %s", err) + } + defer configFile.Close() + fileInfo, err := configFile.Stat() + if err != nil { + t.Fatalf("Stat failed: %s", err) + } + err = configFile.Truncate(fileInfo.Size() / 4) + if err != nil { + t.Fatalf("Truncate failed: %s", err) + } + err = configFile.Sync() + if err != nil { + t.Fatalf("Sync failed: %s", err) + } + } + + // Populate datastore with 100 server entries. + + err = OpenDataStore(clientConfig) + if err != nil { + t.Fatalf("OpenDataStore failed: %s", err) + } + defer CloseDataStore() + + paveServerEntries() + + stopController := startController() + + <-noticeCandidateServers + + stopController() + + CloseDataStore() + + drainNoticeChannels() + + // Truncate datastore file before running controller; expect a datastore + // "reset" notice on OpenDataStore. + + t.Logf("test: recover from datastore corrupted before opening") + + truncateDataStore() + + err = OpenDataStore(clientConfig) + if err != nil { + t.Fatalf("OpenDataStore failed: %s", err) + } + defer CloseDataStore() + + <-noticeResetDatastore + + paveServerEntries() + + // Truncate datastore while running the controller. First, complete one + // successful data scan (CandidateServers). The next scan should trigger a + // datastore "failed" notice. + + t.Logf("test: detect corrupt datastore while running") + + stopController = startController() + + <-noticeCandidateServers + + truncateDataStore() + + <-noticeDatastoreFailed + + <-noticeExiting + + stopController() + + CloseDataStore() + + drainNoticeChannels() + + // Restart successfully after previous failure shutdown. + + t.Logf("test: after restart, recover from datastore corrupted while running") + + err = OpenDataStore(clientConfig) + if err != nil { + t.Fatalf("OpenDataStore failed: %s", err) + } + defer CloseDataStore() + + <-noticeResetDatastore + + paveServerEntries() + + stopController = startController() + + <-noticeCandidateServers + + stopController() + + CloseDataStore() +} diff --git a/psiphon/exchange_test.go b/psiphon/exchange_test.go index d56ac3ef2..bc43fb592 100644 --- a/psiphon/exchange_test.go +++ b/psiphon/exchange_test.go @@ -95,13 +95,13 @@ func TestServerEntryExchange(t *testing.T) { // Generate server entries to test different cases // - // Note: invalid signagture cases are exercised in + // Note: invalid signature cases are exercised in // protocol.TestServerEntryListSignatures - makeServerEntryFields := func(IPaddress string) protocol.ServerEntryFields { + makeServerEntryFields := func(IPAddress string) protocol.ServerEntryFields { n := 16 fields := make(protocol.ServerEntryFields) - fields["ipAddress"] = IPaddress + fields["ipAddress"] = IPAddress fields["sshPort"] = 22 fields["sshUsername"] = prng.HexString(n) fields["sshPassword"] = prng.HexString(n) From 91a29ec447a296791f0055090556daa2383a1438 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Sun, 28 Jul 2019 15:29:02 -0400 Subject: [PATCH 18/23] Update vendored bolt --- vendor/github.com/Psiphon-Labs/bolt/tx.go | 23 ++++++++++++++++++++--- vendor/vendor.json | 6 +++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/vendor/github.com/Psiphon-Labs/bolt/tx.go b/vendor/github.com/Psiphon-Labs/bolt/tx.go index ec902a5cc..514d00f8d 100644 --- a/vendor/github.com/Psiphon-Labs/bolt/tx.go +++ b/vendor/github.com/Psiphon-Labs/bolt/tx.go @@ -391,9 +391,26 @@ func (tx *Tx) Check() <-chan error { // SynchronousCheck performs the Check function in the current goroutine, // allowing the caller to recover from any panics or faults. func (tx *Tx) SynchronousCheck() error { - ch := make(chan error) - tx.check(ch) - return <-ch + checkErrChannel := make(chan error) + + // tx.check may send multiple errors to the channel, and we must consume them + // all to ensure tx.check terminates. Only the first error is returned from + // SynchronousCheck. + firstErrChannel := make(chan error) + go func() { + var err error + for nextErr := range checkErrChannel { + if err != nil { + err = nextErr + } + } + firstErrChannel <- err + }() + + // Invoke bolt code that may panic/segfault in the current goroutine. + tx.check(checkErrChannel) + + return <-firstErrChannel } func (tx *Tx) check(ch chan error) { diff --git a/vendor/vendor.json b/vendor/vendor.json index f42e21279..0cfc5b79c 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -33,10 +33,10 @@ "revisionTime": "2017-02-28T16:03:01Z" }, { - "checksumSHA1": "dVfefYjTFuN1AKIJyCcqNrlLEJo=", + "checksumSHA1": "67iDmaqZg4yqCUDeSlS8uaavYaw=", "path": "github.com/Psiphon-Labs/bolt", - "revision": "b7c055003ce9d8a1bddb9416648cb7d955a3148d", - "revisionTime": "2019-07-19T17:53:53Z" + "revision": "e81ac70c2ed7bcd43e90d848343c42830df1d999", + "revisionTime": "2019-07-28T19:25:17Z" }, { "checksumSHA1": "d3DwsdacdFn1/KCG/2uPV1PwR3s=", From 91319431d6e9e82ac293463e177db09595a0af89 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 29 Jul 2019 10:59:47 -0400 Subject: [PATCH 19/23] Enable temporarily disabled test case --- psiphon/controller_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/psiphon/controller_test.go b/psiphon/controller_test.go index 7f653697c..8a337e2f5 100644 --- a/psiphon/controller_test.go +++ b/psiphon/controller_test.go @@ -437,9 +437,6 @@ func TestQUIC(t *testing.T) { } func TestFrontedQUIC(t *testing.T) { - - t.Skipf("temporarily disabled") - controllerRun(t, &controllerRunConfig{ expectNoServerEntries: false, From a3f4d059ab7a753976842a449200e8c0f53e4044 Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 29 Jul 2019 11:01:01 -0400 Subject: [PATCH 20/23] Don't attempt to log server IP address --- psiphon/dataStore.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/psiphon/dataStore.go b/psiphon/dataStore.go index 35da2462f..628bed0db 100644 --- a/psiphon/dataStore.go +++ b/psiphon/dataStore.go @@ -705,9 +705,7 @@ func (iterator *ServerEntryIterator) Next() (*protocol.ServerEntry, error) { if serverEntry == nil { // In case of data corruption or a bug causing this condition, // do not stop iterating. - NoticeAlert( - "ServerEntryIterator.Next: unexpected missing server entry: %s", - string(serverEntryID)) + NoticeAlert("ServerEntryIterator.Next: unexpected missing server entry") continue } From bc20caf5ae06f3980ad3fb6affefe606453a32cf Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 29 Jul 2019 11:20:50 -0400 Subject: [PATCH 21/23] Rename file to conform with conventions --- psiphon/{dataStore_recovery_test.go => dataStoreRecovery_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename psiphon/{dataStore_recovery_test.go => dataStoreRecovery_test.go} (100%) diff --git a/psiphon/dataStore_recovery_test.go b/psiphon/dataStoreRecovery_test.go similarity index 100% rename from psiphon/dataStore_recovery_test.go rename to psiphon/dataStoreRecovery_test.go From 7f3a7443d23852ccdd87eae31036b66b16869cbf Mon Sep 17 00:00:00 2001 From: Rod Hynes Date: Mon, 29 Jul 2019 20:32:26 -0400 Subject: [PATCH 22/23] Add tests to exercise duplicate session ID handling --- psiphon/server/server_test.go | 2 +- psiphon/server/sessionID_test.go | 279 +++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 psiphon/server/sessionID_test.go diff --git a/psiphon/server/server_test.go b/psiphon/server/server_test.go index e9396860a..510b3e004 100644 --- a/psiphon/server/server_test.go +++ b/psiphon/server/server_test.go @@ -740,7 +740,7 @@ func runServer(t *testing.T, runConfig *runServerConfig) { // TODO: monitor logs for more robust wait-until-loaded. For example, // especially with the race detector on, QUIC-OSSH tests can fail as the - // client sends its initial pacjet before the server is ready. + // client sends its initial packet before the server is ready. time.Sleep(1 * time.Second) // Test: hot reload (of psinet and traffic rules) diff --git a/psiphon/server/sessionID_test.go b/psiphon/server/sessionID_test.go new file mode 100644 index 000000000..c293a8ea4 --- /dev/null +++ b/psiphon/server/sessionID_test.go @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2016, Psiphon Inc. + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package server + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "testing" + "time" + + "github.com/Psiphon-Labs/goarista/monotime" + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon" + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" + "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol" +) + +func TestDuplicateSessionID(t *testing.T) { + + testDataDirName, err := ioutil.TempDir("", "psiphond-duplicate-session-id-test") + if err != nil { + t.Fatalf("TempDir failed: %s", err) + } + defer os.RemoveAll(testDataDirName) + + psiphon.SetEmitDiagnosticNotices(true, true) + + // Configure server + + generateConfigParams := &GenerateConfigParams{ + ServerIPAddress: "127.0.0.1", + EnableSSHAPIRequests: true, + WebServerPort: 8000, + TunnelProtocolPorts: map[string]int{"OSSH": 4000}, + } + + serverConfigJSON, _, _, _, encodedServerEntry, err := GenerateConfig(generateConfigParams) + if err != nil { + t.Fatalf("error generating server config: %s", err) + } + + var serverConfig map[string]interface{} + json.Unmarshal(serverConfigJSON, &serverConfig) + + serverConfig["LogFilename"] = filepath.Join(testDataDirName, "psiphond.log") + serverConfig["LogLevel"] = "debug" + + serverConfigJSON, _ = json.Marshal(serverConfig) + + numConcurrentClients := 100 + + stoppingEvent := "stopping existing client with duplicate session ID" + abortingEvent := "aborting new client with duplicate session ID" + + // Sufficiently buffer channel so log callback handler doesn't cause server + // operations to block while handling concurrent clients. + duplicateSessionIDEvents := make(chan string, numConcurrentClients) + + setLogCallback(func(log []byte) { + strLog := string(log) + var event string + if strings.Contains(strLog, stoppingEvent) { + event = stoppingEvent + } else if strings.Contains(strLog, abortingEvent) { + event = abortingEvent + } + if event != "" { + select { + case duplicateSessionIDEvents <- event: + default: + } + } + + }) + + // Run server + + serverWaitGroup := new(sync.WaitGroup) + serverWaitGroup.Add(1) + go func() { + defer serverWaitGroup.Done() + err := RunServices(serverConfigJSON) + if err != nil { + t.Fatalf("error running server: %s", err) + } + }() + + defer func() { + p, _ := os.FindProcess(os.Getpid()) + p.Signal(os.Interrupt) + serverWaitGroup.Wait() + }() + + // TODO: monitor logs for more robust wait-until-loaded. + time.Sleep(1 * time.Second) + + // Initialize tunnel clients. Bypassing Controller and using Tunnel directly + // to permit multiple concurrent clients. + // + // Limitation: all tunnels still use one singleton datastore and notice + // handler. + + psiphon.SetNoticeWriter(ioutil.Discard) + + clientConfigJSONTemplate := ` + { + "DataStoreDirectory" : "%s", + "SponsorId" : "0", + "PropagationChannelId" : "0", + "SessionID" : "00000000000000000000000000000000" + }` + + clientConfigJSON := fmt.Sprintf( + clientConfigJSONTemplate, + testDataDirName) + + clientConfig, err := psiphon.LoadConfig([]byte(clientConfigJSON)) + if err != nil { + t.Fatalf("LoadConfig failed: %s", err) + } + err = clientConfig.Commit() + if err != nil { + t.Fatalf("Commit failed: %s", err) + } + + err = psiphon.OpenDataStore(clientConfig) + if err != nil { + t.Fatalf("OpenDataStore failed: %s", err) + } + defer psiphon.CloseDataStore() + + serverEntry, err := protocol.DecodeServerEntry( + string(encodedServerEntry), + common.GetCurrentTimestamp(), + protocol.SERVER_ENTRY_SOURCE_EMBEDDED) + if err != nil { + t.Fatalf("DecodeServerEntry failed: %s", err) + } + + dialTunnel := func(ctx context.Context) *psiphon.Tunnel { + + dialParams, err := psiphon.MakeDialParameters( + clientConfig, + func(_ *protocol.ServerEntry, _ string) bool { return false }, + func(_ *protocol.ServerEntry) (string, bool) { return "OSSH", true }, + serverEntry, + false, + 1) + if err != nil { + t.Fatalf("MakeDialParameters failed: %s", err) + } + + tunnel, err := psiphon.ConnectTunnel( + ctx, + clientConfig, + monotime.Now(), + dialParams) + if err != nil { + t.Fatalf("ConnectTunnel failed: %s", err) + } + + return tunnel + } + + handshakeTunnel := func(tunnel *psiphon.Tunnel, expectSuccess bool) { + + _, err = psiphon.NewServerContext(tunnel) + + if expectSuccess && err != nil || (!expectSuccess && err == nil) { + t.Fatalf("Unexpected handshake result: %s", err) + } + } + + ctx, cancelFunc := context.WithCancel(context.Background()) + defer cancelFunc() + + // Test: normal case + // + // First tunnel, t1, fully establishes and then is superceded by new tunnel, t2. + + t1 := dialTunnel(ctx) + + handshakeTunnel(t1, true) + + t2 := dialTunnel(ctx) + + expectEvent := <-duplicateSessionIDEvents + + if expectEvent != stoppingEvent { + t.Fatalf("Unexpected duplicate session ID event") + } + + handshakeTunnel(t2, true) + + t1.Close(true) + t2.Close(true) + + // Test: simultaneous/interleaved case + // + // First tunnel connects but then tries to handshake after second tunnel has + // connected. + + t1 = dialTunnel(ctx) + + // TODO: await log confirmation that t1 completed registerEstablishedClient? + // Otherwise, there's some small chance that t2 is the "first" tunnel and the + // test could fail (false negative). + + t2 = dialTunnel(ctx) + + expectEvent = <-duplicateSessionIDEvents + + if expectEvent != stoppingEvent { + t.Fatalf("Unexpected duplicate session ID event") + } + + handshakeTunnel(t1, false) + + handshakeTunnel(t2, true) + + t1.Close(true) + t2.Close(true) + + // Test: 100 concurrent clients, all with the same session ID. + // + // This should be enough concurrent clients to trigger both the "stopping" + // and "aborting" duplicate session ID cases. + + tunnels := make([]*psiphon.Tunnel, numConcurrentClients) + + waitGroup := new(sync.WaitGroup) + for i := 0; i < numConcurrentClients; i++ { + waitGroup.Add(1) + go func(i int) { + defer waitGroup.Done() + tunnels[i] = dialTunnel(ctx) + }(i) + } + waitGroup.Wait() + + for _, t := range tunnels { + t.Close(true) + } + + receivedEvents := make(map[string]int) + for i := 0; i < numConcurrentClients-1; i++ { + receivedEvents[<-duplicateSessionIDEvents] += 1 + } + + if receivedEvents[stoppingEvent] < 1 { + t.Fatalf("No stopping events received") + } + + if receivedEvents[abortingEvent] < 1 { + t.Fatalf("No aborting events received") + } +} From 76fbe22f06636bff4f3edc84283f93469d624cba Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Tue, 30 Jul 2019 14:04:11 -0400 Subject: [PATCH 23/23] Add x86 and x86_64 native library for Android. --- .../PsiphonTunnel/libs/x86/libtun2socks.so | Bin 0 -> 182592 bytes .../PsiphonTunnel/libs/x86_64/libtun2socks.so | Bin 0 -> 196656 bytes MobileLibrary/Android/make.bash | 5 ++++- 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100755 MobileLibrary/Android/PsiphonTunnel/libs/x86/libtun2socks.so create mode 100755 MobileLibrary/Android/PsiphonTunnel/libs/x86_64/libtun2socks.so diff --git a/MobileLibrary/Android/PsiphonTunnel/libs/x86/libtun2socks.so b/MobileLibrary/Android/PsiphonTunnel/libs/x86/libtun2socks.so new file mode 100755 index 0000000000000000000000000000000000000000..563d34eb4e364abb75084eaff1adf98eae3ca513 GIT binary patch literal 182592 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

jSoL3$?|0S8OJT2XQ$#g06p97cS zm`9!&-=>~0r0u7u@e%!BY2weXP)+P~Is;GZPC>8o1dq@R4x9I9-u*|zj)j`uKrLdm;EqMw) ziC|UV9Q>IXJl(%Z*Exd?hnsYrJn#2)&ZesH9`+bEbK`rgBv78(v4km={{0&$Whs8G zuX_r{NF|~7rI%c-e}W_uzmGhG`z1WWsF1W`za*_HP7N48u)r<-W|MUV=@9Y^+L1|C z*%iUAE45l?lE^VqDXD`JP1MyUiZ2nP`aO4jJ``D=%`zfOijg#v)Jii}^d4=HZErPw z9m2B-*zLO86ezqz!ud_ZmGbP}V%`1YKBR|Z6JD1r*IetiBoa>7&Cw(u_@2?<8Gee~ zV46OkdtqFLv{lbdd4^Sw(VB&J&57ISTl%=ZJWcN({1jH66wS0_n3N{x=%SZ>T`lm< z@LHx9wTrPX5gxEe$rIFxvX6gBT{Cj2RQfiT+QzHe52p5#z$~Oafw1}9U&j3;Xce>= zTDw6WY{mc1{KovAZ1c)Az7B`4_%7H=8{c=QrF;Khq+92vi-g;VANQeKZmK2dm6URD zN!KfGktIjZtYq)~N*;Ksetd;ZBk63m&e!0K<0*%?iLv(Dto%0|7Z<$siS_W^l@^g=I0mV2&{< z4+RP({HcJ<1WqR0=Gr#}KBH-|e{qfrkL%S6hJg^C zw1#b!VfBF8tfCQT#}Yohqj9KLCSrF6+ejj z4wIreO*UrL5G?;-*bt=UG6ZGK$`E{oHy@Qlsg7m$m}}Nv#=Z~m7PB`SKLek zji|@>iKv$rGHO`VAIHFpO-7OgovVW~CFlf#u*$L!PG8rLm@{^Aa$sPcD~3ooU0)uN z`1_T;IZ$!@x4DYrTQD|jM86*mbO?FMbuV21ANlG%Q zN8A<(#xknPaEVDMHE6db&vjc02v)VtVSjiA8@xBUe$IGqRgJhjzD_Z-C~y0PYQig) z2`@i6;Z4d_b?OOEnWSPp;Z4DCjg zmEg&y7}x_k`0sg{NQ-4WP)A~3lx%BXB%7Q8@pZqaqehsuTS+4E^13nA%6uy}Oy*l` zSe}%U@sds=r;4Mc`Kl7Va^Uf5%nJi*IHmcw#&FMI8drY7UF1dsn_RyDekX}P0xeTT z(te?0sEV~KGKChF#MK%!WxijX>W9dfMyRn9WbAV@&`ow@H`49cK1`=@d@`R1VL)G+ zn9oi6bbIz3>5T|pdO<{R&8B4G>9*`gBp&z){y}UDX~mAUh4PZgkD52!rZ!9R`y%10 zd&M~{U?rwxprxz&mwu4SjjMPV3x%Ym>*v7$OW9MB<)^!ehf%)!)KfpKN%)zg&?UN& z?l5L>mYAaB>EvPilWKf_oly2aW~KTQ%3-)gyA}KKCju1A&{yupFn{8ghZEuY6X)3# zUYpY%bjNJurTv1EWP8&6g7YwV`*jA6NOJ~yWZnIhe!wW|L#&bIS+RWf|I>yQ@|I!s zYd*aLH^WAh>nzNAo?Pl=RgFqQB4ON%KxMd`Pc+td3F?^U5vbAhsEYP=KS1)d(S(z< zo_h7<bU7z=HG{ETd(2oD4&%YWGrwL! z*vc(M7boXerOUC;~G{pO9MuuZkAQ#HN@0j|O@rfMYez1k%1B zi5?1Um$0YwviqsPvx4M#lo&$!FB(~l<%EYa7;M=nq2E4C4>n(?{8u;Op;5lhd({o6 z**8jorL0v7e=LS5$2=pHF(CbsX^Xqh1!h%$*r*giof5?Q8Ft_O@$l=+jQ{iWa zx`2_pTJ2!y3DY@T7K+>S$bAS7^qlbMsoV-T(hZkKm4W!TxzyHv2dgaQ z&S?KdX7B~F{`JdURlV|p563I(QUIw1;drUv7pFtw#Sc*5Pa_uR8n41%ocf2@z&e3R5ok{kUneqzE zl$`h*3@WYXrG+F>Vw1Eu+(LA=N#hS&MLm4By!l9tUowMdVjAL0r9hqsaPqA*D>_xZ z3v2p5?v*&Bcl5J+7VvBn6J?i{IpNP3il}s!SR`2GDbRe$v5&1dCv0I= zhew7a@*Rmp{lw>2{YThXsY0}O_27@RSIyCM;u#cb(ew-QB%jvM0R03&i;@05NO2!8 zOZK;Zws3+xqw4>Bf6rJ}{Sh_LmB7FqRKOD<;V+_YRXeUvRIA!;bi;wsaBtag`Q5-U zSh;1P=D?NTuhoP=nHRi6`_`+;A{t#KbB8K0+@^=mi@wi2gM z+9`*lGfk?)zWf~ht#QP-hqHVwX zPRY42hDg5R8N1?v_afEnCdv0ng#QVO{~XP~oChkTe@=AHqZZxEs;87~I24BP@{f@R zgc3SUEaT8TF^5XTJ+UV@!ZPc?LqY?j;PlkD#4Z|sSxdN_#x`Tl+-yu#Mjz*LI(4To zbw7Q*a!a^G3H4cA57{1=6ItT559DUPJxz|RU1m?qgjCtnvfSs7+c)hw!11nnCC1?; z_B6t84TU#(!h65d{+^uAoWmTwa$kLY{b=6}mvA5P{%}+OC>u3;1-|WR@?@nG)tB?N zIm*;Wrzu^uUmx(x{2boq34c-S>y&Sm(S13QnM1a&^7>a|YdxVq%DYV29nLg=q@d5f z&WcRUwA*E0IJT1t#0fiu(nYeVbGt(-lE~>vN%9fBIWmcwgx)qu#H@+EkKp7nMcbPr z;r=JEJrpd3u}h7}V=v-(BcEIWdbHfb3PjqtR`@4oSRbqL^cD{b9bThw1~>3#^=cXV zBnnWU@RTpqF1Q{I$paRcU^RqQEmPI2oYIHLDK1S*@e@+S^R@U5M`p2+kj-*QA}e4@$r_Ic{tMIg#1ojdt^AQZXOoAc z+{yWXkvA4aUAg6;$!0z(;SF-m7_rNW-zEaiHv(4nPvl$519{{-MjnutD)~w}Oe?;^7ML6o>RZ684bt`GuY5FnIrl~ilNn%s@BxLQKU{6m8{} z`MCCUV#5Bu%{Uurf3>+~4wH@XEM??tM-V^Yg2RK?}X z!xzfQQROfbCksf(L-{|95&WM?X8d6+9C2)fmkL%HJ)4=AM%(3VxAe;`?|R`ql>6;q zwsW4G4-b7?YMJ#IgK)E5ktru^c%@-peq@@e{>}!PF-=wPYP51@RDZdKH(TW%=$#$A zQgJg~a}$G$JZTISj3EgEFb7*w{9m}`d~uoT%<>toBJ1zxNc(bBiF+odw2!volH}Wq zd4$8vyM<=)LP|JW#-4szRaOCF4@8EtV1t2jUW0SOIiyjMiDg`YM1GUVXsH@8(b6*0 zS*ebr=12N}gX(|Hj{CeUyiLjKTuPDsyR)HgXFsYom{QuS4)(ZMh5_$>I8(~#h?6+h ze5f;JhV4<3#$IcQC-o)WKETgj}79W5iQp1h2mV&4e4{+yk|!R<8O@2;U$>zJUbZRSzxj~YJc)u zss%^u7U=aPW2qw7SuW=+=|b_bI9|Q6U2Zt|~5&qLC->sX*zQLRJp6$-eJkMrc z_1oRYIdjkUqKX`L%0u5T+I!tXrl8qTvw2iHUijiIpUmrc%Hb_4Ex4}5DIJg9{+hEq z)2S%5rxiw~<=FF-M*O5s^j;6&X;nre^je(n3cyh8L`oZ2=k9xC#pD4po4NxI@fF!o z{bsaXkrQttp|-k=xYB%knme}6RduMb6>lX`kAD8KUV8MvBGsct9^(;)Q;{cv(DKN% zKX*!V$8L>eW#EWHJ~Hr}(xS?;&99*!*a zc=p*9c}0@tF#G-8JI8JwRgpchBCz}nvS!BK!-bl-JTG*P5mTA87db6Jsm*qTR%=g8 zjy;s-s9X>0TG<@{$R^>JbcUJE^!QZr z``e=;zv#D82eY={TLpKI%A@7eTWMwsOZ4C?pw zJzK+DJuCOpQ7e3%+ffNj!O#j8IQC{fgR^@tUyr!?Hw610j(2_N>;9SCc5dSDN+dJ% z9p4QR?jzn`@mFnT{NXo@C-nq-5a?F(8ju#J-4~lo1q18d z=k~_IE`a0s1vJKl&yHRDTM_p6&QZcP_FgRwP9o_Dd$0E+N>!dyb)G?|IOtR~6!k4T zD_Yt>(e93AIb26d%WRC-kK+OeCRnN3Vro=p)J6c-01{d;_tG1=hM z^!Q;i-+0P{>U)O>Ty0cFi-RIxySzbS?eeDhEEuWpk@@G2N2G;I&sHrQ6la`VGXLUU$NIBO=EO|36icff12P7~K+CTFbY$ zr~;|zi8E8ZvZv+eZh0)0{jE3Yhm~6%AFtRq^OY*6hjQ2)4sTQZTo00|>skpleu_TN zo@%dU{!`^Oy5-3P&#S$NE#C&4FCfQ+=^Q=yDJ6~S|rb6Bj)L;1t_sw}LQ zNnB*r8X1tw*r~+C5jq1!;x;pu!%`GyDH|yiC`+a{G4y#n^`tj9)+r@Y(+p~&;qs=C zexG)v{2%|d$m`B=DdR&|jWCX9fgdR?7ZpCsl(>)ck6$i-C69%w#A&+3SCK_A`yS2` zzuAw2wtYmvg1xgX!pxJSKHzpubS}a`VUM{zDOUO2hCiz;W zdB=FMvE|4!R9Or!ZGiUOiqJ4{Z zjvcfo?>T0lO@KtTzeh>gN^Yf04WamGD$)ED;Vb)A$p`G>7Za$2!du%gl&jt;M*cMG z6A`g=JMsU`_xHM_iSh})+vUc-Rke60?=Idb4{q$675>y-Cn!_^bMi&LA9REGCRKPd zUfFFprU84UB%prvX+Aw(&W^B^31)-3th-6-G#wgL9jwJ~78l4tvNc zAEQ%Gv`kX5y(?fJo2si8|j#K3-R} zPP*5|L=v z#NNWKQ=gvWdsh@F7B+925|l^>lp_*~|3wOB{=ZFRL%B#k`RTeZE&MuD_?c3wDoa0g zluy^)F4e^y!?0QZn(@FmErxS(tV*Er{krSbpriSh&~E2J=?%VOcTjvWkoSoP9o0d6 znd}p1gYf7)qBzAmxgWHfPfGg<)wg`pZXbwG*4>~-t@*57cq{72m+jQZmd^}5E0tlw zNV(BX`BFH_2*Z&r1$Q(>QCH9s15&3IBA%FS$ z-LUj3ESX-lz_-3z1m#=*gplqVzCXaLVp3onnYE)3U7&QHfJjLHYr|8@MzLVE2 z%@>KfU&}KyN662(%C&!!>?IlgQB|juZ=}B?bmhdyg^$$l=Y_Y?B=ZS9autBPK2%@P zyIzT0KBPC%R^PwSO^H8+g0cSA-_yGQ;M!p<99$H|eG;bQ2Y$}?^h6^Q>(jaO_@3VE z*iU~ZK0()55XF+_O@*ln- zh+Jo~dhWJe;03u(IX+hyKmLw(vG=7HRVnX*}sz(+D}Vs<;mU! zl6h*-xh_Qa%b~CwE%(-t`VxtAWw7Xr)-g*KPQ;40RVU&&r?)gHOD5U(%1R~>!mde?<#P?eA_h=t8 z+SNgf#5(01K=XCVca`W)<76rSRO%bpiGC*fFintMkD-o=qXzg8hUE7Z9O?1M=1-0< zd^vgJN7K3c=|N{!sHm^?uqC7M zvT_!WmcF<9L}u}SqT8xJ!@Wv{-UFC#xe2(aCu_FrZ1k5V*_= zZ&Igboyofx(MZi3JDKmC%2-TUVTj#>iN!yZaI;;KrmyUO-zSZk{x#JYnSS$(%udn; zj@Oa(nDNZfI%HGK1LgCKJMZ`-d}Fo6{V*OM z8{%jsGO*cETCMgU7IVf@NdQxo8L7~2f@~YAC)K&J@#Wa0)v_A_2aE<{R6?1R3g7(vS$5Nu`t+Im=;%j^TKiJui^7 zkFNe~vFGItyqBUMYXAQyBGEmksOIbam-C92_}SlGlH=>VkpjaTJEYw9?>MDPor-1H zfthjujk}$pi|h=;;Tkw(nH1g@uvs4c5M;ALyir2U;v6j29REI6vl~&E(%K(^Efz+< z!~RbT46MVxn57&Xv|q11IDH-^%EyoSskMkSBYnSK^{>BZil29w`I^)gS^uw*<{hJ( z_W=p=Pyk-6sbb*r37X5IrR;jp#yuIKvEeeD0qh*4>{E*JHC8cC(`Uy55VNn*J#H|?$fF2_(n+&8F(*1 zKR`nHQ_lFQy|JVCZ|}^LqhXPS!r$H*BG@vm@``IQ4{A?BeJ|t^#a)r+&g}1S&RZ3H zC1lLdHdRV z#vvT}ynWJLsQs5bZkV-J2oi+L)O&C``AUu5Iwno4<0gVuEG72(wk6oJUEcS-CvXig&)s`zwxmfX+whOA+ z6j7qCS?=spBK@!&o^pA%W!Q=zgn3SzZ^+|~|C}bc{S9VFvcH|HzC$Ydvg>XU_J$Ku z>}T@%Fo_Ep92J?|jMo##pBM~$@Md+M-0-1o_h~T?I}m$?cjdR$&EdnP<(s)#=H8_l zHgBD?DV1?2N>-X@Z&uHfPjt?)D+1D0%kxE?CDRjKr6yQcZ8`s_xII{NtL9JhU8|Sx zP|KE)^QZEq)a2$V&v7SCGk$3Pn~0MA@8gZV>c%a$oSp*tyAB1k#y&Tyo2k{ZD^gVH z0sPsdDkbeI+Izr54E5Qu>s7G}OtIl@%cNP67>#B;&wW+XAHAk{PUfeb@6u;^;iZKK zhK?1j6uZIc4qJ{f1Vp2hAHX*=0vYXpbk#PIVBj6o(aH7m?AUHZjs45j_797f_`cN( zl>UGCzR(%BC9J`he^0xJ27I+8&?>I{#}s>@zNf91Tj!_-9HkqOc*4S(tJpc3$^2xB z7f&U2-tB7V_j~q%8%1oQH0o`_z>*Bj4pW)+@s%QG`zK zri+AM)OI3~`iG<*h^YDI1~ifL&&Mfw%h|{|%r@mL?o+;xBcCrxtxUFh+`{D%uow{O z?n!E*=!uk0h&X+JX5OkOh%8@5gY%6^kPk(&qn{~?Y2SMa;_`7P}qgg+%g7!Pl0uCG&Ked{YY$2`8f+%sCg0x`vDEN}Yy1$&HEce|9$mnoTDfH` zpXs3cl|SHcaGwv-cK(r?c=IN7rTBV>5}ULeZXfYJ!u;X&?xR8@8{ZH?4#vX!V5_w7 z5W?bT(ep+O$#xu)R^M48>N|?ON}kfy6DVUpb&6M*sMDwGl=j3ois;$D{10rt&BJ`y z6xTp)1kIiIjC}4xIVo#yk&fy(+6;63YMhw50vrK+l#q{ps(;37Z4gdgd+FUuQN1|&x~)kLLGzMBqJgOt&60AJhU ze)*E{p3%O}Gq?@!IRt*%FG*_D9cdcXzelM|#{?c=yh{#AseQn#MZ?F?dQ!SBqT^q8`y~>7o_J;! zw+*Sr{xOnDkD_f&H_Lb!Pml9o#l#LHLX6pHrWc_bpHrj7eK|`8{77->dEU$^k?^84 zzNYKS_zz!1R7h-;uS+)M>ut5%w zhZ&%fEY1r7uHB1xJ2v%ac=#$mJ0T$(6Tl~zh)&i&H?97Ysh@NA{C|8a_vyK?pE8}f z{>b#9m3wuFtb<&mv&=tAtPXQP?B`?^!!wo&oSEadc|4KtX2=huRByLw8^^KDL${Ms17 zv-vnp;9<+v0;@maNTC`R%j`BinowHu>4e@wgQrKA;h9LFbt~P*@s6vMxr%Zn6SI_$ zRV&{@43hmvyI`njNPAJu5BE*{NVxWIW zzia_9@c%C}0JGA&1e#D{q`Pl$;&a|k$WCVMZc9QgdWPn0|6V6P46;KPBkJz1J59%o z*innj8qWjfiw^sR9S_==g4zO?VQh2iaH}WywnQhyN^iT?i#4ZXb$Waau}QtL>EfDH zZ-x_JnfVNbZCqAmW@O;?gxs?^K;x@`%iP+uRn?{rrlvzK;6U9{Ae?` zL!`1-=lOBwSb<7HjFXZhOQxj%{`1@y@FH8oou>R|Q|l3@{K^$n7Uz%ckD2e6z&G+g zU?Bu9_ZD(Iv{EB!9i&8I6oqy`;|wi=gm7s#o<&`P6iLdJ^exKD(>_Rg6eC!`{ZNNl zu_+syGmI-?R8|8u%dcaHknQkruIe zPRDk^i*4x;*$V5t%wrM37Z;58esO$v{HWqGWm}l)GYNF!6rUH|6Vs{FSp@{`a6uk< z7|DE^CV@DGbp%g%RHt16y?%)YVVsPgKiV zc}9S8I&fE)dqhP|x9RG8zc77b_nTg1HUTU;A5rt4^5_{V{x1yxoeuUPwEHTjr>Shp zl(^l)0JchOb4|aqo0&S`J}AAsEZ8RUfYt}!r_Lo6v`-d=UE>bE+8;)W)mkZoWFwy!&1_8xl1!D-cgTlM zQir4sMQsTMC2>sRSCUD+2jspX>3Dv0{FR6AcNzLK%QSQ@4N>MTi1k?N9LKlgd#(3! zdii`$5>-8m!b((=tVD&gK3kch5qWAXbca@CZd_@QEuaqCPY^{<-qsJ5AXu{ixX}JQ zZ5U2BD!qNyZ8V?*cD-NKX4d;_0?3EJ|9`RGx3vP__xWSst3(n5@we`~7JqyHkNA7Y zrjo(m`_C@mZ}9Rdp@Zfn5HoI9iH|_yjo&d-ksse-`vtJi4J^2}wGR$5vk~k^nPt&R zjluFsn#=iSicN0Adl`o%tcTjA0y=pLYwssa05WHc!3 zchTSDO@H?vW%~PPux1<>G(NySoj4Nl>kV5kGM#8Sy>@3pHV&N}!or|H!CX3!AMdvM zolYPbAkR`g`<-Ql_6`1ilXXP?d)tGze78yrdSP^|(^WrI*gw*aeu=^A$6rAAvnmL? zC_Ea^S!)Z3eJV{1*AdUz+84d8H;$^_=5fQp3Mwvqw02<5P_5l{!>2gPZDjQ>&Ie=H z`5mv!8(b(6=qc6DdYrb(3wF!hvDYz7GhlzYxgxQ`p-0{y^?;CvuGUc?Gnqd@J;c9) z^2EPlPNt2F@Be}R;2ko~cgJX$II<+pW?Bt%NV}W<2hWOd^nk_1aIdT4!pzK;g9h&c z@!NOD>T8tUm#`Cm+Xrw8q2uB?JF^fz_d$2OJuT7LuRb^Z1K(RPA96y;vy z{0An3^B+p=cmU3aMyXN=uVrvR0ZlZcbIJ10((cX=%((PMn3V}1^7hwu*UYu1{V75FneY6?@YDc&hgbAHQTzEuXR&mM{V((V(8Bjm5B&b{ZeI1z z-*00{F@91iX+AT*=YYiiVG0;bUtyRh9{#=2e@qP>wuYU)!BC{AQSf@s1WeS`?8yza zc)_WIn`)aP$z8QArO9`AwuhBB!n_;AaeARCVc}fGts;(geDuj^MBXaleQv8+U+096=M{bo{j2++@Ahwe2`c&O<&M*aZs1LEU)nGp0pOd^yS z$dBuQ+$8rP@;g{pDmxFSo^GV&lBA9O}(Xe ziU-g>z5BNhN^m-a>ct^}{2wYZxUT-_;&^ZUuuxG4vB-zP^+}1cPZ0i5l>31p$L`7k zQ9B;=U{QWNQTxhGEXN!86JPlxkS%)RV*X^2k^5FYIbQeL#LG_7eQ$l3>!R$Jxlubv zTwmj|Fy96re+HVgt-Yhq_+-3A-^Vh>aq{Tf!?$q_GsT7XoYNuY$?0t1Am=bi(@K)( zI#2ZwNZYGqX8Y1Nm(}ibZvVB)bTteOt&fMM0FH*CMhH6uuj0(%)A(OgNyxcFrhJ+) zvgl1OI9=Bcjo0p2`g`i;^u`R7KlgC|ddhpE8T{G%T71IIL!A{1G(PuN;(vxQ6y0_N z7=ES&7@o-=%Z_QoOp)n=IgH)?36uwwKJ7jNzU8{@{NHTm z9|4f+U+|G}kvJy7@tZU|sZH=Z=XPbM(N504GVR1ga96Xz{jhlH)zW|6sVdWzb-LEM z-6iQ6$GUHR;J*F=p}8#64DCu-byDwAD()?fgfjdc>UJO7E7N)rCD%_;#WD(?$;UaaYb{RjY9E`2x7*o@Y4NlkAb@insc9n+K zyFKV%$EsoXjSrrDhy5~Iq_yg2YqzHF`G9-plHKZ2XeW-pcM!`?e%#3{-0I!!Tf7&Y zyYJWZ9n5_Of4Fy@u0O`T#Y3zAm|k4gzTGZx4t{s;7WKwmnoeoZ?=8`woz!1>s=l;A z_jGl1URGjT$E+^)pyF*G=8jr&|6}Tz>0a)8g@Kl-vi~rZ34*_*x?oMy3l`Vnp@Hm` z>6lz*TR1e3+ejFpuw#oum7@!hPBee<8ni&N$NAc{>3%?dA{X zmAjwiyWF}w*$zoDe(3|F+JRNl@NVR%@S1x=irka+**$6ZWuf661$w0QRRP-L|40CX z)|YHutgdMOu;K=G#B?`L-`-^2SJ65E%p?8Y|jAK0z))in|8lW1D2SS9tj{@8Dr)R z{=_HD9J=I(X}3+CBS+FS{Tj!Qyu6R?z&Hq%1@vJ!+hGX3d)Hci2>Qsa`>41J?3NeR!iB)==a&M&FNsIF1+;PoScAP4)*?BP$^{kbN0eV#E5kT+%}1(9?21@u&rf(xUQ+6l^8 z25BKuK1J?9$Ymp_%Ls2LQ-w*$J;MIrJf8b(P%YBiFk7&3sFNC`&-?UbvOeX>BS2CW ze!#EOHEXETmE=FM3{c|u=tOjch-CFfr)!eAtgPmiuZPA*W7UuoJxi<7nYy#&l5ok4 zuyE&DEDvF`2?pUgpSd>0Ly2g4oIfMt0KeS1;|Hd_>D*74G1M_ZMmG%guPY40lxn{~ zOaJqPG2NnkK)8deuFZzf#JnN@>1YWrGHLMH+3Z+QI}5AFs&KK{YL?6 zPag?t=Uxxg8u*iT%lQk=7W7j)erB2Rzu!N8Rxm?1YtD$q+)vVkNwnj-GCm;|S^CAA zEesAL)S%o&jPwc|CpFT%%?uIF>00B&cHriqQEH5QTb{?QH|Po=uJF$ZZHrg$Nd8xx zz~9PblMxo}C|B=^ z<^DtF&*1OdU=s0Py94}1Khx5sS5uv?Yv3Ncg?*9_yVi$x5$jXQsjDoc{$a#dR=>!~ zy&*?FR8-3iFE*foAs1n z1(*C6)5p))J_^YYXc9-YUQlH65(n7AegLd9?zTkw5?LYB_ZE`1UlPsIS7})$>QP{2 zsb(^ddk5%&*Nc#0T3rop_8EW`_|cO^_440c!;)xQ`(v_+`;U*OkkjSvqnh;fW$0i! zYG`#)H#O}i?A1TUAI@A4&3$U6e_0hcaeTbCp+5Ou+|akhQuxHeJhhE`PW8ZNF)7g zOT{;}=@1~4SszSFrGF*`PIZ@ui;|<<<&mP~3GVXJqGY-7Vf8*hr@1ymjjycTk-W=a z9ERjv2!=ciS5i7Um}aT{CKbcPiod!y zi`-5TZ&oP|Z{DmjaE)_PV)edTr`pQAu{d93-rHu!5im{8ix)Ufq(oLZtt5K% zIeQej)tO(T!ibx-FQmX~{`X~f^Vgro>BPy_+&9zic#s@C#S;DQZRYCZZ5Tg6W6wOq zpO28AMgq0AwR_PP4Sq-;RSa0OOcL!Gpujq)_a8P`+{ylc9R4babg2RyN9U$$p8V^$ zNlYAnaS`#-jdf7Z?IP#0=cF4OKpqLF(1eQ23D+_NE?C4HHL+%fEh1BoyDmH-0ayBw znq(I0>p+;Iq=*X%0gY|NbY?mo0#K-f^%BGeWA$ioIwu!*G)y`a?zdzQfqPI#aNKln zy;<75^|B5X<$g+5odQJvd?bio`V}BLhd%@HS^Cs^M%cFY0rp-QpXF~e4Jgmi+RAIx z#Q-F8J`-Y9_2GJlzt3cxKkK~7budA&XmUNj4g4~=*reXc;{=V4$& zzslfgaqUhg)lT)kUk|F$s}M`GxvF+I;hnem4OMJ=T)c1KW~GW`v8Q|^4RwlZu~xXXI_6g#-CQ@O(ByGc6z4ZH^Fnc z{T1iF3(q~*P47vanPv@)dBd)MTi z4f<{PV=uFc{WBM=CvX+((_E+PhUxyzv*T?y&t32d|Jr8DA=f>&03T*22A3qYTBde= zOL^S8K}kje!Sj(*1sE?=y^q|i74hDNnJg*2Me-1@w(qNVuR)`M`XBuw^>_29A6{bvc%5$A8#aL2rUQtAmU;L%A^fy;e9a^;a&CwT6?b&t|hxe>Fl^(KZ zU|b3@3f8j&#hCy=eq>aLO#ovw@Lunp5Pmf&oL#4U*T>?`>e8CZRZ?ZjFg^Ze^^uW_N%Win?_T_R5O zie$hUbK|v*2`7fla${&id^39%(D&ZQRDparjZqNO&JCRkWu z>6$RIzD>47>v&K`=LTo5plyqa%6kU0qbO%H^Ub^hJr56GkK%hb$$W@VwlX%8#Ek?*wM$6XL*Fn|w8i-0)O~wIvciK0Y!TylHT675AMSEge z%!>0u5n{f7PHtEGuU=|6wm{Q23AAfaY$45bFE^l8fofI zu~S!`eT?Vm2U3)r)K%PQ-jX})wAqD)<4;hgz2q@W%MeDbM~{9|1|roJxSQ!=nJt&49MU(= zFsvV=^I^j3LT zVdH+{+iA^M#8=Su;Pqktmq!1bY+5|cwrKrtR!9->pZpE$7x4(!?l!-FHzHV?)<_Wsd`uU>d z1Kzv2UyA94|2Uh&BlI7{LgH4?svouFeCdi7tuF5@(SXY51zFDzayHY9ajxPfj|ais1IU?1ejz-p22IxT6qvQYN*vjLRALP)sLHbOF@B@aNpdX@ zqnTGkSXXHd*A<8SZ&)scrd}S+EZWJdZx}AN#Xgy1o){TCcrt}22(#x%yf|rwB-X?+ zS{ERo6_5yb+R9W|p;LSRgpYW=**P>wyl3YOBUWkC43RO$FEYpsafPrz&V5;Wh6!a( zvp*YF5JMz0f}O|Q-A4XfHI{nJSm^IChN6Dlhj2<-IQIo)0BXV>yZ1J8_3@I%v6n+c zPU25MC<^|ocfv&R|9iy%-{{*KnFtHL$;=T&n{V`aLl-jtfV8*uOrW^mW<|V`HcgIa z{;oCa=Uh|eNL%F#fk7f6tCSJwSJMmZ5o?^3{PDb(YPuP8>0@KLdG8nT-rMiyqNv{6 ziR}qmD+|=75$hUG?c-{01ul0D3kRWFHe74|0%oq+Z^t5%nG38ScBS6!tyJMPw0I4R zJ(GCT%A@NVE-dQ3eYNWU%XI_^t-D>KA_b=gYq_K0B3}WWectUNV2peWr!o$(ds%+r z?Ug5RVw%57AYcZ{{GpiFN=G+MJ&Zp3^;+)7t5c(!r`B$~;a!#XHs}6sS0y-LJb)6w zSu^|H%L3T6zr~Y)+K7avZlyoAJ?016V07Oy{nGXUFr>0WBgZx1vD*-B~NYFeUS%z7_zoDl5HbSL=b|zo`5z5ne z3Gz#Te)cniUoU|`#DCdO48Lh5+(_F<ACpFLbhM*RfIf=WM; zZhksmyVZ$p^*DD1))xqMEGs#YV z&B~`wkK6#GU&4a`+lDTz4qWxj6Y^E##oHKF**w@ zdslSuqa_++VFKp7gp0h(L{>0l!9Ft?G@+@v1dUUawHoT?b_qbM^UO)MqBs;bqUFY; zjkI|SGMOI9&tl3zxlykA1LVdt^K$VX70%1WD2`b=Iv%1hXGlkC~&w8olQ!{C`D zp}(-821pQQUvFW0vP`@GN=LrP{9u_WQ%n!pB`~0JuoN-U9OxP=%l=R+wg}^D_CBo( zLoeB)gCVrH>y=Kawe}Gd0ZqF&6pQOyi|A}`wumw-g^vm{x7+XdBj)ALf8m+rKO;(> z!;RgbV?9c!e04Rc+noXrV7)H2n7bmVr z-`54dz`YuO(b|p9C7YRZw&}Mp;Z}O14S`_Bi)OiBAy@n4EIH%g);6>nr_E#XZjdx& zcPOmhiUZ4@`lkBiLtZA;o%km8Hu(=2PQE?q`K!OhFtieHq5HWz<13N=oujdTh?j?L!WZnNS z8%h00w3R!mHV!>wO-DvKT`TU?Q&KRqB{x^ja@a&=1I0ug+e8)O9y%BOY=Qc=!PF-c z(%{61bn`(Y{JRH=mng1%p<%v^X1w7+p7(6g~U+E!F$Ximk>O)#LXIzlRJ1e$`RI*jv#OpD7 z%`e6wz-;FLasm=Gs>mq%U!Qfr>3}>59&<3>zh=lS1^6~1ln3)o72?A?V0Vz19w+so zz-A}O>Doch$AvQFCe}wP%`ekX_&C#PKU~L%v4kmgDW4dsRrfq-$Jz|@Oa9k5M}9C% z%*`0*jv~S6u4t<&3Uq$j)NRRwDf`g0!uRRsn1}nA+g+decQ~15?hEQ7>rP&o4>1x5 zn3DFV97YHwipEQnl7Eogx5hdv?xzGWi3*~`F@ks1`-F>=*B}};f{B2{No^GyPG~`| z*O3D$S6cpF8GBB0>!H19I|=kR(>*q|VXQGBVR+za^}39H+^&1)Z)$G&Vqf z^#{j8OC##eqv~;Q?p@p7Kq`^l|33w`ou^C|h}lJmR#twn)mwIh5u+8BvoJ(Q7^+oy zcK;q+VHElMhS$ZHo)j%ABD;8C?Z!*X?0l+6XK3^gwAFC1g8a4@jUpIy<_A=nyG#Do zfNWF=8}Z-@DTrnCydi4c$y%0wIj`#CA%1x+p5%?^?|57wU9ic5IhT&UcXQZBBJ#6K}LI+tLm(rlP_ z)~;V#fKJ;+FzBlRo-kjAe6jSPV8T+fip~In79SH=0iS3d37f(=o#KZKF%>8@&KsUJ z6iGDLP^IjBw0Q_~X#eYe@WlN?fpad0bLMWg_+jLb0%Bx~MLF`a$-7S)Kh`CTl2>c6$l}={-l{+Luj)YhT5mwEN>jzS0K9 zuMd6FnRXZ6n3o4sGlvJb-ztpLJo$P*XL3@P8AzlKsU?ehGL8N6kczT0j-V{?FxzW} zP{Ttzk1}*uZiXy@fzQ#`}U~n)WVF)X#GBbDskmf?G;C&U^=5%h0*De_9+QnOQ9UI~(=%iK-TBp*(Q3p$wsQj);mmOCr>fu)D%eAS7rd1#`R+oPPoSFoTynmY z@?dxA?tEsVw!&UA! zt8GJKB#;Xnv<&|M0Y~K?L*F$AbI{^zY4`pF6a6n119Pngci9J-$AlQ-W@<3BN%pJ( zFU&I)&;5JaeXW24UpNv*c3%KS{+>T+_bre>cvz<{uzA^{-_^*MQkJS3H2slh%=Ev` z^pEwwY51L7kk1IN|1|Pr4DkA^E(^gLa7n{k9@AY`S zJ=uz$9agU~ZQGNMYPQh0beuEkRTV3K43kDS!PfVTEI`zrwolVD%gM`*Jw`@**k=W{ z0)EPnYZwwo27{1bZ5X*wv`oQF$xAcKE&!1zEOd=~6U+FBLggwX-%1LW@p~#2MW`su zy^_=>sxm)WNHrLSlz+@vEUY4sxn)3wxnHf!JbsaO;*7B%_e$K_+rL?F#=q8#KLrC4 zb$4$XhrxY?Bz0F?Xtfb1HI_T4YhuFb`i)TB>Aa@Ne@s&suWd6AV(a!k1Dm0cR^J$> zJteWXO-Rc-}%7p^i_AwA#L!8tbDu-hzsuq%2$Mop+-X^OvE!2f{rt7>- zf%dbA7-0$3U9%#iFI`Mf%|aqc#yGcsSpp`Xd(Xn(Mj5&dqz&>Q+{b%%L`*dYsD7dQ zX4q-JL9OPO)JbMzW)hY%K31RZmSj0nGUgIp@sy3!VtnQdO~-p~mcdQ1Y@tx?x-y~K zLZO z(FT#`g`qW=(c<1E!@QZZ_cRU-IqlaoUh0pssXB-LuHn`g46hfbm;YgMl)or~dUHJP z=`!+JchS@(3@2|ljLj2KdsJTlIdTdZ0PYv+)`v%O1pfl}98I3W(tKMDZpw#?ff%=A=1tjCKmfY9m7N}0fgbTaB0*iute zA92pIKzspb2n+B!ZuyU)9kt6_oQ_sn)w_D4zl1xQG}BPc7QWK(oo}oOZFW+p3GYA; z8{KRrA}}y2B>D{R2KIHTp&>zE4+MQx&B98dL6!Om+4C<8^W=JOGepRYjth~Z>umou zGWym$fzme57T<{&jq(NqlB$AaBbhOEwdR)|+9meCsMjv8nf;5){p|;0O0gzym;3r{ z9TS@%q|5R?z_LTiak>3hl4&%7aIs4#f(X`veE|eoz#z26zBW0%!kKrk3th39&I zBEJTM;SJh-|0uI68F~1meVVAf>_c|biNs18yYP3i#SN`F2KrA64k!a3m0sw@=4X$# z^<+xOp^&{yH-?|)?ZcUizQXhN!gD^2vQvdy2MQ6Q#v?2xp5+bQnT5EUL;SE=hl|a$ ze@r*blGTj!@dDGA$>mP_1;7}KIHr^AXSrm2-tv}g3#|(}eR@R9{6?UZHez?qdfC3@ z52rf{5uPKgq{`X;rT;4g>H)dgcZ=2Coi?UmJhCE{J-%`M=o+|_eIiAMwmYprIK5{Aqqeyjo##5BuS7k5YO+de~ zCe=b1-DQaD{W9ModnZPPkT{RK2Y%?Z&z49JntQu|SG#;xvtO0`xdiM>Gz$6aEpn{G zkV!+6j4gDb$88yBovo9Flu5bHJce*gj*OnT7&T%c;jLpF_p?aFUMcd~Ug{M3n~lKy zxCD37(;B7f#hJqWteG(i20=GoCi`d2ox68VUKl_3NJ7<>jORw7mR$ z)H4}WCq*ytGW`8Kovo7_y0|5#zo58ogAY{K{QNgEdCkv%2J5Yp@$~$1Lj3bhk{Tg4 zYy^&qM%?XEJm?+4i}BLDAW23y`?ibwgsF#@lE_Fm_S68$N;8E#LI<6dCDVpm_Df3F>xl{X9BV)LOsDMB|tx58vTU zytmcTy4*{J{c`CyO{~_owN-e@F!Y@abX49Vofw2`U^p?9=O!G9{XA@?FGCa9&q1ob zPeQa(R*X09!?7i>nywg;JEV_UAKFm+9G=AGpySLX>2N(7S~x_M%gjW+I_O+{^ESOM zkO`yTbd6JozS(6u^mL%#Xj}LHTE+Pu`!Cv*a#FX`(|#4_FxAHHd+BV92y4TtIH)&Y z$b7HHP?v&w^U-1<-ijcG%))q6Rg{(skA`t#5TpIXF|wL7Jod*sCY@UD7jBGo;cGAFfSmQzJnG zI>?EWa;YoRIhN{q3t>hpZ1@;y`Vg?mb}>LfJU4UuTno0-y9R)5W!$|r!Y(8U(an|f zbw-)}q+>?lr*#78%3){VIi+F(_|(sYAd zUc;GNo`gkHGW$MQk9_cuS@PJumx?pyr?ar0R_~&T0rAa;#}~8QUa8USKK2MZ)X)S% zCH}?foLHP*4DnykKahYP89$v*d%MRsFG#+JGfaH^G07aiUm1UCDEX$GSM9hZ*{WHs z=N8kzY#N|{JGJt)rkzfXf?`DJm~6`A{sg=THjkf${=Eg&>l5k8n`*Y47h6Dh9^aK2 zzai@nb(*Pgu&wYdnDIC&94p&tT6l!idvQ_iW8Z# z3a$O8`XYzb$NeGoF&$YT+_rYZZ_RXAe?_JQLTd2qJD?GbRu%3+0q)1-?W7CDX-Q63D=%S{(H&&_(vonjGWKCIbgDKM6U<&j$ znAhtj4XT$5CV@H07mz*XLoeM?7ZIY0VSr7kb+Oqc>tYL#kEe4x-iuA@@1~S+31(th zc35G$%@F!t!YB5V7O~NfMtEa|T332IW%Dv-R&I^7Nxa>#tMXFjw~r()95otop-g|G z{|$6|zWSTIzsEu~+@CL$rHe_RVLtx;$9O&NhR_4#aGo-sXw`<Ty0%!G!;ouT=N~ zZlrQ;|3@%=-X_+kKf;3=s*|;2lYb9vzZv<%a6%UN3(PX20>oD5<@BI`Wy!(rMmm3J z|N8r1rvC3Z{Qaz&Ei=ImVSlMVthT8vaU8UhjH;~%N|HMRYpUQtj)0c(<6*(F(0`>L+Q)%&YaR=k>ClHzPwfaeq~5pS!!b=go>C@=O_N4J}wJWDUh*)fg*| zv&IW^Jpy>(|Evt-6;%19o;S--fr}2B%D!l7{omKa;ez?@wJwYfW;6`fU$~;o3rDjj zF`0+#Cz$iBUj%jA);`L%`EezMd4GCh-3Pr{o&g`!I%{x9B< zDR5%AdR^#UFCl(>L!_49n@-Q_Bxd5Td2~G|Xqs}DhO1u;J!ARyqDU?LyJex6bOvcrsyY(VR~XIM~jw6GrwJnFtI0jU(FuxTm}*NHhG&_ zakz{v-&Wm&+=2NI6~}By0F2C&zh!aumu5YvrU$4gw;JJYtCzv}ehB>x{FQ!sy5QCR zD+8~42_PsTkj!CY!+i@l5WG?jKXbaw5%hjXs{pmijJ$pso9G??!P{E+Ylgy3stD>= zixWYFUw_78uebUo)bG3h4b1d$U$Dakw?0n6zst6;6JgFH-h$9pe>(< z+Fs}Oe+RvZ0lbS>cySO&H52@}jOm{a!Ok0R=LqGdN3Ti@Mc9r9r?@L=QlZMf{KiyS z-5dApGsxA0Ju-BdTY&o~@w0ZLpJDa-qwew`Yk!8jv|E|P%<*G__ytzKaUR{d!hcv$ ztWD0pX_}2E#K(L=Z{s|=TjUSHK28_+msGFwb_y!eB4#Yu`-=Qgnh0OK_}X~Sff6~4 z9W1WiMOsg<@!Al%*BTeDB#X?O)T}YjC;W2I(z*VOX8&>F2I#gdT3&q+17SAQ;-sg9 zs`pp-X!4a-we}^aBO#C`y_2Q=DLeT)t!Lh*pBwu8GZ_w%Sopcb-o?*b*>R3<6U+G5jc9;uq z#xgu6y!KWeI_>hKX?@}euDLlKE7Cd}`Ma)N&qCReJYvTIx4iEN$LaN>XafGD-{q}P z`DaXq?Rbq`^`!@ur<)W~>?tc&MedZ9>>W(FHrz4{JgulEsfBZQFA+z|z(U+6VuZKX z+X~HrBB7Sj&_do~!C$XDYd5`&$XJe<43S4F~3IA@rl`f?g%X;ccr$e4muP;ep zi2j0kx=*;aTUa)h?zbI0NKAoq&+%p`Bq;+k1H#7novzmd44rNzy5xmq23ibi33cUF$W8|IVzNtBMI(NrQ9yaZG4;unk zy9=BZnt=tUlwYM+inluL%Kc~q3`vq|?!S=8`ZLbo=lkz_YGa?Ma zS1a~Y)iO3;tF{ZoDU=@Al;Ip3N)F)mn|_`jQ9y79jO*+HvsoZq57VGOpw@APWiiKCL#{H`kPg<92L;Oh0Qdy+nuqT> zAMr(Ep1(?yl;6l7-(SXk!wfrlfq@%;t}^@efU2R?mJ*E4vyInun?4#oKxTyYP=tG78S{U)I-0>!W_9CmH1CkWPk=6(_ zrsHHD#TCQAG0)`d2CmfN0Zcw9)lGw8JA+zD$32*zx;&sR2!Ozl8J(Fh=)J+l!v;sU zOAO9WxD&!lhdM*TK3562#Tm9GhW>oG>%y^i6lBrlc4$=Kn0E=-X*nTmraE;^s>zFLT{2fBATz;Lp_1EGUX%Y!fC&s z68#d!e}Ez0AW{FjcrL&jAY)BZ90GZxB#({q_K7NM55{7@Wql|72VdCYjbPv^QCEOg zj@vP0D0Dy&tO%`Vcq`6QL4^f3Hd(g4p9wyMZGUSaAN*C*4uj|N1h9q^_xK?9N4klGv&;EU;w^g) zoV@oS(mgrQR|q4rPw>avon1tE;fm%qUTX>3idEFtj}YH@)QX(9@>C?Zogs3F%aWpO zn;C3gG`-H0^PX{1m#dd-!1_jw6yi*dRIfLPa{}}g#8K{Ni#W!u9YAcGnC zq)b>}4mm1Km!{u=k?Ej;e|5U{6AS|}D<-3`Cqw*B^4FZ*N<{b9ZkXJ$0;$ z;pBw$@)F!gif=vJ>0EX;kvfU9OM2dp3_19eyc^Qf`r>W-A34ftIOujGVc&}69gZ&j zO<={EA01)0H?1C^k3-%rvTy#4h@a5T+!k97-G{(+6EAjo=Cl(u+QAy_{ZaXraZ2B> z#b+L$r<+FT<>W7ELt^N$p3x(g%(DniRHNMg_sY;<1l87-QGJOo=dphjFv1#`mtf7F zuGx#QJ5c7_y-4Pokw6XobsViM2<3(v{f6snX>oEqBm^1seP;dss2HmmT%3K9$%{j| z|3;s*Qv;tF6YWSvWv~wj)LkY%M)Q<#y6kDH>{plWeVK!Czs1vV=C<#ew85)vB|L(a zI$cE{R}DH*tk~(Y_2!w`u#S68JHbb4uBFf%H)oO&ekWGTVzx_hc1T68?XN)}g zapyZ>lsnqJxqmz{QlH04^97CEp%E`b@UWxlFRC+R*SW8Mo+UH2!o+sHNvP~F}u9tG$Ki(3Cur7hx~_r$P?|Hy(3EiO293T_x07G^uH{K+-=@&NDRwc zJDm1ziHe=8WajiA7wy@zChVQdxg9F6khEeBw3jKyVE*Wt%`KqdwCN<<#zwQ37i0!d zHy(&Msb4`J{S}X>2W*M43mAq^k=?~+FA0X5KoCX)_;M%gh5qG+Q^H8r)?2WDc$&vM zU|uTS{%yqOg8ZFbES_ffFH%vp2M(ZJSnL?34;~q%C~172C>gwHj!4RU0nX>wk2+;1 zU!DItf6(9yW!!Ed-H}P=-#NG_yPld><|%dIcrqtN&~FhIWU{%*jO4E}y?WUEy{yb% zq7b60;OS*bY%wl>BhRzC{7oe{lkzvCxEY(jQ3{Nv{7n@%Q}Z|SUqYd2iY4$AHRwD! z=u0Atn6(6!`&-aLc2R|Zof)rfu1~%wlh7O37D!)~Sdaa!s`%KNeXG=x3hu17)(>`jx_+`Zk| zd$=`x%3^O;Nt!7;iBm2}E?~>fuSL~rpJ#6t)W*u3ds(L0OL*WBIst}PiOzxTnPR2y zTXDQu$_B6TDk;vMtV(SfT{7D^srNwinhoslT8ihrh;&_*t1)&yi-Zwj@7GyF8o)QY zg^HJ&6=kO7KEC(fhl42XQ}XwDCfZyaubo++e6@9XV^Q*={HzLXQ>U@SM3D zCR{qoNqvsT?OT2ao)rZd4U!IOGZ}G7flaKqO`Yp;l)*L-yFS2HCv~NJT~h=lGm%;N!c?Opi!JwQ_L??Z1M0BUb=k8ij*~6RI8B7t>?adgBMAh>R(z_yER#!{Uy(_15Bw>A)RjQ z!P1o9Ph;T=OHmLHLFAnA&NO`|t21`xt-VZ}?>11=0}5pZK)D z;(jg>^(45MRCRe#PXgy@bj3HaDkWz6_x(_15x_2k^;mjicDV0*falN|L;+@n3G)yT zDVI9UuuFxK^=(moFF`xWWCB}|!O&arL(1)v5vO=>7KwQ1%Qr{iLb=6>cFq%wAFUk9rjw%dOhe#I0rGXkLWt zkfeob`%An72ihxGQrTzqDH>(0T=uo$qGUFQL+0d%c)f{Xz)n9pKcbUTqOCl-eN=O5 zrkgU^uc#U0j&0qlF$Z+eHK#Kb_4#GJYa!@XvO=)@b?ez%nGkfVk9aGyLtsk4_A|j? znbZDBR1cC##a)xo11=-NYE`X3ED?Bc9q^_#yW7|a8z`Shl9)Ezo4L$jAl7A|cbGh} z{o%g8uWlMjbWK8eBIn8%8jopb5}O@zu+GP=+e5yLSB7~M47|)UVf;d|&-@UsZh~xz z5?9-poOQ89sC&PpgPOlTfDIo9&|mW|I|3?2@?VfPI|cwt&qW#kKwvg$;t1Mlo|=7! zdsPo=|0M0UUIly#>nr;mBz7q2!caE8ofjDSOo9sX37YLJS$hsw-wq?Bm^!d<&!$)y zYQ9h-+wezqPWA0%`zw*j{z(Y5!jie}z*oiInnRvqbCbm;L02NL`i>%D$WAKxIk=d1 z?>n^5Z%eyGDD))&kOTS05ShGWu;@p;vret@=X=>o1zuThh>-&ztjHwE_p%H4#@nbf zI2x+5U(`)ma5LT9D8uj1X*T;jjgcZ*Fka7PeC6T(!T7)93Xwq>tAZ_!k*h9prUJ@C zz#<`Y;yv>3A=~aYkKR2w&lf92{%>@+i&*q4ls5d@i~vX#DCT z)`3pnjG(K=D^GbM2eT9G_R3}L*z83WkG%B4(spMuEebMjB%1- zOyEyqNzEQ(*Te>of!XnvAqbJKw zs9>m*WG@>bMfW7m`y-h2mr5+3IL_&MiMJ;!I#+Q#C)pB+KC%f#(3elbBPiG?#1Bs6 zJ4qj~4MSP}FxW9yhSsOc#~bhfo4KL&-kPfk&IoO~YVRiFHacUL@$Y-TMB{yt!=d=< z>2_(nimsi_cx6zl_#mAh814RTQw!1W;!h|3OYn!!jV!lse# zc84~5&+5&)Tx;HT^Hj1}X=oSpiA^;HG!T3+H+v}nT{)v>i&=qMES1cdqFW{7a4S(y zL@CN|q^8@SdQ_3B-k_>MmvMtbyZmt^{0*B2p^fgovgE7zv4=LP(XjE~(TuI9l2HPi z%&?VyI10E*ad6H49ujI4M|(cmteFh361Z!Sr5fa(0plEnZ(Kry*srl3V64yS?GCOr z)&s#<%R>7_i#1kxC6>*-I;&ViHIpCjP7RRpj%B>#JTqR6Q{$C2SB~8>Ropkr5MeB>o-^fEN{eH<2hf z*sob?KAB}dc>&!&!7l)aniZIB5A`0IxJ zoqIRQxp_5YQ|G-J%W2-<+R&4qg8BHr-frm$lhF)gFrpa0M!E_jCB0`vVlvO9tfdFG z&!|D63dKi$hJ91r4(4(CGO@oPT;=2d>vD26vZfB*oDW}c(pKp~1%jRH>l4nAmmLzeBf{jc-a zNs)3K3+ru>!OjYWYIy`?PUk~&J`ERQ4(%IwA&8vA7w(%5WzykqaE&!=5@lb7bgEbK z{}l>GRf!_0AYPd#?929J7(fs&YOy99<%s|v&V2iJgDW^h|HM>LKh%9DQk!vZ{}1(u z3DseA$Re5UJIthxp|$pxdFNk)U5qZM45Qrp^0!QV7t*F3wbTBfs-QoD#uu3+J@=jq z6xzvQAFBh|5imi_fR8m7gPn2rz#eDC(R}Bw8KQl`b&U}@24Jid5X#kSc0Avb^yD=n zImZlIRjCz?=J&T*Yust-AoIaThvQmcmE=tx+YC&o!P+FknGxu~b`|n4^8f>4od#(4 z$f*YQZfrJ45}Ovv{aJKW4zru)onTdp~jdvK-3 zg#O#7=Vhkr$(B5gtI9slGP3<}*RVC%T%3KECn{TR>zEVDawrrc<+8$B`1Fz1!iK%9 zg%|jfcANN0X>ZC}_$BSlpLNff9gpbu*T&vL|HQeFBEz6&_;)hHX5$iL?f%Z;??0jU zvBLYyGuv2oZEH8)YQo(xAe$Js0)02}ZNvA}&krU3fqTwpk7;j?B)45jdY^@i%e)<= zx5;-3WaNSn0YmvPE3=;OFim`gCV>3YqK?7Ne6x1u&n6(F*z4)ehFkZClXKnI9X7bN zc22<0qpLv3cO5pSX<$g zQMKz6RUWzn>o`*h=Bok1w#t#6SNrE+jD6BSCx3pcmK5)`5gcp}n5t0s>D_BkZ4n2Z z*I@~x>1%!2z}-CMKNdUoC=}n@FzEAriBIN1d$5$@0%pm?KLOLhh@hUSCOa)GC#)Th zV%zupR5lpjs1pJLl&`Gk77Htg$}RZV`g*T5ByH^ottjIJ13NV zJpTz$?}sW|pdJuSv)q`9#sCTf_eB$9ou`CDnuwq?&)sZVZx+;nlxT~g@>DbqsVZOW zWdH;2)(3qq(n13!d+Pr+lo;B2^N>MK>dOLtQ0s#f&mNbT7Zrdw65_%6r#A)bP5Gx3 z!mlW>pDB?4G}AXSQs}LiT^FaV%;Itt)Eu7Qi=N6bh1wDAKcCvB?Bk+UYn+Z)S=Sc;a45v6L8nLjalz;TWg#bZ@$Z<}tMG{;^TH zQAyN?SVLkn5Yl8yTTY<`_O#F3RDP8Z*XZpd|6Xh-NJGP8BPBr$!X zQsnTnm+G2_7RcIINkh9*L(UcfnIy z`IC0XiI=R;$1@oE{PsVDFTG0*zPvy`>XFH(f-lmErz4pT3ndruxXA-kH?mv+K#Z;; zpgNry%o_`t-_CsqBAoB&bV^rg0xD7=q?k<7sQ9hd=T{0*=LZtD;%VlA-XzhuAY{^# z>*$*Pah-9baea>%mCOVD$&Y8I(E*tA2(w+9zM;=O_~Fvi3DcT5zZi@A*TN9oPx==| zYPPmNn;gD(^QShFVE5kcLVS23U^|HKrmGqbzQ3r3CIL{XJg2e|rF@tabrjLt3Q7(G zJCFXIh>+UN4c?r=+?Y7NeSPwMEZs-voM0Z?dy?gwGs%6Xn^c}ZUEQQuBP`a+zwa6O zmvsD;c!ar_mnJ!i5S#zyT-P~I4&t&R-Mp#w02_r$LRdHUF=Vi!#Fw4U{plt`#as6e zSvtb`&zCp=5O>li2f5qE@|>qjw$+_UMoIORIaCCYlTuKk%T+i%O?VD@`oMWI7Ronp zuW7)0)-;j)o?a=Z@oTLIW;^Y-^OAF0rj_uxSTrCva-}Fo&zs@UCO0#d=`VAh43TUx z-LfhDwLb3vonG=6uQ$Em2kzUixjQE6$x%x$Vx(nmxAeU-61)68TzA6p-R|q7-0q3h zJQ~7Vs>yXd@LHnU%?zmvFZr|qo6U#9FtrO=l>Ib2HCIV4nNRsKUdT+XIVFmk`O>*#rtQZewNrk4&l?dnll!K+&_}^DY(ctE!Qr;En4KCJ1Of=)lNfM3l^xHo5ax3Lm&+kshH5r+;2qkD z6&Cq=zqiKRtx4Clro;Q3PN_$&KaDj!tR=}sqT*HV@7bWBemdL z8b#kQ#|x%XYI9liC=9LLAspvFw|p+7X$U6G-0{XP$>a1*eYKfH4BvVL;?fbYpb_9i z>;Asvo8b88(k&qf)KSY%0nJ09^s?xQ)Pq++Xx*SQlcPAUl16J7>xt6zbxy*G!GXgD z4xBFdDGQ^cIMW%z9nc5tA3Fr!J8v-X&7|EyFeV@&f;S3qMWjJ{K>D|ukoo;5-B|m< z<(X^E_fvxJYu!q|PgG#kJ>8FZL-l2ZNwr@>FD1x%t5hhn^PT*25@Z$-<+URr$~8F< zCBYvJ!_t4W7U=)iEd8%tL-(~MS&4s)7(aLc!8h!aq>b&z+h-LueI#+R!3dmmAIV*- z`Zy*NPN!@MnM+YpoX+)d)zC(}#+-Y805G(BJ1!dP&Fs7Z+}ob~0}Yr=BpD!qb;qq> za0-gO<7bpMkurJ$1jby6Em_mU+*gn>;^K%mBb=TQ@gn||u+mRViFi$1my-71zf4vT z8j?&ykBc(9*gsLf9>coNFAOWQh#vUKFyd}|BeR?377qEzxp}@?hUyJ4KHhF|;x=Ge z#UIYD=PT)IL-dQT_8~KpTW#Qb2NOvC`^5&nZwWbouBwU<^TpZ8H3 zoG!u`Yrj^S*lIpaJ`*sae0w$CdMsj3<@u*y9;N;obDj>l*2TU{Sv?WwyWMVI$oavV zPi>MwIK!?5h5c6=k7i!7K1-b+bhD}`O*zizGfT%JI-}7)q|=)~+qSh=TyLO}&)0C0 zA1kNfhzGvE%+9|is!VX5Z&Pcymlq}_eIx|$$S^6Z_yhf$HM3^V<(WaI$-gf`$2IGV zmPR<8O()}4J^~uzt?OtyS-LEmEr~CTTsGd@op}wR+}oGiJYc<>`RroxkpGA3=$`n- zyg;8_Abs`(NLQnBG?ul_hhxbeU*_&R%4v_FEU;$%M58p` z!wQ^TC@@OR2}-+f?CYZ-f>$>+L>2yGR!(TWyo~QTmd1QTC*%yU3YCdtu(tXaD+a!T zBk1#aum*|2?O}n)qqlZiIfwE!mdRiDZ}bGriIpb*#3vX_XAEL+XDR^w^98m?pYd~y z@1^&BCnqOiXdGrbZ<3>GWapR=gA0NZNMJLHbgaz`4!0@wS-CUINWbaLEca)Soe@Lj zj6s5z3AIOMu%rMyEO*~D)_7i+XUUTV5P(H;KAAttTBn^9N{4%U-YhmTL)yTZr);0V zUXZD`FvTJ~3E`bYzKnwW|FL#1@Nreu{?DY-HZ22_ zmH5xg8sPb6fajY5o^J+tz8T=u`;Hm?wp4P%B53N25N-O;VNhZ^%}g6>?l*QkvgE68 z>ZAJSXD}0_4HgjDLKQo%mJNMeL)An}&s8sX6YF=6|2YIM zm;gJgcFqiF&fNAG^Bs6%)@Y|noZP|sGuUNUWCSF(Vln0im1dD+l#;i|QTJ~9G2ewX zN87&v&Y?WarHtYgW8#IWPJRCbZ)WhO5i5s6Q#pIhT|_Ui&b5C}MdWST@ncdN1hmVd zXvf#}ejcX10{0^P4T`|=yofVDjBBcJJg-1Ft}i4UE)%baD7w;?`x;OK-pN6xM42#5 z*M?jzh(^iBOnE6Mmv}dx9be=BkRPASkmiH!G=E5hol>)gz6kdG6R!hu8Luh(-%IJ% zg)HEIWMB#)4}~x*J;Y0Dh;F&hV4r-Kk&mI7)a!68&b-wyn^mKHFm($8s4y)&6v z6(EPfnydHhg#m3bXvpEBDvbx1UtK43sx{yL4h{pXPO<1$&4z}=Z-)DUzYbIGhm_f{ z!PG}>OZh2>cV6-{pQbBjcjDfEwV+IXjs;~pf4t<)l+r5S8CYbm(XRrL2kWU>AMX5{ z)`t~~&HAtjVPzSx$C(qd9x%@si%*Q{oD-X!IrMwE_-LcJ(B-^qdoHI~FD^#aZ2Qa5 znaP9jJv0-q@%3mU`-Zdf2&bV8)y>J2`E-7?{Y%Wzq<=EuUeIH_@bAQ>#O^-whz47u z&nh!hmo3bUo!flQ(3$#(<%L^ln#Y+`PZcFsPSC55G`Hc%CnyMc!VuU^iGXm}%97d2 z&k->&JfixS86$JRD!N)pX*cw_*qtCIobO&?HmR=2Bi=KSWMzwCPk~J;WiebDyH8)J z4g}SWpLAH9^jx!hptFEmXbTQ`ik79c;LukI-&Q@k1D-f7w zrZaPA+p}4efh;(EWOFienRV&O>nEQBmYJ~@&0d-*rXMnS#L;nNC?2|^F=JXOG*?~S z`gsZ0vK^?U<`DGMJc(EY@k^aUsb`rRY5b-(F+ZGwnBR54bkcOImeLQv0mPygnz?J9 z`Uen7aix2JX#l8f^?mPOO{Rl?VlutSAJd+hFP~>>wQXC%9yGz?{ckSc&%Va7D#>$+cJWuUn^*c_Vadvvwj&gPn)-V<)0&S#fIpc8~6o$r5sJlv^ zm}cXse194zsTcUzK^J@(@P zev*fa;dmtU=_Jm2>C=A2g32`{htqHS$uy!a_9FX_O8l*?8!*GtT`hXjncq*W=)Z^E z_{I5ce>Y$svtU23W^Ay({Q;yM8js;-PIFh~J8!rB&6IlE_T^7ODck5%$MvP7;$4fY zvu$tN-b%0>hFQfA=ncK?m`Gu7IiUdIE$mg9jz$TSair}pCeM-LcF(&zbIOdc06mTpyvQ)!jv9ZMww7?3Rca^iO;Dd#H%FCLid(%<*IPB z_T~N!l}9+i1T5M0jOV$3v&E~vSC05TN#E}X<`ELRds(=0RyeUS^>ID~;<58)>QbJp z{q-q;A^!Cu!;jWy_~=a`98g=q2!02y(eOTF1KDXK#s(5IHwFwx;SWNIL7fYG{36cZ z1r;O~%iZI=8!im)U6QH=;~$P1v{0OyKl6+dGBeq89${^+4oW*LGxz_yCZDyPx84d& zY!=n5(r)LHv;b}GR^;u>&MUXfcjVmuI@L2`;%)xgP9x=WEE?3}Atg?;837ZwK zD*)%$tZdbBj!o&aU7N2{Y9#;pi(dUGSzhwJ{QNS<~{@fZ3TW88eGCKvnj*=pr5VEjtx z5#GVFue-T~?$p|23^DeuflK5GuDk#4;SF-}uY?v%ePc$D1r^Ayp-NV!E72Xu@K3wW zt>+>&XuD7=U9>}o)({P)ymn0C4ULva*(@bpzK?tr>QA&|p7PllkeWf-^ovQVa=IP^ zD(1Llv|~DHQ#(COs2zcclAKcA!H9se37?`!dV6nGDD@P@gz~f-z;MnjSCg~d&hz7G z?E_n}%6{iP3$A+4g4bNYPSEEl7}TrH^Jse=FBp4N@T%cY7P(wOVFA)ur6=DR)c+7l zHDO3F4Pf|eFXK1Uk`!3w$zNU_nrz0u62< zk{Prhk&_UzZK+lNKq2W8(b?(a-zcP|NqKnbNKFRntZbji&L(9Bif{diep4q7cRNB; zsdAbK_?^{%xd#*d_mdg>=rShkBFOF<`cg>8;;4!z$zZ$~x?I9bj2#D|9+rdx!X`4E z5o3AQScteBJj!nWBw+IeXFYO7JH8@nOJIY!dHi|N)z9%HBo%dDKDM)d3^xIAxD`ii zj^Ah3ASgAB32KZA&L8E)Wgq@*wWzVe}Y0`huJmCoS`COq?*px_3W^Nj(r#$ zg}%gRl#C=MQfy55E|#+!z@_2G*j8A{)8pmVapVBqsYx3?{OH(xh1;aVhEsH;m?@vq z)`+_f4R6TJwXxjsXF!EVnNFRqswCH?3ChS9#zi4@zDlIuuLe%L#h)^=WY#W!)xX+h z*|HavaT|ZUMvdhXY^mXu{D!L}FYw3;2MKI#rVp8shwh{SYjLLA2U2 zw5Pk<4Nhfp2d84#Q`{znEU32luCe&81>eFo79c8`>B&=q3i&N_80n`6m}15&FB{Lp z`0W2mw#!7>ze479kAutve+-??FW<$M%-^{z`odWj5`T+e%uG zjE|pFc`@@=tnMaF`~TVcSDX5qgZf+l zKh{5&&1AVe#Y_ufT3`sCw|%gpsu$koE-P|&AmLq|>R?!d`Bmu5E_P=~dUaSHF_BCY7IGjH;ayd|1JHiP0b*}R}b!YAq8jugqu^bdQN+7dEOkoKS zhAkHBHynfQiB3!XF98<91J>mK=AG1wGo!0-6OUYmWI~SKF`d2jp`7G_0gi`B{(Pyo zesoT6{TTj_&FK^ydtBM;a>TakV4V@S4%V6P*1^aMym`94q@=gLkbq7#Cl?x*??07=HUH8*$8=Dwl(qM4D(_1!LsFC~?zu|!CF4eNRI0_MLNo`v z{iqEw#8k2Ig}4(aV-@=dEmY88wOJnjFEYy%S?wfO(t?;XVsr#SWIVH33(QoDLR~ml z>TlpM8$3O5if4RFS@pWfA&y-lN}#mN-;^v+$uwK#*WTF!)9?omLnD~JPnu&`LKa_l zn9zr>%;Jj@)TOosd4#Ooc;){EqClBCq~fV_nNfj$YaAuL#(cwNiT5`0k^#lZL7q8Z z;v)Pceg2Da;{4YYnH77{V4ZbWvtpfBCwW_)epdoSp!8p(SC#-bii~&_5TP7NA;OM* zy<^sh0xkLV*=rD@?cdbrT+tkX@}N0RH9&Lt%GMV^Y}!j*2xlxANpN2M`-u6w5WlQ~ zm{(_sj?wXd{cENr`2(txd^3#9ccnLOP+2EpG=wB6fEB(v9mx06j86P6RQJy_XHgxr zBlfNpz^obXLVf<(gsFhuVp-H@aA>Iy!wWtSRjyWHYSCRT42Ge=Xk8CUt7{DtVc5TZ z&=R3@MHUf?{#tmES(iu9pPMu-0BttAm_XFM44MBrYMG|U1-r4+4|2WiHTDW4FZth}=8H^z$!q@ATK1it ztYtsskC$9eDQ(PrMZd%Te8{8Gtpiv3VFTgwm~m<74KKXeeOSw!x1>+}4TvLtInRA{ z5ls)ivzgpmQ=HRVbJnnrv1R1Sz`L;hvGYN$$VPLGSk3i#`D6_=iT_8?xSKRBHx@Id zyIZH`a1kG6WtiAjQazq~RCZ%|m>9^@crfugd2D?A1FciJ5u){`P)_0?8*LvH^w(hL z9xyF(^%SKdUBmfLZJj#W=8x~qyrrngctYk)oP6OR-`$zF%J(Z;7}}~o*!U-;;R(Qu zpW8Y$H}R?gr(aURD_?q^aB0C;=k3G+%Z~{4cBpzNURI5l;w-Ad;_NRzb{y!2K1^47 z&BY^_NV#_aB+%^mbdAIvx$Z6Y8eeIh8cG~A%|7p57p{DB`LoW;T+{wk0H1T1*2b_M zeYk(Egnw4q#e) zVBao{-w(LT4lo}@mua%o$EY8z+Za9A)R^iuHf~yU&7XNwoy&U4LRY;y+9AV(^pq&) za96*Nm+*r*y)_HcPWX-aZcBkgLTyjg$jP%1-9VzaL=ZOGU02q6ub{>)_!^VwM0ZAh zB@WK)OH-Lpgo*i&R9Zmv3x5*x9#ysTX=u`QMQhQmd)L6zlEWxnvlz4ESw-r*bgsFpx-;6|t!_Hej*a|kmhaFka9-n*(+TT(4q{1-fu{pVL_AUd~eyA%3TVW`%D{`!7jTylbYRuWCCL?>`st zhV_%ZJV=x6)o=ga0PfSGt8Y~@;sNH z2k!D6-SSvw!2c~5VF*fgo*Jwji-95n!mDPWckhO=nOSExE}j#$r@pTlYvfh|eNl9^ z@&B?hrREhY0YpznejXXc$i!S+}@ z&viS&x-$V63j3%*a3*lA%xHGK?40VH)0T(V5&ySw9yog2FRA!Jt)-9XPye*&mP4Zw z2+(7yN5zSddJb5tW~b=e`YmMGq8&GpB6l8V zI!j2Exbupfrc#y>ZmV|Jt)+KW(J_UY|jxW|%{6MitYn67nIhZ5Hq z;tW_fyQ~FmG7+&V@ZEH~V+SdXDBJ$rUvBJzjSD?|=+QZ)dP<)CM|S`-XR1WM2029f zh^5x3oeZBad@c1Qy)*Wh`tYSgfE``Eh*v@hM}4nKU77j5ggJ&|TE~<6d|f_w4$X;n z^yvY@6M<-Y2`iRvUWMdIhb4 z3{|@q_s97QHIX#b$i@DzA2~LZ8sv;hKp)o?RDKbLalRnDuCVfp#A7C!Qh!t@n zY4B`%Z16^}HAtJF2@6lY|NECMJY8DZjCDlo6NMnSo&%%2>RfgepyC(wT}#F6VsHMt ztQOQa2bFyh)5kB6QD?Tm4Av)5Rn-DOFN#?*xvE+UqaA;?55-k27)Y^j2+4DLYx8T& z;(RZLxs=W&!iQL;%=*d-#oEdW#oEdWW!Bb0;Me*oq2Lu*LwcPWK+F~V6`|Huz~9l0 z)++qsLAos$nv8CqE!E4QR;0LW>#?EU`r>e3eXR3jbjU99YyPaJ-@@U0PX04T%%8iD z>vxgr@Wm2s9q(iww=fvl%wzFzdH-9%B6GPM&$0$*PG)e}e)MMM76^6hr7YyP(1{pg zL8sI_^Y8qXG36Av({vN{H1HO7r{PwY=T0l?ZJ@&qro#^5#xKuHovv|ULjCJ{KT5q> zafEa=xq2IcNzT|O5ggW=3M=R3C!T`iD_-#9s=_(S zJUQEvM1k+WXe*}ig2CFnn!Nardilxe{~z`>keBYB&iAyP`8fG5^(JDa-@=k1+CRX< z2-;`(3%vr_cIJo?8)Q$HTbl7E3GLK4i#sdZbPQjYEfm4%J6VmN+0_pR{2A#M1ociY z4m-JSLqXqkOEc5MZbKor0k{oC&U7QjraFYE0P(&V1dI4*OxhxTuhK%e5U&AX@lM?e z<)!&WQ2sZDecSRqCT+|ALTO2VLHX2GDhrZ^%CQ|LJbPD@xX(RiE|Bi_5W z6ge#s-pxT=PwjzXyznQiOeGyeu60F{pLNPa{ta03Icb7sd9s*@pEI$4DB`E# z?=gjvUj3M4mBaoyERme&NcNT_hsJYW%4kjA^jO=r`(egf$O8YbWDbH{N#)+epqn%r z;If!Jjfq#=$Ocoiy;Mwr6A<=EaWsc%ihA~J(?qq z4hQxMD|a%TtxtyW)6=@1*2iD=ZqD~+jiN_2cf*V@8n?IbxwpQiOxA|J{K`Fv=WHOT z-v)J<5W(AN)H#%~JGdX!DxvMi)>{_j#0Lf&@bfr0*ieHQq5Ff}AGb&{X~=&!V;^(2 zq|(orn1?N=D390yavqSZzg2%Eo%17;x;#SpmgArPQDfNbiBD{uEm%mtq>(p3C;~*~GlrpWXsG)^X=@x#? zTpO&r21!MXB&fnU%5*Qmm-@AonZYHk^);c?zmvhx~(H|JhUu~NLtc6rsEwZ+@qR3$FYRi# zr<4I_Phi@3Cvx1LfWP(^|8ze9IRe2As(JUl0NNBK3B&$#2P}SR!5^$**!F<5uH(m) zKIHh<`g}YSeyZ^|`{@l^#4XOlvVw5V@p-ol$mK`0hy3n3&Fk{+@|WDHEVkUk5uN=T zyi-S4uE>wKm<2ylJu2~BrzwRk$>x8z+{@oH_mF#jy6(rJv(c4_eC~~rwJ)pg2Y^F+ zf1l#M+T=~)ocOKC#ktWA&CE3auuzyxR!_Mp46JMVUr5gn!==iHyv1Sk+Jo-$w}#st zjGvI4niC%bkIap4&b0o=bkEQ%Zq8)iO|@g)1ZYaQ%DO{<{yCjBK*HcK%Jyj5ei}$K z_5L+=4v!=E=d?Sw1v29N7rr!1@8?-G%D4fbl`(Pell98I$f$(9RVDEjCghRltoZRX zgVmW-HkK+vAGVS5s&99HEavZ3ALFc~7je9qzsYeYRW8jp@#P|_skS%YpA%Ffe%)z` zvKmFag4_FQ_Z$8JBz8kF(0dxgm9xW%RvZH=x#G1$G(u#j$_8{H<2;vUT>F74l==dn z?RZ=pu3TD>Xm_v8t6Yi(qOo%?i&V}=0a>E7yNJKd$u?W=%jt5?04KnqSJ@MuNSrQ9 zLgHlIQk6I{*&+ku^Kec0hf()RxKASSJMZ$?1DG0gbew|e^{O%_TDL7@txdcV-MZ5v z%`0%cg8k04K(!1vTOS9V{$xF<)hMyb$_hB>No@6v?;Dfbr)3!>;`^Q$esf?-t#%Sa}y*=@<7XPrw)cutTsTre3MxXuRhjR$f|&V1;G28d<`B@)9dV za09nYmYjVLOcsf2+Nff$u*vAsP)budh6A{Nr(0|?VYsi*h^e2nIe z_i8jh`ERUdP&6Z%@9%%s5b3ESt;99B(zW*8z8W~ntg((V(GD?8cb#}B zr%95xS}yvZJf_z_w$g4aNOY>)jfL=U9Bgic_Zt3f%lXHZd$;xJG)S8GKjmh=Y+|0s zdnBGAOC*vhj8Iwt#CS{=CqPU;R4@8^ylcTHuNYaGaBL}>vq_fVr*_C$INoii@ zp61kr-KlboY02}@h}grQ7S*(OgbjKSjPy1)a^5Pt<*@3<~(W2(dm)JGcxv}5X$Pc}>h zLo*qzr-*UBReSOV;eP2KGoZ4?^T3g{Of<#TE~*KU?Y*T#SrBwui^;TOznxUivI)(c zUTE0~%c6sKL!%_rFjWcg5`Wxp477c;SVGG&oO4A^)bd}H&S)gxQTzQrPt#R;z2BhM z!%ZafZltW1$>dVBO;Yb2?4az2?6z0&Cu_Yn^63xm5xuRs$k3bJA2m0xH7D2HuI999 zghzCfXvuCGCBhhbY0P+)*mv4R0uKIjdun){|((h#VebA30`DD~&)&I)bI7_yk23n~mj@NSN30ibtR86X%l z+Lp}xd!DpI`{+gd!ij&$FQXUiZNl$)cQ@~-|C<)oYwid}ILLFq+5c3&R-5mxf0hr} zbcZWl3;Q{L$!^QmQ|;XF4Bu&PV|F!ujJi|*G0ex*UOw+cmU*__O)6mXShxo+G;kYu z%~>23`lEem$TY<`q#5Jzc{XATdI&dG>=W%bwe|1J;g5ZA2IaC+lM&zje-GN?#_cND4o`QQ- z7(>D@sGen^Y+S`plRMi1N`8$OVgFF^@Z;ye@;9)xGfY<8D)aEc+hgrSd1S;fS%m) zK@kzn5@;lKtz;xS&jO?xkxlG2-LMmh1#R2*oF}-%mRRx0XXWuv124OgOauJ{>QWPG z%sHHHD3wby*bCIMnL_0+rEcMsp&#N+m%pT-DWJjcFYiLeEk@x#hxSW}mBjgivfl8; zQ={Iu#4mdvGE?tuR3@`XLjo*Hj{k)3hT9kx6Og`;7*IMF$G{bsXduB2q$YhTGlQ#p z3AlG?hw6&f60PH~Q_U_zJgGCkm-3cMOTBraN+_f^Ts}2=+Zm?uw!h~LP@+SO)#+<{ zAt$OQ5uTp-loKy!)zpB6dtM1AhsJrcCsU8NLT80bqYbaBMstN%xHB?2dYhzPVpe*~ zL!;3bakbFl;hoP+y6lPT@A69>_Q9{yQdSyB9Ri| zk45k`)G&33P_CN3Ica&@*sp(KD*3vtwXDL^tH(P7{L{a++2`W1o;&uBK_6y?flB!@#)T9^n*8m zyhsoq_-{11Ey)Kc++2A$dh4&L+=P$P8@ghZG|mQQ^+&b36Sy(rAxNUg9e=@mjw?zC zh(4lgnZo}2Io2#$U^SIFS<$3)J0H*ff0mkGMUyH9e!(JVS0YMD+e(#L@+ji4Vp6?I z&E`dRh^f8*O6q#(zmU3i@Mk#0)D&d4{%$*8xxc}A3jcS)v9@gwW4Lf#wUf5D!K=^V z40gsJu`(6MFxqtTlq*hF@F<(m=@^eWpka2P3L%B#lNZPGQKS;i+O+UyZm|zXdL@6~=#b);Bcj1OF zd(ekueNQ<%D(6Pz+Oa@#9N<-R3aCTU(l5L12yHl%fk<;7S4O(HdS|2+DZG1cDX7$)F;T@Q2ZjM z#s%OmD<05J<;ji*w1pSxctAGZ;rEnJ`9m)9(0@yv5a9H*j+Xg zqrmV^;-|fgn{{_$uic&woN)}?%ya%9xU#h6Z?!}$SiDjh{a-J z@oHA6pvId?G(TKvcnMcMPLxAvb6*YJ@67M3F=7LE4*{jtXx%JeMmfi+%K_^}668Oz zfhasWM*gtaum3UlsG-o3#r!tvYAEp+~sTZ8Dv(ld;Uw4#q{hb8|P+D zrux*MP_U?JcM>Twsh@7T-^}7j{!$0<&Sz{G1mn*44>AOy(G7Pc5HG^flvINEHil(t zv`K#E)2y9Gfzs}OK}zg@ooQB_C*Au7R82j10mgOBh8ZajqpDh4a+kvXL^~AER;0Yu z>|YKXS`sUK=(n>zn~$sa&O--#j-1(Zbj+mPp{I;k;2h5A2Z2${R42MDHT5O_O?5qD z>N;%dO8)8nAIsF`j_El%QMFC#%c>91A{~I?C1=cG)*@PY$^Wn^qNWpad1$m$1VO$3 zPKfv~{85=UUZQSUxo&RxE^l#xQ6gVtIARXrQ?2+C+>f$(3SLan&C7;*UdS7FjO%AY zuM*wBk8TOanxF95r1RnH-QLRSxkg@yZoU}jE<&yk_53|=+<>mS>8U)L@QorBKM}v; zU7;THka*+J6EK96Gn$pXhKddrm@p;*dRWJ9C z6MxWv^g07*sfjn7*UGyO?L#!I+Xmpep9YcN1PmG6lUc z9Rwrr6-)id$9N32eK4)ipOqoIv*|`LT%w4qXX)Jb**VS;4K>LRLK`WE%a!taUMXz* zOAZE(agPH^F*M@rp{|$nFchFC@_{M}$MvcpV?uZM*%jJD=1Az}(6REN(EiYXcLk(5 zDGl)7^2Twi*I?*Sh zU5bXe$ek+w%j%Ep42NauFLX~rF5;oW$N^A=b|sf6s+JrJuhKwSZw13w7(f4GLfaCcS#5wZyX|>HcXR@oZId47^qP-q+Lmta zy3#-2G&bHghCSmapSB$pWg_uwn@d0bXEo@_yZ9T7ZE}Osb&Ix|oTDW#B9~c|Xs+^(ZrhsK}QAhfus6;K4nCQzrFA{@RbEH%P|Q z7FhCr{5SQUk@CAZcFa9$wO%rng%DvgjdNYMqPD+3nN|(%jagu{xqpmN47MnkH-cE^ zY31%jRdCm7ZyD`7H}DOo<@>r$qPjRO4`Ot2?=-#G7vJKaW`RV9{EeyrHVx;ixbFbo z&F>A~Y=Ora)UkkPwyL4;fF8W$4*C@IL%8>K7%4?YYhN4Aw|_*wqX@>SXm&o+FPga* zd|}%P`W2t4t_aW)dSfn*64@nlKf@CnxFg#s;C(hcx2v5Wr1J&kPNnkWDsHGv7ls$+a6O~ zk>p`42|qT8-1tXax0^vLA9U9}$}cpL$7y(cI5f{Mj4)JlC^)uqTeRbY@Ir=QrQIC1 z%Rc$px?Ky-G?Y?>vT5XtY)H9D)45jDIe3O{2x~ib2%?OxzC-yl6#paDV!5RT(AW7J zE}<~;hi&Jo_h@GfIopo?l{#0PW&5KZAaMB$PXGcEN&o$oz0tLQgCd3-{L+X9b(wmK zE^A-TU?pA4shL_Xq89HmvLMKmNg6DdU}sd@GM;J|@u$vM^6I^M-6I>s?O}y2v!*|( z3d%ZT0)IYUBTb=^s8>?SWww%6z)YT{Zz$^=y)Xr^37=cOJQC z@{1*DzcOFKYEb5IQtY7L@CHaW6Gps&%361@n9Dvy`ddU?L3lJhcVVGJaw7()8F z)O)TfKhF$Asd*O+fWf(+T2cX6dK&ioQ3HVQT zBijbpmEF%Q4R3d5VfO$WaCq`;!bX-oTW=j?@;pu!|1d+6=CAN4Nx-9Baj3s>Z6gfi zequve9wm{SJ8s-4BUPRF7<71M1`%gGDDF*AcXji9>iikbNe(^`lIgjnm;+}6C`SKD zg;wS^^6v3fShbw;MWCtJAkF`g&TD`)>M3RvVpPOqsi|A>KSb380Fm-puR~i?h~%Z# zOZr>=Gw9jz@+RxsBwn^{A7}ga7^aYk1fn@v<_)Q*^eo1^eBMpSdRNT5lXw@+dRN3d z?0bzTX1&AP8lV5ojVENiW2a*odSc_atasGEjH?S8$7a1#T`WO0qv^Q0>c@uC%=3~v zVSHdE?7y_eh@2G}ueK}ws~mM_YQzkcZzO$p-A*{(K=fz1i4qZjmPIdlfJ(9npbaj- zV6ecxKuYJD|h1?cY1W z0EGnnHg!@uFWpK2hyS()*9v-ga3vCKW0VhKkG>@JqF}*3YS1014&k5ZqB@PxM-?bCW;H@#l74UrOdKig5B$2x%vvnt1V|Db0&zoF9o(QN zG-|#1rs|~Ja>`}3>^^KkPbkcgKbK;xTwj%z6M!T|km4T?KpF{;1mVX&3`qPoP_^(P zjJtJ$UO@Tz!>|OBP^XpE=5w4Nd?o!JZrx%csBCO3*epmf5tJon-IeV zVj#lkYF0!TG-s}S8Zp>Td&~@K^0Y;k82q7EDf;kUD)1UA)VZy|;WacWnIzfQuuu|; z)k0u#i=8;K&6-weBi-=|EMvE=Gs3b;b{9yJXVh(0QDLxzQm)+W9Qv4o*0f3 z*c&#Ij4tn5)i_KMmjO-ow75<{+5W6I0LxSm?U=^opto<)K(;(ZJ$ag5*nQHKfLs3* z1Q3)FG>q-^0I+QsDEjq}iFSW@koRtKlL*5O&rnk>+DFGQV4oiW*b^)oqK(uz8242| z8uDfG7#A#}{}85f+yv%J5bb!b0uD1xR_e|ag$`UFYXwT(onixaDrnjISSRnCZC2!s zb{t@s@e9yxs>#DtyO-zamYtP*qHA}UQ{KRYUBDVXEco~Y@zfd7kGFqZHuop&+6;Yqp_Yyq_{a}X_& ziD_((|LvD4NkYo-s|X*|g1l85yP+Ap-(V%WIc~c}jAl=JtX(*wLSCyE?bp)wA_7UEi~)~1JEApqNM6y*4G|eOIj-_ zNeO;RHZygk2(VYOK6Vd@4kVVfv3p6y&vYN&$naOq4=04!YskdU=RVwAgHv8a0$BYbDKrXxk`aP zV+{~xuaE5{kBGb7$jVHA-aW><>M@qc_nPk_@+VEIfYk3zs*uz(CRIf0fJqgTdfudB zq#FQH|l1__gmWvb^FR%XhFo!kYm#(=ow!{!I220Y5Av>?G#BhCy z&!Rv`(|`YqbRwX@rKW}2*edUrR{7IVuuQ1xIbOSglBDPx>oZg)DqRI04HdTe87e%N zir$k753}T{2EU7@4d_&D1_@>0s6T@vfqHurZw*Zp#2|?U{>8kdfS7{V2hoU#9@^u*P<^R!^Q9zYbSD&a}Qxzjgl2tZi#8%}nI_&yKgr&06pxowaKL z_^HbgdQjElkG0+s`jovx!nnI}w&aGK*6P!E_h|~s?QU=4mHzJ;`PX^PyF6sp(9>Ac8SYNvdKLh z8p`uu18u#v)tBUW%v;7LZ#?jUZDsI(K~;FmUy_4ggz$&^nj(vJoXEqaS|Oura!EQp zp7b8}OPr^e0+)&~xf~VEtlC`b6x|Y!RdcITowZTyG8o8BNX)A-&8Zg>&^7Uq>O~^t zF;Wefxi2|;e zXMp_^sKyArsVk|d3nw}*ajo1Ly=^*=tt(FpO||QVHzU`1%_7=n#|A^FFQc@ur*$Jw z4{8L<2koH!Qhm@1W5eT2J|g6Jau@J$dqM+~$QRDV3jUcmJf!!*VqSZ*&mBiwGdvmGG`i0>Go zjRweQ$Mx!w%Eqs!9OD>EoaMF@dh>AJ&2w+bb5@0M8*!HNH_utlh;g7S;=r|+Qh`Nw z8C4j3wXPgJ^r>h^KF@t)%#7I)O1_etLR2^M3|KD}<)r<-)fz`KbRqM+aQ}~FZ`F~; zoRlPE|0B@&@%r6dyip%vEOltUhOcegi=k%Z>?gs}9Og+QJuP5Drv1a~-x8$XWBi>X zlTwvCS0s|X;n0q%c&s4toHsY*6vX^H^%YAyLg##{X`-51VY(c7`6RO230mNPhI~xR z0%r$c7cwNqZ8vl{^orW}cfL|>QR3J7+RK?5z_LDu=AIY=Gg)r3nf|5WyVAc2B(`n8 z>X_-pVK3Q+P{HUH_|rJJO$~W$KOhJO{W0-irNMv96#JkpwkgoxPjbiN`wQqZ?LBeP z+eDzrBf0Tgl1E0Xn#2N5-s_Uq5`N{KhB91#8owyO^{4WS(p!HDzbLx(a%D5oW3-r~ z-$O&3Z!jTn4Oefs{5|YnBE-l}X6%yUn*hErTaL!dhoPOKp{1H?TU(7HsLAuKUPnC| zLH!iJ3MrUIxWx*MAD%Qhvn*f2{1QXD#D8kVv7yioZ`}sTUy{A0FXCeK(-va=#37F6 zE(IXDj#OW6$rqP?kuw_M&rRx`J|-tMmzR)-yq}n^fMPaZxdu+bJGr);y3pO9gwvwd zcawqDt4r;$OU6^!pFtx!Yri?bpb0>X7)(QNb8n7L~Yw8n5NYjRbX~JBQ#jV zgF(GN1gInS-wi(-Yv6kUmwJXt`*9WC62`>r30AEty5(aKaG4t6?1kixDcBV6`zx>@ zyV(7>VKMk$?#UfLe~tBN4R8_v(zgF1bYT_^x5g-jyHTLr`o{EIfpKWUJ6_e=T>ARS z514%&t${{9;V>SkLOkE7VPmyq41J@;)|&=ywEj^Aa?-M92s=)Xq| zeqMB27o2Vs(y?y+OjtzRTU`?D0)ONnbiZ1k`&KXHFPN9+I@MjhxKgQ>LU-Owwvj&x zo^5+8|6=)|ds|#NcHQ!)i_cscbKDrJ9l z_YFeMkB%7R_};plFN0-PnG667$sH0ZuaU2~!RMW($O>Czqk0D3XTWj?UhSO37 zwD3$|-dSS3-7Br79w!-*=_Lcy zDh~+`p;1MNs_3h!6?=t?mf(XM7^P%4o?|UbAvH}iPty!VbyiSkhDWjRiX@Cffw|q2 zZONerupSR(#gV3wK=^+&YgYXPy+r%6L*@*P@`wbzl*-CZ#AS3Uy zjNcd+L4EQN1=)|(ap)MsRh+Jk?lPDEm{sExY9yLA&mB| z7K6|~2IqQ9dVPk~n916`>MVDwA(44aPD2TSZk+kr&-5=i8-N-NB^X{}uj+EQsyPdFkxrXqL zH_Z?ZxDSZ?xvfk1+dsq3&JeDJkAo*n#2Cz&DMNkxw~3rLR;1K&|!D0 z>T%4w%ELD=aOX8nBA(_~Zlj9I$D^~4bPOeaKo$O-<<{nQD<3TDtu%#hE_V$UnT9v^ ztzM=|$zev``pDdnQ$3U*kYOWNcHVE!MGg;unbU?uG7CzSq1Om!4Y>c~!@L{t3(_;8 ze^(~^IieJGI+!_SUnXlnBXL{oSxCi9p#Iw}onBG-=6B)Fnk(S}x4WI;3FD}WekV5crC4q%DTFt`nzJuKecJM20We;$@}AdO&5 z2w6C*Ib=}%AU}qa^gqPD@NIU*O579h*}$?NW`lyEdMBS{_H~{Cp7_n7)9z2qEWE=| zHxV(qtYyc)SUmjsO zr*|LPn>;XRZiqs!`(n8N&z2v)n#~Wb{bQ-{-N0ceM*Mm3ZT+Rpvg564qMb>;=+LXZ zut}Zt=Y2tPh*l@$4ZfMA_(n(fEp=9;IEku?j96&x5|SI*L2eq=s?Yz^n}**NS^xFa zD=Y%(^=z}4jZ}2Z3M^~z9z%;%yhPB-QlUgp;af6LtwC0QI z-{)VYf16^D(tY=rM41G5BhR*eRJwFK=lfZp+y4`T4o7b&?Glf+0&m>^V2wfkY=Pqa zXaCda*__ud*4tLO=jk8Pbvr-7A_%Z=bi4;WupqV+(KD^T{Bn?}2D{9n=;qT90c4pA zd*(z1X5sGV0D@~bPyrX%Ey-)_mgHhxE+p$Qw+mr3)b&ET1cu05GR@bs(cDn43Qc7N zj7R7EOHMVG2D8KPpV|Z#e$7+oGrFVH=-xykhT%i)W zHJzBHM*L#4Sz85nKx*2QH=dvlyGQjimCu#V8DRD9V^RIr5zOM>wuPwald!o9{_l^LsgY?Iky9?J?44OVXq;1uXl5 zNkJ-akTG*$;~aqW%lKpX_YWwJ{{JHIUc>zW_hHD#z$QXt36+z06Vz?G9Ui)UgXWob z5JdW8_#hiEH-M!-hzFItroKk%FrW*Q$n;TeUyEN<|U3TL9V9HJeKmCH}tg%!6&$s5x73FkS83r-|?ozc8Y8^ zkM7k8N`MBt+IP)${w5KpgTZdw{y746K!C=gn#gmL!jn@*^$7(@v3e1+&c!NQ5gY2- zBuElPPTl>Sd}N8RpE5azvlKgZ_x_74F{kdHf1bs-#yWL(d&$3D30Mu#_ZL8>z1q^d zbD?Ov!LXCQhCERf@s_=Y!V&s*Uk-gDhFq9Ef!E!-`}@|Yp#JrlEo`NnHH*}lI-1t?48s+&N|=-K{I>TXR>C zzptS{DQAt@o~+Av)^zbq%r0lmdJ_JglX)`ECFQ$}VHY2h@$PK4F063~t6HZHC&CcY z_SHFK3kinM_=Gd3o)|9SOC=8^QVdF%g`4@h5OU0(ul-Lj7m{ok;i9a6{zE^s>{@Kd zwV1eXqduo8fT}c=mqQ(zLZ2gF@*{Xm>J|;P!w>D;Goqa&?F@gt?z6{3@wp5X&=I`! z7l_NlFqe+VJ=x^;neanhYZ-EPmZ3nRZiz4E*_&-O#fG}>7CsY(`ex~nH`Ym!ujaJq z(|n#~C=b2kJxbp#!kiU*kJ4tASloG^d*f;|Oga}b+}T@1rdceqWiP55uF@Q}Qy&8H z-s*3z89$x9m^M6o2UFGL8?LZ@1a8k$g}9asxt2KZyZc?nYun%LcpW*xj#tMhmf*DC z24{xr?uxemim?;=$9xucUAIBQ>oJ-N=W`*EQAn2WA}&Rp=wZm&-B-7kS2<=+r>}0k z2EKnTR@&(1_EGt;=+3(J1hjKzVf}4sY;HR`6kRc`=eaP9U4q^2Njod+x^B6sIl8rO zJv)HqyF%M46C1dhm3myj*&HrYvnv6(njk1izpVO_8#WH3p<)DC6h96c6jYBu7*1VR zW!;7q`GmpU184%XzldoRbI^vXd6YEDMx>EJzcI!4edpZUk*70=!>?YPaJKc4v z#~g;6xjfVvUJhW%n>P~3axBtL@-T59Wzhwng0Fnn1$7%uu+`8LhCpX+nA98U7T5Q} z%QY-Ri&&CpZEyyJ0~MhFRBrS5Z3KmNEd#nw5*wNFm5E}5F+@0`WZu3X2Z{&b=LzF&vEA7<*t*!37I%@to9vpxxBT_ z(|ZtZV#Iw-eFw_9cY&UKch*LJA}+<4&Hi5rzaPNO_gn!@Xm5Zfv^PK#+8dy!=V!c` zE(Whi4FmrSQGomwps5Sbj01r-FqK#LdzJNn_9??CJ40aAbqAP!59k2up)dTtZ<DKt@_ z`XrQ?f#2w#{YTs6X3h=`12U7X0b#msgNEipM0s}|+-Ath^^#?S3@1oV7OCdxrq7x4 z*@pB4l1tHGuf`+39G$!CB(+dXp`fmjxr}exa+Ax*BDTfjb2$VvFov)hCZAyHt68YN z4FmsG_6>%CfAtxj=5BCZ1HT#lH`EgWC)*d0t@@tDL5>!cueJ)+#NgH%%|I!`hg63- z*pl>%T=z-JbG9rLKSSRQb^7C#W!46-X|Efq+_oz0Oi&b*Xy@Y$nAdem4xacJnb@;h zvx7I9$pYF-`Zv>qtX1L@yTMP=KuE)JAaj#~Jm~iSoT#4K7Y1LqXT30JZqo}3_WnO0 z4*!fD%3<9651M+)IZT@w2;Lg8tnA$dKW#iNOKb#?|EnzL*evozq#q(c#y#R1$%@*C zDZ!Gr!MunuAiT=o8>DyWzLa5Lo*A)deoQS*QU47C)eR!B?0|X0XHv_+D#Z;IddYh& z6j@VhADe8NI64?V+|18LH1o_(n%RHcYP(@XmIsw(Hb$>uWS*NaeGYr;no>eC2vHk` z?LuFMw!W)X!F&-R74R(>oTs0*M3;o<^ywQ{QN?|aQUxB3W1{WtTBHIrddcqB1N0gX zVReLUF@3izhw?W{aeEj4;p@Mo_xA`iN(h(-veLiIO0UnP`)bTOV-@j0$VnEm?rLVM zaY#6=Qu-VFvT?ExrOQpKDwlxqiI1h8g+8zk&OtF`kv#*J;+dTvS&Tb~PYa{yTdl96 zBmb{ER9U)swEe$$>&~n7>JQ_${GggPeVA7x)-&{srBR3n)g(xsEr$M+oj-Q$C40#tdxhRqD0cxY( zIqrmDQB+_|o%}eJw`^&eEhTQz;tAuqf^3@GeH8VQYklxF(v?(nC-Cp%w1|7Bv=Si7 z&p*%nn$>{kJYioG6Rzk#GQqAjCm%O6Um7tVe#l6rKJgC?mxxFw2#Iq7AvVF~()Nq= zyK3`JL}+d*I4N++CHKAyR6})8Ln5#L6m26p1MadCRd(el=EGp(6*pO$&N7<2D>L8! zE%UwXUB924`TiK+EjBc2s(Ug9emAKZhm5c1`FhqQ)>9=jD=jue+pmSq4Esr*I8oGM zIZqgjLML0Mo;Ve(Cp`RjJF$k-J~IsU|Xa^7HA z<+`zkbx4f2E0LFKqMuz(F9MubkH=T}(A31MMsEKsnF0^5w8(uK+5i`2G$qB%qMbG5 zXgx}#!^tF&=|cND=XOOm?|uk{AZOBU9GbuS0lq{x&+U>nAh$p%1YZ}P(h5QR6s^fy zc_oE__|p9xDd@iwA(73*X#2A~3F6=J+c{_Sfh6Mn&ye2xe~w6Anb;WZc$hD4Vxtw# zy~ri04w@WB%*+w9efKsHGyT=QQQ7BZmp=#EK#P;%iS`>y3y^5vshMSdJCv{6lI zXqB1#Ia;P{|JQ}+CD2Ur=Jmt@{;W);v(}nRBRc2)b<$4ih~73+Z|e?NbUWc0-n87* zA>I*dvtud?ZR!G(VQojZ=6keb6L?IWX5MX7n?Dkc=n~1tX+GUAFF9+(D4f+p!EeX_ zT6foAO{6%!H7Ir$#jJ@#!XS1n@zX$i$@iv*QY}zKu&;vu7l^_C3*TjHc`-U)dABSt zoUI+{zj38M!{k5TypkzI*?l>O0xg_xkUK;me=&&*7_iH~2tH5cbW+yBJ9y`mPl@`gN=_ z-Q>{*ro@C?w=v?3S406~2^7SJ^7&GC4^b8CuJ z?v1~{DilA3D=mmnPly6I#dywCn(WR53tv!Qo~bNiDm#As=8;1OVDsH&5qCo6K)ir@ zaevKoR&cFR1bfaXXH_28mm;+(_LmbfaW9;5=e7P6`_Jlc2AkVF0`xR@$r#>pg-BdBS=`e4)shmG8OTAA(kA6}WB@i0-Q^Ht+=Y4{uh91{E_8vVW2PI%|{b z7L$+awT*6W)bnQ5N;3#D`g@cq{h9afx)=rY)vMDek~h!)p)%DWqAbzCuyxGL9p|m9 z5iD~Hoy7&-x&dT*0tb0@arUV4@xjtF+eu8aJX?*LEcCzgNxCOcG|TG@^?mCagTu66 zH^cMbEMe~(djtA-2fbeQInkRTvQGmVq?hb1p%uT0ClQC@U!-Y{*096p!@Mk;(lb4V z0SWCeut+-muC?D^=}$Gyzt1*r<~t&bwT;0&gmJGa4r0O_a8Rr7vmMY%7RS%)n%E}J zscjUdaBU!84Uc9=pOYaZTlvDvS<6kXzZ3BS4naT&kj_JXs3-xhv#|Bt`rLxOs^k0 z8*$zYjo;Ycm~!{HHMPv`M)JyorQDRNl^={mKRg+<-quTig{xQaQ{mQ6;b)3lU(F9k z6>9jYkqb>NTo<1jtpF@V1`T=qoNXKfJM;M(0HesE7o)88K+GCIu} zmIl=q+f5Sc<{Z0@4fnHwV+`3Cyb6i>9Ro3%otkuE%Q({evp|`8L1SlM!>`6&ChVks zZJK-0OD>`T=tKR=OE;Sy{FlU{2K+n3p+*k=*Vs3qO|zzD_Jghe17wc>gKfdy|3UZ= z_=`fO+)F8!UjLb%|^Nj7KcN z_l$)rKGiHc$sAPxllD5yyc%AB{Bw}j`#RE0irW}tjJnzC1>@G0!fxX-o|O&4_UXIr zcxohF!`_%dV;Q?YU@fv^m+Up(f^PjA;)6f`H1m$tXU556CPT*QOO9Nv_H8jqGboxSnIqP65Hm}Jrdj61upGq9z!)vjj*O<9eBd;% z|1oO-fx^ez5r znWMV`l%r96X~wbY_HEHSse0d}y;i^JYn>yJjDOp^m>*Q}qFT{yMmY#uoW!~*62Fiz z*INf1|InZCAFdpT&g|_N>;x6j&Zj9DI;?ajRFpdObbkr{qrP^!RiyIO=&VrPVxHg)+5KF9pB=s;@98FFS9)Y^CZ|5N6IG-l@GZ~e$Fiv zvm()-vePNEmu%>qD2ukoO=2j1i$ZC~uZV69$2bj0K!bX^!b!x+*PPun!9z?ap^u6R zo5Jheo(psaIDWS?=tK%rK;VV|m?`v3!$^c!#^A+soe~^v5eA*HGCav+#GRE>b!}dB zJyq;-R(2APrIwhsH|MyK7&Su>Ud64HC+KY?=3b_-jPy6xnc$*=5$tBXlh?6}Pto?z zs&a!Nb=1kwbro{uGHp zt~2|iKix*u*E+((FowMi5e$uN-p5j3(^`2X`2v^lJ(PSkL}YJZ_9{AELPgFFz!FST zohdro(gQZK0di`$aP_pUbb2JmIoMm5srnMCwtm3Jg8Bzlzw;`R2yna#E0Y8q_Nwo7 zSA?DGHAQlrQwag?Ud%Tho$~m{+^OZ=RrBe7H=&PbZq>96TAZkkZaegcPSk{h_BvR* z{)jlZSUH6|u07YpGin9bg+=Evg(e_GZo`CK5|Frk^@o`<%z4!4* zNtBFg3lPB&7fw<+D2Z%Of-#P9!suO26nkRJjuT8ISu?Vfj5LF0f8-Ysq zvk&vr{k(-s6dY+1i@P{qOh<)qZ;doBb>vyZ^dCqjHxDuNs5_&im;vETe-fWL<4wIP zm`r7|EE`%^dZC)YQI)9ZP3l3R`ahNDFOZbz%w%c$xV}Z!O)0zn;9ZcO?}17y%u6RJ z=)GTAaNxQ9Efu%y`5EKpH>4uZH}3wth)eo?Ltnf5$3r(i^<%!uiQj}Jk9r4)QtRov&irKcRFw?u!Jf^Qs@tCzc0$y-9IvH|jvbXpQJ|8l1g`olZl57*0A zE0ztt@a)SA8LfbPN2f}qN-o^ltll9jZ;)LoU)foRJy4}yC0nIGx+9T)P3RK+x@mHj ztEDth6)%GM(6egl`sy90`Ufeyyf80Y_7YFoFT4ZklG^|&-q7Xja|LqkzH3RwA5Hq~ zg*Qoqp1OeP?WpPR3WX}C+ZK*AEE;)a(KHSnar4W%s#soKOFTJc)*bpy>jli!tbK2u zeNu`I}#(|OiyqW?vr zn^}A){t@zF_@AsVrc(j6bQV=P#NDvJkx?e{HeJj1oJ7mqZ#T55RGptxb2|?htLXZ! zlo!yq!mO-@qqj?lvB#Btyzf4dzHJjq`f}Enr~mKPmtVT~6|65Gr8Kn4|Hb<9hW%$avv9@j5ov3OC(8OclE_0J9ZW(9uiC7N<@wYho^S0@J}TuBS= zarmfxf>!uty@g>_KX2rbs|%iz&ok`#&2_jh21c`v1rd%ZXAkNMBaWs zy(9(-FVc~P0{(*qACQ+1$RpZqtkBy=8dgvLjAvW8!Qt5jdruKG^p*Gjc$z4@|B|aE z@~i-iY2vp`pOw93{R)?-uxZVcr;ra@of*W&z%Hevw0D>3PVz9I8;dtAltmHttw9Z{w}>|1yZ&zPitM6JXS6}5^xqE;J{)FA?;69`eu z2Nr@{ZifG`M5CX%+ydhOmv6tH6JA_B}{DWRfy8~ca?x|28 z!}7l8cXuAs1HyC!@z(wpqYp;*4CnFPCVYDf`Ns12euH#f*iy*%%{;yrg>SjbH?*nw z!hYFHYlvJJ5#;)#IhA`pFaC!l{v}wZFR%2x|B>~O@|hK(D&GJ6_y1Apprb}!b}J8{ z+}4b^jv%BU+OrLzn*ID;$sRtwzM$?$3qH50Y3M@dP-NbI z+#$9o zwEY9o(W&O$lDK2Ya`|v?qg8 zD_yh&5!sBqw&)jY zvZ1O9c{tgyoC~g2YFLf44`Q9ZYSPfGA)=v0!)5^<930{+F<+8qoxa$tyseDUN{Dn( z@$|2Gj%=8hz4I;>bt6}~4iL9i)$}=9nflu7<PiYlnwDZ z6>)L>4dNp%P@4RGk{M*=efsx)2pMPD$fhj_g**+c+z+aN7+R8$=mWBvu4LgWd19%p zbfX{OX#&bMT`J`vJvz#m#oD}5rkHBd3!kEOMmtXqep>RdM!qCLT#Bq0@x_2~A-|wP zJoen4s`&gNt@?x@Eu{3QwD&k2ldni;8IJ$(yz{)}vz8mX_EE|b&2IMsRo z%W9<3q)$_SDQU%rK%}|!do(Kpjnt=SLY|b<4~=|DOtX=}5)v5xwEQO`MJSp61d(~+ zQ%}o0?&U*syg_Ulc?*R8uJ}-W9XY}TjpIBP_o zHgVdbPn$X2tWP7H$^a(E7Easr>1Iy5^r<+6ySUuRB_@d2qQ(LmNys2c5~hkETVC2k zQPw7A5h1EXN0l9f=g2su@o*AkO1PU-RYL7-Jw5p&v5-ebD{1is^*`Hlyka*MnfLmy{)&&v;__Lr_m7a(;layL z#R^!7Gz@?Eic}W)Q72*+-wPSDxKYgF4-4;*ig9vKIOWG9Ai_c%Dj?yHL>7GZn>14~ z0%9Xcc&%I1{myDtaX@#XG6G7Nq>za!V(B#}POEzxTlmhNlm(-OiAL;J`a_<0K2L5? z!<hKs>eD7pXY^?^rxmxq3Jfo1B^<(2tH z7gwG<*QJ$*&vjvC2GV7f=|>k;oJNd4rw zEsva=E^4S7X_W0STUvIwakINWElaFbDC-JZ#-9G8X|<4l?7nG|OK%un$L9z)k38&f zOU;TseC@e$^Gp9^{N`G29^vgs3!eHXtW@J~8fuJOI3f1!Bh44SEB0-pn#1m%ch2#dtvE%ejh9!6W~B)?vdVwJrL)@DQKt+)RXK{!W7Hbo)J6e-U>m&q0Zs&u$f zJv2)?)Azg=MnYv|yeyfNS4_Y0eI(Y_ zUL>7Y>2bmU+0)oE@4`!H+^k=2_3(~nic&RXp6u6hKCT5;r;{Q z34JPZenOv$oS)LCBIl>|smS@HJ{37XqfbT7&+1c=^K<%C(EV5!#bQtF|>GJPTC9vUpy7gF+}!G-!l%04u>NMB5-3tL}E`G*E8 z^o7)5Xi(G`c}X3H2CMXi)M99mc~U~89z%n&#Nt9~GBn6aNiL)=LxXrZFZX~ zxKZ6pCnJ}+Tp~|D#zR}u59@a-7E)U&gOyxocCiV&Pi!95vtn@`lQZ$^VZ+KKz-^rI z_h$QBv=6#t`sRz-K7T?gB=S#+kLz<=&e!Yns*Dk-`crlXFC$!RIZn@TQ*w^6S@QVv zi&LxY#VM=3Ki!q=>)vj4^d)+&XnU*&=u9WAc%q{{9@22PhI=%;MZnvV4>t7+-(i7o9S zY}MkZU7dnC-JR&QJ4q%My~$c1Ywt)W`t0uB?sRv1y!$=fz1yr>rN%x(;ZzxPE)8pt2d#;Q+70# zj&-DC(Rbu_Qol0~(nMh_Lb|iXxX_;(~S<&uPM|)pX zDw_?o+B-U8o>=ijD${Z8(P&>Rm9l$jy;OfPndp;dkbGj9Y_@i1%M|ZMa9jbgv^2G* zV(C_1(YY1LeNwX4QegG>(&|sr8N?BCZmK3Um$W_&s;^er$#&It=|sYgxA$#}S*h;##O%cOSYKy6vBRoiOi4N1ST(hoPRtPs zQ$Ohp86;gXBI(n<*t`2-H=ds zN4r$Ua^vOGGs*PDlJQ+6)*fXn>I*F+$WkiR*&om5m`O{qWs}yix)H9}Hgeq_%SO>b zNM71<8z9k_Q~#{4O857s+mq<3_T`+vwK^=Qb0KYj4vgo54CKxI@)_xZM94+aV6W@(bt_8`A1u#W0Y1B z4Un{Nz0Y2|vANmm?nN>7(9o?t?b{gR{n41c`aV0k6T9xL$Oq~;*ouVI@5~LkK z-4ur0*_Y_i0dl5;gejY*G*Y_#NgAoUcRO=X)P|yKm`jefBPQuSzaXg`x-qKMTt_0g zi)?t zEv?nH4_Ym29;(+ty)jDL-`mmE-rdWYYCFU_(VJ4bpNUYZ6_ncc)KaS1Yh?)ZI4*Ez^bRj%2G09J)|9Ao{C6CNa0AyHI1>5SxxW#LlV#`odBT~A_OswwUSDXx4jIL;_NS956D76rc#W7;+9tOQ0)CAm( zXmqvrMzORk%G90SWp{MNI-ay;)}-NOs#T3C4cU!xCk?yg{@&Qmw4|#j$aPAokf?o^ z-J#S#R$Qe;m>ycC2RjmIQTzV;6qA+g=*#qu&a<f?BOGN)ixcBH?1 z$^F?T?ekuwW9?eCCU*2%@g3bshAs9Min+T}=5V)FrNbC%?qydZr20^74Te8K@VkM+ zn`?NO*sa~k6)uyBfmrAq%|xMQ0t*YTr@L28eastb{-o76)2A+; zbXRYCPj`oxg((SZR;AG0ser{pM^93n_Qkfvc4CCFrqp>Pwqg6SI3}A^JQmYjEWmqp z3d+QzloH;D1!<5hV(Q#1&{gzgJGxEIx_gqbK5g16{+KQXIxMzRF)*36r_`BgQA*U? zzRl#5fRAfkVFm`PZC%)oE-?;NJk(n2Rsy0dG8u2{ z%UsGLOt{>2y47H&zeryqoe)1r57j0(f)_!SOfhSNlIhyaV$Et+)(}jRwu&dI^u+37 z9muUDE$Ty$VymXEsWzg|Yw2h2wY9dkZcQf%vnuhr2qbeg2(8F^U6&2gznP0fe;=Y5 zQL9arJsGQURu@?xV`*U3v~-XiMuG5 z=w8+$oH6&}AtS}gfn?Rxv+CKER13=uk(|ObV?)*`%};r-C&VI~Q>iCoyDZUVR9G)~GtDo}Cz?1?jCd^}fJ%l&$^q!DQ0m%(A|7ffuWWu>mhBal5cVkc2tcR_yi4mH21RAtss zCoF-{_<9^-#-+P@FvB`jP*P+=ovBh~1JukRiK8&YDWZ5#jB$ifouhT*_oy?v4hN$; z?Tc+qB=ji;zT&0ykvN^$m54Kb>b6RQ(qM{RE2Hfz3UtqkRv+CXf`VF+63NV6n1VMj zn!ux#O1sVJUbd&xGPHCz8IL5Dl-jn6UqK}*iaFiKKXoPc0*0Big`T)tQ!FfXBc%Gb z(y^M2K4fjumlka(v#eCKMjTy8iYO_?CC*z(32g02>2qyDDKb43>)q~-aqU#JYMLp5 ztJ-wr_GoL563QHXlw(zBLCCmMv{)GvtfxDb5)X>;1G$%I_!YLavXtIKT%I9{$=uW5 z(WMvJ{k>22vK|nhWOo!Niuk5*lO$LYxv4ONuqZQDqV*&bG;=2|qo~$uZh4g7!nJ@r z%C7<6T28IxP7!@Ss@xRCGlj5{-#T+Y+aU4uu$8TRO-QOpRU~K3-e=`nz z<7^h;P~KsCN0<1d8LQG{?b}#ClciO!Z8DFyyGneb*v5E30*s`;&rYU7VF0 z*0rv$-?*W^x~^{h9d2v5lUi$aG}=Hx>N37@m&33AS)a7j-F0#F_V;YXSf@jB{f4Yy z(_M*ZO3G{m1-FVU7|l|+y%*m~j;ql`$)+t^64-LFWf{Mr@dS{j_6v5kr*J@Mkumb2 zomct3MK7c4>y(|3R_PNYYL!|=iD;Q6dKJE!MBIL;{-H?ghDSHFiq~V^#uiz3#d?zI zT~aUEpHT}}t*%_xZ+{>D3$cEcr%cHqtNf1sR65a9;FL>tEV*9?snvOF##`aK3dlz< zyzvJl+jqqi7~^*tH=!L(#8S%l;d+g=6NWgIU2aY8uy4QJuFO>I4!aUp@5t6r+HnWV5Ye2raPW0-d5%v*?P+L z{#`3v7MJ1%%(xR)*?4p9L@(}awUa?bwd>9})MV+X+z#EHzl~L;sXY;_pgXo^Hk?pw zvJ=BH)3US!MP@x)lExktx4f)-b<8D1lmV0tMBeZ!?MU>~SUdXKleYLD@jc#@8IO8u zG3Az|BvtAakINL49a{x_$|v~>_*jB_l2c`4|8PgTht(sdGMZTGyX1b|a!9dmJoyfw z)Z^N`+GY95cx6N`5!a=#=ce7$9mQE@lb;L%$yS%FRX1o(IXb)hM6l^1TxA8Ux#?!I z^j48*8TxN6M|#IADno`XUq;%u;(T1Din*2bpzOdFh>I$-ku#5+8j5yf709)hUq+|P zEe*33mmpiD3AShOwYmBzjZw>7r&^BzuEvfY#p%BOjf^*x%Y$4I&vVO$(7{fkbnCE4z zYbW`}dX@fbRlfgK^a@%dh7FEB#~;Xawbn)`AQZ8qnZe(Uw9=ifzSB;eGb7%8NO*oXUQheadn|G)(q6%f_ z(|2=0>YoXBODzL|B^NVglrB_$G3EvaLPqW8ru$pt>75)^QM6W0o?M7-zkjZ@byOcN zosROuUQ+}Ac0P|9Q)RnWnr3s!%cr_RZ91TIxv(p@#>7{JWG3)n?b6eP`MhAGRsvZ{b&c zy~6Em+CXCB0AmA8@3GI(=PTR>bXzzRZ%#2Oh+=I+rO3XJYsq>xmA10_P(ic?x95mI z6^F0h-jdBKtpm~b>_O6jvM<`1ruedvGoBOxOCx1wFNE zzZW*CzH37Kff%l$N7Vu*voOrAi!)w&xsO6`fv_-SZIMpgx46HmyHh#0?^_(L>XMrS z?qfYz#lnd*NU~VFZ*k}zcDm;HN4><0E#rX=$?mvW@S}-EeDwYo6ANR-_^0ytuMt6Q z7m+?q!1&P9jwD(|9&&4#-tf0~u()JW#>5f*FS}6u#2KM9g4S1h=V^ybaZ%aF%nvs% zlPrTrIbk?zEoxVa-Ax{1%W0nnZ0}I(E4>mxGwNkCl9t;a1>s(Aa-N@~viXVj?d{9r z?Y-NUZBVYnx4#m~9h<1P_r^ZEraihTvNpT*W#7H@-h1y|diOmmjl6azrGr=5HESaH z82Vb*$5M$nYDkY9X-6&BE?*CeV|yz;o?aONS?7?;2e)_(uaTfmFT*!yg0k+BtyA%c zDwh&zsv;^6@;#Xn8mE&Q7O#L^Zj-2eu=SyJ>~XDIyQWs;Q-&Aq-5r;aywq-yn-x>` z4t7(dsv=pk{m(|S?0vGE&!W0_TP(HI!hMgG7*V6PM!CduJJO6%ZaNFKq@L)OzvLN0qQj4i1E;@8SX1@x^>p+;yBB>9A7ubI4E`+1ClvH=2B&v zs2h2N&T?20WcjR4WWB8^dR45>>1sp$IBg`u{c^8!W1*Ij>u{z+;q++6_aCvS+O`~dp>Cc*AsxUtPG7)5S;DFO> z&`jzixFXvI?x{2azn7k!bta#mbuM#EaEx)Bh1MHgq3io@)xIm(4e>UxPbuamW$dRp zSTf-{$HEHC5idhFGGB6|^cugLf~CJRe}O*t`>(?@(d9($`M(&FO%Bq;Pn95a`%I=sQmvg+oSt({-2Xv?`g4820= z)$>dC1lG;B*UvAhetv$j#A)F;OZW9nuj?q z%@M~YOdhe3aIph2WeU{kL?Nx_kmu||zrO1HQW}eLKNV=0U%IcTdVbkparON2J=d+9 zA1YcHxM_YlH7TopVSZ`#NfP+V{NlP`9Z}>dznTBM>g?rQ$FI)BubaOp5W6WiR&_9v zOCXxGjXaLI^2$}`Rnl>)9NBbCIl_T0rWm!JV$=o$Ek5Mxpk*y5sne3))vM0uGWE-* zTQ@&k^uc*~1*{J;>#?r{|9I&}4sC%j@e{s9&_d8E6-CQo2wF3=+l1!Ieng9zsz2dd2%k3L`vUaApvc&s zVn#_|Q0o6YlJx>{PR=i;3#=-5_Y<$YXx7PxTDK5LbCB_4KY5eRxiP5vDFjdH zO|#BxX~Q}44Hvy0fhib6O~JsZ54kR=#<#qX{!DPz37fn{r-XWSyQ=X|_$9(?yy3}g z_$k6GczAEF@M*$Z2*1-4-`=d_OMA$JyivkSB%EJ_V-d7AXzvt)e;bEVRH-3PTT}<@ z=9kyz5lKS&IZ2vv(saj1rk_KBR!=`G`4#>#_%HhNzstj~~Xl2@8ImBcBPIQ-Q3hgJdYzjOSH+)R<~)1+G~8Bqr{SG`;JyBgPQ zq#q~zj3+!4_<#sKvsqK{34Nkuv#=@lsux)4?>sr z((UMu?Je1nO^~$1D7??W``_6PlI}F=7V|vo5~Je>rJuBZ>G8->L(nUQjlsZrPheee zYfgEkFT)I&bEGRahWv!q0_`lcH!BKF0d_&V1dW%Lm^R4d-|5Ms{#rRo+T)~i2nwwu2d}pDZfOdz^oaWB;fh2=Bf1Fb1S|2r49mH5DVAf;0j>_+UHM%3ywx)l> zf!&_EWyWY4{;t=|I!8@gD47gAY-Fw>xYeB1)80x9;gh-_A>It}cxSKrh50`L?FzIA z`b}i(DVaBNZJN<}Mc?o@YKXF$qZr?C2~RYu*CP3)v3~woAn@-#tg*noa9}i7`i#ceHG7rovT71niA0v%JZ<=+UpKBgcWq!t|%r(JE zvb{|F<+sf`1DxlUxz|(V#$cFW`F!Voc&Fwn@A~-@^NOzbpY(_?`E`*-#qB)j%z18p z2~U0vLFwlMk{`UTeIoG>LpuO%r-`rTN2IF+`Nb+Q)-`q|;b-8ThL;yK&DFl4z+V>5 z(2`FXN;&@KStnuQX67e5@J{dGmvXL#cO2dl;pHcJN1z>nc3KF2vc$9=IO?DG)5Hz) zlzhL5>&d%4KksAk9)Oo_R6o)6r=iKqLcF>@WOV&j&LHHSoLD|gQh;1siStyY9 znHxoSRs0V9$5ZjHPR^ZEZA|hUlMW5?o;*^mlA}23Op(rDZvMtL3@OvtV;a^3`*IT& zJw8qvRd>=x8Ck5)AMcT(Ga`!lR!Lnj@RZMRKr2;|ZpnP~_L5oWFHPAzZU2BrK*d~F z`g|q)XW)P3ZGy1oG*flZCanR|X@08Y zJiVNxrr|vV@2E*PPlol{)gydjfXbM%8R%Dtx7fr}bJYgjJE8-^{3{J*byWyj3$%sM z_Lw;NdG+K9f~w1Y;-ralkBO75%i}rqhRr(4zy0uH>Z+g6PVsLqw7U&W+VUK4tHSA^sa5dYNO`1Y<9|ARj9Sz^7nP_-(%a+)-c@*1n|YouB9 zYIh22@Hic6f)A2ap_!!RBg_KwG_M!)laDZUX(Rj`;qT$RQ0Llxc}k%%*qJLF(zl05 zV#VAN3ha_$8JT-)4aC=6#n3 zrIva2jQIQpM1Vb`Mf9e`+f2Ok#JestPiO6N@u{6;sO3b&ztTj!QQ{rvvyl6I>{^M} zpC7L}*p-)(T4zYz&xvy4)y^LTJY`qDxXc>p-9B|E1?l5OOmc0+cYOja&_dAS(B#F( zo;1CFx^U4SxO&9fGMGjG=93o=Fp-`8q z&QpTYfl`)dh&M_+5ncHSZ5-Ou(BxcxVsoE>wjbIKA>_<++dQUQLvWqv3UO2E$z*n# zxTpj5lXT0WorP9nXrj9+p`C&D+s2{rw!k|LZ@t9NDNn8qvy$KecuQ+$oxd==J~|^5 z7%bEdlFxDCCW(8GiJR3|g*L-9ynEqw>r_XaE6@g@9XIjwbnJ$_ZeeyUv|+o5TgL#o zOghy*I;Pg_D+C_#kq=UQ)Q4Of{Cyv4wX%iB$?IHgRz9V_PCz>g&6SA|w6oC8KpXe3 zTj0;~=8r}2mA--TP&fB@sUp0MaHd)HlRgMTi$i-rC^>z--8*F{T^@&b6y8-C-X`ON zYR%!LTdafd9)h<SJ>&VFae0sQsF}afX2PA$Y`#nm`EWOB{|99#Sv%{n)Kx!`>%-8Bq1|CMnJJ2VsvV6|t` zh!Z!nfg&3k8PBo}{R%wc&9hFM zmxm24<$A&X6&{;^yW#nLFHfLb^FR~1uY>0-JokEewrLg#j}m_Q8sU2hU&xnD{o>2G zIYjtM!jqi)jaT+4a->r1C()zlh?gYZCrv!xw*6qCZ6Re|cq{fhaRHU5v|rh}Y@JpT zaEb7{yy1`PaFL76gcm#R57S-EY(&R=r-Dwye3V(@^nT(7WCdJQTk#vyj{dg^DzOx zb&YF77k%ANMKq{<<(sJ|_(I_Snj>Gtwm=4C-k2g@ymeOJYr?hAE1X3NPH&()b9)4+)T>iF#{*A(W8Q$j%uTTGm)r}qblP9@J+Z`hQ z{l~OnpK!NNKHRTTUznoy89Ysz;^vTX+8J0DJuIc}m@7QAOE^ZaPF>)8yr&n;!BMOxRUD&cMI#iWF_|+v08ritTcc_!aM-b()O~d-6h4XN0j{ zynmT1oR1Rs3~^WX%{m`7<27@yM=0NI$#|-O zb{JZ_5OU_m+`aNm*~HYmwS{<7#Jk2A2?h3=;ox-@;uDlMe1`bR{%h*kke~ZfjNnDY zKS%sY;!7ReJ}oo1R7g8rA$*4L518<58~1yfsUhgyp%=fIlx^i**uC4i|IYM}U;hS< z`P2|p5efkeH0@NB6(gUe%mhpdlx0V z6lIen9P!Dtm;Hzy0+N3f;RA&CnQ)&vheV_b6f<%u`aVwl3F1%9J&%NnzKwFuOv9du zgw6Sad4L&E#`6i%ZQ7mnQw!}Zw1=P-OIi6z`7c5XL;IN!^5#V28wm$w($2sAm-4In zFCpIlH|y-pv_Jl#+zMYVqAuM0~2IPoKVmEpcjeD)ak6>(>^$2apspZt*-X}=>9 z|9w1zP*PZaGv^GB+(iPX{M#)~ob$vl z`9q%RxPgnjemC{w9;v&efu!NQ6LVd#=ofxUx-s}T+&%_~l(%IW?fF60j&sX-ThWL7 z+f(M51H^Co<5_1b=ThFRUJ9)Bs92?&C*XY=-X9uXZ`;((uMjU=&NdUvdet|ViC1@E zuD-GJwF((!Xya#2Fxd^PkK*pPO6uB1Jd&wG|fo zhYE+PjQumDdF;bkdst}G(2hcrY~+V3u&zKGhxRTZWZOCL&`oBBYziU|CCEdu+F!1^ zoB0g>h~dwbXM1P9ts{JG#JNJ8FPS*r{xR(n3LNlhpZegM!rE#3=_qM-eZ=T-(k}NBM~%^ zy4SaX8-sJ(K<`;ZN$23ftW6C$y)bjYE@dOZiE8$DkdD_8uYRlo!pD zv0ZdNr{OL8(`VFt$XuO_1&)zBTy% z1zgZRPsx3~xpNY}*8_e!tTq_+Nx3OlRO&a}j7=6=j!yoYS?9-OH%ESV2L9GJU8T#D z#J@=V$IIRLd2`MB`Q!7X84IdhtM|W%U;5?jIOfti!M_q{|CA|HHcjcLPvv!r^slo2 zh&M*Oi3)+u!-mH&q(0crW)SJWG=S#PU7!< zcGg*E@*WHX*0_4+0Aa@nd&;L=a?e3JSL`eszEi|0e{R;}dL%*Rc)C}sK zZ`B%B+V>#o);*7|y+->MS$=|A9h7pNC4S3^S*NOq3pFmXGU3ikMR)iOi>6?^uk>j> z8)8vib#m5W3sU_=$J9Yv>7m)sHbbj}_NZ{FcH7RZ!kxNp{D&lE+zrnFJn?IkQ5>oT zc1C^hF(0b({Y$!MNcZ5^cy4KK`y*1c-LLIxl|wk+dX$8vPpTL+$mGvbXaZVWcK_tYIGd@tb-&0VLqqTBrH zR2`J`r-^^ypR;?v-;>TOFF z6u7^07L00cmo`chujD7Q&UO>etCNslc@A5iHYuo&jI(j#HWT;DbN9a;SnDI0jI*OY zWVL1~FhlB;4YBAQ)Nf|iX`HX?=PhT(hWMmke{f@$+}`5Ta54tcqQ|Kcv9}m#7*JOYAhUN6%1(oxkJgdl$GC+BCES(B8t8%V}e**q)X%pUG zVr*JjqBjaZOYa6A7~im^3$;G}U@P?>#EZ;n@$*XMFl6GcPvN zNd-CAt7mW1#4oumn@47x*nzP2>CsxndW?_3yBc26_tI9XJZ3#5I$(nEEpvp6+)fd` zoA3e7Gx52TSFN&Yg6#IFvxZ=^_GyUTC}**AiZ}-;gC6$;1pYuAGKwLuwgRcom4a>sLTk!nA6Z?%#8aNr}p(S2VCBJw*xnopDFV$NOp zEHlqnN}G)l{tV%NnkjR(&x|Z3eeElZ0f|3F{3~yD@}B|n)_FV-@Y_YNR`(&;4=}z~ zWObESmQ9^QfyWA4tdhL95O<8Y2RN6ydGslp4G5XK4FUNfct5=5Z*!b)7V`5c*)6iPVu-8xB{L@l+wzju_j)dBCb88{=6zRr<>4mLoM}q!Nr=p~ z5N|W_wq<0tKz~MjogTDV7x51efB$`s^Igt;^@KdEFAt^Wudf<>cV(O9g&GCCERMsH z{zHrp@|r@Q`sTHM{$!x&{Y5@0D4SO5TSpoPYaHiI*QhUhn1y8^uJ{=C5`Skc`tvnz z8ESs#y4rn3gT;HUD|)c#rso@8s6JW!72eEN9b5>@QTR7+GWNX^@pmbwvV=_%7M~;R zB4GnQVWO`~*3#~TNfqQLv_;THJv19y2-?%o9_3uxOZicGJXFo1kZg_?cuv9dPR_GD z<^^w%7IEx^r}z;k=Y37Kd7qQC$w9)G6E1pJ((v938K@WA+Za>?3;!wjTmB3Dm*G#p zLVjtBN;YZ^z#rsXenMLfZ4{cf%_7jAhPFU)q0_)9wEfW3-Ygp}k1=^m{M{!04Te`} zqbB}qJ+wp64if(^5A7JVqtIS$XcgdTXcN$Ik(f4P+zl4>dG|FXk4x~Kg-_Z|enKmW zK!-M8QMAp!2-*y^YN4q$7)?@7WJT_b#y@TzNsj}yL{ z@Y_t8ls#zPzb5*2lJI82ae1jSXKW`s_jzvNy#j9=yr|1O-W^^uOYId_KFm0UcSiv) zufoghLpK#XV;O=!O59V#b;nGe9%aWiM~|v``yg>H5$AppF52E_-VGPs?ypm%Zf7O_ zqmE~Pk-k&!d;0xsap5cDC|=Kc>oF(uY^2Z@LMw+RDoK9QcU91AXrlAnacw`LhrY;p zGvQ&v|4zc|=C=io%rBO*M4?YZ$NV(yj18m8lKVVp3&ErCmcH|vYq-#V_1V5I(w!#V zH0l1zl)lAAaP>kxEktNC+85P zO~y#0iZqn&fT{4bB=FlmjGZfU1;t#_48&MW#` zKj(wox~s;?CDPd6?KnGq`X#eI=cbW@e!*reCynKgAa75YIga@}N?VEyHbb9+{t?cl zE%WreSnF7n$2euj_BNOVqkGwahH7IZdI9h zw_2d6+;2;f-q3!q6Qpsl-*NtN?lMG*9&|+_S9rOjvY?w6k?uk!>*5{wXF1pHigJ?Y z`|!Mot+kTy@@K9(VbM4E`R12CuppQ&-f6w#4R62mo(g52NYr_^6uteKk2}s+Dcj7S zUv=W>TAutTqfo)(EoB;O={?%3I6c{-K z|6$g=e|^>I0z-$dI%9%=bJe*BPJtDlbeyqIU3GSY6W}N~1s(!tz+<3&Kp)*;9+nIJPlf(gYQ%DgLU927zL-my7BCFP!6djB90Q*LC&8nj^&j*zXoKg$Fn9$_g5{ruAFKjrz|COj z2c!c|fX9Uno&(E%NV|h$V8!RCKNtaLz$h4+zUu4*li(q65{8};0##u1@isLRcARk19r*v4E+X% z!NcGfcm^B?r@`b;k=uXd8teimz};Z@=hPRR0xy9xzocD`(;vKZd?#rC2Dt{q;AwE? z3hnSk;$I~koBg_#)1Y@ zHRLDZ;IxE;B`4_Ta^9f@+OMVjVB}`XFZ4I?KE1C{Pp}DWTSU8n*6)%ISO%U02f&gS zXfJRPn0zDk1gF4*VE9eEYXO`9r$Eb|b*z)nK^q(Z!=QYVV<$LvEAMgzC&4qIb=$0S z32X!HQ}F*D?Fo)o@Lo*0Ud(eTU!^>}i?R-!0e8#w9n>4N!9(B#cm}lYB>%6GJ{SfE zs(7E3An#wC5L`<5*NL}`dV@(Y4u(U-2dBWw)3npwlml!7)8G_%1e^gUz_R7sqx}uS z-^#Q0;LHm8QLf)cI$&re`TrB;0Fz+Zy|gbF0Z)N#;5l#tEc<8pzzQ(5igJOYU>uwQ zM?vfD)DujCr@*q+v>Vt~jXX`#UNz(cM(Qaim;@)lDe$s{H}G!iZxY@}KY*j)LC|iZ zyx`cHS*QF($^kA1XTT=G2YJsrXg5AdHfgJ ztCxC%VQ?=P0S|)X;3?2b%sN-V2{3Y&^uQ=smZTlPF!(e$3LXQ;-i>^G2Y#>|oB}IB ztB-qvzyYue90PZQ6W}OVmLfhFNh7cS3LnqPZ2`-kLXJUekY_0WjrRC6^ahv&+rTjQ zqaOrA&(IIx*hk6t9OVQ<;J{x{UT_NBFV`Pqyn*B3Ik_IAzrIU*{}0+9wEmj>KpUI_ z!{8-w3|#oXDbFWqFEIQm+DERB&_Dl9xxfl=608I5zok8e4juvr#<}+!oB&Iwi2rxA z2RQckv;#Q)8NMe1+DEDX|Dk^1a&Ytu#0Mw7IP07TtqJm27Y7`cHoUZVUrI!+g8 z-{d%l!7=bGSQg~CNPB^sL95hpj(~08Bxo-n{KupRt_CN-EudBAIJ<=oj)V4VshiMm zCcl@73vL11UgtRbLHqTT4Ge*oz%W?y6ViK=<1~Sh+u#GIe$R1Ef#Vg9vuK8Ea5Xq^ zJNbe3n_16-W8h^lT*K5+al$GIZcRgP2nGumwl2RN~m^(z=z zM!DrWMA?2$x_3LyGvL4q@|Nqjk@h9hc>rE;3XFqg4^mz*3?2d_;4!cbJPl5OGoan< zIOV?}PjERn0Y<^HhuD(?+rSeN4xR-Ez>DB0X#J9W!G+)iSOrdjVX$ni~L2pk8Gfz~?G14CfxugDLq0!P7SZ~}~jR)oEFFan+cCqe5n@gAn!U~;|Vq`?Vr z44edyf-~SLFtovOrsW#6eoYx$$Op7GvUer8i7>G25&GdbvYPv7mR>oU=*Bs7jg>PZSV=b9r_jM;4|RZR^$w9>!6-j;oC+U;8+)B z2PZ*HS|`~}*=MO2$Q0s)o}gdBfw<$G6M7GF=urNC(gG*8Q*XKcf4~3N0{=}du<)*c z^(KznIhJv((#m+Nm}y^Cvc0X<=`&)|DN+1J_w@@Jht9Z>rjk`GB)SGc|fl(Zxd z`N@5fk_W>(A!+_se^cKMSoUPVI{m+NJ4pQS2igDPC>!ORW8!B4>n!0(&c`?=IV{3$ zj>A0Y;nc({3&U`Gx76))eJ4fQN=OF$FACb6|fFG zOnH7vU;QLtl~Jxz4*M4YYdJjS9IJ)*Lcp4YcMSS@(1td3F<@Qhyn^#e;o;*+i@-Bd zKjD$|xgPjFyqt$Q-wS<`@Rh>Pc?ozNEGJLv8`<`_zR9v~=D3|>1xEwNCXP;y?Hq#~ zALjTt$7eZS;P^Jj4>*3waXt68+{|%1#|n-Hj!hh$9NRetIX=wsagNV&yuk5ojvsLR zlH+>r1G$;wc8(Ps4IG;|Iyts;403#!VP+Z;dO_$9~n$opTYMU95nbLgC8~c34@9^}OjV8W$V9-{3;zUBWk- z>$t%k2KN{|VDRGxKX35s2ES+UKMgKeuG78M;4*`a23rhvfTFA72GfQ!;;1YvjgG~lo3_fl!Zt(pEM-6_|;1Pp=Z}3Y7 zzhUsK!S5RUp21%jyl#aq->VJ2-rySzE;Cqbu*KkG20IPzFgRfFX@h@m@UIPi+TbyR zCk>u8IBoEE;6;O%4c@rYl+)mC2H$FMy}^XR_Zs|w!9O+l34{M&aKhj>4W2XjGlPM9b-p(l zyxHKb2CEFNGT3O)YOJkYWmh(?-FSz+eCbLx7H?!c$e4u4H^JjkKB0W~-CSEsQ(b(} zJl($4TFO^>Q@eUJru(d=UG1qZYiVCBE+P6P8BbeF(|m!Q%Y=Nx+FBaxk}rw&#Ik4V zv*=4DR7LJfEajuP?Qv^qCtr1LZSU)A-$f?bU~8#-?Ku;$tGB(UyTe+_r_0s9r7BaM z+16CbTFQqxd*t)COZnn)Z0WY%eputtC46By)y*eUU-3`u5IJNP6T3u?sfGGl>;!4A zG7hn0M4t$s*eh~~z2g2{n?mdkv1x=)>=-$=+?1UoBt1E9<&gdmKCzeN5PQi@M|es& z?&J`@8V<3u50vC5k9w$!t3%q#kmwm(i8jf z3Vd!DB$b9BrkrYb;ZwHH7qO=}m3ES!#F29R8HbziWo)F&@GTUA`MGI-jBA%q?CP>F zV?(-3pv!mI!)J-zHG$pk1`=j-$nVn}lE0L1;tV_|0@lZWj|=m&4Soicd_(41_`K~R kVRFcRKVq5r9fMEyQ{A6i1mRU}Vgk;<_brzRlyLd||7*FRW&i*H literal 0 HcmV?d00001 diff --git a/MobileLibrary/Android/PsiphonTunnel/libs/x86_64/libtun2socks.so b/MobileLibrary/Android/PsiphonTunnel/libs/x86_64/libtun2socks.so new file mode 100755 index 0000000000000000000000000000000000000000..59f18fc790cbdba091e5f4ac024f32ac754b5cc2 GIT binary patch literal 196656 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

RCGOnZ;XpoeaoSLDbNoU9=~IK*FKBxm7l>X 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�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 literal 0 HcmV?d00001 diff --git a/MobileLibrary/Android/make.bash b/MobileLibrary/Android/make.bash index a1c58ce47..3888b23f7 100755 --- a/MobileLibrary/Android/make.bash +++ b/MobileLibrary/Android/make.bash @@ -55,7 +55,8 @@ echo " Gomobile version: ${GOMOBILEVERSION}" echo " Dependencies: ${DEPENDENCIES}" echo "" -gomobile bind -v -x -target=android/arm,android/arm64 -tags="${BUILD_TAGS}" -ldflags="$LDFLAGS" github.com/Psiphon-Labs/psiphon-tunnel-core/MobileLibrary/psi +# Note: android/386 is x86 and android/amd64 is x86_64 +gomobile bind -v -x -target=android/arm,android/arm64,android/386,android/amd64 -tags="${BUILD_TAGS}" -ldflags="$LDFLAGS" github.com/Psiphon-Labs/psiphon-tunnel-core/MobileLibrary/psi if [ $? != 0 ]; then echo "..'gomobile bind' failed, exiting" exit $? @@ -66,6 +67,8 @@ unzip -o psi.aar -d build-tmp/psi yes | cp -f PsiphonTunnel/AndroidManifest.xml build-tmp/psi/AndroidManifest.xml yes | cp -f PsiphonTunnel/libs/armeabi-v7a/libtun2socks.so build-tmp/psi/jni/armeabi-v7a/libtun2socks.so yes | cp -f PsiphonTunnel/libs/arm64-v8a/libtun2socks.so build-tmp/psi/jni/arm64-v8a/libtun2socks.so +yes | cp -f PsiphonTunnel/libs/x86/libtun2socks.so build-tmp/psi/jni/x86/libtun2socks.so +yes | cp -f PsiphonTunnel/libs/x86_64/libtun2socks.so build-tmp/psi/jni/x86_64/libtun2socks.so javac -d build-tmp -bootclasspath $ANDROID_HOME/platforms/android-23/android.jar -source 1.7 -target 1.7 -classpath build-tmp/psi/classes.jar:$ANDROID_HOME/platforms/android-23/optional/org.apache.http.legacy.jar PsiphonTunnel/PsiphonTunnel.java if [ $? != 0 ]; then