diff --git a/auth/baseFormat.go b/auth/baseFormat.go deleted file mode 100644 index 1e39a57ef996d21c5694f05a300dc25e5a6bd214..0000000000000000000000000000000000000000 --- a/auth/baseFormat.go +++ /dev/null @@ -1,85 +0,0 @@ -package auth - -import ( - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" - "gitlab.com/elixxir/crypto/cyclic" -) - -const saltSize = 32 - -type format struct { - data []byte - pubkey []byte - salt []byte - ecrPayload []byte -} - -func newFormat(payloadSize, pubkeySize uint, pubkey *cyclic.Int, - salt []byte) format { - - if len(salt) != saltSize { - jww.FATAL.Panicf("Salt is wrong size, should be %v, is %v", - saltSize, len(salt)) - } - - if payloadSize < pubkeySize+saltSize { - jww.FATAL.Panicf("Size of format is too small, must be big " + - "enough to contain public key and salt") - } - - f := buildFormat(make([]byte, payloadSize), pubkeySize) - - copy(f.pubkey, pubkey.LeftpadBytes(uint64(pubkeySize))) - copy(f.salt, salt) - - return f -} - -func buildFormat(data []byte, pubkeySize uint) format { - f := format{ - data: data, - } - - f.pubkey = f.data[:pubkeySize] - f.salt = f.data[pubkeySize : pubkeySize+saltSize] - f.ecrPayload = f.data[pubkeySize+saltSize:] - return f -} - -func unmarshalFormat(b []byte, pubkeySize uint) (format, error) { - if uint(len(b)) < pubkeySize+saltSize { - return format{}, errors.New("Received format too small") - } - - return buildFormat(b, pubkeySize), nil -} - -func (f format) Marshal() []byte { - return f.data -} - -func (f format) GetPubKey(grp *cyclic.Group) *cyclic.Int { - return grp.NewIntFromBytes(f.pubkey) -} - -func (f format) GetSalt() []byte { - return f.salt -} - -func (f format) GetEcrPayload() []byte { - return f.ecrPayload -} - -func (f format) GetEcrPayloadLen() int { - return len(f.ecrPayload) -} - -func (f format) SetEcrPayload(ecr []byte) { - if len(ecr) != len(f.ecrPayload) { - jww.FATAL.Panicf("Passed ecr payload incorrect lengh. Expected:"+ - " %v, Recieved: %v", len(f.ecrPayload), len(ecr)) - } - - copy(f.ecrPayload, ecr) -} diff --git a/auth/callback.go b/auth/callback.go new file mode 100644 index 0000000000000000000000000000000000000000..50ab6055776a074f893eddc0f985cb97f16cd578 --- /dev/null +++ b/auth/callback.go @@ -0,0 +1,37 @@ +package auth + +import ( + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/client/interfaces/message" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/xx_network/primitives/id" + "time" +) + +type RequestCallback func(requestor contact.Contact, message string) +type ConfirmCallback func(partner contact.Contact) + +func RegisterCallbacks(rcb RequestCallback, ccb ConfirmCallback, + sw interfaces.Switchboard, storage *storage.Session) stoppable.Stoppable { + + rawMessages := make(chan message.Receive, 1000) + sw.RegisterChannel("Auth", &id.ID{}, message.Raw, rawMessages) + + stop := stoppable.NewSingle("Auth") + + go func() { + select { + case <-stop.Quit(): + return + case msg := <-rawMessages: + //check the message is well formed + if msglen(msg.Payload) != 2* + cmixMsg := format.Unmarshal(msg.Payload) + } + + }() + +} diff --git a/auth/ecrformat.go b/auth/ecrformat.go deleted file mode 100644 index 7943c501d77a94d66bd7b0df5d9814131ccf2ddb..0000000000000000000000000000000000000000 --- a/auth/ecrformat.go +++ /dev/null @@ -1,73 +0,0 @@ -package auth - -import ( - "github.com/pkg/errors" - jww "github.com/spf13/jwalterweatherman" -) - -const ownershipSize = 32 - -type ecrFormat struct { - data []byte - ownership []byte - payload []byte -} - -func newEcrFormat(size uint, ownership []byte) ecrFormat { - if size < ownershipSize { - jww.FATAL.Panicf("Size too small to hold") - } - - if len(ownership) != ownershipSize { - jww.FATAL.Panicf("ownership proof is the wrong size") - } - - f := buildEcrFormat(make([]byte, size)) - - copy(f.ownership, ownership) - - return f - -} - -func buildEcrFormat(data []byte) ecrFormat { - f := ecrFormat{ - data: data, - } - - f.ownership = f.data[:ownershipSize] - f.payload = f.data[ownershipSize:] - return f -} - -func unmarshalEcrFormat(b []byte) (ecrFormat, error) { - if len(b) < ownershipSize { - return ecrFormat{}, errors.New("Received ecr format too small") - } - - return buildEcrFormat(b), nil -} - -func (f ecrFormat) Marshal() []byte { - return f.data -} - -func (f ecrFormat) GetOwnership() []byte { - return f.ownership -} - -func (f ecrFormat) GetPayload() []byte { - return f.payload -} - -func (f ecrFormat) GetPayloadSize() int { - return len(f.payload) -} - -func (f ecrFormat) SetPayload(p []byte) { - if len(p) != len(f.payload) { - jww.FATAL.Panicf("Payload is the wrong length") - } - - copy(f.payload, p) -} diff --git a/auth/fmt.go b/auth/fmt.go new file mode 100644 index 0000000000000000000000000000000000000000..39f13a002126e7003bd1b247cdfd7d1d95904ca6 --- /dev/null +++ b/auth/fmt.go @@ -0,0 +1,207 @@ +package auth + +import ( + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/xx_network/primitives/id" +) + +//Basic Format////////////////////////////////////////////////////////////////// +const saltSize = 32 + +type baseFormat struct { + data []byte + pubkey []byte + salt []byte + ecrPayload []byte +} + +func newBaseFormat(payloadSize, pubkeySize int) baseFormat { + + if payloadSize < pubkeySize+saltSize { + jww.FATAL.Panicf("Size of baseFormat is too small, must be big " + + "enough to contain public key and salt") + } + + f := buildBaseFormat(make([]byte, payloadSize), pubkeySize) + + return f +} + +func buildBaseFormat(data []byte, pubkeySize int) baseFormat { + f := baseFormat{ + data: data, + } + + f.pubkey = f.data[:pubkeySize] + f.salt = f.data[pubkeySize : pubkeySize+saltSize] + f.ecrPayload = f.data[pubkeySize+saltSize:] + return f +} + +func unmarshalFormat(b []byte, pubkeySize int) (baseFormat, error) { + if len(b) < pubkeySize+saltSize { + return baseFormat{}, errors.New("Received baseFormat too small") + } + + return buildBaseFormat(b, pubkeySize), nil +} + +func (f baseFormat) Marshal() []byte { + return f.data +} + +func (f baseFormat) GetPubKey(grp *cyclic.Group) *cyclic.Int { + return grp.NewIntFromBytes(f.pubkey) +} + +func (f baseFormat) SetPubKey(pubKey *cyclic.Int) { + pubKeyBytes := pubKey.LeftpadBytes(uint64(len(f.pubkey))) + copy(f.pubkey, pubKeyBytes) +} + +func (f baseFormat) GetSalt() []byte { + return f.salt +} + +func (f baseFormat) SetSalt(salt []byte) { + if len(salt) != saltSize { + jww.FATAL.Panicf("Salt incorrect size") + } + + copy(f.salt, salt) +} + +func (f baseFormat) GetEcrPayload() []byte { + return f.ecrPayload +} + +func (f baseFormat) GetEcrPayloadLen() int { + return len(f.ecrPayload) +} + +func (f baseFormat) SetEcrPayload(ecr []byte) { + if len(ecr) != len(f.ecrPayload) { + jww.FATAL.Panicf("Passed ecr payload incorrect lengh. Expected:"+ + " %v, Recieved: %v", len(f.ecrPayload), len(ecr)) + } + + copy(f.ecrPayload, ecr) +} + +//Encrypted Format////////////////////////////////////////////////////////////// +const ownershipSize = 32 + +type ecrFormat struct { + data []byte + ownership []byte + payload []byte +} + +func newEcrFormat(size int) ecrFormat { + if size < ownershipSize { + jww.FATAL.Panicf("Size too small to hold") + } + + f := buildEcrFormat(make([]byte, size)) + + return f + +} + +func buildEcrFormat(data []byte) ecrFormat { + f := ecrFormat{ + data: data, + } + + f.ownership = f.data[:ownershipSize] + f.payload = f.data[ownershipSize:] + return f +} + +func unmarshalEcrFormat(b []byte) (ecrFormat, error) { + if len(b) < ownershipSize { + return ecrFormat{}, errors.New("Received ecr baseFormat too small") + } + + return buildEcrFormat(b), nil +} + +func (f ecrFormat) Marshal() []byte { + return f.data +} + +func (f ecrFormat) GetOwnership() []byte { + return f.ownership +} + +func (f ecrFormat) SetOwnership(ownership []byte) { + if len(ownership) != ownershipSize { + jww.FATAL.Panicf("ownership proof is the wrong size") + } + + copy(f.ownership, ownership) +} + +func (f ecrFormat) GetPayload() []byte { + return f.payload +} + +func (f ecrFormat) PayloadLen() int { + return len(f.payload) +} + +func (f ecrFormat) SetPayload(p []byte) { + if len(p) != len(f.payload) { + jww.FATAL.Panicf("Payload is the wrong length") + } + + copy(f.payload, p) +} + +//Request Format//////////////////////////////////////////////////////////////// +type requestFormat struct { + ecrFormat + id []byte + msgPayload []byte +} + +func newRequestFormat(ecrFmt ecrFormat) (requestFormat) { + if len(ecrFmt.payload) < id.ArrIDLen { + jww.FATAL.Panicf("Payload is not long enough") + } + + rf := requestFormat{ + ecrFormat: ecrFmt, + } + + rf.id = rf.payload[:id.ArrIDLen] + rf.id = rf.payload[id.ArrIDLen:] + + return rf +} + +func (rf requestFormat) GetID() (*id.ID, error) { + return id.Unmarshal(rf.id) +} + +func (rf requestFormat) SetID(myId *id.ID) { + copy(rf.id, myId.Marshal()) +} + +func (rf requestFormat) SetMsgPayload(b []byte) { + if len(b) > len(rf.msgPayload) { + jww.FATAL.Panicf("Message Payload is too long") + } + + copy(rf.msgPayload, b) +} + +func (rf requestFormat) MsgPayloadLen() int { + return len(rf.msgPayload) +} + +func (rf requestFormat) GetMsgPayload() []byte { + return rf.msgPayload +} diff --git a/auth/request.go b/auth/request.go new file mode 100644 index 0000000000000000000000000000000000000000..bafa9c5fbb5d385dbdb5e18137cb9858d14fef37 --- /dev/null +++ b/auth/request.go @@ -0,0 +1,151 @@ +package auth + +import ( + ds "gitlab.com/elixxir/comms/network/dataStructures" + "github.com/pkg/errors" + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/interfaces/contact" + "gitlab.com/elixxir/client/interfaces/params" + "gitlab.com/elixxir/client/interfaces/utility" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/storage/auth" + "gitlab.com/elixxir/client/storage/e2e" + "gitlab.com/elixxir/crypto/diffieHellman" + cAuth "gitlab.com/elixxir/crypto/e2e/auth" + "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/states" + "io" + "strings" + "time" + jww "github.com/spf13/jwalterweatherman" +) + +const eol = string(0x0a) + +func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, + storage *storage.Session, net interfaces.NetworkManager) error { + /*edge checks generation*/ + + // check that messages can be sent over the network + if !net.GetHealthTracker().IsHealthy() { + return errors.New("Cannot create authenticated message " + + "when the network is not healthy") + } + + // check that an authenticated channel does not already exists + if _, err := storage.E2e().GetPartner(partner.ID); err == nil || + !strings.Contains(err.Error(), e2e.NoPartnerErrorStr) { + return errors.Errorf("Authenticated channel already " + + "established with partner") + } + + // check that the request is being sent from the proper ID + if !me.ID.Cmp(storage.GetUser().ID) { + return errors.Errorf("Authenticated channel request " + + "can only be sent from user's identity") + } + + // check that the message is properly formed + if strings.Contains(message, eol) { + return errors.Errorf("Message cannot contain 'EOL'") + } + + //lookup if an ongoing request is occurring + rqType, _, _, err := storage.Auth().GetRequest(partner.ID) + if err != nil && !strings.Contains(err.Error(), auth.NoRequest) { + return errors.WithMessage(err, "Error on lookup of potential "+ + "existing request") + } else if rqType == auth.Receive { + return errors.WithMessage(err, "Cannot send a request after"+ + "receiving a request") + } else if rqType == auth.Sent { + return errors.WithMessage(err, "Cannot send a request after"+ + "already sending one") + } + + grp := storage.E2e().GetGroup() + + /*generate embedded message structures and check payload*/ + cmixMsg := format.NewMessage(storage.Cmix().GetGroup().GetP().ByteLen()) + baseFmt := newBaseFormat(cmixMsg.ContentsSize(), grp.GetP().ByteLen()) + ecrFmt := newEcrFormat(baseFmt.GetEcrPayloadLen()) + requestFmt := newRequestFormat(ecrFmt) + + //check the payload fits + facts := me.StringifyFacts() + msgPayload := facts + message + eol + msgPayloadBytes := []byte(msgPayload) + + if len(msgPayloadBytes) > requestFmt.MsgPayloadLen() { + return errors.Errorf("Combined message longer than space "+ + "available in payload; available: %v, length: %v", + requestFmt.MsgPayloadLen(), len(msgPayloadBytes)) + } + + /*cryptographic generation*/ + //generate salt + salt := make([]byte, saltSize) + _, err = rng.Read(salt) + if err != nil { + return errors.Wrap(err, "Failed to generate salt") + } + + //generate ownership proof + ownership := cAuth.MakeOwnershipProof(storage.E2e().GetDHPrivateKey(), + partner.DhPubKey, storage.E2e().GetGroup()) + + //generate new keypair + newPrivKey := diffieHellman.GeneratePrivateKey(256, grp, rng) + newPubKey := diffieHellman.GeneratePublicKey(newPrivKey, grp) + + /*encrypt payload*/ + requestFmt.SetID(storage.GetUser().ID) + requestFmt.SetMsgPayload(msgPayloadBytes) + ecrFmt.SetOwnership(ownership) + ecrPayload, mac, fp := cAuth.Encrypt(newPrivKey, partner.DhPubKey, + salt, ecrFmt.payload, grp) + + /*construct message*/ + baseFmt.SetEcrPayload(ecrPayload) + baseFmt.SetSalt(salt) + baseFmt.SetPubKey(newPubKey) + + cmixMsg.SetKeyFP(fp) + cmixMsg.SetMac(mac) + cmixMsg.SetContents(baseFmt.Marshal()) + + /*store state*/ + //fixme: channel is bricked if the first store succedes but the second fails + //store the in progress auth + err = storage.Auth().AddSent(partner.ID, newPrivKey, newPrivKey, fp) + if err != nil { + return errors.Errorf("Failed to store auth request: %s", err) + } + //store the message as a critical message so it will alwasy be sent + storage.GetCriticalRawMessages().AddProcessing(cmixMsg) + + /*send message*/ + round, err := net.SendCMIX(cmixMsg, params.GetDefaultCMIX()) + if err != nil { + // if the send fails just set it to failed, it will but automatically + // retried + jww.ERROR.Printf("request failed to transmit, will be "+ + "handled on reconnect: %+v", err) + storage.GetCriticalRawMessages().Failed(cmixMsg) + } + + /*check message delivery*/ + sendResults := make(chan ds.EventReturn, 1) + roundEvents := net.GetInstance().GetRoundEvents() + + roundEvents.AddRoundEventChan(round, sendResults, 1*time.Minute, + states.COMPLETED, states.FAILED) + + success, _, _ := utility.TrackResults(sendResults, 1) + if !success { + jww.ERROR.Printf("request failed to transmit, will be " + + "handled on reconnect") + storage.GetCriticalRawMessages().Failed(cmixMsg) + } + return nil +} diff --git a/auth/requestFormat.go b/auth/requestFormat.go deleted file mode 100644 index de8e5031e2c3ffd99456005489b593c785952b0f..0000000000000000000000000000000000000000 --- a/auth/requestFormat.go +++ /dev/null @@ -1,8 +0,0 @@ -package auth - -type requestFormat struct { - ecrFormat - id []byte - facts []byte - message []byte -} diff --git a/interfaces/message/type.go b/interfaces/message/type.go index b314af9798c099f55355aefea64d9867caec5db3..19c71c879df7a70f0b2470c7a78cb0ec4ed6d6dd 100644 --- a/interfaces/message/type.go +++ b/interfaces/message/type.go @@ -10,6 +10,8 @@ const ( NoType Type = 0 // A message with no message structure + // this is a reserved type, a message sent with this type will be + // ignored on reception. To send a raw message use SendCMIX. Raw Type = 1 //General text message, contains human readable text diff --git a/network/message/critical.go b/network/message/critical.go index e2a06de29fcfaa52219331092dd5596404fb11f7..2720b84f41a2dd835d6a7db9bf585da4efb522e2 100644 --- a/network/message/critical.go +++ b/network/message/critical.go @@ -6,6 +6,7 @@ import ( "gitlab.com/elixxir/client/interfaces/params" "gitlab.com/elixxir/client/interfaces/utility" ds "gitlab.com/elixxir/comms/network/dataStructures" + "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/states" "time" ) @@ -35,7 +36,10 @@ func (m *Manager) processCriticalMessages(quitCh <-chan struct{}) { // processes all critical messages func (m *Manager) criticalMessages() { critMsgs := m.Session.GetCriticalMessages() - //try to send every message in the critical messages buffer in paralell + // try to send every message in the critical messages and the raw critical + // messages buffer in paralell + + //critical messages for msg, param, has := critMsgs.Next(); has; msg, param, has = critMsgs.Next() { go func(msg message.Send, param params.E2E) { //send the message @@ -66,4 +70,41 @@ func (m *Manager) criticalMessages() { critMsgs.Succeeded(msg) }(msg, param) } + + critRawMsgs := m.Session.GetCriticalRawMessages() + param := params.GetDefaultCMIX() + //raw critical messages + for msg, has := critRawMsgs.Next(); has; msg, has = critRawMsgs.Next() { + go func(msg format.Message) { + //send the message + round, err := m.SendCMIX(msg, param) + //if the message fail to send, notify the buffer so it can be handled + //in the future and exit + if err != nil { + jww.ERROR.Printf("Failed to send critical message on " + + "notification of healthy network") + critRawMsgs.Failed(msg) + return + } + //wait on the results to make sure the rounds were sucesfull + sendResults := make(chan ds.EventReturn, 1) + roundEvents := m.Instance.GetRoundEvents() + + roundEvents.AddRoundEventChan(round, sendResults, 1*time.Minute, + states.COMPLETED, states.FAILED) + + success, numTimeOut, numRoundFail := utility.TrackResults(sendResults, 1) + if !success { + jww.ERROR.Printf("critical message send failed to transmit "+ + "transmit %v/%v paritions: %v round failures, %v timeouts", + numRoundFail+numTimeOut, 1, numRoundFail, numTimeOut) + critRawMsgs.Failed(msg) + return + } + critRawMsgs.Succeeded(msg) + }(msg) + } + + + } diff --git a/network/message/handler.go b/network/message/handler.go index 0447a4ee8d70d5ff5380fd3a4e2f1d6912b7aeee..f740f7756284610d4f64db825491ea5de5a1b467 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -66,14 +66,14 @@ func (m *Manager) handleMessage(ecrMsg format.Message) { // and add it to garbled messages to be handled later msg = ecrMsg raw := message.Receive{ - Payload: msg.GetRawContents(), + Payload: msg.Marshal(), MessageType: message.Raw, Sender: &id.ID{}, Timestamp: time.Time{}, Encryption: message.None, } - m.Switchboard.Speak(raw) m.Session.GetGarbledMessages().Add(msg) + m.Switchboard.Speak(raw) return } @@ -83,6 +83,12 @@ func (m *Manager) handleMessage(ecrMsg format.Message) { relationshipFingerprint) // If the reception completed a message, hear it on the switchboard if ok { - m.Switchboard.Speak(xxMsg) + if xxMsg.MessageType == message.Raw { + jww.WARN.Panicf("Recieved a message of type 'Raw' from %s."+ + "Message Ignored, 'Raw' is a reserved type. Message supressed.", + xxMsg.ID) + } else { + m.Switchboard.Speak(xxMsg) + } } } diff --git a/storage/auth/request.go b/storage/auth/request.go index cbc744cae9f95d12b85424311c233f51ba30b975..449e99854fc6ff97d12e069d2d4e46996f6f22ae 100644 --- a/storage/auth/request.go +++ b/storage/auth/request.go @@ -5,15 +5,15 @@ import ( "sync" ) -type requestType uint +type RequestType uint const ( - Sent requestType = 0 - Receive requestType = 1 + Sent RequestType = 0 + Receive RequestType = 1 ) type request struct { - rt requestType + rt RequestType //data if sent sent *SentRequest //data if receive diff --git a/storage/auth/sentRequest.go b/storage/auth/sentRequest.go index 2a99d256779dd9ece29009b150954f4cd26ecd3e..c2c67d7283193e44bb0cfe3c7df2c92cd1334083 100644 --- a/storage/auth/sentRequest.go +++ b/storage/auth/sentRequest.go @@ -7,6 +7,7 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" + "sync" "time" ) @@ -19,6 +20,7 @@ type SentRequest struct { myPrivKey *cyclic.Int myPubKey *cyclic.Int fingerprint format.Fingerprint + sentMux sync.Mutex } type sentRequestDisk struct { @@ -34,27 +36,27 @@ func loadSentRequest(kv *versioned.KV, partner *id.ID, grp *cyclic.Group) (*Sent "SentRequest Auth with %s", partner) } - ipd := &sentRequestDisk{} + srd := &sentRequestDisk{} - if err := json.Unmarshal(obj.Data, ipd); err != nil { + if err := json.Unmarshal(obj.Data, srd); err != nil { return nil, errors.WithMessagef(err, "Failed to Unmarshal "+ "SentRequest Auth with %s", partner) } myPrivKey := grp.NewInt(1) - if err = myPrivKey.GobDecode(ipd.MyPubKey); err != nil { + if err = myPrivKey.GobDecode(srd.MyPubKey); err != nil { return nil, errors.WithMessagef(err, "Failed to decode private "+ "key with %s for SentRequest Auth", partner) } myPubKey := grp.NewInt(1) - if err = myPubKey.GobDecode(ipd.MyPubKey); err != nil { + if err = myPubKey.GobDecode(srd.MyPubKey); err != nil { return nil, errors.WithMessagef(err, "Failed to decode public "+ "key with %s for SentRequest Auth", partner) } fp := format.Fingerprint{} - copy(fp[:], ipd.Fingerprint) + copy(fp[:], srd.Fingerprint) return &SentRequest{ kv: kv, @@ -65,14 +67,14 @@ func loadSentRequest(kv *versioned.KV, partner *id.ID, grp *cyclic.Group) (*Sent }, nil } -func (ip *SentRequest) save() error { +func (sr *SentRequest) save() error { - privKey, err := ip.myPrivKey.GobEncode() + privKey, err := sr.myPrivKey.GobEncode() if err != nil { return err } - pubKey, err := ip.myPubKey.GobEncode() + pubKey, err := sr.myPubKey.GobEncode() if err != nil { return err } @@ -80,7 +82,7 @@ func (ip *SentRequest) save() error { ipd := sentRequestDisk{ MyPrivKey: privKey, MyPubKey: pubKey, - Fingerprint: ip.fingerprint[:], + Fingerprint: sr.fingerprint[:], } data, err := json.Marshal(&ipd) @@ -94,25 +96,25 @@ func (ip *SentRequest) save() error { Data: data, } - return ip.kv.Set(versioned.MakePartnerPrefix(ip.partner), &obj) + return sr.kv.Set(versioned.MakePartnerPrefix(sr.partner), &obj) } -func (ip *SentRequest) delete() error { - return ip.kv.Delete(versioned.MakePartnerPrefix(ip.partner)) +func (sr *SentRequest) delete() error { + return sr.kv.Delete(versioned.MakePartnerPrefix(sr.partner)) } -func (ip *SentRequest) GetPartner() *id.ID { - return ip.partner +func (sr *SentRequest) GetPartner() *id.ID { + return sr.partner } -func (ip *SentRequest) GetMyPrivKey() *cyclic.Int { - return ip.myPrivKey +func (sr *SentRequest) GetMyPrivKey() *cyclic.Int { + return sr.myPrivKey } -func (ip *SentRequest) GetMyPubKey() *cyclic.Int { - return ip.myPubKey +func (sr *SentRequest) GetMyPubKey() *cyclic.Int { + return sr.myPubKey } -func (ip *SentRequest) GetFingerprint() format.Fingerprint { - return ip.fingerprint +func (sr *SentRequest) GetFingerprint() format.Fingerprint { + return sr.fingerprint } diff --git a/storage/auth/store.go b/storage/auth/store.go index 22980ad44d35c8bf066ca9975fb1ca7e91077a23..e7a15c07e908977c9199f33b4a487c86f259d25e 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -15,6 +15,8 @@ import ( "time" ) +const NoRequest = "Request Not Found" + const storePrefix = "requestMap" const requestMapKey = "map" @@ -85,7 +87,7 @@ func LoadStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*St for _, rDisk := range requestList { r := &request{ - rt: requestType(rDisk.T), + rt: RequestType(rDisk.T), } partner, err := id.Unmarshal(rDisk.ID) @@ -302,6 +304,28 @@ func (s *Store) GetReceivedRequestData(partner *id.ID) (contact.Contact, error) return *r.receive, nil } +// returns request with its type and data. the lock is not taken. +func (s *Store) GetRequest(partner *id.ID) (RequestType, *SentRequest, contact.Contact, error) { + s.mux.RLock() + r, ok := s.requests[*partner] + s.mux.RUnlock() + + if !ok { + return 0, nil, contact.Contact{}, errors.New(NoRequest) + } + + switch r.rt { + case Sent: + return Sent, r.sent, contact.Contact{}, nil + case Receive: + return Receive, nil, *r.receive, nil + default: + return 0, nil, contact.Contact{}, + errors.Errorf("invalid Type: %s", r.rt) + } +} + + // One of two calls after using a request. This one to be used when the use // is unsuccessful. It will allow any thread waiting on access to continue // using the structure diff --git a/storage/e2e/store.go b/storage/e2e/store.go index b30d1c47913cbad1f5b885ad85b28a622d3d7957..a3694aafc722dfbe08068c261f15868c9bb89fc1 100644 --- a/storage/e2e/store.go +++ b/storage/e2e/store.go @@ -30,6 +30,9 @@ const ( grpKey = "Group" ) +var NoPartnerErrorStr = "No relationship with partner found" + + type Store struct { managers map[id.ID]*Manager mux sync.RWMutex @@ -97,6 +100,11 @@ func LoadStore(kv *versioned.KV, myID *id.ID, rng *fastRNG.StreamGenerator) (*St fingerprints := newFingerprints() kv = kv.Prefix(packagePrefix) + grp, err := utility.LoadGroup(kv, grpKey) + if err != nil { + return nil, err + } + s := &Store{ managers: make(map[id.ID]*Manager), @@ -108,6 +116,7 @@ func LoadStore(kv *versioned.KV, myID *id.ID, rng *fastRNG.StreamGenerator) (*St fa: &fingerprints, rng: rng, myID: myID, + grp: grp, }, } @@ -171,7 +180,7 @@ func (s *Store) GetPartner(partnerID *id.ID) (*Manager, error) { m, ok := s.managers[*partnerID] if !ok { - return nil, errors.New("Could not find relationship for partner") + return nil, errors.New(NoPartnerErrorStr) } return m, nil @@ -247,11 +256,6 @@ func (s *Store) unmarshal(b []byte) error { return errors.WithMessage(err, "Failed to load e2e DH public key") } - s.grp, err = utility.LoadGroup(s.kv, grpKey) - if err != nil { - return errors.WithMessage(err, "Failed to load e2e group") - } - return nil } diff --git a/storage/messages.go b/storage/messages.go index b608877ed82c7fdf7422c21a9594309e2f98e8a1..f5b6e43a8d11251c0fe866a1bf5fa14c221c4fa9 100644 --- a/storage/messages.go +++ b/storage/messages.go @@ -1,7 +1,8 @@ package storage const ( - criticalMessagesKey = "CriticalMessages" - garbledMessagesKey = "GarbledMessages" - checkedRoundsKey = "CheckedRounds" + criticalMessagesKey = "CriticalMessages" + criticalRawMessagesKey = "CriticalRawMessages" + garbledMessagesKey = "GarbledMessages" + checkedRoundsKey = "CheckedRounds" ) diff --git a/storage/session.go b/storage/session.go index a37cc31d0ca3fb5382a264795667a92cf7d9407b..9c34818966a32166f3ac6c958496dd0ce2ea3a06 100644 --- a/storage/session.go +++ b/storage/session.go @@ -45,15 +45,16 @@ type Session struct { baseNdf *ndf.NetworkDefinition //sub-stores - e2e *e2e.Store - cmix *cmix.Store - user *user.User - conversations *conversation.Store - partition *partition.Store - auth *auth.Store - criticalMessages *utility.E2eMessageBuffer - garbledMessages *utility.MeteredCmixMessageBuffer - checkedRounds *utility.KnownRounds + e2e *e2e.Store + cmix *cmix.Store + user *user.User + conversations *conversation.Store + partition *partition.Store + auth *auth.Store + criticalMessages *utility.E2eMessageBuffer + criticalRawMessages *utility.CmixMessageBuffer + garbledMessages *utility.MeteredCmixMessageBuffer + checkedRounds *utility.KnownRounds } // Initialize a new Session object @@ -123,7 +124,12 @@ func New(baseDir, password string, u userInterface.User, cmixGrp, s.criticalMessages, err = utility.NewE2eMessageBuffer(s.kv, criticalMessagesKey) if err != nil { - return nil, errors.WithMessage(err, "Failed to create e2e message buffer") + return nil, errors.WithMessage(err, "Failed to create e2e critical message buffer") + } + + s.criticalRawMessages, err = utility.NewCmixMessageBuffer(s.kv, criticalRawMessagesKey) + if err != nil { + return nil, errors.WithMessage(err, "Failed to create raw critical message buffer") } s.conversations = conversation.NewStore(s.kv) @@ -172,6 +178,11 @@ func Load(baseDir, password string, rng *fastRNG.StreamGenerator) (*Session, err return nil, errors.WithMessage(err, "Failed to load session") } + s.criticalRawMessages, err = utility.LoadCmixMessageBuffer(s.kv, criticalRawMessagesKey) + if err != nil { + return nil, errors.WithMessage(err, "Failed to load raw critical message buffer") + } + s.garbledMessages, err = utility.LoadMeteredCmixMessageBuffer(s.kv, garbledMessagesKey) if err != nil { return nil, errors.WithMessage(err, "Failed to load session") @@ -218,6 +229,12 @@ func (s *Session) GetCriticalMessages() *utility.E2eMessageBuffer { return s.criticalMessages } +func (s *Session) GetCriticalRawMessages() *utility.CmixMessageBuffer { + s.mux.RLock() + defer s.mux.RUnlock() + return s.criticalRawMessages +} + func (s *Session) GetGarbledMessages() *utility.MeteredCmixMessageBuffer { s.mux.RLock() defer s.mux.RUnlock()