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 }