From 5f448ac2c2be033ab003f257637b9f90afda4cf8 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 20 Apr 2023 12:18:54 -0700 Subject: [PATCH 1/5] Enable a SendPeerMessage EngineHook for Fuzzbot --- .gitignore | 4 +++- app/app.go | 15 ++++++++------- app/enginehooks.go | 10 ++++++++++ peer/cwtch_peer.go | 4 ++-- peer/profile_interface.go | 2 +- peer/storage.go | 2 +- protocol/connections/engine.go | 14 ++++++++++++-- protocol/connections/peerapp.go | 4 +++- protocol/files/manifest.go | 10 ++++++++++ .../model/{peermessage.go.go => peermessage.go} | 0 .../autodownload/file_sharing_integration_test.go | 4 ++-- testing/cwtch_peer_server_integration_test.go | 2 +- .../encrypted_storage_integration_test.go | 2 +- .../filesharing/file_sharing_integration_test.go | 2 +- 14 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 app/enginehooks.go rename protocol/model/{peermessage.go.go => peermessage.go} (100%) diff --git a/.gitignore b/.gitignore index 4d509d2..7e47152 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,6 @@ testing/encryptedstorage/tordir *.tar.gz data-dir-cwtchtool/ tokens -tordir/ \ No newline at end of file +tordir/ +testing/autodownload/download_dir +testing/autodownload/storage \ No newline at end of file diff --git a/app/app.go b/app/app.go index 8ff8087..1e12b88 100644 --- a/app/app.go +++ b/app/app.go @@ -29,9 +29,10 @@ type application struct { acn connectivity.ACN plugins sync.Map //map[string] []plugins.Plugin - engines map[string]connections.Engine - appBus event.Manager - appmutex sync.Mutex + engines map[string]connections.Engine + appBus event.Manager + appmutex sync.Mutex + engineHooks connections.EngineHooks settings *settings.GlobalSettingsFile } @@ -94,11 +95,11 @@ func LoadAppSettings(appDirectory string) *settings.GlobalSettingsFile { } // NewApp creates a new app with some environment awareness and initializes a Tor Manager -func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.GlobalSettingsFile) Application { +func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.GlobalSettingsFile, engineHooks connections.EngineHooks) Application { app := &application{engines: make(map[string]connections.Engine), eventBuses: make(map[string]event.Manager), directory: appDirectory, appBus: event.NewEventManager(), settings: settings} app.peers = make(map[string]peer.CwtchPeer) - + app.engineHooks = engineHooks app.acn = acn statusHandler := app.getACNStatusHandler() acn.SetStatusCallback(statusHandler) @@ -373,7 +374,7 @@ func (app *application) ActivateEngines(doListen, doPeers, doServers bool) { log.Debugf("ActivateEngines") for _, profile := range app.peers { - app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()]) + app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()], app.engineHooks) app.eventBuses[profile.GetOnion()].Publish(event.NewEventList(event.ProtocolEngineCreated)) } app.QueryACNStatus() @@ -398,7 +399,7 @@ func (app *application) ActivatePeerEngine(onion string) { profile := app.GetPeer(onion) if profile != nil { if _, exists := app.engines[onion]; !exists { - app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()]) + app.engines[profile.GetOnion()], _ = profile.GenerateProtocolEngine(app.acn, app.eventBuses[profile.GetOnion()], app.engineHooks) app.eventBuses[profile.GetOnion()].Publish(event.NewEventList(event.ProtocolEngineCreated)) app.QueryACNStatus() diff --git a/app/enginehooks.go b/app/enginehooks.go new file mode 100644 index 0000000..97d3bbd --- /dev/null +++ b/app/enginehooks.go @@ -0,0 +1,10 @@ +package app + +import "git.openprivacy.ca/cwtch.im/tapir" + +type DefaultEngineHooks struct { +} + +func (deh DefaultEngineHooks) SendPeerMessage(connection tapir.Connection, message []byte) error { + return connection.Send(message) +} diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 642c8b1..1f793be 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -293,7 +293,7 @@ func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpass // GenerateProtocolEngine // Status: New in 1.5 -func (cp *cwtchPeer) GenerateProtocolEngine(acn connectivity.ACN, bus event.Manager) (connections.Engine, error) { +func (cp *cwtchPeer) GenerateProtocolEngine(acn connectivity.ACN, bus event.Manager, engineHooks connections.EngineHooks) (connections.Engine, error) { cp.mutex.Lock() defer cp.mutex.Unlock() conversations, _ := cp.storage.FetchConversations() @@ -323,7 +323,7 @@ func (cp *cwtchPeer) GenerateProtocolEngine(acn connectivity.ACN, bus event.Mana identity := primitives.InitializeIdentity("", (*ed25519.PrivateKey)(&privateKey), (*ed25519.PublicKey)(&publicKey)) - return connections.NewProtocolEngine(identity, privateKey, acn, bus, authorizations), nil + return connections.NewProtocolEngine(identity, privateKey, acn, bus, authorizations, engineHooks), nil } // SendScopedZonedGetValToContact diff --git a/peer/profile_interface.go b/peer/profile_interface.go index fe28871..9079bfe 100644 --- a/peer/profile_interface.go +++ b/peer/profile_interface.go @@ -69,7 +69,7 @@ type CwtchPeer interface { // most functions Init(event.Manager) - GenerateProtocolEngine(acn connectivity.ACN, bus event.Manager) (connections.Engine, error) + GenerateProtocolEngine(acn connectivity.ACN, bus event.Manager, engineHooks connections.EngineHooks) (connections.Engine, error) AutoHandleEvents(events []event.Type) Listen() diff --git a/peer/storage.go b/peer/storage.go index 197cb16..350c4b1 100644 --- a/peer/storage.go +++ b/peer/storage.go @@ -47,7 +47,7 @@ func createKey(password string, salt []byte) [32]byte { } func initV2Directory(directory, password string) ([32]byte, [128]byte, error) { - os.Mkdir(directory, 0700) + os.MkdirAll(directory, 0700) key, salt, err := CreateKeySalt(password) if err != nil { diff --git a/protocol/connections/engine.go b/protocol/connections/engine.go index 5ad7e0a..e525bc6 100644 --- a/protocol/connections/engine.go +++ b/protocol/connections/engine.go @@ -72,7 +72,8 @@ type engine struct { tokenManagers sync.Map // [tokenService][]TokenManager - shuttingDown atomic.Bool + shuttingDown atomic.Bool + onSendMessage func(connection tapir.Connection, message []byte) error } // Engine (ProtocolEngine) encapsulates the logic necessary to make and receive Cwtch connections. @@ -85,13 +86,21 @@ type Engine interface { Shutdown() } +type EngineHooks interface { + SendPeerMessage(connection tapir.Connection, message []byte) error +} + // NewProtocolEngine initializes a new engine that runs Cwtch using the given parameters -func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, peerAuthorizations map[string]model.Authorization) Engine { +func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, peerAuthorizations map[string]model.Authorization, engineHooks EngineHooks) Engine { engine := new(engine) engine.identity = identity engine.privateKey = privateKey engine.ephemeralServices = make(map[string]*connectionLockedService) engine.queue = event.NewQueue() + + // the standard send message function + engine.onSendMessage = engineHooks.SendPeerMessage + go engine.eventHandler() engine.acn = acn @@ -320,6 +329,7 @@ func (e *engine) createPeerTemplate() *PeerApp { peerAppTemplate.OnAuth = e.ignoreOnShutdown(e.peerAuthed) peerAppTemplate.OnConnecting = e.ignoreOnShutdown(e.peerConnecting) peerAppTemplate.OnClose = e.ignoreOnShutdown(e.peerDisconnected) + peerAppTemplate.OnSendMessage = e.onSendMessage return peerAppTemplate } diff --git a/protocol/connections/peerapp.go b/protocol/connections/peerapp.go index 08ac088..e2ac4d6 100644 --- a/protocol/connections/peerapp.go +++ b/protocol/connections/peerapp.go @@ -23,6 +23,7 @@ type PeerApp struct { OnAuth func(string) OnClose func(string) OnConnecting func(string) + OnSendMessage func(connection tapir.Connection, message []byte) error version atomic.Value } @@ -48,6 +49,7 @@ func (pa *PeerApp) NewInstance() tapir.Application { newApp.OnAuth = pa.OnAuth newApp.OnClose = pa.OnClose newApp.OnConnecting = pa.OnConnecting + newApp.OnSendMessage = pa.OnSendMessage newApp.version.Store(Version1) return newApp } @@ -154,7 +156,7 @@ func (pa *PeerApp) SendMessage(message model2.PeerMessage) error { } if err == nil { - err = pa.connection.Send(serialized) + err = pa.OnSendMessage(pa.connection, serialized) // at this point we have tried to send a message to a peer only to find that something went wrong. // we don't know *what* went wrong - the most likely explanation is the peer went offline in the time between diff --git a/protocol/files/manifest.go b/protocol/files/manifest.go index 3ffaa6a..7c3dbdd 100644 --- a/protocol/files/manifest.go +++ b/protocol/files/manifest.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "git.openprivacy.ca/openprivacy/log" "io" "os" "sync" @@ -237,6 +238,9 @@ func (m *Manifest) PrepareDownload() error { defer m.lock.Unlock() m.chunkComplete = make([]bool, len(m.Chunks)) + if m.ChunkSizeInBytes == 0 || m.FileSizeInBytes == 0 { + return fmt.Errorf("manifest is invalid") + } if info, err := os.Stat(m.FileName); os.IsNotExist(err) { useFileName := m.FileName @@ -293,6 +297,12 @@ func (m *Manifest) PrepareDownload() error { } break } + + if chunkI >= len(m.Chunks) { + log.Errorf("file is larger than the number of chunks assigned. Assuming manifest was corrupted.") + return fmt.Errorf("file is larger than the number of chunks assigned. Assuming manifest was corrupted") + } + hash := sha512.New() hash.Write(buf[0:n]) chunkHash := hash.Sum(nil) diff --git a/protocol/model/peermessage.go.go b/protocol/model/peermessage.go similarity index 100% rename from protocol/model/peermessage.go.go rename to protocol/model/peermessage.go diff --git a/testing/autodownload/file_sharing_integration_test.go b/testing/autodownload/file_sharing_integration_test.go index bdd5835..1212202 100644 --- a/testing/autodownload/file_sharing_integration_test.go +++ b/testing/autodownload/file_sharing_integration_test.go @@ -57,7 +57,7 @@ func TestFileSharing(t *testing.T) { os.RemoveAll("tordir") os.RemoveAll("./download_dir") - log.SetLevel(log.LevelDebug) + log.SetLevel(log.LevelInfo) os.Mkdir("tordir", 0700) dataDir := path.Join("tordir", "tor") @@ -97,7 +97,7 @@ func TestFileSharing(t *testing.T) { acn.WaitTillBootstrapped() defer acn.Close() - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") diff --git a/testing/cwtch_peer_server_integration_test.go b/testing/cwtch_peer_server_integration_test.go index 93d0a56..24707a8 100644 --- a/testing/cwtch_peer_server_integration_test.go +++ b/testing/cwtch_peer_server_integration_test.go @@ -139,7 +139,7 @@ func TestCwtchPeerIntegration(t *testing.T) { const ServerAddr = "nfhxzvzxinripgdh4t2m4xcy3crf6p4cbhectgckuj3idsjsaotgowad" serverKeyBundle, _ := base64.StdEncoding.DecodeString(ServerKeyBundleBase64) - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") diff --git a/testing/encryptedstorage/encrypted_storage_integration_test.go b/testing/encryptedstorage/encrypted_storage_integration_test.go index 78b4f2d..0c81f23 100644 --- a/testing/encryptedstorage/encrypted_storage_integration_test.go +++ b/testing/encryptedstorage/encrypted_storage_integration_test.go @@ -59,7 +59,7 @@ func TestEncryptedStorage(t *testing.T) { defer acn.Close() acn.WaitTillBootstrapped() - app := app2.NewApp(acn, cwtchDir, app2.LoadAppSettings(cwtchDir)) + app := app2.NewApp(acn, cwtchDir, app2.LoadAppSettings(cwtchDir), app2.DefaultEngineHooks{}) app.CreateProfile("alice", "password", true) app.CreateProfile("bob", "password", true) diff --git a/testing/filesharing/file_sharing_integration_test.go b/testing/filesharing/file_sharing_integration_test.go index 5287acb..8dc9b08 100644 --- a/testing/filesharing/file_sharing_integration_test.go +++ b/testing/filesharing/file_sharing_integration_test.go @@ -97,7 +97,7 @@ func TestFileSharing(t *testing.T) { acn.WaitTillBootstrapped() defer acn.Close() - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") From 7255a6c71e66963e193c181df8b4bb1b7ddcd38e Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 20 Apr 2023 13:32:36 -0700 Subject: [PATCH 2/5] Fixup EngineHook API --- app/app.go | 10 +++++++--- testing/autodownload/file_sharing_integration_test.go | 2 +- testing/cwtch_peer_server_integration_test.go | 2 +- .../encrypted_storage_integration_test.go | 2 +- testing/filesharing/file_sharing_integration_test.go | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 1e12b88..df1f893 100644 --- a/app/app.go +++ b/app/app.go @@ -51,7 +51,7 @@ func (app *application) IsFeatureEnabled(experiment string) bool { type Application interface { LoadProfiles(password string) CreateProfile(name string, password string, autostart bool) - + InstallEngineHooks(engineHooks connections.EngineHooks) ImportProfile(exportedCwtchFile string, password string) (peer.CwtchPeer, error) EnhancedImportProfile(exportedCwtchFile string, password string) string DeleteProfile(onion string, currentPassword string) @@ -95,11 +95,11 @@ func LoadAppSettings(appDirectory string) *settings.GlobalSettingsFile { } // NewApp creates a new app with some environment awareness and initializes a Tor Manager -func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.GlobalSettingsFile, engineHooks connections.EngineHooks) Application { +func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.GlobalSettingsFile) Application { app := &application{engines: make(map[string]connections.Engine), eventBuses: make(map[string]event.Manager), directory: appDirectory, appBus: event.NewEventManager(), settings: settings} app.peers = make(map[string]peer.CwtchPeer) - app.engineHooks = engineHooks + app.engineHooks = DefaultEngineHooks{} app.acn = acn statusHandler := app.getACNStatusHandler() acn.SetStatusCallback(statusHandler) @@ -110,6 +110,10 @@ func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.Global return app } +func (app *application) InstallEngineHooks(engineHooks connections.EngineHooks) { + app.engineHooks = engineHooks +} + func (app *application) ReadSettings() settings.GlobalSettings { app.appmutex.Lock() defer app.appmutex.Unlock() diff --git a/testing/autodownload/file_sharing_integration_test.go b/testing/autodownload/file_sharing_integration_test.go index 1212202..bbed71a 100644 --- a/testing/autodownload/file_sharing_integration_test.go +++ b/testing/autodownload/file_sharing_integration_test.go @@ -97,7 +97,7 @@ func TestFileSharing(t *testing.T) { acn.WaitTillBootstrapped() defer acn.Close() - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") diff --git a/testing/cwtch_peer_server_integration_test.go b/testing/cwtch_peer_server_integration_test.go index 24707a8..93d0a56 100644 --- a/testing/cwtch_peer_server_integration_test.go +++ b/testing/cwtch_peer_server_integration_test.go @@ -139,7 +139,7 @@ func TestCwtchPeerIntegration(t *testing.T) { const ServerAddr = "nfhxzvzxinripgdh4t2m4xcy3crf6p4cbhectgckuj3idsjsaotgowad" serverKeyBundle, _ := base64.StdEncoding.DecodeString(ServerKeyBundleBase64) - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") diff --git a/testing/encryptedstorage/encrypted_storage_integration_test.go b/testing/encryptedstorage/encrypted_storage_integration_test.go index 0c81f23..78b4f2d 100644 --- a/testing/encryptedstorage/encrypted_storage_integration_test.go +++ b/testing/encryptedstorage/encrypted_storage_integration_test.go @@ -59,7 +59,7 @@ func TestEncryptedStorage(t *testing.T) { defer acn.Close() acn.WaitTillBootstrapped() - app := app2.NewApp(acn, cwtchDir, app2.LoadAppSettings(cwtchDir), app2.DefaultEngineHooks{}) + app := app2.NewApp(acn, cwtchDir, app2.LoadAppSettings(cwtchDir)) app.CreateProfile("alice", "password", true) app.CreateProfile("bob", "password", true) diff --git a/testing/filesharing/file_sharing_integration_test.go b/testing/filesharing/file_sharing_integration_test.go index 8dc9b08..5287acb 100644 --- a/testing/filesharing/file_sharing_integration_test.go +++ b/testing/filesharing/file_sharing_integration_test.go @@ -97,7 +97,7 @@ func TestFileSharing(t *testing.T) { acn.WaitTillBootstrapped() defer acn.Close() - app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage"), app2.DefaultEngineHooks{}) + app := app2.NewApp(acn, "./storage", app2.LoadAppSettings("./storage")) usr, _ := user.Current() cwtchDir := path.Join(usr.HomeDir, ".cwtch") From 93c9813d9647d4e1650573e6ccd7da006d9cc9d3 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 20 Apr 2023 13:36:43 -0700 Subject: [PATCH 3/5] Move EngineHooks into Protocol --- app/app.go | 2 +- {app => protocol/connections}/enginehooks.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {app => protocol/connections}/enginehooks.go (91%) diff --git a/app/app.go b/app/app.go index df1f893..e74f7a2 100644 --- a/app/app.go +++ b/app/app.go @@ -99,7 +99,7 @@ func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.Global app := &application{engines: make(map[string]connections.Engine), eventBuses: make(map[string]event.Manager), directory: appDirectory, appBus: event.NewEventManager(), settings: settings} app.peers = make(map[string]peer.CwtchPeer) - app.engineHooks = DefaultEngineHooks{} + app.engineHooks = connections.DefaultEngineHooks{} app.acn = acn statusHandler := app.getACNStatusHandler() acn.SetStatusCallback(statusHandler) diff --git a/app/enginehooks.go b/protocol/connections/enginehooks.go similarity index 91% rename from app/enginehooks.go rename to protocol/connections/enginehooks.go index 97d3bbd..adcb90b 100644 --- a/app/enginehooks.go +++ b/protocol/connections/enginehooks.go @@ -1,4 +1,4 @@ -package app +package connections import "git.openprivacy.ca/cwtch.im/tapir" From 746bfffb7c82a99a78b991da4620c9c83b7e9c17 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 20 Apr 2023 13:38:10 -0700 Subject: [PATCH 4/5] EngineHooks into enginehooks.go --- protocol/connections/engine.go | 4 ---- protocol/connections/enginehooks.go | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/protocol/connections/engine.go b/protocol/connections/engine.go index e525bc6..9cd0872 100644 --- a/protocol/connections/engine.go +++ b/protocol/connections/engine.go @@ -86,10 +86,6 @@ type Engine interface { Shutdown() } -type EngineHooks interface { - SendPeerMessage(connection tapir.Connection, message []byte) error -} - // NewProtocolEngine initializes a new engine that runs Cwtch using the given parameters func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, peerAuthorizations map[string]model.Authorization, engineHooks EngineHooks) Engine { engine := new(engine) diff --git a/protocol/connections/enginehooks.go b/protocol/connections/enginehooks.go index adcb90b..a37300a 100644 --- a/protocol/connections/enginehooks.go +++ b/protocol/connections/enginehooks.go @@ -2,6 +2,10 @@ package connections import "git.openprivacy.ca/cwtch.im/tapir" +type EngineHooks interface { + SendPeerMessage(connection tapir.Connection, message []byte) error +} + type DefaultEngineHooks struct { } From 210c91f7f761c22ba8c4947365128f547d521bb2 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 20 Apr 2023 13:38:54 -0700 Subject: [PATCH 5/5] Mutex enginehooks --- app/app.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/app.go b/app/app.go index e74f7a2..b9c1b8b 100644 --- a/app/app.go +++ b/app/app.go @@ -111,6 +111,8 @@ func NewApp(acn connectivity.ACN, appDirectory string, settings *settings.Global } func (app *application) InstallEngineHooks(engineHooks connections.EngineHooks) { + app.appmutex.Lock() + defer app.appmutex.Unlock() app.engineHooks = engineHooks }