diff --git a/README.md b/README.md index e494e57d83614256744b08ea2adf0af371103f4d..26fc33259e9795344bb0477e1fcb97c94e287c05 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,10 @@ Available Commands: Flags: --accept-channel Accept the channel request for the corresponding recipient ID --auth-timeout uint The number of seconds to wait for an authentication channelto confirm (default 120) + --delete-all-requests Delete the all contact requests, both sent and received. --delete-channel Delete the channel information for the corresponding recipient ID + --delete-receive-requests Delete the all received contact requests. + --delete-sent-requests Delete the all sent contact requests. --destfile string Read this contact file for the destination id -d, --destid string ID to send message to (if below 40, will be precanned. Use '0x' or 'b64:' for hex and base64 representations) (default "0") --e2eMaxKeys uint Max keys used before blocking until a rekey completes (default 800) diff --git a/api/client.go b/api/client.go index 0aee60d576cae5301f0e7d5e48f0d91e68f50a21..a289fea1e030118346df4011ef5601e49438fe6d 100644 --- a/api/client.go +++ b/api/client.go @@ -684,6 +684,24 @@ func (c *Client) GetNodeRegistrationStatus() (int, int, error) { return numRegistered, len(nodes) - numStale, nil } +// DeleteAllRequests clears all requests from client's auth storage. +func (c *Client) DeleteAllRequests() error { + jww.DEBUG.Printf("Deleting all requests") + return c.GetStorage().Auth().DeleteAllRequests() +} + +// DeleteSentRequests clears sent requests from client's auth storage. +func (c *Client) DeleteSentRequests() error { + jww.DEBUG.Printf("Deleting all sent requests") + return c.GetStorage().Auth().DeleteSentRequests() +} + +// DeleteReceiveRequests clears receive requests from client's auth storage. +func (c *Client) DeleteReceiveRequests() error { + jww.DEBUG.Printf("Deleting all received requests") + return c.GetStorage().Auth().DeleteReceiveRequests() +} + // DeleteContact is a function which removes a partner from Client's storage func (c *Client) DeleteContact(partnerId *id.ID) error { jww.DEBUG.Printf("Deleting contact with ID %s", partnerId) @@ -742,8 +760,8 @@ func (c *Client) DeleteContact(partnerId *id.ID) error { //delete conversations c.storage.Conversations().Delete(partnerId) - // call delete requests to make sure nothing is lingering. - // this is for saftey to ensure the contact can be readded + // call delete requests to make sure nothing is lingering. + // this is for saftey to ensure the contact can be readded // in the future _ = c.storage.Auth().Delete(partnerId) diff --git a/bindings/client.go b/bindings/client.go index 47e4b34a34943c09a740eaec61ef9c6f26965538..1996507cbc0a005ae20006763f6596fe1ca25834 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -265,6 +265,7 @@ func (c *Client) WaitForNetwork(timeoutMS int) bool { func (c *Client) NetworkFollowerStatus() int { return int(c.api.NetworkFollowerStatus()) } + // HasRunningProcessies checks if any background threads are running. // returns true if none are running. This is meant to be // used when NetworkFollowerStatus() returns Stopping. @@ -449,6 +450,21 @@ func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) { return &NodeRegistrationsStatus{registered, total}, err } +// DeleteAllRequests clears all requests from Client's auth storage. +func (c *Client) DeleteAllRequests() error { + return c.api.DeleteAllRequests() +} + +// DeleteSentRequests clears sent requests from Client's auth storage. +func (c *Client) DeleteSentRequests() error { + return c.api.DeleteSentRequests() +} + +// DeleteReceiveRequests clears receive requests from Client's auth storage. +func (c *Client) DeleteReceiveRequests() error { + return c.api.DeleteReceiveRequests() +} + // DeleteContact is a function which removes a contact from Client's storage func (c *Client) DeleteContact(b []byte) error { contactObj, err := UnmarshalContact(b) diff --git a/cmd/root.go b/cmd/root.go index 7f38db02a83e6cbcd869637e9c5a6fbec920cd14..a3ce0ce3bad8f8188e3a24dad103d75b138dcfbc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -304,6 +304,18 @@ var rootCmd = &cobra.Command{ deleteChannel(client, recipientID) } + if viper.GetBool("delete-receive-requests") { + client.DeleteReceiveRequests() + } + + if viper.GetBool("delete-sent-requests") { + client.DeleteSentRequests() + } + + if viper.GetBool("delete-all-requests") { + client.DeleteAllRequests() + } + msg := message.Send{ Recipient: recipientID, Payload: []byte(msgBody), @@ -1030,6 +1042,21 @@ func init() { viper.BindPFlag("delete-channel", rootCmd.PersistentFlags().Lookup("delete-channel")) + rootCmd.PersistentFlags().Bool("delete-receive-requests", false, + "Delete the all received contact requests.") + viper.BindPFlag("delete-receive-requests", + rootCmd.PersistentFlags().Lookup("delete-receive-requests")) + + rootCmd.PersistentFlags().Bool("delete-sent-requests", false, + "Delete the all sent contact requests.") + viper.BindPFlag("delete-sent-requests", + rootCmd.PersistentFlags().Lookup("delete-sent-requests")) + + rootCmd.PersistentFlags().Bool("delete-all-requests", false, + "Delete the all contact requests, both sent and received.") + viper.BindPFlag("delete-all-requests", + rootCmd.PersistentFlags().Lookup("delete-all-requests")) + rootCmd.Flags().BoolP("send-auth-request", "", false, "Send an auth request to the specified destination and wait"+ "for confirmation") diff --git a/storage/auth/store.go b/storage/auth/store.go index 2bb90faf774bb777b28b33799934d89f9a966fe9..fb9aa2b04be8875bae32de4c74752db3dd80ddee 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -403,7 +403,7 @@ func (s *Store) Done(partner *id.ID) { r.mux.Unlock() } -// delete is one of two calls after using a request. This one is to be used when +// Delete is one of two calls after using a request. This one is to be used when // the use is unsuccessful. It deletes all references to the request associated // with the passed partner, if it exists. It will allow any thread waiting on // access to continue. They should fail due to the deletion of the structure. @@ -418,16 +418,9 @@ func (s *Store) Delete(partner *id.ID) error { switch r.rt { case Sent: - delete(s.fingerprints, r.sent.fingerprint) - if err := r.sent.delete(); err != nil { - jww.FATAL.Panicf("Failed to delete sent request: %+v", err) - } - + s.deleteSentRequest(r) case Receive: - if err := util.DeleteContact(s.kv, r.receive.ID); err != nil { - jww.FATAL.Panicf("Failed to delete recieved request "+ - "contact: %+v", err) - } + s.deleteReceiveRequest(r) } delete(s.requests, *partner) @@ -438,3 +431,91 @@ func (s *Store) Delete(partner *id.ID) error { return nil } + +// DeleteAllRequests clears the request map and all associated storage objects +// containing request data. +func (s *Store) DeleteAllRequests() error { + s.mux.Lock() + defer s.mux.Unlock() + + for partnerId, req := range s.requests { + switch req.rt { + case Sent: + s.deleteSentRequest(req) + delete(s.requests, partnerId) + case Receive: + s.deleteReceiveRequest(req) + delete(s.requests, partnerId) + } + + } + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting all requests: %+v", err) + } + + return nil +} + +// DeleteSentRequests deletes all Sent requests from Store. +func (s *Store) DeleteSentRequests() error { + s.mux.Lock() + defer s.mux.Unlock() + + for partnerId, req := range s.requests { + switch req.rt { + case Sent: + s.deleteSentRequest(req) + delete(s.requests, partnerId) + case Receive: + continue + } + } + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting all sent requests: %+v", err) + } + + return nil +} + +// DeleteReceiveRequests deletes all Receive requests from Store. +func (s *Store) DeleteReceiveRequests() error { + s.mux.Lock() + defer s.mux.Unlock() + + for partnerId, req := range s.requests { + switch req.rt { + case Sent: + continue + case Receive: + s.deleteReceiveRequest(req) + delete(s.requests, partnerId) + } + } + + if err := s.save(); err != nil { + jww.FATAL.Panicf("Failed to store updated request map after "+ + "deleting all receive requests: %+v", err) + } + + return nil +} + +// deleteSentRequest is a helper function which deletes a Sent request from storage. +func (s *Store) deleteSentRequest(r *request) { + delete(s.fingerprints, r.sent.fingerprint) + if err := r.sent.delete(); err != nil { + jww.FATAL.Panicf("Failed to delete sent request: %+v", err) + } +} + +// deleteReceiveRequest is a helper function which deletes a Receive request from storage. +func (s *Store) deleteReceiveRequest(r *request) { + if err := util.DeleteContact(s.kv, r.receive.ID); err != nil { + jww.FATAL.Panicf("Failed to delete recieved request "+ + "contact: %+v", err) + } +} diff --git a/storage/auth/store_test.go b/storage/auth/store_test.go index 6568cd75540f7633b711d64380e106435b50d359..f1f10414836eb6c37596593322d112dbcfcc9394 100644 --- a/storage/auth/store_test.go +++ b/storage/auth/store_test.go @@ -905,6 +905,170 @@ func TestStore_GetAllReceived_MixSentReceived(t *testing.T) { } +// Unit test. +func TestStore_DeleteReceiveRequests(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + if _, _, err := s.GetReceivedRequest(c.ID); err != nil { + t.Fatalf("GetReceivedRequest() returned an error: %+v", err) + } + + err := s.DeleteReceiveRequests() + if err != nil { + t.Fatalf("DeleteReceiveRequests returned an error: %+v", err) + } + + if s.requests[*c.ID] != nil { + t.Errorf("delete() failed to delete request for user %s.", c.ID) + } +} + +// Unit test. +func TestStore_DeleteSentRequests(t *testing.T) { + s, _, _ := makeTestStore(t) + partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) + rng := csprng.NewSystemRNG() + sidhPrivKey, sidhPubKey := genSidhAKeys(rng) + sr := &SentRequest{ + kv: s.kv, + partner: partnerID, + partnerHistoricalPubKey: s.grp.NewInt(1), + myPrivKey: s.grp.NewInt(2), + myPubKey: s.grp.NewInt(3), + mySidHPrivKeyA: sidhPrivKey, + mySidHPubKeyA: sidhPubKey, + fingerprint: format.Fingerprint{5}, + } + if err := s.AddSent(sr.partner, sr.partnerHistoricalPubKey, + sr.myPrivKey, sr.myPubKey, sr.mySidHPrivKeyA, + sr.mySidHPubKeyA, sr.fingerprint); err != nil { + t.Fatalf("AddSent() returned an error: %+v", err) + } + + err := s.DeleteSentRequests() + if err != nil { + t.Fatalf("DeleteSentRequests returned an error: %+v", err) + } + + if s.requests[*sr.partner] != nil { + t.Errorf("delete() failed to delete request for user %s.", + sr.partner) + } + + if _, exists := s.fingerprints[sr.fingerprint]; exists { + t.Errorf("delete() failed to delete fingerprint for fp %v.", + sr.fingerprint) + } +} + +// Tests that DeleteSentRequests does not affect receive requests in map +func TestStore_DeleteSentRequests_ReceiveInMap(t *testing.T) { + s, _, _ := makeTestStore(t) + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + rng := csprng.NewSystemRNG() + _, sidhPubKey := genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + + err := s.DeleteSentRequests() + if err != nil { + t.Fatalf("DeleteSentRequests returned an error: %+v", err) + } + + if s.requests[*c.ID] == nil { + t.Fatalf("DeleteSentRequests removes receive requests!") + } + +} + +// Tests that DeleteReceiveRequests does not affect sent requests in map +func TestStore_DeleteReceiveRequests_SentInMap(t *testing.T) { + s, _, _ := makeTestStore(t) + partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) + rng := csprng.NewSystemRNG() + sidhPrivKey, sidhPubKey := genSidhAKeys(rng) + sr := &SentRequest{ + kv: s.kv, + partner: partnerID, + partnerHistoricalPubKey: s.grp.NewInt(1), + myPrivKey: s.grp.NewInt(2), + myPubKey: s.grp.NewInt(3), + mySidHPrivKeyA: sidhPrivKey, + mySidHPubKeyA: sidhPubKey, + fingerprint: format.Fingerprint{5}, + } + if err := s.AddSent(sr.partner, sr.partnerHistoricalPubKey, + sr.myPrivKey, sr.myPubKey, sr.mySidHPrivKeyA, + sr.mySidHPubKeyA, sr.fingerprint); err != nil { + t.Fatalf("AddSent() returned an error: %+v", err) + } + + err := s.DeleteReceiveRequests() + if err != nil { + t.Fatalf("DeleteSentRequests returned an error: %+v", err) + } + + if s.requests[*partnerID] == nil { + t.Fatalf("DeleteReceiveRequests removes sent requests!") + } + +} + +// Unit test. +func TestStore_DeleteAllRequests(t *testing.T) { + s, _, _ := makeTestStore(t) + partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) + rng := csprng.NewSystemRNG() + sidhPrivKey, sidhPubKey := genSidhAKeys(rng) + sr := &SentRequest{ + kv: s.kv, + partner: partnerID, + partnerHistoricalPubKey: s.grp.NewInt(1), + myPrivKey: s.grp.NewInt(2), + myPubKey: s.grp.NewInt(3), + mySidHPrivKeyA: sidhPrivKey, + mySidHPubKeyA: sidhPubKey, + fingerprint: format.Fingerprint{5}, + } + if err := s.AddSent(sr.partner, sr.partnerHistoricalPubKey, + sr.myPrivKey, sr.myPubKey, sr.mySidHPrivKeyA, + sr.mySidHPubKeyA, sr.fingerprint); err != nil { + t.Fatalf("AddSent() returned an error: %+v", err) + } + + c := contact.Contact{ID: id.NewIdFromUInt(rand.Uint64(), id.User, t)} + _, sidhPubKey = genSidhAKeys(rng) + if err := s.AddReceived(c, sidhPubKey); err != nil { + t.Fatalf("AddReceived() returned an error: %+v", err) + } + + err := s.DeleteAllRequests() + if err != nil { + t.Fatalf("DeleteAllRequests returned an error: %+v", err) + } + + if s.requests[*sr.partner] != nil { + t.Errorf("delete() failed to delete request for user %s.", + sr.partner) + } + + if _, exists := s.fingerprints[sr.fingerprint]; exists { + t.Errorf("delete() failed to delete fingerprint for fp %v.", + sr.fingerprint) + } + + if s.requests[*c.ID] != nil { + t.Errorf("delete() failed to delete request for user %s.", c.ID) + } + +} + func makeTestStore(t *testing.T) (*Store, *versioned.KV, []*cyclic.Int) { kv := versioned.NewKV(make(ekv.Memstore)) grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(0))