github.com/status-im/status-go@v1.1.0/server/pairing/server.go (about)

     1  package pairing
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/elliptic"
     6  	"crypto/rand"
     7  	"encoding/json"
     8  	"net"
     9  	"runtime"
    10  	"time"
    11  
    12  	"github.com/ethereum/go-ethereum/log"
    13  
    14  	"go.uber.org/zap"
    15  
    16  	"github.com/status-im/status-go/timesource"
    17  
    18  	"github.com/status-im/status-go/api"
    19  	"github.com/status-im/status-go/logutils"
    20  	"github.com/status-im/status-go/server"
    21  )
    22  
    23  /*
    24  |--------------------------------------------------------------------------
    25  | type BaseServer struct {
    26  |--------------------------------------------------------------------------
    27  |
    28  |
    29  |
    30  */
    31  
    32  type BaseServer struct {
    33  	server.Server
    34  	challengeGiver *ChallengeGiver
    35  
    36  	config ServerConfig
    37  }
    38  
    39  // NewBaseServer returns a *BaseServer init from the given *SenderServerConfig
    40  func NewBaseServer(logger *zap.Logger, e *PayloadEncryptor, config *ServerConfig) (*BaseServer, error) {
    41  	cg, err := NewChallengeGiver(e, logger)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	bs := &BaseServer{
    47  		Server: server.NewServer(
    48  			config.Cert,
    49  			config.ListenIP.String(),
    50  			nil,
    51  			logger,
    52  		),
    53  		challengeGiver: cg,
    54  		config:         *config,
    55  	}
    56  	bs.SetTimeout(config.Timeout)
    57  	return bs, nil
    58  }
    59  
    60  // MakeConnectionParams generates a *ConnectionParams based on the Server's current state
    61  func (s *BaseServer) MakeConnectionParams() (*ConnectionParams, error) {
    62  	return NewConnectionParams(s.config.IPAddresses, s.MustGetPort(), s.config.PK, s.config.EK, s.config.InstallationID, s.config.KeyUID), nil
    63  }
    64  
    65  func MakeServerConfig(config *ServerConfig) error {
    66  	tlsKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	AESKey := make([]byte, 32)
    72  	_, err = rand.Read(AESKey)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	ips, err := server.GetLocalAddressesForPairingServer()
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	now := timesource.GetCurrentTime()
    83  	log.Debug("pairing server generate cert", "system time", time.Now().String(), "timesource time", now.String())
    84  	tlsCert, _, err := GenerateCertFromKey(tlsKey, now, ips, []string{})
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	config.PK = &tlsKey.PublicKey
    90  	config.EK = AESKey
    91  	config.Cert = &tlsCert
    92  	config.IPAddresses = ips
    93  	config.ListenIP = net.IPv4zero
    94  
    95  	return nil
    96  }
    97  
    98  /*
    99  |--------------------------------------------------------------------------
   100  | type SenderServer struct {
   101  |--------------------------------------------------------------------------
   102  |
   103  | With AccountPayloadMounter, RawMessagePayloadMounter and InstallationPayloadMounterReceiver
   104  |
   105  */
   106  
   107  type SenderServer struct {
   108  	*BaseServer
   109  	accountMounter      PayloadMounter
   110  	rawMessageMounter   PayloadMounter
   111  	installationMounter PayloadMounterReceiver
   112  	backend             *api.GethStatusBackend
   113  }
   114  
   115  // NewSenderServer returns a *SenderServer init from the given *SenderServerConfig
   116  func NewSenderServer(backend *api.GethStatusBackend, config *SenderServerConfig) (*SenderServer, error) {
   117  	logger := logutils.ZapLogger().Named("SenderServer")
   118  	e := NewPayloadEncryptor(config.ServerConfig.EK)
   119  
   120  	bs, err := NewBaseServer(logger, e, config.ServerConfig)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	am, rmm, imr, err := NewPayloadMounters(logger, e, backend, config.SenderConfig)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	return &SenderServer{
   131  		BaseServer:          bs,
   132  		accountMounter:      am,
   133  		rawMessageMounter:   rmm,
   134  		installationMounter: imr,
   135  		backend:             backend,
   136  	}, nil
   137  }
   138  
   139  func (s *SenderServer) startSendingData() error {
   140  	logger := s.GetLogger()
   141  	beforeSending := func() {
   142  		if s.backend != nil {
   143  			err := s.backend.LocalPairingStarted()
   144  			if err != nil {
   145  				logger.Error("startSendingData backend.LocalPairingStarted()", zap.Error(err))
   146  			}
   147  		}
   148  	}
   149  	s.SetHandlers(server.HandlerPatternMap{
   150  		pairingChallenge:      handlePairingChallenge(s.challengeGiver),
   151  		pairingSendAccount:    middlewareChallenge(s.challengeGiver, handleSendAccount(logger, s.accountMounter, beforeSending)),
   152  		pairingSendSyncDevice: middlewareChallenge(s.challengeGiver, handlePairingSyncDeviceSend(logger, s.rawMessageMounter, beforeSending)),
   153  		// TODO implement refactor of installation data exchange to follow the send/receive pattern of
   154  		//  the other handlers.
   155  		//  https://github.com/status-im/status-go/issues/3304
   156  		// receive installation data from receiver
   157  		pairingReceiveInstallation: middlewareChallenge(s.challengeGiver, handleReceiveInstallation(s.GetLogger(), s.installationMounter)),
   158  	})
   159  	return s.Start()
   160  }
   161  
   162  // MakeFullSenderServer generates a fully configured and randomly seeded SenderServer
   163  func MakeFullSenderServer(backend *api.GethStatusBackend, config *SenderServerConfig) (*SenderServer, error) {
   164  	config.ServerConfig.InstallationID = backend.InstallationID()
   165  	config.ServerConfig.KeyUID = backend.KeyUID()
   166  	err := MakeServerConfig(config.ServerConfig)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	config.SenderConfig.DB = backend.GetMultiaccountDB()
   172  	return NewSenderServer(backend, config)
   173  }
   174  
   175  // StartUpSenderServer generates a SenderServer, starts the sending server
   176  // and returns the ConnectionParams string to allow a ReceiverClient to make a successful connection.
   177  func StartUpSenderServer(backend *api.GethStatusBackend, configJSON string) (string, error) {
   178  	conf := NewSenderServerConfig()
   179  	err := json.Unmarshal([]byte(configJSON), conf)
   180  	if err != nil {
   181  		return "", err
   182  	}
   183  	if len(conf.SenderConfig.ChatKey) == 0 {
   184  		err = validateAndVerifyPassword(conf, conf.SenderConfig)
   185  		if err != nil {
   186  			return "", err
   187  		}
   188  	}
   189  
   190  	ps, err := MakeFullSenderServer(backend, conf)
   191  	if err != nil {
   192  		return "", err
   193  	}
   194  
   195  	err = ps.startSendingData()
   196  	if err != nil {
   197  		return "", err
   198  	}
   199  
   200  	cp, err := ps.MakeConnectionParams()
   201  	if err != nil {
   202  		return "", err
   203  	}
   204  
   205  	return cp.ToString(), nil
   206  }
   207  
   208  /*
   209  |--------------------------------------------------------------------------
   210  | ReceiverServer
   211  |--------------------------------------------------------------------------
   212  |
   213  | With AccountPayloadReceiver, RawMessagePayloadReceiver, InstallationPayloadMounterReceiver
   214  |
   215  */
   216  
   217  type ReceiverServer struct {
   218  	*BaseServer
   219  	accountReceiver      PayloadReceiver
   220  	rawMessageReceiver   PayloadReceiver
   221  	installationReceiver PayloadMounterReceiver
   222  	backend              *api.GethStatusBackend
   223  }
   224  
   225  // NewReceiverServer returns a *SenderServer init from the given *ReceiverServerConfig
   226  func NewReceiverServer(backend *api.GethStatusBackend, config *ReceiverServerConfig) (*ReceiverServer, error) {
   227  	logger := logutils.ZapLogger().Named("SenderServer")
   228  	e := NewPayloadEncryptor(config.ServerConfig.EK)
   229  
   230  	bs, err := NewBaseServer(logger, e, config.ServerConfig)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	ar, rmr, imr, err := NewPayloadReceivers(logger, e, backend, config.ReceiverConfig)
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  
   240  	return &ReceiverServer{
   241  		BaseServer:           bs,
   242  		accountReceiver:      ar,
   243  		rawMessageReceiver:   rmr,
   244  		installationReceiver: imr,
   245  		backend:              backend,
   246  	}, nil
   247  }
   248  
   249  func (s *ReceiverServer) startReceivingData() error {
   250  	logger := s.GetLogger()
   251  	beforeSending := func() {
   252  		if s.backend != nil {
   253  			err := s.backend.LocalPairingStarted()
   254  			if err != nil {
   255  				logger.Error("startSendingData backend.LocalPairingStarted()", zap.Error(err))
   256  			}
   257  		}
   258  	}
   259  	s.SetHandlers(server.HandlerPatternMap{
   260  		pairingChallenge:         handlePairingChallenge(s.challengeGiver),
   261  		pairingReceiveAccount:    handleReceiveAccount(logger, s.accountReceiver),
   262  		pairingReceiveSyncDevice: handleParingSyncDeviceReceive(logger, s.rawMessageReceiver),
   263  		// TODO implement refactor of installation data exchange to follow the send/receive pattern of
   264  		//  the other handlers.
   265  		//  https://github.com/status-im/status-go/issues/3304
   266  		// send installation data back to sender
   267  		pairingSendInstallation: middlewareChallenge(s.challengeGiver, handleSendInstallation(logger, s.installationReceiver, beforeSending)),
   268  	})
   269  	return s.Start()
   270  }
   271  
   272  // MakeFullReceiverServer generates a fully configured and randomly seeded ReceiverServer
   273  func MakeFullReceiverServer(backend *api.GethStatusBackend, config *ReceiverServerConfig) (*ReceiverServer, error) {
   274  	config.ServerConfig.InstallationID = backend.InstallationID()
   275  	config.ServerConfig.KeyUID = backend.KeyUID()
   276  
   277  	err := MakeServerConfig(config.ServerConfig)
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  
   282  	// ignore err because we allow no active account here
   283  	activeAccount, _ := backend.GetActiveAccount()
   284  	if activeAccount != nil {
   285  		config.ReceiverConfig.LoggedInKeyUID = activeAccount.KeyUID
   286  	}
   287  	config.ReceiverConfig.DB = backend.GetMultiaccountDB()
   288  
   289  	return NewReceiverServer(backend, config)
   290  }
   291  
   292  // StartUpReceiverServer generates a ReceiverServer, starts the sending server
   293  // and returns the ConnectionParams string to allow a SenderClient to make a successful connection.
   294  func StartUpReceiverServer(backend *api.GethStatusBackend, configJSON string) (string, error) {
   295  	conf := NewReceiverServerConfig()
   296  	err := json.Unmarshal([]byte(configJSON), conf)
   297  	if err != nil {
   298  		return "", err
   299  	}
   300  
   301  	// This is a temporal solution to allow clients not to pass DeviceType.
   302  	// Check DeviceType deprecation reason for more info.
   303  	conf.ReceiverConfig.DeviceType = runtime.GOOS
   304  
   305  	err = validateReceiverConfig(conf, conf.ReceiverConfig)
   306  	if err != nil {
   307  		return "", err
   308  	}
   309  
   310  	ps, err := MakeFullReceiverServer(backend, conf)
   311  	if err != nil {
   312  		return "", err
   313  	}
   314  
   315  	err = ps.startReceivingData()
   316  	if err != nil {
   317  		return "", err
   318  	}
   319  
   320  	cp, err := ps.MakeConnectionParams()
   321  	if err != nil {
   322  		return "", err
   323  	}
   324  
   325  	return cp.ToString(), nil
   326  }
   327  
   328  /*
   329  |--------------------------------------------------------------------------
   330  | type KeystoreFilesSenderServer struct {
   331  |--------------------------------------------------------------------------
   332  */
   333  
   334  type KeystoreFilesSenderServer struct {
   335  	*BaseServer
   336  	keystoreFilesMounter PayloadMounter
   337  	backend              *api.GethStatusBackend
   338  }
   339  
   340  func NewKeystoreFilesSenderServer(backend *api.GethStatusBackend, config *KeystoreFilesSenderServerConfig) (*KeystoreFilesSenderServer, error) {
   341  	logger := logutils.ZapLogger().Named("SenderServer")
   342  	e := NewPayloadEncryptor(config.ServerConfig.EK)
   343  
   344  	bs, err := NewBaseServer(logger, e, config.ServerConfig)
   345  	if err != nil {
   346  		return nil, err
   347  	}
   348  
   349  	kfm, err := NewKeystoreFilesPayloadMounter(backend, e, config.SenderConfig, logger)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  
   354  	return &KeystoreFilesSenderServer{
   355  		BaseServer:           bs,
   356  		keystoreFilesMounter: kfm,
   357  		backend:              backend,
   358  	}, nil
   359  }
   360  
   361  func (s *KeystoreFilesSenderServer) startSendingData() error {
   362  	logger := s.GetLogger()
   363  	beforeSending := func() {
   364  		if s.backend != nil {
   365  			err := s.backend.LocalPairingStarted()
   366  			if err != nil {
   367  				logger.Error("startSendingData backend.LocalPairingStarted()", zap.Error(err))
   368  			}
   369  		}
   370  	}
   371  	s.SetHandlers(server.HandlerPatternMap{
   372  		pairingChallenge:   handlePairingChallenge(s.challengeGiver),
   373  		pairingSendAccount: middlewareChallenge(s.challengeGiver, handleSendAccount(logger, s.keystoreFilesMounter, beforeSending)),
   374  	})
   375  	return s.Start()
   376  }
   377  
   378  // MakeFullSenderServer generates a fully configured and randomly seeded KeystoreFilesSenderServer
   379  func MakeKeystoreFilesSenderServer(backend *api.GethStatusBackend, config *KeystoreFilesSenderServerConfig) (*KeystoreFilesSenderServer, error) {
   380  	config.ServerConfig.InstallationID = backend.InstallationID()
   381  	config.ServerConfig.KeyUID = backend.KeyUID()
   382  
   383  	err := MakeServerConfig(config.ServerConfig)
   384  	if err != nil {
   385  		return nil, err
   386  	}
   387  
   388  	return NewKeystoreFilesSenderServer(backend, config)
   389  }
   390  
   391  // StartUpKeystoreFilesSenderServer generates a KeystoreFilesSenderServer, starts the sending server
   392  // and returns the ConnectionParams string to allow a ReceiverClient to make a successful connection.
   393  func StartUpKeystoreFilesSenderServer(backend *api.GethStatusBackend, configJSON string) (string, error) {
   394  	conf := NewKeystoreFilesSenderServerConfig()
   395  	err := json.Unmarshal([]byte(configJSON), conf)
   396  	if err != nil {
   397  		return "", err
   398  	}
   399  
   400  	err = validateKeystoreFilesConfig(backend, conf)
   401  	if err != nil {
   402  		return "", err
   403  	}
   404  
   405  	ps, err := MakeKeystoreFilesSenderServer(backend, conf)
   406  	if err != nil {
   407  		return "", err
   408  	}
   409  
   410  	err = ps.startSendingData()
   411  	if err != nil {
   412  		return "", err
   413  	}
   414  
   415  	cp, err := ps.MakeConnectionParams()
   416  	if err != nil {
   417  		return "", err
   418  	}
   419  
   420  	return cp.ToString(), nil
   421  }