Page MenuHomePhabricator

D12225.id40679.diff
No OneTemporary

D12225.id40679.diff

diff --git a/lib/handlers/peer-to-peer-message-handler.js b/lib/handlers/peer-to-peer-message-handler.js
--- a/lib/handlers/peer-to-peer-message-handler.js
+++ b/lib/handlers/peer-to-peer-message-handler.js
@@ -9,13 +9,16 @@
} from '../types/identity-service-types.js';
import {
peerToPeerMessageTypes,
+ secondaryDeviceLogoutP2PMessageValidator,
type PeerToPeerMessage,
+ type SecondaryDeviceLogoutP2PMessage,
} from '../types/tunnelbroker/peer-to-peer-message-types.js';
import { getConfig } from '../utils/config.js';
import { getContentSigningKey } from '../utils/crypto-utils.js';
import { getMessageForException } from '../utils/errors.js';
import { hasHigherDeviceID, olmSessionErrors } from '../utils/olm-utils.js';
import { getClientMessageIDFromTunnelbrokerMessageID } from '../utils/peer-to-peer-communication-utils.js';
+import { removeDeviceFromDeviceList } from '../shared/device-list-utils.js';
async function peerToPeerMessageHandler(
message: PeerToPeerMessage,
@@ -106,6 +109,24 @@
'Decrypted message from device ' +
`${message.senderInfo.deviceID}: ${decrypted}`,
);
+
+ try {
+ const parsedMessageToDevice = JSON.parse(decrypted);
+ if (
+ !secondaryDeviceLogoutP2PMessageValidator.is(parsedMessageToDevice)
+ ) {
+ return;
+ }
+ const { userID, deviceID: deviceIDToLogOut } = message.senderInfo;
+ await removeDeviceFromDeviceList(
+ identityClient,
+ userID,
+ deviceIDToLogOut,
+ );
+ // broadcast device list update here
+ } catch (e) {
+ console.log(e);
+ }
} catch (e) {
if (e.message?.includes(olmSessionErrors.messageAlreadyDecrypted)) {
console.log(
diff --git a/lib/shared/device-list-utils.js b/lib/shared/device-list-utils.js
--- a/lib/shared/device-list-utils.js
+++ b/lib/shared/device-list-utils.js
@@ -6,6 +6,7 @@
SignedDeviceList,
} from '../types/identity-service-types.js';
import { getConfig } from '../utils/config.js';
+import { getContentSigningKey } from '../utils/crypto-utils';
import {
composeRawDeviceList,
rawDeviceListFromSignedList,
@@ -134,4 +135,57 @@
};
}
-export { verifyAndGetDeviceList, createAndSignInitialDeviceList };
+async function signDeviceListUpdate(
+ deviceListPayload: RawDeviceList,
+): Promise<SignedDeviceList> {
+ const deviceID = await getContentSigningKey();
+ const rawDeviceList = JSON.stringify(deviceListPayload);
+
+ // don't sign device list if current device is not a primary one
+ if (deviceListPayload.devices[0] !== deviceID) {
+ return {
+ rawDeviceList,
+ };
+ }
+
+ const { olmAPI } = getConfig();
+ const curPrimarySignature = await olmAPI.signMessage(rawDeviceList);
+ return {
+ rawDeviceList,
+ curPrimarySignature,
+ };
+}
+
+async function removeDeviceFromDeviceList(
+ identityClient: IdentityServiceClient,
+ userID: string,
+ deviceIDToRemove: string,
+): Promise<void> {
+ const { getDeviceListHistoryForUser, updateDeviceList } = identityClient;
+ if (!updateDeviceList) {
+ throw new Error('calling device list update on non-native device');
+ }
+
+ const deviceLists = await getDeviceListHistoryForUser(userID);
+ if (deviceLists.length < 1) {
+ throw new Error('received empty device list history');
+ }
+
+ const lastSignedDeviceList = deviceLists[deviceLists.length - 1];
+ const { devices } = rawDeviceListFromSignedList(lastSignedDeviceList);
+ if (devices.includes(deviceIDToRemove)) {
+ return;
+ }
+ const newDevices = devices.filter(it => it !== deviceIDToRemove);
+
+ const newDeviceList = composeRawDeviceList(newDevices);
+ const signedDeviceList = await signDeviceListUpdate(newDeviceList);
+ await updateDeviceList(signedDeviceList);
+}
+
+export {
+ verifyAndGetDeviceList,
+ createAndSignInitialDeviceList,
+ removeDeviceFromDeviceList,
+ signDeviceListUpdate,
+};
diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js
--- a/native/profile/secondary-device-qr-code-scanner.react.js
+++ b/native/profile/secondary-device-qr-code-scanner.react.js
@@ -7,6 +7,7 @@
import { View } from 'react-native';
import { parseDataFromDeepLink } from 'lib/facts/links.js';
+import { signDeviceListUpdate } from 'lib/shared/device-list-utils.js';
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
import {
@@ -36,7 +37,6 @@
import {
composeTunnelbrokerQRAuthMessage,
parseTunnelbrokerQRAuthMessage,
- signDeviceListUpdate,
} from '../qr-code/qr-code-utils.js';
import { useStyles } from '../themes/colors.js';
import Alert from '../utils/alert.js';
diff --git a/native/qr-code/qr-code-utils.js b/native/qr-code/qr-code-utils.js
--- a/native/qr-code/qr-code-utils.js
+++ b/native/qr-code/qr-code-utils.js
@@ -58,29 +58,4 @@
return Promise.resolve(payload);
}
-async function signDeviceListUpdate(
- deviceListPayload: RawDeviceList,
-): Promise<SignedDeviceList> {
- const deviceID = await getContentSigningKey();
- const rawDeviceList = JSON.stringify(deviceListPayload);
-
- // don't sign device list if current device is not a primary one
- if (deviceListPayload.devices[0] !== deviceID) {
- return {
- rawDeviceList,
- };
- }
-
- const { olmAPI } = getConfig();
- const curPrimarySignature = await olmAPI.signMessage(rawDeviceList);
- return {
- rawDeviceList,
- curPrimarySignature,
- };
-}
-
-export {
- composeTunnelbrokerQRAuthMessage,
- parseTunnelbrokerQRAuthMessage,
- signDeviceListUpdate,
-};
+export { composeTunnelbrokerQRAuthMessage, parseTunnelbrokerQRAuthMessage };

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 3:15 PM (18 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2571332
Default Alt Text
D12225.id40679.diff (5 KB)

Event Timeline