diff --git a/connect/authCallbacks.go b/connect/authCallbacks.go new file mode 100644 index 0000000000000000000000000000000000000000..3c4670bd3fce5be27d230e4b67d8fef43143d661 --- /dev/null +++ b/connect/authCallbacks.go @@ -0,0 +1,146 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 Privategrity Corporation / +// / +// All rights reserved. / +//////////////////////////////////////////////////////////////////////////////// + +package connect + +import ( + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/auth" + "gitlab.com/elixxir/client/cmix/identity/receptionID" + "gitlab.com/elixxir/client/cmix/rounds" + clientE2e "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/crypto/contact" +) + +// clientAuthCallback provides callback functionality for interfacing between +// auth.State and Connection. This is used both for blocking creation of a +// Connection object until the auth Request is confirmed and for dynamically +// building new Connection objects when an auth Request is received. +type clientAuthCallback struct { + // Used for signaling confirmation of E2E partnership + confirmCallback Callback + requestCallback Callback + + // Used for building new Connection objects + connectionE2e clientE2e.Handler + connectionParams Params + authState auth.State +} + +// getClientAuthCallback returns a callback interface to be passed into the creation +// of an auth.State object. +// it will accept requests only if a request callback is passed in +func getClientAuthCallback(confirm, request Callback, e2e clientE2e.Handler, + auth auth.State, params Params) *clientAuthCallback { + return &clientAuthCallback{ + confirmCallback: confirm, + requestCallback: request, + connectionE2e: e2e, + connectionParams: params, + authState: auth, + } +} + +// Confirm will be called when an auth Confirm message is processed. +func (a clientAuthCallback) Confirm(requestor contact.Contact, + _ receptionID.EphemeralIdentity, _ rounds.Round) { + jww.DEBUG.Printf("Connection auth request for %s confirmed", + requestor.ID.String()) + defer a.authState.DeletePartnerCallback(requestor.ID) + + // After confirmation, get the new partner + newPartner, err := a.connectionE2e.GetPartner(requestor.ID) + if err != nil { + jww.ERROR.Printf("Unable to build connection with "+ + "partner %s: %+v", requestor.ID, err) + // Send a nil connection to avoid hold-ups down the line + if a.confirmCallback != nil { + a.confirmCallback(nil) + } + return + } + + // Return the new Connection object + if a.confirmCallback != nil { + a.confirmCallback(BuildConnection(newPartner, a.connectionE2e, + a.authState, a.connectionParams)) + } +} + +// Request will be called when an auth Request message is processed. +func (a clientAuthCallback) Request(contact.Contact, + receptionID.EphemeralIdentity, rounds.Round) { +} + +// Reset will be called when an auth Reset operation occurs. +func (a clientAuthCallback) Reset(contact.Contact, + receptionID.EphemeralIdentity, rounds.Round) { +} + +// serverAuthCallback provides callback functionality for interfacing between +// auth.State and Connection. This is used both for blocking creation of a +// Connection object until the auth Request is confirmed and for dynamically +// building new Connection objects when an auth Request is received. +type serverAuthCallback struct { + // Used for signaling confirmation of E2E partnership + confirmCallback Callback + requestCallback Callback + + // Used for building new Connection objects + connectionParams Params +} + +// getServerAuthCallback returns a callback interface to be passed into the creation +// of a xxdk.E2e object. +// it will accept requests only if a request callback is passed in +func getServerAuthCallback(confirm, request Callback, params Params) *serverAuthCallback { + return &serverAuthCallback{ + confirmCallback: confirm, + requestCallback: request, + connectionParams: params, + } +} + +// Confirm will be called when an auth Confirm message is processed. +func (a serverAuthCallback) Confirm(contact.Contact, + receptionID.EphemeralIdentity, rounds.Round, *xxdk.E2e) { +} + +// Request will be called when an auth Request message is processed. +func (a serverAuthCallback) Request(requestor contact.Contact, + _ receptionID.EphemeralIdentity, _ rounds.Round, e2e *xxdk.E2e) { + if a.requestCallback == nil { + jww.ERROR.Printf("Received a request when requests are" + + "not enable, will not accept") + } + _, err := e2e.GetAuth().Confirm(requestor) + if err != nil { + jww.ERROR.Printf("Unable to build connection with "+ + "partner %s: %+v", requestor.ID, err) + // Send a nil connection to avoid hold-ups down the line + a.requestCallback(nil) + } + // After confirmation, get the new partner + newPartner, err := e2e.GetE2E().GetPartner(requestor.ID) + if err != nil { + jww.ERROR.Printf("Unable to build connection with "+ + "partner %s: %+v", requestor.ID, err) + // Send a nil connection to avoid hold-ups down the line + a.requestCallback(nil) + + return + } + + // Return the new Connection object + a.requestCallback(BuildConnection(newPartner, e2e.GetE2E(), + e2e.GetAuth(), a.connectionParams)) +} + +// Reset will be called when an auth Reset operation occurs. +func (a serverAuthCallback) Reset(contact.Contact, + receptionID.EphemeralIdentity, rounds.Round, *xxdk.E2e) { +} diff --git a/connect/connect.go b/connect/connect.go index e7d4d14c5c8b1cdee3da162226ba8f7c59313e31..fff58c54ba17865de7ba5ad65682838c1ab0b9e3 100644 --- a/connect/connect.go +++ b/connect/connect.go @@ -16,8 +16,6 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/auth" "gitlab.com/elixxir/client/catalog" - "gitlab.com/elixxir/client/cmix/identity/receptionID" - "gitlab.com/elixxir/client/cmix/rounds" clientE2e "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/receive" @@ -122,7 +120,7 @@ func Connect(recipient contact.Contact, e2eClient *xxdk.E2e, cb := func(connection Connection) { signalChannel <- connection } - callback := getAuthCallback(cb, nil, e2eClient.GetE2E(), e2eClient.GetAuth(), p) + callback := getClientAuthCallback(cb, nil, e2eClient.GetE2E(), e2eClient.GetAuth(), p) e2eClient.GetAuth().AddPartnerCallback(recipient.ID, callback) // Perform the auth request @@ -164,16 +162,10 @@ func StartServer(identity xxdk.ReceptionIdentity, cb Callback, net *xxdk.Cmix, p Params) (*xxdk.E2e, error) { // Build callback for E2E negotiation - callback := getAuthCallback(nil, cb, nil, nil, p) + callback := getServerAuthCallback(nil, cb, p) - client, err := xxdk.LoginEphemeral(net, callback, identity) - if err != nil { - return nil, err - } - - callback.connectionE2e = client.GetE2E() - callback.authState = client.GetAuth() - return client, nil + // Return an ephemeral E2e object + return xxdk.LoginEphemeral(net, callback, identity) } // handler provides an implementation for the Connection interface. @@ -231,96 +223,6 @@ func (h *handler) Unregister(listenerID receive.ListenerID) { h.e2e.Unregister(listenerID) } -// authCallback provides callback functionality for interfacing between -// auth.State and Connection. This is used both for blocking creation of a -// Connection object until the auth Request is confirmed and for dynamically -// building new Connection objects when an auth Request is received. -type authCallback struct { - // Used for signaling confirmation of E2E partnership - confirmCallback Callback - requestCallback Callback - - // Used for building new Connection objects - connectionE2e clientE2e.Handler - connectionParams Params - authState auth.State -} - -// getAuthCallback returns a callback interface to be passed into the creation -// of an auth.State object. -// it will accept requests only if a request callback is passed in -func getAuthCallback(confirm, request Callback, e2e clientE2e.Handler, - auth auth.State, params Params) *authCallback { - return &authCallback{ - confirmCallback: confirm, - requestCallback: request, - connectionE2e: e2e, - connectionParams: params, - authState: auth, - } -} - -// Confirm will be called when an auth Confirm message is processed. -func (a authCallback) Confirm(requestor contact.Contact, - receptionID receptionID.EphemeralIdentity, round rounds.Round) { - jww.DEBUG.Printf("Connection auth request for %s confirmed", - requestor.ID.String()) - defer a.authState.DeletePartnerCallback(requestor.ID) - - // After confirmation, get the new partner - newPartner, err := a.connectionE2e.GetPartner(requestor.ID) - if err != nil { - jww.ERROR.Printf("Unable to build connection with "+ - "partner %s: %+v", requestor.ID, err) - // Send a nil connection to avoid hold-ups down the line - if a.confirmCallback != nil { - a.confirmCallback(nil) - } - return - } - - // Return the new Connection object - if a.confirmCallback != nil { - a.confirmCallback(BuildConnection(newPartner, a.connectionE2e, - a.authState, a.connectionParams)) - } -} - -// Request will be called when an auth Request message is processed. -func (a authCallback) Request(requestor contact.Contact, - receptionID receptionID.EphemeralIdentity, round rounds.Round) { - if a.requestCallback == nil { - jww.ERROR.Printf("Received a request when requests are" + - "not enable, will not accept") - } - _, err := a.authState.Confirm(requestor) - if err != nil { - jww.ERROR.Printf("Unable to build connection with "+ - "partner %s: %+v", requestor.ID, err) - // Send a nil connection to avoid hold-ups down the line - a.requestCallback(nil) - } - // After confirmation, get the new partner - newPartner, err := a.connectionE2e.GetPartner(requestor.ID) - if err != nil { - jww.ERROR.Printf("Unable to build connection with "+ - "partner %s: %+v", requestor.ID, err) - // Send a nil connection to avoid hold-ups down the line - a.requestCallback(nil) - - return - } - - // Return the new Connection object - a.requestCallback(BuildConnection(newPartner, a.connectionE2e, - a.authState, a.connectionParams)) -} - -// Reset will be called when an auth Reset operation occurs. -func (a authCallback) Reset(requestor contact.Contact, - receptionID receptionID.EphemeralIdentity, round rounds.Round) { -} - // FirstPartitionSize returns the max partition payload size for the // first payload func (h *handler) FirstPartitionSize() uint { diff --git a/xxdk/e2e.go b/xxdk/e2e.go index 0bba070b0cc1acaef2bafaab030d11a44d1afb22..4683d8df1acb6dfbc9b88030460ca62531f965da 100644 --- a/xxdk/e2e.go +++ b/xxdk/e2e.go @@ -37,6 +37,8 @@ type E2e struct { e2eIdentity ReceptionIdentity } +// AuthCallbacks is an adapter for the auth.Callbacks interface +// that allows for initializing an E2e object without an E2e-dependant auth.Callbacks type AuthCallbacks interface { Request(partner contact.Contact, receptionID receptionID.EphemeralIdentity, round rounds.Round, e2e *E2e)