diff --git a/keyserver/src/socket/tunnelbroker.js b/keyserver/src/socket/tunnelbroker.js index 65f5969a6..73ba1ecb6 100644 --- a/keyserver/src/socket/tunnelbroker.js +++ b/keyserver/src/socket/tunnelbroker.js @@ -1,73 +1,78 @@ // @flow import WebSocket from 'ws'; import { + refreshKeysTBMessageValidator, type TBKeyserverConnectionInitializationMessage, type MessageFromTunnelbroker, tunnelbrokerMessageTypes, } from 'lib/types/tunnelbroker-messages.js'; import { ServerError } from 'lib/utils/errors.js'; import { fetchOlmAccount } from '../updaters/olm-account-updater.js'; import { type IdentityInfo } from '../user/identity.js'; import { uploadNewOneTimeKeys } from '../utils/olm-utils.js'; async function createAndMaintainTunnelbrokerWebsocket( identityInfo: IdentityInfo, ) { const accountInfo = await fetchOlmAccount('content'); const deviceID = JSON.parse(accountInfo.account.identity_keys()).ed25519; openTunnelbrokerConnection( deviceID, identityInfo.userId, identityInfo.accessToken, ); } function handleTBMessageEvent(event: ArrayBuffer): Promise { - const message: MessageFromTunnelbroker = JSON.parse(event.toString()); + const rawMessage = JSON.parse(event.toString()); + if (!refreshKeysTBMessageValidator.is(rawMessage)) { + throw new ServerError('unsupported_tunnelbroker_message'); + } + const message: MessageFromTunnelbroker = rawMessage; if (message.type === tunnelbrokerMessageTypes.REFRESH_KEYS_REQUEST) { return uploadNewOneTimeKeys(message.numberOfKeys); } throw new ServerError('unsupported_tunnelbroker_message'); } function openTunnelbrokerConnection( deviceID: string, userID: string, accessToken: string, ) { try { const tunnelbrokerSocket = new WebSocket('ws://127.0.0.1:51001'); tunnelbrokerSocket.on('open', () => { const message: TBKeyserverConnectionInitializationMessage = { type: 'sessionRequest', accessToken, deviceId: deviceID, deviceType: 'keyserver', userId: userID, }; tunnelbrokerSocket.send(JSON.stringify(message)); console.info('Connection to Tunnelbroker established'); }); tunnelbrokerSocket.on('close', async () => { console.warn('Connection to Tunnelbroker closed'); }); tunnelbrokerSocket.on('error', (error: Error) => { console.error('Tunnelbroker socket error', error.message); }); tunnelbrokerSocket.on('message', handleTBMessageEvent); } catch { console.log('Failed to open connection with Tunnelbroker'); } } export { createAndMaintainTunnelbrokerWebsocket }; diff --git a/lib/types/tunnelbroker-messages.js b/lib/types/tunnelbroker-messages.js index 1bf65208a..5e871fac2 100644 --- a/lib/types/tunnelbroker-messages.js +++ b/lib/types/tunnelbroker-messages.js @@ -1,44 +1,55 @@ // @flow +import t, { type TInterface } from 'tcomb'; + +import { tShape, tString } from '../utils/validation-utils.js'; + type TBSharedConnectionInitializationMessage = { +type: 'sessionRequest', +deviceId: string, +accessToken: string, +deviceAppVersion?: string, +userId: string, }; export type TBKeyserverConnectionInitializationMessage = { ...TBSharedConnectionInitializationMessage, +deviceType: 'keyserver', }; export type TBClientConnectionInitializationMessage = { ...TBSharedConnectionInitializationMessage, +deviceType: 'web' | 'mobile', }; export type TBNotifyClientConnectionInitializationMessage = { ...TBClientConnectionInitializationMessage, +notifyToken: string, +notifyPlatform: 'apns' | 'fcm' | 'web' | 'wns', }; export type MessageToTunnelbroker = | TBKeyserverConnectionInitializationMessage | TBClientConnectionInitializationMessage | TBNotifyClientConnectionInitializationMessage; export const tunnelbrokerMessageTypes = Object.freeze({ REFRESH_KEYS_REQUEST: 'RefreshKeyRequest', }); export type TBRefreshKeysRequest = { +type: 'RefreshKeyRequest', +deviceId: string, +numberOfKeys: number, }; +export const refreshKeysTBMessageValidator: TInterface = + tShape({ + type: tString('RefreshKeyRequest'), + deviceId: t.String, + numberOfKeys: t.Number, + }); + // Disjoint enumeration of all messages received from Tunnelbroker // Currently, only a single message export type MessageFromTunnelbroker = TBRefreshKeysRequest;