diff --git a/e2e/interface.go b/e2e/interface.go index be2419e83e417418900fdb0ca3747f691a562168..ecbaf75be5de5e6087a1b2de32d241546c72148e 100644 --- a/e2e/interface.go +++ b/e2e/interface.go @@ -28,6 +28,8 @@ type Handler interface { // on, a unique ID for the message, and the timestamp sent on. // the recipient must already have an e2e relationship, otherwise an error // will be returned. + // Will return an error if the network is not healthy or in the event of + // a failed send SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params Params) ([]id.Round, e2e.MessageID, time.Time, error) @@ -120,4 +122,22 @@ type Handler interface { // RemoveService removes all services for the given tag RemoveService(tag string) error + + /* === Unsafe =========================================================== */ + + // SendUnsafe sends a message without encryption. It breaks both privacy + // and security. It does partition the message. It should ONLY be used for + // debugging. + // It does not respect service tags in the parameters and sends all + // messages with "Silent" and "E2E" tags. + // It does not support critical messages. + // It does not check that an e2e relationship exists with the recipient + // Will return an error if the network is not healthy or in the event of + // a failed send + SendUnsafe(mt catalog.MessageType, recipient *id.ID, + payload []byte, params Params) ([]id.Round, time.Time, error) + + // EnableUnsafeReception enables the reception of unsafe message by + // registering bespoke services for reception. For debugging only! + EnableUnsafeReception() } diff --git a/e2e/manager.go b/e2e/manager.go index 6f7a87bb8b931dc7dc162bdb4c9b722a9cf4a123..c47a18644f0fb135177fdfbcfed9278744c4941c 100644 --- a/e2e/manager.go +++ b/e2e/manager.go @@ -8,6 +8,7 @@ import ( "gitlab.com/elixxir/client/e2e/rekey" "gitlab.com/elixxir/client/event" "gitlab.com/elixxir/client/network" + "gitlab.com/elixxir/client/network/message" "gitlab.com/elixxir/client/stoppable" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" @@ -87,3 +88,22 @@ func (m *manager) StartProcesses() (stoppable.Stoppable, error) { return multi, nil } + +// EnableUnsafeReception enables the reception of unsafe message by registering +// bespoke services for reception. For debugging only! +func (m *manager) EnableUnsafeReception() { + m.net.AddService(m.myID, message.Service{ + Identifier: m.myID[:], + Tag: ratchet.Silent, + }, &UnsafeProcessor{ + m: m, + tag: ratchet.Silent, + }) + m.net.AddService(m.myID, message.Service{ + Identifier: m.myID[:], + Tag: ratchet.E2e, + }, &UnsafeProcessor{ + m: m, + tag: ratchet.E2e, + }) +} diff --git a/e2e/sendE2E.go b/e2e/sendE2E.go index 9be80fb1149968c2b61d875ca732d531e7ed510f..c1b1229ce84f1eef5fb7df7aa865602290047d2e 100644 --- a/e2e/sendE2E.go +++ b/e2e/sendE2E.go @@ -71,12 +71,13 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, "message, no relationship found with %s", recipient) } - //return the rounds if everything send successfully + //Generate the message ID msgID := e2e.NewMessageID(partner.GetSendRelationshipFingerprint(), internalMsgId) wg := sync.WaitGroup{} + //handle sending for each partition for i, p := range partitions { if mt != catalog.KeyExchangeTrigger { // check if any rekeys need to happen and trigger them diff --git a/e2e/sendUnsafe.go b/e2e/sendUnsafe.go new file mode 100644 index 0000000000000000000000000000000000000000..e602a14f96a508245c4d9b27e8908961832dfb6c --- /dev/null +++ b/e2e/sendUnsafe.go @@ -0,0 +1,97 @@ +package e2e + +import ( + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/catalog" + "gitlab.com/elixxir/client/e2e/ratchet" + "gitlab.com/elixxir/client/network/message" + "gitlab.com/elixxir/crypto/e2e" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" + "sync" + "time" +) + +func (m *manager) SendUnsafe(mt catalog.MessageType, recipient *id.ID, + payload []byte, params Params) ([]id.Round, time.Time, error) { + + //check if the network is healthy + if !m.net.IsHealthy() { + return nil, time.Time{}, errors.New("cannot " + + "sendE2E when network is not healthy") + } + + return m.sendUnsafe(mt, recipient, payload, params) +} + +func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID, + payload []byte, params Params) ([]id.Round, time.Time, error) { + //timestamp the message + ts := netTime.Now() + + //partition the message + partitions, _, err := m.partitioner.Partition(recipient, mt, ts, + payload) + if err != nil { + return nil, time.Time{}, errors.WithMessage(err, "failed to send unsafe message") + } + + jww.WARN.Printf("unsafe sending %d messages to %s. Unsafe sends "+ + "are unencrypted, only use for debugging", + len(partitions), recipient) + + //encrypt then send the partitions over cmix + roundIds := make([]id.Round, len(partitions)) + errCh := make(chan error, len(partitions)) + + wg := sync.WaitGroup{} + + //handle sending for each partition + for i, p := range partitions { + + //set up the service tags + srvc := message.Service{ + Identifier: recipient[:], + } + if i == len(partitions)-1 { + srvc.Tag = ratchet.Silent + } else { + srvc.Tag = ratchet.E2e + } + + //send the cmix message, each partition in its own thread + wg.Add(1) + go func(i int, payload []byte) { + + unencryptedMAC, fp := e2e.SetUnencrypted(payload, m.myID) + + var err error + roundIds[i], _, err = m.net.SendCMIX(recipient, fp, + srvc, payload, unencryptedMAC, params.CMIX) + if err != nil { + errCh <- err + } + wg.Done() + }(i, p) + } + + wg.Wait() + + //see if any parts failed to send + numFail, errRtn := getSendErrors(errCh) + if numFail > 0 { + jww.INFO.Printf("Failed to unsafe send %d/%d to %s", + numFail, len(partitions), recipient) + return nil, time.Time{}, errors.Errorf("Failed to unsafe send %v/%v sub payloads:"+ + " %s", numFail, len(partitions), errRtn) + } else { + jww.INFO.Printf("Successfully Unsafe Send %d/%d to %s", + len(partitions)-numFail, len(partitions), recipient) + } + + //return the rounds if everything send successfully + jww.INFO.Printf("Successful Unsafe Send of %d messages to %s", + len(partitions), recipient) + return roundIds, ts, nil +} diff --git a/e2e/unsafeProcessor.go b/e2e/unsafeProcessor.go new file mode 100644 index 0000000000000000000000000000000000000000..942e0a1a91258a3ccf60272e865f3badd64ce2f7 --- /dev/null +++ b/e2e/unsafeProcessor.go @@ -0,0 +1,36 @@ +package e2e + +import ( + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/network/historical" + "gitlab.com/elixxir/client/network/identity/receptionID" + "gitlab.com/elixxir/crypto/e2e" + "gitlab.com/elixxir/primitives/format" +) + +type UnsafeProcessor struct { + m *manager + tag string +} + +func (up *UnsafeProcessor) Process(ecrMsg format.Message, receptionID receptionID.EphemeralIdentity, + round historical.Round) { + //check if the message is unencrypted + unencrypted, sender := e2e.IsUnencrypted(ecrMsg) + if !unencrypted { + jww.ERROR.Printf("Received a non unencrypted message in e2e "+ + "service %s, A message might have dropped!", up.tag) + } + + //Parse + message, done := up.m.partitioner.HandlePartition(sender, + ecrMsg.GetContents(), nil) + + if done { + message.RecipientID = receptionID.Source + message.EphemeralID = receptionID.EphId + message.Round = round + message.Encrypted = false + up.m.Switchboard.Speak(message) + } +} diff --git a/go.mod b/go.mod index 0d045618487b259259566189623c0b31ac3990a9..9ab45bff77e2beb8302467bb1c38ffd6e7230b46 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/spf13/viper v1.7.1 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 gitlab.com/elixxir/comms v0.0.4-0.20220308183624-c2183e687a03 - gitlab.com/elixxir/crypto v0.0.7-0.20220328164108-c72388181116 + gitlab.com/elixxir/crypto v0.0.7-0.20220331001626-1829e71edf56 gitlab.com/elixxir/ekv v0.1.6 gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f gitlab.com/xx_network/comms v0.0.4-0.20220311192415-d95fe8906580 diff --git a/go.sum b/go.sum index a28b5a590f07d922e1e6993633a57c265559208e..2fa579cae8672c0e1e60c00501032730dc42e15a 100644 --- a/go.sum +++ b/go.sum @@ -287,6 +287,10 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220328163237-3bdc3e1369ca h1:jPhotwqZFJYHR4 gitlab.com/elixxir/crypto v0.0.7-0.20220328163237-3bdc3e1369ca/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= gitlab.com/elixxir/crypto v0.0.7-0.20220328164108-c72388181116 h1:HvMO//NbadCiKGI10cdW98WimYf0YIudzQeUznYAgRQ= gitlab.com/elixxir/crypto v0.0.7-0.20220328164108-c72388181116/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= +gitlab.com/elixxir/crypto v0.0.7-0.20220330235853-295c470e0e62 h1:t0cy5vu9m32Vq/pPAGjXLzMp9AceIlc+DSM4fyL1SLQ= +gitlab.com/elixxir/crypto v0.0.7-0.20220330235853-295c470e0e62/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= +gitlab.com/elixxir/crypto v0.0.7-0.20220331001626-1829e71edf56 h1:1HJHlRwh3dDbvw3qIK17jK5R6W87S4tz/gkJT8aMLKQ= +gitlab.com/elixxir/crypto v0.0.7-0.20220331001626-1829e71edf56/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= gitlab.com/elixxir/ekv v0.1.6 h1:M2hUSNhH/ChxDd+s8xBqSEKgoPtmE6hOEBqQ73KbN6A= gitlab.com/elixxir/ekv v0.1.6/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=