diff --git a/app/applets.go b/app/applets.go index 5b235db..912c7fc 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) } diff --git a/model/attr/scope.go b/model/attr/scope.go index d02cd15..8c9d67d 100644 --- a/model/attr/scope.go +++ b/model/attr/scope.go @@ -78,21 +78,3 @@ func (scope Scope) IsPublic() bool { 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 -} 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") diff --git a/protocol/files/manifest_test.go b/protocol/files/manifest_test.go index 697073d..caa14ad 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,20 @@ 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) 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..2acbd63 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..f8122b2 100644 --- a/storage/v1/profile_store.go +++ b/storage/v1/profile_store.go @@ -6,13 +6,10 @@ import ( "encoding/json" "git.openprivacy.ca/openprivacy/log" "io/ioutil" - "os" "path" ) 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 @@ -24,48 +21,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 +42,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 }