forked from mystiq/hydrogen-web
fetch and verify keys on olm call signalling message
This commit is contained in:
parent
50ae51e893
commit
9efe294a79
4 changed files with 41 additions and 37 deletions
|
@ -38,7 +38,6 @@ export class DeviceMessageHandler {
|
|||
|
||||
async prepareSync(toDeviceEvents, lock, txn, log) {
|
||||
log.set("messageTypes", countBy(toDeviceEvents, e => e.type));
|
||||
this._handleUnencryptedCallEvents(toDeviceEvents, log);
|
||||
const encryptedEvents = toDeviceEvents.filter(e => e.type === "m.room.encrypted");
|
||||
if (!this._olmDecryption) {
|
||||
log.log("can't decrypt, encryption not enabled", log.level.Warn);
|
||||
|
@ -54,20 +53,6 @@ export class DeviceMessageHandler {
|
|||
}
|
||||
const newRoomKeys = this._megolmDecryption.roomKeysFromDeviceMessages(olmDecryptChanges.results, log);
|
||||
|
||||
// const callMessages = olmDecryptChanges.results.filter(dr => this._callHandler.handlesDeviceMessageEventType(dr.event?.type));
|
||||
// // load devices by sender key
|
||||
// await Promise.all(callMessages.map(async dr => {
|
||||
// dr.setDevice(await this._getDevice(dr.senderCurve25519Key, txn));
|
||||
// }));
|
||||
// // TODO: pass this in the prep and run it in afterSync or afterSyncComplete (as callHandler can send events as well)?
|
||||
// for (const dr of callMessages) {
|
||||
// if (dr.device) {
|
||||
// this._callHandler.handleDeviceMessage(dr.event, dr.device.userId, dr.device.deviceId, log);
|
||||
// } else {
|
||||
// console.error("could not deliver message because don't have device for sender key", dr.event);
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: somehow include rooms that received a call to_device message in the sync state?
|
||||
// or have updates flow through event emitter?
|
||||
// well, we don't really need to update the room other then when a call starts or stops
|
||||
|
@ -76,33 +61,42 @@ export class DeviceMessageHandler {
|
|||
}
|
||||
}
|
||||
|
||||
_handleUnencryptedCallEvents(toDeviceEvents, log) {
|
||||
const callMessages = toDeviceEvents.filter(e => this._callHandler.handlesDeviceMessageEventType(e.type));
|
||||
for (const event of callMessages) {
|
||||
const userId = event.sender;
|
||||
const deviceId = event.content.device_id;
|
||||
this._callHandler.handleDeviceMessage(event, userId, deviceId, log);
|
||||
}
|
||||
}
|
||||
|
||||
/** check that prep is not undefined before calling this */
|
||||
async writeSync(prep, txn) {
|
||||
// write olm changes
|
||||
prep.olmDecryptChanges.write(txn);
|
||||
const didWriteValues = await Promise.all(prep.newRoomKeys.map(key => this._megolmDecryption.writeRoomKey(key, txn)));
|
||||
return didWriteValues.some(didWrite => !!didWrite);
|
||||
const hasNewRoomKeys = didWriteValues.some(didWrite => !!didWrite);
|
||||
return {
|
||||
hasNewRoomKeys,
|
||||
decryptionResults: prep.olmDecryptChanges.results
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
async _getDevice(senderKey, txn) {
|
||||
let device = this._senderDeviceCache.get(senderKey);
|
||||
if (!device) {
|
||||
device = await txn.deviceIdentities.getByCurve25519Key(senderKey);
|
||||
if (device) {
|
||||
this._senderDeviceCache.set(device);
|
||||
}
|
||||
async afterSyncCompleted(decryptionResults, deviceTracker, hsApi, log) {
|
||||
// if we don't have a device, we need to fetch the device keys the message claims
|
||||
// and check the keys, and we should only do network requests during
|
||||
// sync processing in the afterSyncCompleted step.
|
||||
const callMessages = decryptionResults.filter(dr => this._callHandler.handlesDeviceMessageEventType(dr.event?.type));
|
||||
if (callMessages.length) {
|
||||
await log.wrap("process call signalling messages", async log => {
|
||||
for (const dr of callMessages) {
|
||||
// serialize device loading, so subsequent messages for the same device take advantage of the cache
|
||||
const device = await deviceTracker.deviceForId(dr.event.sender, dr.event.content.device_id, hsApi, log);
|
||||
dr.setDevice(device);
|
||||
if (dr.isVerified) {
|
||||
this._callHandler.handleDeviceMessage(dr.event, dr.userId, dr.deviceId, log);
|
||||
} else {
|
||||
log.log({
|
||||
l: "could not verify olm fingerprint key matches, ignoring",
|
||||
ed25519Key: dr.device.ed25519Key,
|
||||
claimedEd25519Key: dr.claimedEd25519Key,
|
||||
deviceId, userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -685,7 +685,9 @@ export class Session {
|
|||
async writeSync(syncResponse, syncFilterId, preparation, txn, log) {
|
||||
const changes = {
|
||||
syncInfo: null,
|
||||
e2eeAccountChanges: null
|
||||
e2eeAccountChanges: null,
|
||||
hasNewRoomKeys: false,
|
||||
deviceMessageDecryptionResults: null,
|
||||
};
|
||||
const syncToken = syncResponse.next_batch;
|
||||
if (syncToken !== this.syncToken) {
|
||||
|
@ -706,7 +708,9 @@ export class Session {
|
|||
}
|
||||
|
||||
if (preparation) {
|
||||
changes.hasNewRoomKeys = await log.wrap("deviceMsgs", log => this._deviceMessageHandler.writeSync(preparation, txn, log));
|
||||
const {hasNewRoomKeys, decryptionResults} = await log.wrap("deviceMsgs", log => this._deviceMessageHandler.writeSync(preparation, txn, log));
|
||||
changes.hasNewRoomKeys = hasNewRoomKeys;
|
||||
changes.deviceMessageDecryptionResults = decryptionResults;
|
||||
}
|
||||
|
||||
// store account data
|
||||
|
@ -747,6 +751,9 @@ export class Session {
|
|||
if (changes.hasNewRoomKeys) {
|
||||
this._keyBackup.get()?.flush(log);
|
||||
}
|
||||
if (changes.deviceMessageDecryptionResults) {
|
||||
await this._deviceMessageHandler.afterSyncCompleted(changes.deviceMessageDecryptionResults, this._deviceTracker, this._hsApi, log);
|
||||
}
|
||||
}
|
||||
|
||||
_tryReplaceRoomBeingCreated(roomId, log) {
|
||||
|
|
|
@ -160,7 +160,7 @@ export class Sync {
|
|||
const isCatchupSync = this._status.get() === SyncStatus.CatchupSync;
|
||||
const sessionPromise = (async () => {
|
||||
try {
|
||||
await log.wrap("session", log => this._session.afterSyncCompleted(sessionChanges, isCatchupSync, log), log.level.Detail);
|
||||
await log.wrap("session", log => this._session.afterSyncCompleted(sessionChanges, isCatchupSync, log));
|
||||
} catch (err) {} // error is logged, but don't fail sessionPromise
|
||||
})();
|
||||
|
||||
|
|
|
@ -41,5 +41,8 @@ Runs before any room.prepareSync, so the new room keys can be passed to each roo
|
|||
- e2ee account
|
||||
- generate more otks if needed
|
||||
- upload new otks if needed or device keys if not uploaded before
|
||||
- device message handler:
|
||||
- fetch keys we don't know about yet for (call) to_device messages identity
|
||||
- pass signalling messages to call handler
|
||||
- rooms
|
||||
- share new room keys if needed
|
||||
|
|
Loading…
Reference in a new issue