From 369a0bc809e360edb7719d2ed64c294ac957e93f Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 7 Dec 2021 17:01:27 -0800 Subject: [PATCH 1/5] Fix Invite Construction for Groups --- peer/cwtch_peer.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 7e1cc40..764baef 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -421,7 +421,6 @@ func (cp *cwtchPeer) AutoHandleEvents(events []event.Type) { } // ImportGroup initializes a group from an imported source rather than a peer invite -// Status: TODO func (cp *cwtchPeer) ImportGroup(exportedInvite string) (int, error) { gci, err := model.ValidateInvite(exportedInvite) if err != nil { @@ -640,7 +639,7 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) (string, error) { val, exists := conversationInfo.Attributes[k] if exists { if val != v { - // this is inconsistent! + // the keybundle is inconsistent! return "", model.InconsistentKeyBundleError } } @@ -761,7 +760,7 @@ func (cp *cwtchPeer) SendInviteToConversation(conversationID int, inviteConversa return errors.New("server bundle not found") } - invite = model.MessageWrapper{Overlay: model.OverlayInviteContact, Data: fmt.Sprintf("tofubundle:server:%s||%s", base64.StdEncoding.EncodeToString([]byte(bundle)), groupInvite)} + invite = model.MessageWrapper{Overlay: model.OverlayInviteGroup, Data: fmt.Sprintf("tofubundle:server:%s||%s", base64.StdEncoding.EncodeToString([]byte(bundle)), groupInvite)} } inviteBytes, err := json.Marshal(invite) @@ -961,7 +960,7 @@ func (cp *cwtchPeer) eventHandler() { // it learns nothing else about each connection). // store the base64 encoded signature for later use - // TODO Server Connections should sent Connection ID + // TODO Server Connections should send Connection ID ci, err := cp.FetchConversationInfo(ev.Data[event.GroupServer]) if ci == nil || err != nil { log.Errorf("no server connection count") -- 2.25.1 From e2524224631fa032414dfa5abb547f882a7ffb10 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 7 Dec 2021 17:01:43 -0800 Subject: [PATCH 2/5] Test Invalid Chunk Store --- protocol/files/manifest_test.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/protocol/files/manifest_test.go b/protocol/files/manifest_test.go index 697073d..cb0608b 100644 --- a/protocol/files/manifest_test.go +++ b/protocol/files/manifest_test.go @@ -28,7 +28,7 @@ func TestManifest(t *testing.T) { t.Logf("%v", manifest) - // Try to tread the chunk + // Try to read the chunk _, err = manifest.GetChunkBytes(1) if err == nil { t.Fatalf("chunk fetch should have thrown an error") @@ -43,6 +43,11 @@ func TestManifest(t *testing.T) { t.Fatalf("chunk fetch error: %v", err) } + _, err = manifest.GetChunkBytes(0) + if err != nil { + t.Fatalf("chunk fetch error: %v", err) + } + json, _ := json.Marshal(manifest) t.Logf("%s", json) @@ -112,7 +117,21 @@ func TestManifestLarge(t *testing.T) { t.Fatalf("could not store chunk %v %v", i, err) } + + // Attempt to store the chunk in an invalid position... + _, err = cwtchPngOutManifest.StoreChunk(uint64(i+1), contents) + if err == nil { + t.Fatalf("incorrect chunk store") + } + } + + // Attempt to store an invalid chunk...should trigger an error + _, err = cwtchPngOutManifest.StoreChunk(uint64(len(cwtchPngManifest.Chunks)), []byte{0xff}) + if err == nil { + t.Fatalf("incorrect chunk store") + } + err = cwtchPngOutManifest.VerifyFile() if err != nil { t.Fatalf("could not verify file %v", err) -- 2.25.1 From 9b09754f0ee3d0cdfdc23a87f993836013e1a078 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 7 Dec 2021 17:02:02 -0800 Subject: [PATCH 3/5] Remove Old Code --- model/attr/scope.go | 20 +----- storage/profile_store.go | 18 ----- storage/v1/file_enc.go | 6 +- storage/v1/profile_store.go | 65 ------------------- .../file_sharing_integration_test.go | 5 +- 5 files changed, 4 insertions(+), 110 deletions(-) diff --git a/model/attr/scope.go b/model/attr/scope.go index d02cd15..ac4890e 100644 --- a/model/attr/scope.go +++ b/model/attr/scope.go @@ -77,22 +77,4 @@ func (scope Scope) IsPublic() bool { // IsConversation returns true if the scope is a conversation scope func (scope Scope) IsConversation() bool { return scope == ConversationScope -} - -// GetLocalScope takes a path and attaches the local scope to it -// Deprecated: Use ConstructScopedZonedPath -func GetLocalScope(path string) string { - return string(LocalScope) + Separator + path -} - -// GetPublicScope takes a path and attaches the local scope to it -// Deprecated: Use ConstructScopedZonedPath -func GetPublicScope(path string) string { - return string(PublicScope) + Separator + path -} - -// GetPeerScope takes a path and attaches the peer scope to it -// Deprecated: Use ConstructScopedZonedPath -func GetPeerScope(path string) string { - return string(PeerScope) + Separator + path -} +} \ No newline at end of file diff --git a/storage/profile_store.go b/storage/profile_store.go index 8c08943..37caf1b 100644 --- a/storage/profile_store.go +++ b/storage/profile_store.go @@ -1,7 +1,6 @@ package storage import ( - "cwtch.im/cwtch/event" "cwtch.im/cwtch/model" "cwtch.im/cwtch/storage/v1" ) @@ -9,14 +8,6 @@ import ( // ProfileStore is an interface to managing the storage of Cwtch Profiles type ProfileStore interface { GetProfileCopy(timeline bool) *model.Profile - GetNewPeerMessage() *event.Event - CheckPassword(string) bool -} - -// CreateProfileWriterStore creates a profile store backed by a filestore listening for events and saving them -// directory should be $appDir/profiles/$rand -func CreateProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) ProfileStore { - return v1.CreateProfileWriterStore(eventManager, directory, password, profile) } // LoadProfileWriterStore loads a profile store from filestore listening for events and saving them @@ -24,12 +15,3 @@ func CreateProfileWriterStore(eventManager event.Manager, directory, password st func LoadProfileWriterStore(directory, password string) (ProfileStore, error) { return v1.LoadProfileWriterStore(directory, password) } - -// ReadProfile reads a profile from storage and returns the profile -// Should only be called for cache refresh of the profile after a ProfileWriterStore has opened -// (and upgraded) the store, and thus supplied the key/salt -func ReadProfile(directory string, key [32]byte, salt [128]byte) (*model.Profile, error) { - return v1.ReadProfile(directory, key, salt) -} - -// ********* Versioning and upgrade ********** diff --git a/storage/v1/file_enc.go b/storage/v1/file_enc.go index 6afa192..5598ebb 100644 --- a/storage/v1/file_enc.go +++ b/storage/v1/file_enc.go @@ -63,11 +63,7 @@ func DecryptFile(ciphertext []byte, key [32]byte) ([]byte, error) { func ReadEncryptedFile(directory, filename string, key [32]byte) ([]byte, error) { encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename)) if err == nil { - data, err := DecryptFile(encryptedbytes, key) - if err == nil { - return data, nil - } - return nil, err + return DecryptFile(encryptedbytes, key) } return nil, err } diff --git a/storage/v1/profile_store.go b/storage/v1/profile_store.go index 88078d5..5cd9d07 100644 --- a/storage/v1/profile_store.go +++ b/storage/v1/profile_store.go @@ -6,7 +6,6 @@ import ( "encoding/json" "git.openprivacy.ca/openprivacy/log" "io/ioutil" - "os" "path" ) @@ -24,48 +23,6 @@ type ProfileStoreV1 struct { salt [128]byte } -// CheckPassword returns true if the given password produces the same key as the current stored key, otherwise false. -func (ps *ProfileStoreV1) CheckPassword(checkpass string) bool { - oldkey := CreateKey(checkpass, ps.salt[:]) - return oldkey == ps.key -} - -// InitV1Directory generates a key and salt from a password, writes a SALT and VERSION file and returns the key and salt -func InitV1Directory(directory, password string) ([32]byte, [128]byte, error) { - os.Mkdir(directory, 0700) - - key, salt, err := CreateKeySalt(password) - if err != nil { - log.Errorf("Could not create key for profile store from password: %v\n", err) - return [32]byte{}, [128]byte{}, err - } - - if err = ioutil.WriteFile(path.Join(directory, versionFile), []byte(version), 0600); err != nil { - log.Errorf("Could not write version file: %v", err) - return [32]byte{}, [128]byte{}, err - } - - if err = ioutil.WriteFile(path.Join(directory, saltFile), salt[:], 0600); err != nil { - log.Errorf("Could not write salt file: %v", err) - return [32]byte{}, [128]byte{}, err - } - - return key, salt, nil -} - -// CreateProfileWriterStore creates a profile store backed by a filestore listening for events and saving them -// directory should be $appDir/profiles/$rand -func CreateProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) *ProfileStoreV1 { - key, salt, err := InitV1Directory(directory, password) - if err != nil { - return nil - } - - ps := &ProfileStoreV1{fs: NewFileStore(directory, profileFilename, key), key: key, salt: salt, directory: directory, profile: profile} - - return ps -} - // LoadProfileWriterStore loads a profile store from filestore listening for events and saving them // directory should be $appDir/profiles/$rand func LoadProfileWriterStore(directory, password string) (*ProfileStoreV1, error) { @@ -87,28 +44,6 @@ func LoadProfileWriterStore(directory, password string) (*ProfileStoreV1, error) return ps, nil } -// ReadProfile reads a profile from storqage and returns the profile -// directory should be $appDir/profiles/$rand -func ReadProfile(directory string, key [32]byte, salt [128]byte) (*model.Profile, error) { - os.Mkdir(directory, 0700) - ps := &ProfileStoreV1{fs: NewFileStore(directory, profileFilename, key), key: key, salt: salt, directory: directory, profile: nil} - - err := ps.load() - if err != nil { - return nil, err - } - - profile := ps.GetProfileCopy(true) - - return profile, nil -} - -// GetNewPeerMessage is for AppService to call on Reload events, to reseed the AppClient with the loaded peers -func (ps *ProfileStoreV1) GetNewPeerMessage() *event.Event { - message := event.NewEventList(event.NewPeer, event.Identity, ps.profile.LocalID, event.Key, string(ps.key[:]), event.Salt, string(ps.salt[:])) - return &message -} - // load instantiates a cwtchPeer from the file store func (ps *ProfileStoreV1) load() error { decrypted, err := ps.fs.Read() diff --git a/testing/filesharing/file_sharing_integration_test.go b/testing/filesharing/file_sharing_integration_test.go index d24db99..5c1bd13 100644 --- a/testing/filesharing/file_sharing_integration_test.go +++ b/testing/filesharing/file_sharing_integration_test.go @@ -33,7 +33,6 @@ import ( func waitForPeerPeerConnection(t *testing.T, peera peer.CwtchPeer, peerb peer.CwtchPeer) { for { state := peera.GetPeerState(peerb.GetOnion()) - //log.Infof("Waiting for Peer %v to peer with peer: %v - state: %v\n", peera.GetProfile().Name, peerb.GetProfile().Name, state) if state == connections.FAILED { t.Fatalf("%v could not connect to %v", peera.GetOnion(), peerb.GetOnion()) } @@ -42,8 +41,8 @@ func waitForPeerPeerConnection(t *testing.T, peera peer.CwtchPeer, peerb peer.Cw time.Sleep(time.Second * 5) continue } else { - peerAName, _ := peera.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name) - peerBName, _ := peerb.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.Name) + peerAName, _ := peera.GetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name) + peerBName, _ := peerb.GetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name) fmt.Printf("%v CONNECTED and AUTHED to %v\n", peerAName, peerBName) break } -- 2.25.1 From 93cbe0556c8697e188e3c800a02086a566be42e6 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 7 Dec 2021 17:02:23 -0800 Subject: [PATCH 4/5] Add Error Checking for Non-specified Plugins (quality) --- app/applets.go | 14 +++++++++----- app/plugins/plugin.go | 9 +++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/applets.go b/app/applets.go index 5b235db..a3e2d23 100644 --- a/app/applets.go +++ b/app/applets.go @@ -113,9 +113,13 @@ func (ap *appletPlugins) AddPlugin(peerid string, id plugins.PluginID, bus event pluginsinf, _ := ap.plugins.Load(peerid) peerPlugins := pluginsinf.([]plugins.Plugin) - newp := plugins.Get(id, bus, acn, peerid) - newp.Start() - peerPlugins = append(peerPlugins, newp) - log.Debugf("storing plugin for %v %v", peerid, peerPlugins) - ap.plugins.Store(peerid, peerPlugins) + newp,err := plugins.Get(id, bus, acn, peerid) + if err == nil { + newp.Start() + peerPlugins = append(peerPlugins, newp) + log.Debugf("storing plugin for %v %v", peerid, peerPlugins) + ap.plugins.Store(peerid, peerPlugins) + } else { + log.Errorf("error adding plugin: %v", err) + } } diff --git a/app/plugins/plugin.go b/app/plugins/plugin.go index 2d271fc..be8252b 100644 --- a/app/plugins/plugin.go +++ b/app/plugins/plugin.go @@ -2,6 +2,7 @@ package plugins import ( "cwtch.im/cwtch/event" + "fmt" "git.openprivacy.ca/openprivacy/connectivity" ) @@ -21,13 +22,13 @@ type Plugin interface { } // Get is a plugin factory for the requested plugin -func Get(id PluginID, bus event.Manager, acn connectivity.ACN, onion string) Plugin { +func Get(id PluginID, bus event.Manager, acn connectivity.ACN, onion string) (Plugin, error) { switch id { case CONNECTIONRETRY: - return NewConnectionRetry(bus, onion) + return NewConnectionRetry(bus, onion), nil case NETWORKCHECK: - return NewNetworkCheck(bus, acn) + return NewNetworkCheck(bus, acn), nil } - return nil + return nil, fmt.Errorf("plugin not defined %v", id) } -- 2.25.1 From c5b61cdaf7636a71721a5e3b21debfa9c0deeebf Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 7 Dec 2021 17:03:01 -0800 Subject: [PATCH 5/5] Formatting + Quality --- app/applets.go | 2 +- model/attr/scope.go | 2 +- protocol/files/manifest_test.go | 1 - storage/v1/file_enc.go | 2 +- storage/v1/profile_store.go | 2 -- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/applets.go b/app/applets.go index a3e2d23..912c7fc 100644 --- a/app/applets.go +++ b/app/applets.go @@ -113,7 +113,7 @@ func (ap *appletPlugins) AddPlugin(peerid string, id plugins.PluginID, bus event pluginsinf, _ := ap.plugins.Load(peerid) peerPlugins := pluginsinf.([]plugins.Plugin) - newp,err := plugins.Get(id, bus, acn, peerid) + newp, err := plugins.Get(id, bus, acn, peerid) if err == nil { newp.Start() peerPlugins = append(peerPlugins, newp) diff --git a/model/attr/scope.go b/model/attr/scope.go index ac4890e..8c9d67d 100644 --- a/model/attr/scope.go +++ b/model/attr/scope.go @@ -77,4 +77,4 @@ func (scope Scope) IsPublic() bool { // IsConversation returns true if the scope is a conversation scope func (scope Scope) IsConversation() bool { return scope == ConversationScope -} \ No newline at end of file +} diff --git a/protocol/files/manifest_test.go b/protocol/files/manifest_test.go index cb0608b..caa14ad 100644 --- a/protocol/files/manifest_test.go +++ b/protocol/files/manifest_test.go @@ -117,7 +117,6 @@ func TestManifestLarge(t *testing.T) { t.Fatalf("could not store chunk %v %v", i, err) } - // Attempt to store the chunk in an invalid position... _, err = cwtchPngOutManifest.StoreChunk(uint64(i+1), contents) if err == nil { diff --git a/storage/v1/file_enc.go b/storage/v1/file_enc.go index 5598ebb..2acbd63 100644 --- a/storage/v1/file_enc.go +++ b/storage/v1/file_enc.go @@ -63,7 +63,7 @@ func DecryptFile(ciphertext []byte, key [32]byte) ([]byte, error) { func ReadEncryptedFile(directory, filename string, key [32]byte) ([]byte, error) { encryptedbytes, err := ioutil.ReadFile(path.Join(directory, filename)) if err == nil { - return DecryptFile(encryptedbytes, key) + return DecryptFile(encryptedbytes, key) } return nil, err } diff --git a/storage/v1/profile_store.go b/storage/v1/profile_store.go index 5cd9d07..f8122b2 100644 --- a/storage/v1/profile_store.go +++ b/storage/v1/profile_store.go @@ -10,8 +10,6 @@ import ( ) const profileFilename = "profile" -const version = "1" -const versionFile = "VERSION" const saltFile = "SALT" //ProfileStoreV1 storage for profiles and message streams that uses in memory key and fs stored salt instead of in memory password -- 2.25.1