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) {
|
async prepareSync(toDeviceEvents, lock, txn, log) {
|
||||||
log.set("messageTypes", countBy(toDeviceEvents, e => e.type));
|
log.set("messageTypes", countBy(toDeviceEvents, e => e.type));
|
||||||
this._handleUnencryptedCallEvents(toDeviceEvents, log);
|
|
||||||
const encryptedEvents = toDeviceEvents.filter(e => e.type === "m.room.encrypted");
|
const encryptedEvents = toDeviceEvents.filter(e => e.type === "m.room.encrypted");
|
||||||
if (!this._olmDecryption) {
|
if (!this._olmDecryption) {
|
||||||
log.log("can't decrypt, encryption not enabled", log.level.Warn);
|
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 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?
|
// TODO: somehow include rooms that received a call to_device message in the sync state?
|
||||||
// or have updates flow through event emitter?
|
// 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
|
// 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 */
|
/** check that prep is not undefined before calling this */
|
||||||
async writeSync(prep, txn) {
|
async writeSync(prep, txn) {
|
||||||
// write olm changes
|
// write olm changes
|
||||||
prep.olmDecryptChanges.write(txn);
|
prep.olmDecryptChanges.write(txn);
|
||||||
const didWriteValues = await Promise.all(prep.newRoomKeys.map(key => this._megolmDecryption.writeRoomKey(key, 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 afterSyncCompleted(decryptionResults, deviceTracker, hsApi, log) {
|
||||||
async _getDevice(senderKey, txn) {
|
// if we don't have a device, we need to fetch the device keys the message claims
|
||||||
let device = this._senderDeviceCache.get(senderKey);
|
// and check the keys, and we should only do network requests during
|
||||||
if (!device) {
|
// sync processing in the afterSyncCompleted step.
|
||||||
device = await txn.deviceIdentities.getByCurve25519Key(senderKey);
|
const callMessages = decryptionResults.filter(dr => this._callHandler.handlesDeviceMessageEventType(dr.event?.type));
|
||||||
if (device) {
|
if (callMessages.length) {
|
||||||
this._senderDeviceCache.set(device);
|
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) {
|
async writeSync(syncResponse, syncFilterId, preparation, txn, log) {
|
||||||
const changes = {
|
const changes = {
|
||||||
syncInfo: null,
|
syncInfo: null,
|
||||||
e2eeAccountChanges: null
|
e2eeAccountChanges: null,
|
||||||
|
hasNewRoomKeys: false,
|
||||||
|
deviceMessageDecryptionResults: null,
|
||||||
};
|
};
|
||||||
const syncToken = syncResponse.next_batch;
|
const syncToken = syncResponse.next_batch;
|
||||||
if (syncToken !== this.syncToken) {
|
if (syncToken !== this.syncToken) {
|
||||||
|
@ -706,7 +708,9 @@ export class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preparation) {
|
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
|
// store account data
|
||||||
|
@ -747,6 +751,9 @@ export class Session {
|
||||||
if (changes.hasNewRoomKeys) {
|
if (changes.hasNewRoomKeys) {
|
||||||
this._keyBackup.get()?.flush(log);
|
this._keyBackup.get()?.flush(log);
|
||||||
}
|
}
|
||||||
|
if (changes.deviceMessageDecryptionResults) {
|
||||||
|
await this._deviceMessageHandler.afterSyncCompleted(changes.deviceMessageDecryptionResults, this._deviceTracker, this._hsApi, log);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tryReplaceRoomBeingCreated(roomId, log) {
|
_tryReplaceRoomBeingCreated(roomId, log) {
|
||||||
|
|
|
@ -160,7 +160,7 @@ export class Sync {
|
||||||
const isCatchupSync = this._status.get() === SyncStatus.CatchupSync;
|
const isCatchupSync = this._status.get() === SyncStatus.CatchupSync;
|
||||||
const sessionPromise = (async () => {
|
const sessionPromise = (async () => {
|
||||||
try {
|
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
|
} 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
|
- e2ee account
|
||||||
- generate more otks if needed
|
- generate more otks if needed
|
||||||
- upload new otks if needed or device keys if not uploaded before
|
- 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
|
- rooms
|
||||||
- share new room keys if needed
|
- share new room keys if needed
|
||||||
|
|
Loading…
Reference in a new issue