Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart broken Olm sessions #780

Merged
merged 18 commits into from
Nov 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/crypto/algorithms/megolm.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ MegolmEncryption.prototype.reshareKeyWithDevice = async function(
},
});
logger.debug(
`Re-shared key for session ${sessionId} with {userId}:{device.deviceId}`,
`Re-shared key for session ${sessionId} with ${userId}:${device.deviceId}`,
);
};

Expand Down
24 changes: 24 additions & 0 deletions src/crypto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export function isCryptoAvailable() {
return Boolean(global.Olm);
}

const MIN_FORCE_SESSION_INTERVAL_MS = 60 * 60 * 1000;

/**
* Cryptography bits
*
Expand Down Expand Up @@ -120,6 +122,15 @@ export default function Crypto(baseApis, sessionStore, userId, deviceId,
// has happened for a given room. This is delayed
// to avoid loading room members as long as possible.
this._roomDeviceTrackingState = {};

// The timestamp of the last time we forced establishment
// of a new session for each device, in milliseconds.
// {
// userId: {
// deviceId: 1234567890000,
// },
// }
this._lastNewSessionForced = {};
}
utils.inherits(Crypto, EventEmitter);

Expand Down Expand Up @@ -1180,6 +1191,19 @@ Crypto.prototype._onToDeviceBadEncrypted = async function(event) {
return;
}

// check when we last forced a new session with this device: if we've already done so
// recently, don't do it again.
this._lastNewSessionForced[sender] = this._lastNewSessionForced[sender] || {};
const lastNewSessionForced = this._lastNewSessionForced[sender][deviceKey] || 0;
if (lastNewSessionForced + MIN_FORCE_SESSION_INTERVAL_MS > Date.now()) {
logger.debug(
"New session already forced with device " + sender + ":" + deviceKey +
" at " + lastNewSessionForced + ": not forcing another",
);
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the keyshare request should still be resent in this situation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so - we'll have resent all outstanding keyshare requests when the session was re-established, so any responses coming back on the old session will already have had their re-requests sent after establishment of the new session.

}
this._lastNewSessionForced[sender][deviceKey] = Date.now();

// establish a new olm session with this device since we're failing to decrypt messages
// on a current session.
// Note that an undecryptable message from another device could easily be spoofed -
Expand Down