2023-01-06 12:21:14 +00:00
package pairing
import (
"bytes"
"crypto/tls"
"crypto/x509"
2023-03-23 11:44:15 +00:00
"encoding/json"
2023-01-06 12:21:14 +00:00
"encoding/pem"
"fmt"
"io"
2023-10-18 06:17:49 +00:00
"net"
2023-01-06 12:21:14 +00:00
"net/http"
"net/http/cookiejar"
"net/url"
2024-08-14 20:10:19 +00:00
"runtime"
2023-09-11 12:19:26 +00:00
"go.uber.org/zap"
2023-01-06 12:21:14 +00:00
"github.com/status-im/status-go/api"
2024-09-26 22:37:32 +00:00
gocommon "github.com/status-im/status-go/common"
2023-01-06 12:21:14 +00:00
"github.com/status-im/status-go/logutils"
2023-08-22 16:18:14 +00:00
"github.com/status-im/status-go/server"
2023-01-06 12:21:14 +00:00
"github.com/status-im/status-go/signal"
2023-11-07 01:51:15 +00:00
"github.com/status-im/status-go/timesource"
2023-01-06 12:21:14 +00:00
)
2023-03-23 11:44:15 +00:00
/ *
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
| BaseClient
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
|
* /
// BaseClient is responsible for lower level pairing.Client functionality common to dependent Client types
type BaseClient struct {
2023-01-06 12:21:14 +00:00
* http . Client
2023-03-20 15:31:39 +00:00
serverCert * x509 . Certificate
baseAddress * url . URL
challengeTaker * ChallengeTaker
2023-01-06 12:21:14 +00:00
}
2023-10-18 06:17:49 +00:00
func findServerCert ( c * ConnectionParams , reachableIPs [ ] net . IP ) ( * url . URL , * x509 . Certificate , error ) {
2023-09-11 12:19:26 +00:00
var baseAddress * url . URL
var serverCert * x509 . Certificate
2023-10-18 06:17:49 +00:00
type connectionError struct {
ip net . IP
err error
}
errCh := make ( chan connectionError , len ( reachableIPs ) )
type result struct {
u * url . URL
cert * x509 . Certificate
}
successCh := make ( chan result , 1 ) // as we close on the first success
for _ , ip := range reachableIPs {
go func ( ip net . IP ) {
2024-09-26 22:37:32 +00:00
defer gocommon . LogOnPanic ( )
2023-10-18 06:17:49 +00:00
u := c . BuildURL ( ip )
cert , err := getServerCert ( u )
if err != nil {
errCh <- connectionError { ip : ip , err : fmt . Errorf ( "connecting to '%s' failed: %s" , u , err . Error ( ) ) }
return
2023-08-23 09:22:32 +00:00
}
2023-10-18 06:17:49 +00:00
// If no error, send the results to the success channel
successCh <- result { u : u , cert : cert }
} ( ip )
}
2023-08-22 16:18:14 +00:00
2023-10-18 06:17:49 +00:00
// Keep track of error counts
errorCount := 0
var combinedErrors string
for {
select {
case success := <- successCh :
baseAddress = success . u
serverCert = success . cert
return baseAddress , serverCert , nil
case ipErr := <- errCh :
errorCount ++
combinedErrors += fmt . Sprintf ( "IP %s: %s; " , ipErr . ip , ipErr . err )
if errorCount == len ( reachableIPs ) {
return nil , nil , fmt . Errorf ( combinedErrors )
}
}
2023-08-22 16:18:14 +00:00
}
2023-09-11 12:19:26 +00:00
}
// NewBaseClient returns a fully qualified BaseClient from the given ConnectionParams
func NewBaseClient ( c * ConnectionParams , logger * zap . Logger ) ( * BaseClient , error ) {
var baseAddress * url . URL
var serverCert * x509 . Certificate
var certErrs error
2023-10-18 06:17:49 +00:00
netIPs , err := server . FindReachableAddressesForPairingClient ( c . netIPs )
if err != nil {
logger . Error ( "[local pair client] failed to find reachable addresses" , zap . Error ( err ) , zap . Any ( "netIPs" , netIPs ) )
signal . SendLocalPairingEvent ( Event { Type : EventConnectionError , Error : err . Error ( ) , Action : ActionConnect } )
return nil , err
}
2023-11-20 05:15:59 +00:00
// if client and server aren't on the same network, netIPs maybe empty, we should check it before invoking findServerCert
if len ( netIPs ) == 0 {
logger . Error ( "[local pair client] no reachable addresses found" )
signal . SendLocalPairingEvent ( Event { Type : EventConnectionError , Error : "no reachable addresses found" , Action : ActionConnect } )
return nil , fmt . Errorf ( "no reachable addresses found" )
}
2023-10-18 06:17:49 +00:00
2023-09-11 12:19:26 +00:00
maxRetries := 3
for i := 0 ; i < maxRetries ; i ++ {
2023-10-18 06:17:49 +00:00
baseAddress , serverCert , certErrs = findServerCert ( c , netIPs )
2023-09-11 12:19:26 +00:00
if serverCert == nil {
certErrs = fmt . Errorf ( "failed to connect to any of given addresses. %w" , certErrs )
2023-10-18 06:17:49 +00:00
logger . Warn ( "failed to connect to any of given addresses. Retrying..." , zap . Error ( certErrs ) , zap . Any ( "netIPs" , netIPs ) , zap . Int ( "retry" , i + 1 ) )
2023-09-11 12:19:26 +00:00
} else {
break
}
}
2023-08-22 16:18:14 +00:00
if serverCert == nil {
certErrs = fmt . Errorf ( "failed to connect to any of given addresses. %w" , certErrs )
signal . SendLocalPairingEvent ( Event { Type : EventConnectionError , Error : certErrs . Error ( ) , Action : ActionConnect } )
return nil , certErrs
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
2023-08-22 16:18:14 +00:00
// No error on the dial out then the URL.Host is accessible
signal . SendLocalPairingEvent ( Event { Type : EventConnectionSuccess , Action : ActionConnect } )
2023-10-18 06:17:49 +00:00
err = verifyCert ( serverCert , c . publicKey )
2023-01-06 12:21:14 +00:00
if err != nil {
return nil , err
}
2023-03-23 11:44:15 +00:00
2023-01-06 12:21:14 +00:00
certPem := pem . EncodeToMemory ( & pem . Block { Type : "CERTIFICATE" , Bytes : serverCert . Raw } )
rootCAs , err := x509 . SystemCertPool ( )
if err != nil {
return nil , err
}
if ok := rootCAs . AppendCertsFromPEM ( certPem ) ; ! ok {
return nil , fmt . Errorf ( "failed to append certPem to rootCAs" )
}
tr := & http . Transport {
TLSClientConfig : & tls . Config {
MinVersion : tls . VersionTLS12 ,
InsecureSkipVerify : false , // MUST BE FALSE
RootCAs : rootCAs ,
2023-11-13 19:06:32 +00:00
Time : timesource . GetCurrentTime ,
2023-01-06 12:21:14 +00:00
} ,
}
cj , err := cookiejar . New ( nil )
if err != nil {
return nil , err
}
2023-03-23 11:44:15 +00:00
return & BaseClient {
2023-03-20 15:31:39 +00:00
Client : & http . Client { Transport : tr , Jar : cj } ,
serverCert : serverCert ,
challengeTaker : NewChallengeTaker ( NewPayloadEncryptor ( c . aesKey ) ) ,
2023-08-22 16:18:14 +00:00
baseAddress : baseAddress ,
2023-03-23 11:44:15 +00:00
} , nil
}
2023-01-06 12:21:14 +00:00
2023-03-23 11:44:15 +00:00
// getChallenge makes a call to the identified Server and receives a [32]byte challenge
func ( c * BaseClient ) getChallenge ( ) error {
c . baseAddress . Path = pairingChallenge
resp , err := c . Get ( c . baseAddress . String ( ) )
2023-02-28 12:32:45 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
return err
2023-02-28 12:32:45 +00:00
}
2023-03-23 11:44:15 +00:00
if resp . StatusCode != http . StatusOK {
return fmt . Errorf ( "[client] status not ok when getting challenge, received '%s'" , resp . Status )
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
2023-03-20 18:39:28 +00:00
return c . challengeTaker . SetChallenge ( resp )
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
/ *
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
| SenderClient
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
| With AccountPayloadMounter , RawMessagePayloadMounter and InstallationPayloadMounterReceiver
|
* /
// SenderClient is responsible for sending pairing data to a ReceiverServer
type SenderClient struct {
* BaseClient
accountMounter PayloadMounter
2023-03-30 10:00:32 +00:00
rawMessageMounter PayloadMounter
2023-04-02 23:08:29 +00:00
installationMounter PayloadMounterReceiver
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
// NewSenderClient returns a fully qualified SenderClient created with the incoming parameters
func NewSenderClient ( backend * api . GethStatusBackend , c * ConnectionParams , config * SenderClientConfig ) ( * SenderClient , error ) {
logger := logutils . ZapLogger ( ) . Named ( "SenderClient" )
pe := NewPayloadEncryptor ( c . aesKey )
2023-09-11 12:19:26 +00:00
bc , err := NewBaseClient ( c , logger )
2023-03-23 11:44:15 +00:00
if err != nil {
return nil , err
2023-02-28 12:32:45 +00:00
}
2023-03-23 11:44:15 +00:00
am , rmm , imr , err := NewPayloadMounters ( logger , pe , backend , config . SenderConfig )
2023-02-28 12:32:45 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
return nil , err
2023-02-28 12:32:45 +00:00
}
2023-03-23 11:44:15 +00:00
return & SenderClient {
BaseClient : bc ,
accountMounter : am ,
rawMessageMounter : rmm ,
installationMounter : imr ,
} , nil
}
func ( c * SenderClient ) sendAccountData ( ) error {
err := c . accountMounter . Mount ( )
2023-02-28 12:32:45 +00:00
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
c . baseAddress . Path = pairingReceiveAccount
resp , err := c . Post ( c . baseAddress . String ( ) , "application/octet-stream" , bytes . NewBuffer ( c . accountMounter . ToSend ( ) ) )
2023-02-28 12:32:45 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
2023-02-28 12:32:45 +00:00
return err
}
if resp . StatusCode != http . StatusOK {
2023-03-23 11:44:15 +00:00
err = fmt . Errorf ( "[client] status not ok when sending account data, received '%s'" , resp . Status )
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
2023-02-28 12:32:45 +00:00
return err
}
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionPairingAccount } )
c . accountMounter . LockPayload ( )
2023-02-28 12:32:45 +00:00
return nil
}
2023-03-23 11:44:15 +00:00
func ( c * SenderClient ) sendSyncDeviceData ( ) error {
err := c . rawMessageMounter . Mount ( )
2023-01-06 12:21:14 +00:00
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
c . baseAddress . Path = pairingReceiveSyncDevice
resp , err := c . Post ( c . baseAddress . String ( ) , "application/octet-stream" , bytes . NewBuffer ( c . rawMessageMounter . ToSend ( ) ) )
2023-01-06 12:21:14 +00:00
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
return err
}
if resp . StatusCode != http . StatusOK {
2023-02-28 12:32:45 +00:00
err = fmt . Errorf ( "[client] status not okay when sending sync device data, status: %s" , resp . Status )
2023-01-06 12:21:14 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
2023-02-28 12:32:45 +00:00
return err
2023-01-06 12:21:14 +00:00
}
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionSyncDevice } )
return nil
}
2023-03-23 11:44:15 +00:00
func ( c * SenderClient ) receiveInstallationData ( ) error {
2023-02-28 12:32:45 +00:00
c . baseAddress . Path = pairingSendInstallation
req , err := http . NewRequest ( http . MethodGet , c . baseAddress . String ( ) , nil )
if err != nil {
return err
}
2023-03-20 22:01:28 +00:00
err = c . challengeTaker . DoChallenge ( req )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
return err
}
2023-02-28 12:32:45 +00:00
resp , err := c . Do ( req )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
return err
}
if resp . StatusCode != http . StatusOK {
err = fmt . Errorf ( "[client] status not ok when receiving installation data, received '%s'" , resp . Status )
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
return err
}
payload , err := io . ReadAll ( resp . Body )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
return err
}
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionPairingInstallation } )
2023-03-23 11:44:15 +00:00
err = c . installationMounter . Receive ( payload )
2023-02-28 12:32:45 +00:00
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventProcessError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
return err
}
signal . SendLocalPairingEvent ( Event { Type : EventProcessSuccess , Action : ActionPairingInstallation } )
return nil
}
2023-03-23 11:44:15 +00:00
// setupSendingClient creates a new SenderClient after parsing string inputs
func setupSendingClient ( backend * api . GethStatusBackend , cs , configJSON string ) ( * SenderClient , error ) {
ccp := new ( ConnectionParams )
err := ccp . FromString ( cs )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
return nil , err
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
conf := NewSenderClientConfig ( )
err = json . Unmarshal ( [ ] byte ( configJSON ) , conf )
if err != nil {
return nil , err
2023-01-06 12:21:14 +00:00
}
2023-03-29 15:51:01 +00:00
err = validateAndVerifyPassword ( conf , conf . SenderConfig )
if err != nil {
return nil , err
}
2023-01-06 12:21:14 +00:00
2023-03-23 11:44:15 +00:00
conf . SenderConfig . DB = backend . GetMultiaccountDB ( )
return NewSenderClient ( backend , ccp , conf )
}
// StartUpSendingClient creates a SenderClient and triggers all `send` calls in sequence to the ReceiverServer
func StartUpSendingClient ( backend * api . GethStatusBackend , cs , configJSON string ) error {
c , err := setupSendingClient ( backend , cs , configJSON )
2023-01-06 12:21:14 +00:00
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
err = c . sendAccountData ( )
if err != nil {
2023-01-06 12:21:14 +00:00
return err
}
2023-03-23 11:44:15 +00:00
err = c . sendSyncDeviceData ( )
2023-01-06 12:21:14 +00:00
if err != nil {
return err
}
2023-03-20 20:16:38 +00:00
err = c . getChallenge ( )
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
return c . receiveInstallationData ( )
}
/ *
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
| ReceiverClient
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
| With AccountPayloadReceiver , RawMessagePayloadReceiver , InstallationPayloadMounterReceiver
|
* /
// ReceiverClient is responsible for accepting pairing data to a SenderServer
type ReceiverClient struct {
* BaseClient
accountReceiver PayloadReceiver
2023-04-02 23:08:29 +00:00
rawMessageReceiver PayloadReceiver
installationReceiver PayloadMounterReceiver
2023-03-23 11:44:15 +00:00
}
2023-01-06 12:21:14 +00:00
2023-03-23 11:44:15 +00:00
// NewReceiverClient returns a fully qualified ReceiverClient created with the incoming parameters
func NewReceiverClient ( backend * api . GethStatusBackend , c * ConnectionParams , config * ReceiverClientConfig ) ( * ReceiverClient , error ) {
2023-09-11 12:19:26 +00:00
logger := logutils . ZapLogger ( ) . Named ( "ReceiverClient" )
bc , err := NewBaseClient ( c , logger )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
return nil , err
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
pe := NewPayloadEncryptor ( c . aesKey )
ar , rmr , imr , err := NewPayloadReceivers ( logger , pe , backend , config . ReceiverConfig )
if err != nil {
return nil , err
}
return & ReceiverClient {
BaseClient : bc ,
accountReceiver : ar ,
rawMessageReceiver : rmr ,
installationReceiver : imr ,
} , nil
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
func ( c * ReceiverClient ) receiveAccountData ( ) error {
c . baseAddress . Path = pairingSendAccount
req , err := http . NewRequest ( http . MethodGet , c . baseAddress . String ( ) , nil )
2023-01-06 12:21:14 +00:00
if err != nil {
return err
}
2023-03-20 15:31:39 +00:00
err = c . challengeTaker . DoChallenge ( req )
2023-03-23 11:44:15 +00:00
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
return err
}
resp , err := c . Do ( req )
2023-01-06 12:21:14 +00:00
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
return err
}
if resp . StatusCode != http . StatusOK {
2023-03-23 11:44:15 +00:00
err = fmt . Errorf ( "[client] status not ok when receiving account data, received '%s'" , resp . Status )
2023-01-06 12:21:14 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
2023-02-28 12:32:45 +00:00
return err
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
payload , err := io . ReadAll ( resp . Body )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingAccount } )
return err
}
2023-01-06 12:21:14 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionPairingAccount } )
2023-03-23 11:44:15 +00:00
err = c . accountReceiver . Receive ( payload )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventProcessError , Error : err . Error ( ) , Action : ActionPairingAccount } )
return err
}
signal . SendLocalPairingEvent ( Event { Type : EventProcessSuccess , Action : ActionPairingAccount } )
2023-01-06 12:21:14 +00:00
return nil
}
2023-03-23 11:44:15 +00:00
func ( c * ReceiverClient ) receiveSyncDeviceData ( ) error {
c . baseAddress . Path = pairingSendSyncDevice
2023-01-06 12:21:14 +00:00
req , err := http . NewRequest ( http . MethodGet , c . baseAddress . String ( ) , nil )
if err != nil {
return err
}
2023-03-20 15:31:39 +00:00
err = c . challengeTaker . DoChallenge ( req )
2023-03-23 11:44:15 +00:00
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
return err
2023-01-06 12:21:14 +00:00
}
resp , err := c . Do ( req )
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
return err
}
if resp . StatusCode != http . StatusOK {
2023-03-23 11:44:15 +00:00
err = fmt . Errorf ( "[client] status not ok when receiving sync device data, received '%s'" , resp . Status )
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
return err
}
2023-02-28 12:32:45 +00:00
payload , err := io . ReadAll ( resp . Body )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
return err
}
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
2023-03-23 11:44:15 +00:00
err = c . rawMessageReceiver . Receive ( payload )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventProcessError , Error : err . Error ( ) , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
return err
}
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventProcessSuccess , Action : ActionSyncDevice } )
2023-01-06 12:21:14 +00:00
return nil
}
2023-03-23 11:44:15 +00:00
func ( c * ReceiverClient ) sendInstallationData ( ) error {
err := c . installationReceiver . Mount ( )
2023-01-06 12:21:14 +00:00
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
c . baseAddress . Path = pairingReceiveInstallation
req , err := http . NewRequest ( http . MethodPost , c . baseAddress . String ( ) , bytes . NewBuffer ( c . installationReceiver . ToSend ( ) ) )
if err != nil {
return err
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
req . Header . Set ( "Content-Type" , "application/octet-stream" )
2023-01-06 12:21:14 +00:00
2023-03-20 15:31:39 +00:00
err = c . challengeTaker . DoChallenge ( req )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
2023-01-06 12:21:14 +00:00
return err
}
2023-03-23 11:44:15 +00:00
resp , err := c . Do ( req )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
2023-01-06 12:21:14 +00:00
return err
}
2023-03-23 11:44:15 +00:00
if resp . StatusCode != http . StatusOK {
err = fmt . Errorf ( "[client] status not okay when sending installation data, status: %s" , resp . Status )
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionPairingInstallation } )
2023-02-28 12:32:45 +00:00
return err
}
2023-03-23 11:44:15 +00:00
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionPairingInstallation } )
return nil
2023-01-06 12:21:14 +00:00
}
2023-03-23 11:44:15 +00:00
// setupReceivingClient creates a new ReceiverClient after parsing string inputs
func setupReceivingClient ( backend * api . GethStatusBackend , cs , configJSON string ) ( * ReceiverClient , error ) {
2023-02-17 13:02:42 +00:00
ccp := new ( ConnectionParams )
err := ccp . FromString ( cs )
2023-01-06 12:21:14 +00:00
if err != nil {
return nil , err
}
2023-03-23 11:44:15 +00:00
conf := NewReceiverClientConfig ( )
err = json . Unmarshal ( [ ] byte ( configJSON ) , conf )
2023-01-06 12:21:14 +00:00
if err != nil {
return nil , err
}
2024-08-14 20:10:19 +00:00
// This is a temporal solution to allow clients not to pass DeviceType.
// Check DeviceType deprecation reason for more info.
conf . ReceiverConfig . DeviceType = runtime . GOOS
err = validateReceiverConfig ( conf , conf . ReceiverConfig )
2023-03-29 15:51:01 +00:00
if err != nil {
return nil , err
}
2023-01-06 12:21:14 +00:00
2023-09-21 00:32:16 +00:00
// ignore err because we allow no active account here
activeAccount , _ := backend . GetActiveAccount ( )
if activeAccount != nil {
conf . ReceiverConfig . LoggedInKeyUID = activeAccount . KeyUID
}
2023-03-23 11:44:15 +00:00
conf . ReceiverConfig . DB = backend . GetMultiaccountDB ( )
return NewReceiverClient ( backend , ccp , conf )
}
// StartUpReceivingClient creates a ReceiverClient and triggers all `receive` calls in sequence to the SenderServer
func StartUpReceivingClient ( backend * api . GethStatusBackend , cs , configJSON string ) error {
c , err := setupReceivingClient ( backend , cs , configJSON )
if err != nil {
return err
2023-02-28 12:32:45 +00:00
}
2023-03-20 18:39:28 +00:00
2023-03-23 11:44:15 +00:00
err = c . getChallenge ( )
2023-01-06 12:21:14 +00:00
if err != nil {
2023-03-23 11:44:15 +00:00
return err
}
err = c . receiveAccountData ( )
if err != nil {
return err
}
2023-03-20 18:39:28 +00:00
err = c . getChallenge ( )
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
err = c . receiveSyncDeviceData ( )
if err != nil {
return err
2023-01-06 12:21:14 +00:00
}
2023-03-20 18:39:28 +00:00
err = c . getChallenge ( )
if err != nil {
return err
}
2023-03-23 11:44:15 +00:00
return c . sendInstallationData ( )
2023-01-06 12:21:14 +00:00
}
2023-08-18 08:51:16 +00:00
/ *
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
| ReceiverClient
| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
type KeystoreFilesReceiverClient struct {
* BaseClient
keystoreFilesReceiver PayloadReceiver
}
func NewKeystoreFilesReceiverClient ( backend * api . GethStatusBackend , c * ConnectionParams , config * KeystoreFilesReceiverClientConfig ) ( * KeystoreFilesReceiverClient , error ) {
2023-09-11 12:19:26 +00:00
logger := logutils . ZapLogger ( ) . Named ( "ReceiverClient" )
bc , err := NewBaseClient ( c , logger )
2023-08-18 08:51:16 +00:00
if err != nil {
return nil , err
}
pe := NewPayloadEncryptor ( c . aesKey )
kfrc , err := NewKeystoreFilesPayloadReceiver ( backend , pe , config . ReceiverConfig , logger )
if err != nil {
return nil , err
}
return & KeystoreFilesReceiverClient {
BaseClient : bc ,
keystoreFilesReceiver : kfrc ,
} , nil
}
func ( c * KeystoreFilesReceiverClient ) receiveKeystoreFilesData ( ) error {
c . baseAddress . Path = pairingSendAccount
req , err := http . NewRequest ( http . MethodGet , c . baseAddress . String ( ) , nil )
if err != nil {
return err
}
err = c . challengeTaker . DoChallenge ( req )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionKeystoreFilesTransfer } )
return err
}
resp , err := c . Do ( req )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionKeystoreFilesTransfer } )
return err
}
if resp . StatusCode != http . StatusOK {
err = fmt . Errorf ( "[client] status not ok when receiving account data, received '%s'" , resp . Status )
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionKeystoreFilesTransfer } )
return err
}
payload , err := io . ReadAll ( resp . Body )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventTransferError , Error : err . Error ( ) , Action : ActionKeystoreFilesTransfer } )
return err
}
signal . SendLocalPairingEvent ( Event { Type : EventTransferSuccess , Action : ActionKeystoreFilesTransfer } )
err = c . keystoreFilesReceiver . Receive ( payload )
if err != nil {
signal . SendLocalPairingEvent ( Event { Type : EventProcessError , Error : err . Error ( ) , Action : ActionKeystoreFilesTransfer } )
return err
}
signal . SendLocalPairingEvent ( Event { Type : EventProcessSuccess , Action : ActionKeystoreFilesTransfer } )
return nil
}
// setupKeystoreFilesReceivingClient creates a new ReceiverClient after parsing string inputs
func setupKeystoreFilesReceivingClient ( backend * api . GethStatusBackend , cs , configJSON string ) ( * KeystoreFilesReceiverClient , error ) {
ccp := new ( ConnectionParams )
err := ccp . FromString ( cs )
if err != nil {
return nil , err
}
conf := NewKeystoreFilesReceiverClientConfig ( )
err = json . Unmarshal ( [ ] byte ( configJSON ) , conf )
if err != nil {
return nil , err
}
err = validateKeystoreFilesConfig ( backend , conf )
if err != nil {
return nil , err
}
return NewKeystoreFilesReceiverClient ( backend , ccp , conf )
}
// StartUpKeystoreFilesReceivingClient creates a KeystoreFilesReceiverClient and triggers all `receive` calls in sequence to the KeystoreFilesSenderServer
func StartUpKeystoreFilesReceivingClient ( backend * api . GethStatusBackend , cs , configJSON string ) error {
c , err := setupKeystoreFilesReceivingClient ( backend , cs , configJSON )
if err != nil {
return err
}
err = c . getChallenge ( )
if err != nil {
return err
}
return c . receiveKeystoreFilesData ( )
}