Skip to content
Snippets Groups Projects
Commit 6cffc570 authored by Jake Taylor's avatar Jake Taylor
Browse files

added api client to support multi-connections for IDs

parent eda76494
No related branches found
No related tags found
2 merge requests!510Release,!238Hotfix/e2e client
Showing with 345 additions and 89 deletions
......@@ -5,7 +5,7 @@
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package messenger
package e2eApi
import "sync"
......
// FIXME: This is placeholder, there's got to be a better place to put
// backup restoration than inside messenger.
package messenger
package e2eApi
import (
"github.com/pkg/errors"
......
......@@ -5,7 +5,7 @@
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
 
package messenger
package e2eApi
 
import (
"bytes"
......
package messenger
package e2eApi
import (
"encoding/binary"
"encoding/json"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv"
"time"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
......@@ -21,9 +24,28 @@ type Client struct {
auth auth.State
e2e e2e.Handler
backup *Container
e2eIdentity TransmissionIdentity
}
func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error) {
// Login creates a new e2eApi.Client backed by the api.Client persistent versioned.KV
// If identity == nil, a new TransmissionIdentity will be generated automagically
func Login(client *api.Client, callbacks auth.Callbacks,
identity *TransmissionIdentity) (m *Client, err error) {
return login(client, callbacks, identity, client.GetStorage().GetKV())
}
// LoginEphemeral creates a new e2eApi.Client backed by a totally ephemeral versioned.KV
// If identity == nil, a new TransmissionIdentity will be generated automagically
func LoginEphemeral(client *api.Client, callbacks auth.Callbacks,
identity *TransmissionIdentity) (m *Client, err error) {
return login(client, callbacks, identity, versioned.NewKV(ekv.MakeMemstore()))
}
// LoginLegacy creates a new e2eApi.Client backed by the api.Client persistent versioned.KV
// Uses the pre-generated transmission ID used by api.Client
// This function is designed to maintain backwards compatibility with previous xx messenger designs
// and should not be used for other purposes
func LoginLegacy(client *api.Client, callbacks auth.Callbacks) (m *Client, err error) {
m = &Client{
Client: client,
backup: &Container{},
......@@ -41,6 +63,63 @@ func Login(client *api.Client, callbacks auth.Callbacks) (m *Client, err error)
return nil, err
}
u := m.Client.GetUser()
m.e2eIdentity = TransmissionIdentity{
ID: u.TransmissionID,
RSAPrivatePem: u.TransmissionRSA,
Salt: u.TransmissionSalt,
DHKeyPrivate: u.E2eDhPrivateKey,
}
return m, err
}
// login creates a new e2eApi.Client backed by the given versioned.KV
func login(client *api.Client, callbacks auth.Callbacks,
identity *TransmissionIdentity, kv *versioned.KV) (m *Client, err error) {
e2eGrp := client.GetStorage().GetE2EGroup()
// Create new identity automatically if one isn't specified
if identity == nil {
rng := client.GetRng().GetStream()
newIdentity, err := MakeTransmissionIdentity(rng, e2eGrp)
rng.Close()
if err != nil {
return nil, err
}
identity = &newIdentity
client.GetCmix().AddIdentity(identity.ID, time.Time{}, !kv.IsMemStore())
}
m = &Client{
Client: client,
backup: &Container{},
e2eIdentity: *identity,
}
//initialize the e2e storage
err = e2e.Init(kv, identity.ID, identity.DHKeyPrivate, e2eGrp,
rekey.GetDefaultEphemeralParams())
if err != nil {
return nil, err
}
//load the new e2e storage
m.e2e, err = e2e.Load(kv,
client.GetCmix(), identity.ID, e2eGrp, client.GetRng(),
client.GetEventReporter())
if err != nil {
return nil, errors.WithMessage(err, "Failed to load a "+
"newly created e2e store")
}
m.auth, err = auth.NewState(kv, client.GetCmix(),
m.e2e, client.GetRng(), client.GetEventReporter(),
auth.GetDefaultTemporaryParams(), callbacks, m.backup.TriggerBackup)
if err != nil {
return nil, err
}
return m, err
}
......@@ -52,7 +131,7 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
e2eGrp := client.GetStorage().GetE2EGroup()
kv := client.GetStorage().GetKV()
//try to load a legacy e2e hander
//try to load a legacy e2e handler
e2eHandler, err := e2e.LoadLegacy(kv,
client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
client.GetEventReporter(), rekey.GetDefaultParams())
......@@ -61,7 +140,7 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
e2eHandler, err = e2e.Load(kv,
client.GetCmix(), usr.ReceptionID, e2eGrp, client.GetRng(),
client.GetEventReporter())
//if no new e2e handler exists, initilize an e2e user
//if no new e2e handler exists, initialize an e2e user
if err != nil {
jww.WARN.Printf("Failed to load e2e instance for %s, "+
"creating a new one", usr.ReceptionID)
......@@ -102,6 +181,8 @@ func LoadOrInitE2e(client *api.Client) (e2e.Handler, error) {
return nil, errors.WithMessage(err, "Failed to load a "+
"newly created e2e store")
}
client.GetCmix().AddIdentity(usr.ReceptionID, time.Time{}, true)
} else {
jww.INFO.Printf("Loaded a modern e2e instance for %s",
usr.ReceptionID)
......@@ -122,6 +203,11 @@ func (m *Client) GetUser() user.Info {
return u
}
// GetTransmissionIdentity returns a safe copy of the Client TransmissionIdentity
func (m *Client) GetTransmissionIdentity() TransmissionIdentity {
return m.e2eIdentity.DeepCopy()
}
// ConstructProtoUserFile is a helper function which is used for proto
// client testing. This is used for development testing.
func (m *Client) ConstructProtoUserFile() ([]byte, error) {
......@@ -190,7 +276,7 @@ func (m *Client) DeleteContact(partnerId *id.ID) error {
// c.e2e.Conversations().Delete(partnerId)
// call delete requests to make sure nothing is lingering.
// this is for saftey to ensure the contact can be readded
// this is for safety to ensure the contact can be re-added
// in the future
_ = m.auth.DeleteRequest(partnerId)
......
package api
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 Privategrity Corporation /
// /
// All rights reserved. /
////////////////////////////////////////////////////////////////////////////////
package e2eApi
import (
"gitlab.com/elixxir/crypto/cyclic"
......@@ -9,20 +15,20 @@ import (
"gitlab.com/xx_network/primitives/id"
)
type Identity struct {
type TransmissionIdentity struct {
ID *id.ID
RSAPrivatePem *rsa.PrivateKey
Salt []byte
DHKeyPrivate *cyclic.Int
}
// MakeIdentity generates a new cryptographic identity for receiving messages
func MakeIdentity(rng csprng.Source, grp *cyclic.Group) (Identity, error) {
// MakeTransmissionIdentity generates a new cryptographic identity for receiving messages
func MakeTransmissionIdentity(rng csprng.Source, grp *cyclic.Group) (TransmissionIdentity, error) {
//make RSA Key
rsaKey, err := rsa.GenerateKey(rng,
rsa.DefaultRSABitLen)
if err != nil {
return Identity{}, err
return TransmissionIdentity{}, err
}
//make salt
......@@ -30,7 +36,7 @@ func MakeIdentity(rng csprng.Source, grp *cyclic.Group) (Identity, error) {
_, err = rng.Read(salt)
//make dh private key
privkey := diffieHellman.GeneratePrivateKey(
privKey := diffieHellman.GeneratePrivateKey(
len(grp.GetPBytes()),
grp, rng)
......@@ -38,16 +44,28 @@ func MakeIdentity(rng csprng.Source, grp *cyclic.Group) (Identity, error) {
newId, err := xx.NewID(rsaKey.GetPublic(),
salt, id.User)
if err != nil {
return Identity{}, err
return TransmissionIdentity{}, err
}
//create the identity object
I := Identity{
I := TransmissionIdentity{
ID: newId,
RSAPrivatePem: rsaKey,
Salt: salt,
DHKeyPrivate: privkey,
DHKeyPrivate: privKey,
}
return I, nil
}
// DeepCopy produces a safe copy of a TransmissionIdentity
func (t TransmissionIdentity) DeepCopy() TransmissionIdentity {
saltCopy := make([]byte, len(t.Salt))
copy(saltCopy, t.Salt)
return TransmissionIdentity{
ID: t.ID.DeepCopy(),
RSAPrivatePem: t.RSAPrivatePem,
Salt: saltCopy,
DHKeyPrivate: t.DHKeyPrivate.DeepCopy(),
}
}
......@@ -5,7 +5,7 @@
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package messenger
package e2eApi
import (
"github.com/pkg/errors"
......
package messenger
package e2eApi
import (
"encoding/binary"
......
......@@ -6,7 +6,7 @@
// Provides various utility functions for access over the bindings
package messenger
package e2eApi
import (
"bytes"
......
......@@ -96,6 +96,12 @@ type State interface {
// VerifyOwnership checks if the received ownership proof is valid
VerifyOwnership(received, verified contact.Contact, e2e e2e.Handler) bool
// AddPartnerCallback that overrides the generic auth callback for the given partnerId
AddPartnerCallback(partnerId *id.ID, cb Callbacks)
// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
DeletePartnerCallback(partnerId *id.ID)
//Closer stops listening to auth
io.Closer
}
......
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 Privategrity Corporation /
// /
// All rights reserved. /
////////////////////////////////////////////////////////////////////////////////
package auth
import (
"gitlab.com/xx_network/primitives/id"
"sync"
)
// partnerCallbacks is a thread-safe wrapper for Callbacks specific to partnerIds
// For auth operations with a specific partner, these Callbacks will be used instead
type partnerCallbacks struct {
callbacks map[id.ID]Callbacks
sync.RWMutex
}
// AddPartnerCallback that overrides the generic auth callback for the given partnerId
func (p *partnerCallbacks) AddPartnerCallback(partnerId *id.ID, cb Callbacks) {
p.Lock()
defer p.Unlock()
if _, ok := p.callbacks[*partnerId]; !ok {
p.callbacks[*partnerId] = cb
}
}
// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
func (p *partnerCallbacks) DeletePartnerCallback(partnerId *id.ID) {
p.Lock()
defer p.Unlock()
if _, ok := p.callbacks[*partnerId]; ok {
delete(p.callbacks, *partnerId)
}
}
// getPartnerCallback returns the Callbacks for the given partnerId
func (p *partnerCallbacks) getPartnerCallback(partnerId *id.ID) Callbacks {
return p.callbacks[*partnerId]
}
......@@ -25,21 +25,21 @@ type receivedConfirmService struct {
func (rcs *receivedConfirmService) Process(msg format.Message,
receptionID receptionID.EphemeralIdentity, round rounds.Round) {
state := rcs.s
authState := rcs.s
//parse the confirm
baseFmt, partnerPubKey, err := handleBaseFormat(msg, state.e2e.GetGroup())
baseFmt, partnerPubKey, err := handleBaseFormat(msg, authState.e2e.GetGroup())
if err != nil {
em := fmt.Sprintf("Failed to handle auth confirm: %s", err)
jww.WARN.Print(em)
state.event.Report(10, "Auth", "ConfirmError", em)
authState.event.Report(10, "Auth", "ConfirmError", em)
return
}
jww.TRACE.Printf("processing confirm: \n\t MYHISTORICALPUBKEY: %s\n\t"+
"MYPUBKEY: %s\n\t PARTNERPUBKEY: %s \n\t "+
"ECRPAYLOAD: %s \n\t MAC: %s",
state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
rcs.SentRequest.GetMyPubKey().TextVerbose(16, 0),
partnerPubKey.TextVerbose(16, 0),
base64.StdEncoding.EncodeToString(baseFmt.data),
......@@ -47,13 +47,13 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
// decrypt the payload
success, payload := cAuth.Decrypt(rcs.GetMyPrivKey(), partnerPubKey,
baseFmt.GetEcrPayload(), msg.GetMac(), state.e2e.GetGroup())
baseFmt.GetEcrPayload(), msg.GetMac(), authState.e2e.GetGroup())
if !success {
em := fmt.Sprintf("Received auth confirmation " +
"failed its mac check")
jww.WARN.Print(em)
state.event.Report(10, "Auth", "ConfirmError", em)
authState.event.Report(10, "Auth", "ConfirmError", em)
return
}
......@@ -63,7 +63,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
em := fmt.Sprintf("Failed to unmarshal auth confirmation's "+
"encrypted payload: %s", err)
jww.WARN.Print(em)
state.event.Report(10, "Auth", "ConfirmError", em)
authState.event.Report(10, "Auth", "ConfirmError", em)
return
}
......@@ -72,7 +72,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
em := fmt.Sprintf("Could not get auth conf SIDH Pubkey: %s",
err)
jww.WARN.Print(em)
state.event.Report(10, "Auth", "ConfirmError", em)
authState.event.Report(10, "Auth", "ConfirmError", em)
return
}
......@@ -83,7 +83,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
// initial identity
if !cAuth.VerifyOwnershipProof(rcs.SentRequest.GetMyPrivKey(),
rcs.GetPartnerHistoricalPubKey(),
state.e2e.GetGroup(), ecrFmt.GetOwnership()) {
authState.e2e.GetGroup(), ecrFmt.GetOwnership()) {
jww.WARN.Printf("Failed authenticate identity for auth "+
"confirmation of %s", rcs.GetPartner())
return
......@@ -91,7 +91,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
// add the partner
p := session.GetDefaultParams()
_, err = state.e2e.AddPartner(rcs.GetPartner(), partnerPubKey,
_, err = authState.e2e.AddPartner(rcs.GetPartner(), partnerPubKey,
rcs.GetMyPrivKey(), partnerSIDHPubKey, rcs.GetMySIDHPrivKey(), p, p)
if err != nil {
jww.WARN.Printf("Failed to create channel with partner %s and "+
......@@ -103,7 +103,7 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
}
// remove the service used for notifications of the confirm
state.net.DeleteService(receptionID.Source, rcs.notificationsService, nil)
authState.net.DeleteService(receptionID.Source, rcs.notificationsService, nil)
// callbacks
c := contact.Contact{
......@@ -112,7 +112,14 @@ func (rcs *receivedConfirmService) Process(msg format.Message,
OwnershipProof: ecrFmt.GetOwnership(),
Facts: make([]fact.Fact, 0),
}
state.callbacks.Confirm(c, receptionID, round)
authState.partnerCallbacks.RLock()
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Confirm(c, receptionID, round)
} else {
authState.callbacks.Confirm(c, receptionID, round)
}
authState.partnerCallbacks.RUnlock()
}
func (rcs *receivedConfirmService) String() string {
......
......@@ -28,11 +28,11 @@ type receivedRequestService struct {
func (rrs *receivedRequestService) Process(message format.Message,
receptionID receptionID.EphemeralIdentity, round rounds.Round) {
state := rrs.s
authState := rrs.s
// check if the timestamp is before the id was created and therefore
// should be ignored
tid, err := state.net.GetIdentity(receptionID.Source)
tid, err := authState.net.GetIdentity(receptionID.Source)
if err != nil {
jww.ERROR.Printf("received a request on %s which does not exist, "+
"this should not be possible: %+v", receptionID.Source.String(), err)
......@@ -47,7 +47,7 @@ func (rrs *receivedRequestService) Process(message format.Message,
//decode the outer format
baseFmt, partnerPubKey, err := handleBaseFormat(
message, state.e2e.GetGroup())
message, authState.e2e.GetGroup())
if err != nil {
jww.WARN.Printf("Failed to handle auth request: %s", err)
return
......@@ -57,15 +57,15 @@ func (rrs *receivedRequestService) Process(message format.Message,
jww.TRACE.Printf("processing requests: \n\t MYHISTORICALPUBKEY: %s "+
"\n\t PARTNERPUBKEY: %s \n\t ECRPAYLOAD: %s \n\t MAC: %s",
state.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
authState.e2e.GetHistoricalDHPubkey().TextVerbose(16, 0),
partnerPubKey.TextVerbose(16, 0),
base64.StdEncoding.EncodeToString(baseFmt.data),
base64.StdEncoding.EncodeToString(message.GetMac()))
//Attempt to decrypt the payload
success, payload := cAuth.Decrypt(state.e2e.GetHistoricalDHPrivkey(),
success, payload := cAuth.Decrypt(authState.e2e.GetHistoricalDHPrivkey(),
partnerPubKey, baseFmt.GetEcrPayload(), message.GetMac(),
state.e2e.GetGroup())
authState.e2e.GetGroup())
if !success {
jww.WARN.Printf("Received auth request of %s failed its mac "+
......@@ -97,11 +97,11 @@ func (rrs *receivedRequestService) Process(message format.Message,
format.DigestContents(message.GetContents()),
base64.StdEncoding.EncodeToString(fp))
jww.INFO.Print(em)
state.event.Report(1, "Auth", "RequestReceived", em)
authState.event.Report(1, "Auth", "RequestReceived", em)
// check the uniqueness of the request. Requests can be duplicated, so we
// must verify this is is not a duplicate, and drop if it is
newFP, position := state.store.CheckIfNegotiationIsNew(partnerID, fp)
newFP, position := authState.store.CheckIfNegotiationIsNew(partnerID, fp)
if !newFP {
// if its the newest, resend the confirm
......@@ -113,10 +113,10 @@ func (rrs *receivedRequestService) Process(message format.Message,
// check if we already accepted, if we did, resend the confirm if
// we can load it
if _, err = state.e2e.GetPartner(partnerID); err != nil {
if _, err = authState.e2e.GetPartner(partnerID); err != nil {
//attempt to load the confirm, if we can, resend it
confirmPayload, mac, keyfp, err :=
state.store.LoadConfirmation(partnerID)
authState.store.LoadConfirmation(partnerID)
if err != nil {
jww.ERROR.Printf("Could not reconfirm a duplicate "+
"request of an accepted confirm from %s to %s because "+
......@@ -125,14 +125,26 @@ func (rrs *receivedRequestService) Process(message format.Message,
}
// resend the confirm. It sends as a critical message, so errors
// do not need to be handled
_, _ = sendAuthConfirm(state.net, partnerID, keyfp,
confirmPayload, mac, state.event, state.params.ResetConfirmTag)
} else if state.params.ReplayRequests {
_, _ = sendAuthConfirm(authState.net, partnerID, keyfp,
confirmPayload, mac, authState.event, authState.params.ResetConfirmTag)
} else if authState.params.ReplayRequests {
//if we did not already accept, auto replay the request
if rrs.reset {
state.callbacks.Reset(c, receptionID, round)
authState.partnerCallbacks.RLock()
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Reset(c, receptionID, round)
} else {
state.callbacks.Request(c, receptionID, round)
authState.callbacks.Reset(c, receptionID, round)
}
authState.partnerCallbacks.RUnlock()
} else {
authState.partnerCallbacks.RLock()
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Request(c, receptionID, round)
} else {
authState.callbacks.Request(c, receptionID, round)
}
authState.partnerCallbacks.RUnlock()
}
}
//if not confirm, and params.replay requests is true, we need to replay
......@@ -159,21 +171,21 @@ func (rrs *receivedRequestService) Process(message format.Message,
// error to see if it did or didnt exist
// Note: due to the newFP handling above, this can ONLY run in the event of
// a reset or when the partner doesnt exist, so it is safe
if err = state.e2e.DeletePartner(partnerID); err != nil {
if err = authState.e2e.DeletePartner(partnerID); err != nil {
if !strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) {
jww.FATAL.Panicf("Failed to do actual partner deletion: %+v", err)
}
} else {
reset = true
_ = state.store.DeleteConfirmation(partnerID)
_ = state.store.DeleteSentRequest(partnerID)
_ = authState.store.DeleteConfirmation(partnerID)
_ = authState.store.DeleteSentRequest(partnerID)
}
}
// if a new, unique request is received when one already exists, delete the
// old one and process the new one
// this works because message pickup is generally time-sequential.
if err = state.store.DeleteReceivedRequest(partnerID); err != nil {
if err = authState.store.DeleteReceivedRequest(partnerID); err != nil {
if !strings.Contains(err.Error(), store.NoRequestFound) {
jww.FATAL.Panicf("Failed to delete old received request: %+v",
err)
......@@ -187,7 +199,7 @@ func (rrs *receivedRequestService) Process(message format.Message,
// (SIDH keys have polarity, so both sent keys cannot be used together)
autoConfirm := false
bail := false
err = state.store.HandleSentRequest(partnerID,
err = authState.store.HandleSentRequest(partnerID,
func(request *store.SentRequest) error {
//if this code is running, then we know we sent a request and can
......@@ -195,8 +207,8 @@ func (rrs *receivedRequestService) Process(message format.Message,
//This runner will auto delete the sent request if successful
//verify ownership proof
if !cAuth.VerifyOwnershipProof(state.e2e.GetHistoricalDHPrivkey(),
partnerPubKey, state.e2e.GetGroup(), ownershipProof) {
if !cAuth.VerifyOwnershipProof(authState.e2e.GetHistoricalDHPrivkey(),
partnerPubKey, authState.e2e.GetGroup(), ownershipProof) {
jww.WARN.Printf("Invalid ownership proof from %s to %s "+
"received, discarding msgDigest: %s, fp: %s",
partnerID, receptionID.Source,
......@@ -233,25 +245,39 @@ func (rrs *receivedRequestService) Process(message format.Message,
// warning: the client will never be notified of the channel creation if a
// crash occurs after the store but before the conclusion of the callback
//create the auth storage
if err = state.store.AddReceived(c, partnerSIDHPubKey, round); err != nil {
if err = authState.store.AddReceived(c, partnerSIDHPubKey, round); err != nil {
em := fmt.Sprintf("failed to store contact Auth "+
"Request: %s", err)
jww.WARN.Print(em)
state.event.Report(10, "Auth", "RequestError", em)
authState.event.Report(10, "Auth", "RequestError", em)
return
}
//autoconfirm if we should
// auto-confirm if we should
authState.partnerCallbacks.RLock()
defer authState.partnerCallbacks.RUnlock()
if autoConfirm || reset {
_, _ = state.confirm(c, state.params.getConfirmTag(reset))
_, _ = authState.confirm(c, authState.params.getConfirmTag(reset))
//handle callbacks
if autoConfirm {
state.callbacks.Confirm(c, receptionID, round)
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Confirm(c, receptionID, round)
} else {
authState.callbacks.Confirm(c, receptionID, round)
}
} else if reset {
state.callbacks.Reset(c, receptionID, round)
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Reset(c, receptionID, round)
} else {
authState.callbacks.Reset(c, receptionID, round)
}
}
} else {
state.callbacks.Request(c, receptionID, round)
if cb := authState.partnerCallbacks.getPartnerCallback(c.ID); cb != nil {
cb.Request(c, receptionID, round)
} else {
authState.callbacks.Request(c, receptionID, round)
}
}
}
......
......@@ -9,7 +9,6 @@ package auth
import (
"encoding/base64"
"github.com/pkg/errors"
"gitlab.com/elixxir/client/auth/store"
"gitlab.com/elixxir/client/cmix"
......@@ -24,7 +23,10 @@ import (
// state is an implementation of the State interface.
type state struct {
// Main Callbacks for all auth operations
callbacks Callbacks
// partner-specific Callbacks
partnerCallbacks partnerCallbacks
net cmixClient
e2e e2eHandler
......@@ -71,6 +73,7 @@ func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
s := &state{
callbacks: callbacks,
partnerCallbacks: partnerCallbacks{callbacks: make(map[id.ID]Callbacks)},
net: net,
e2e: e2e,
rng: rng,
......@@ -112,8 +115,14 @@ func (s *state) CallAllReceivedRequests() {
rr := rrList[i]
eph := receptionID.BuildIdentityFromRound(rr.GetContact().ID,
rr.GetRound())
s.partnerCallbacks.RLock()
if cb := s.partnerCallbacks.getPartnerCallback(rr.GetContact().ID); cb != nil {
cb.Request(rr.GetContact(), eph, rr.GetRound())
} else {
s.callbacks.Request(rr.GetContact(), eph, rr.GetRound())
}
s.partnerCallbacks.RUnlock()
}
}
func makeStorePrefix(partner *id.ID) string {
......@@ -134,3 +143,13 @@ func (s *state) Close() error {
}, nil)
return nil
}
// AddPartnerCallback that overrides the generic auth callback for the given partnerId
func (s *state) AddPartnerCallback(partnerId *id.ID, cb Callbacks) {
s.partnerCallbacks.AddPartnerCallback(partnerId, cb)
}
// DeletePartnerCallback that overrides the generic auth callback for the given partnerId
func (s *state) DeletePartnerCallback(partnerId *id.ID) {
s.partnerCallbacks.DeletePartnerCallback(partnerId)
}
......@@ -11,7 +11,7 @@ import (
"sync"
"time"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/primitives/fact"
......@@ -41,7 +41,7 @@ type Backup struct {
// Callback that is called with the encrypted backup when triggered
updateBackupCb UpdateBackupFn
container *messenger.Container
container *e2eApi.Container
jsonParams string
......@@ -91,7 +91,7 @@ type UpdateBackupFn func(encryptedBackup []byte)
// Call this to turn on backups for the first time or to replace the user's
// password.
func InitializeBackup(password string, updateBackupCb UpdateBackupFn,
container *messenger.Container, e2e E2e, session Session, ud UserDiscovery,
container *e2eApi.Container, e2e E2e, session Session, ud UserDiscovery,
kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) {
b := &Backup{
updateBackupCb: updateBackupCb,
......@@ -135,7 +135,7 @@ func InitializeBackup(password string, updateBackupCb UpdateBackupFn,
// ResumeBackup resumes a backup by restoring the Backup object and registering
// a new callback. Call this to resume backups that have already been
// initialized. Returns an error if backups have not already been initialized.
func ResumeBackup(updateBackupCb UpdateBackupFn, container *messenger.Container,
func ResumeBackup(updateBackupCb UpdateBackupFn, container *e2eApi.Container,
e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV,
rng *fastRNG.StreamGenerator) (*Backup, error) {
_, _, _, err := loadBackup(kv)
......
......@@ -14,7 +14,7 @@ import (
"testing"
"time"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
"gitlab.com/elixxir/client/storage"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv"
......@@ -32,7 +32,7 @@ func Test_InitializeBackup(t *testing.T) {
cbChan := make(chan []byte, 2)
cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup }
expectedPassword := "MySuperSecurePassword"
b, err := InitializeBackup(expectedPassword, cb, &messenger.Container{},
b, err := InitializeBackup(expectedPassword, cb, &e2eApi.Container{},
newMockE2e(t),
newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
......@@ -84,7 +84,7 @@ func Test_ResumeBackup(t *testing.T) {
cbChan1 := make(chan []byte)
cb1 := func(encryptedBackup []byte) { cbChan1 <- encryptedBackup }
expectedPassword := "MySuperSecurePassword"
b, err := InitializeBackup(expectedPassword, cb1, &messenger.Container{},
b, err := InitializeBackup(expectedPassword, cb1, &e2eApi.Container{},
newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
t.Errorf("Failed to initialize new Backup: %+v", err)
......@@ -106,7 +106,7 @@ func Test_ResumeBackup(t *testing.T) {
// Resume the backup with a new callback
cbChan2 := make(chan []byte)
cb2 := func(encryptedBackup []byte) { cbChan2 <- encryptedBackup }
b2, err := ResumeBackup(cb2, &messenger.Container{}, newMockE2e(t), newMockSession(t),
b2, err := ResumeBackup(cb2, &e2eApi.Container{}, newMockE2e(t), newMockSession(t),
newMockUserDiscovery(), kv, rngGen)
if err != nil {
t.Errorf("ResumeBackup returned an error: %+v", err)
......@@ -149,7 +149,7 @@ func Test_resumeBackup_NoKeyError(t *testing.T) {
expectedErr := "object not found"
s := storage.InitTestingSession(t)
rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
_, err := ResumeBackup(nil, &messenger.Container{}, newMockE2e(t), newMockSession(t),
_, err := ResumeBackup(nil, &e2eApi.Container{}, newMockE2e(t), newMockSession(t),
newMockUserDiscovery(), s.GetKV(), rngGen)
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("ResumeBackup did not return the expected error when no "+
......@@ -392,7 +392,7 @@ func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup {
b, err := InitializeBackup(
password,
cb,
&messenger.Container{},
&e2eApi.Container{},
newMockE2e(t),
newMockSession(t),
newMockUserDiscovery(),
......@@ -416,7 +416,7 @@ func Benchmark_InitializeBackup(t *testing.B) {
expectedPassword := "MySuperSecurePassword"
for i := 0; i < t.N; i++ {
_, err := InitializeBackup(expectedPassword, cb,
&messenger.Container{},
&e2eApi.Container{},
newMockE2e(t),
newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
......
......@@ -32,7 +32,7 @@ func (c *Connection) GetId() int {
// partner.Manager is confirmed.
// recipientContact - marshalled contact.Contact object
// myIdentity - marshalled Identity object
func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
func (c *Client) Connect(e2eClientId int, recipientContact []byte) (
*Connection, error) {
cont, err := contact.Unmarshal(recipientContact)
if err != nil {
......@@ -43,8 +43,7 @@ func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
return nil, err
}
connection, err := connect.Connect(cont, myID, myDHPriv, c.api.GetRng(),
c.api.GetStorage().GetE2EGroup(), c.api.GetCmix(), connect.GetDefaultParams())
connection, err := connect.Connect(cont, "test", connect.GetDefaultParams())
if err != nil {
return nil, err
......
......@@ -10,7 +10,7 @@ package cmd
import (
"fmt"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/catalog"
......@@ -25,10 +25,10 @@ import (
type authCallbacks struct {
autoConfirm bool
confCh chan *id.ID
client *messenger.Client
client *e2eApi.Client
}
func makeAuthCallbacks(client *messenger.Client, autoConfirm bool) *authCallbacks {
func makeAuthCallbacks(client *e2eApi.Client, autoConfirm bool) *authCallbacks {
return &authCallbacks{
autoConfirm: autoConfirm,
confCh: make(chan *id.ID, 10),
......@@ -71,7 +71,7 @@ func (a *authCallbacks) Reset(requestor contact.Contact,
fmt.Printf(msg)
}
func registerMessageListener(client *messenger.Client) chan receive.Message {
func registerMessageListener(client *e2eApi.Client) chan receive.Message {
recvCh := make(chan receive.Message, 10000)
listenerID := client.GetE2E().RegisterChannel("DefaultCLIReceiver",
receive.AnyUser(), catalog.NoType, recvCh)
......
......@@ -9,7 +9,7 @@ package cmd
import (
"fmt"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
"io/ioutil"
"time"
......@@ -132,7 +132,7 @@ type receivedFtResults struct {
// initFileTransferManager creates a new file transfer manager with a new
// reception callback. Returns the file transfer manager and the channel that
// will be triggered when the callback is called.
func initFileTransferManager(client *messenger.Client, maxThroughput int) (
func initFileTransferManager(client *e2eApi.Client, maxThroughput int) (
*ftE2e.Wrapper, chan receivedFtResults) {
// Create interfaces.ReceiveCallback that returns the results on a channel
......
......@@ -12,7 +12,7 @@ package cmd
import (
"bufio"
"fmt"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
"gitlab.com/elixxir/client/cmix/identity/receptionID"
"gitlab.com/elixxir/client/cmix/rounds"
"gitlab.com/elixxir/primitives/format"
......@@ -115,7 +115,7 @@ var groupCmd = &cobra.Command{
// initGroupManager creates a new group chat manager and starts the process
// service.
func initGroupManager(client *messenger.Client) (groupChat.GroupChat,
func initGroupManager(client *e2eApi.Client) (groupChat.GroupChat,
chan groupChat.MessageReceive, chan groupStore.Group) {
recChan := make(chan groupChat.MessageReceive, 10)
......
......@@ -14,17 +14,17 @@ import (
"github.com/spf13/cobra"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/api/e2eApi"
)
// initCmd creates a new user object with the given NDF
var initCmd = &cobra.Command{
Use: "init",
Short: ("Initialize a user ID but do not connect to the network"),
Short: "Initialize a user ID but do not connect to the network",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
client := createClient()
e2e, err := messenger.LoadOrInitE2e(client)
e2e, err := e2eApi.LoadOrInitE2e(client)
if err != nil {
jww.FATAL.Panicf("%+v", err)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment