Avoid megolm share requests if the device is not verified

This commit is contained in:
Gil Eluard 2021-01-26 17:33:05 +01:00
parent 8ee6e0e838
commit ccbf29ab84
7 changed files with 36 additions and 336 deletions

View file

@ -5,7 +5,7 @@ Changes to be released in next version
*
🙌 Improvements
*
* Avoid megolm share requests if the device is not verified (#3969)
🐛 Bugfix
* Navigation: Unable to open a room from a room list (#3863).

View file

@ -454,7 +454,6 @@
B1B5574F20EE6C4D00210D55 /* RoomsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B556F820EE6C4C00210D55 /* RoomsViewController.m */; };
B1B5575020EE6C4D00210D55 /* AuthenticationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1B556FB20EE6C4C00210D55 /* AuthenticationViewController.xib */; };
B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B556FC20EE6C4C00210D55 /* AuthenticationViewController.m */; };
B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */; };
B1B5575920EE6C4D00210D55 /* HomeMessagesSearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5570F20EE6C4C00210D55 /* HomeMessagesSearchViewController.m */; };
B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5571120EE6C4C00210D55 /* UnifiedSearchViewController.m */; };
B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5571420EE6C4C00210D55 /* HomeFilesSearchViewController.m */; };
@ -1609,8 +1608,6 @@
B1B556FA20EE6C4C00210D55 /* AuthenticationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthenticationViewController.h; sourceTree = "<group>"; };
B1B556FB20EE6C4C00210D55 /* AuthenticationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AuthenticationViewController.xib; sourceTree = "<group>"; };
B1B556FC20EE6C4C00210D55 /* AuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthenticationViewController.m; sourceTree = "<group>"; };
B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomKeyRequestViewController.m; sourceTree = "<group>"; };
B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomKeyRequestViewController.h; sourceTree = "<group>"; };
B1B5570E20EE6C4C00210D55 /* HomeMessagesSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeMessagesSearchViewController.h; sourceTree = "<group>"; };
B1B5570F20EE6C4C00210D55 /* HomeMessagesSearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeMessagesSearchViewController.m; sourceTree = "<group>"; };
B1B5571020EE6C4C00210D55 /* UnifiedSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnifiedSearchViewController.h; sourceTree = "<group>"; };
@ -3539,7 +3536,6 @@
B1C3361A22F328AE0021BA8D /* Camera */,
B1B556E420EE6C4C00210D55 /* UserDevices */,
B1B5596B20EFA85C00210D55 /* EncryptionInfo */,
B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */,
B1B556B020EE6C4C00210D55 /* BugReport */,
B1098BE921ECFE64000DDA48 /* KeyBackup */,
B1550FCF242148FA00CE097B /* KeyVerification */,
@ -3975,15 +3971,6 @@
path = Authentication;
sourceTree = "<group>";
};
B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */ = {
isa = PBXGroup;
children = (
B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */,
B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */,
);
path = RoomKeyRequest;
sourceTree = "<group>";
};
B1B5570C20EE6C4C00210D55 /* GlobalSearch */ = {
isa = PBXGroup;
children = (
@ -6811,7 +6798,6 @@
B1098BFA21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModel.swift in Sources */,
EC51E7A62514D2E100AAE7DB /* RoomInfoCoordinatorBridgePresenter.swift in Sources */,
EC1CA87524C8259700DE9EBF /* KeychainStore.swift in Sources */,
B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */,
32A6001A22C661100042C1D9 /* EditHistoryCoordinator.swift in Sources */,
B1A15BDB25A6680E00BDCA36 /* SSOURLConstants.swift in Sources */,
F083BD1E1E7009ED00A9B29C /* LegacyAppDelegate.m in Sources */,

View file

@ -33,7 +33,6 @@
#import "ContactDetailsViewController.h"
#import "BugReportViewController.h"
#import "RoomKeyRequestViewController.h"
#import "DecryptionFailureTracker.h"
#import <MatrixKit/MatrixKit.h>
@ -129,11 +128,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
id roomKeyRequestObserver;
id roomKeyRequestCancellationObserver;
/**
If any the currently displayed sharing key dialog
*/
RoomKeyRequestViewController *roomKeyRequestViewController;
/**
Incoming key verification requests observers
*/
@ -3727,80 +3721,31 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
[mxSession.crypto pendingKeyRequests:^(MXUsersDevicesMap<NSArray<MXIncomingRoomKeyRequest *> *> *pendingKeyRequests) {
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: pendingKeyRequests.count: %lu",
pendingKeyRequests.count);
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: pendingKeyRequests.count: %@. Already displayed: %@",
@(pendingKeyRequests.count),
roomKeyRequestViewController ? @"YES" : @"NO");
if (roomKeyRequestViewController)
{
// Check if the current RoomKeyRequestViewController is still valid
MXSession *currentMXSession = roomKeyRequestViewController.mxSession;
NSString *currentUser = roomKeyRequestViewController.device.userId;
NSString *currentDevice = roomKeyRequestViewController.device.deviceId;
NSArray<MXIncomingRoomKeyRequest *> *currentPendingRequest = [pendingKeyRequests objectForDevice:currentDevice forUser:currentUser];
if (currentMXSession == mxSession && currentPendingRequest.count == 0)
{
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Cancel current dialog");
// The key request has been probably cancelled, remove the popup
[roomKeyRequestViewController hide];
roomKeyRequestViewController = nil;
}
}
if (!roomKeyRequestViewController && pendingKeyRequests.count)
if (pendingKeyRequests.count)
{
// Pick the first coming user/device pair
NSString *userId = pendingKeyRequests.userIds.firstObject;
NSString *deviceId = [pendingKeyRequests deviceIdsForUser:userId].firstObject;
// Give the client a chance to refresh the device list
[mxSession.crypto downloadKeys:@[userId] forceDownload:NO success:^(MXUsersDevicesMap<MXDeviceInfo *> *usersDevicesInfoMap, NSDictionary<NSString *,MXCrossSigningInfo *> *crossSigningKeysMap) {
MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:deviceId forUser:userId];
if (deviceInfo)
if (deviceInfo && deviceInfo.trustLevel.isVerified)
{
BOOL wasNewDevice = (deviceInfo.trustLevel.localVerificationStatus == MXDeviceUnknown);
void (^openDialog)(void) = ^void()
{
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Open dialog for %@", deviceInfo);
roomKeyRequestViewController = [[RoomKeyRequestViewController alloc] initWithDeviceInfo:deviceInfo wasNewDevice:wasNewDevice andMatrixSession:mxSession onComplete:^{
roomKeyRequestViewController = nil;
// Check next pending key request, if any
[self checkPendingRoomKeyRequests];
}];
[roomKeyRequestViewController show];
};
// If the device was new before, it's not any more.
if (wasNewDevice)
{
[mxSession.crypto setDeviceVerification:MXDeviceUnverified forDevice:deviceId ofUser:userId success:openDialog failure:nil];
}
else
{
openDialog();
}
}
else
{
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: No details found for device %@:%@", userId, deviceId);
// Ignore this device to avoid to loop on it
[mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{
// And check next requests
[mxSession.crypto acceptAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{
[self checkPendingRoomKeyRequests];
}];
}
else
{
[mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{
[self checkPendingRoomKeyRequests];
}];
}
} failure:^(NSError *error) {
// Retry later
NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Failed to download device keys. Retry");
@ -3972,6 +3917,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter *)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId
{
[coordinatorBridgePresenter.session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismissKeyVerificationCoordinatorBridgePresenter];
}

View file

@ -1379,18 +1379,23 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
- (void)sessionStateDidChangeNotification:(NSNotification*)notification
{
MXSession *session = (MXSession*)notification.object;
if (session.state == MXSessionStateRunning)
if (session.state == MXSessionStateStoreDataReady)
{
[self unregisterSessionStateChangeNotification];
if (session.crypto.crossSigning)
{
// Do not make key share requests while the "Complete security" is not complete.
// If the device is self-verified, the SDK will restore the existing key backup.
// Then, it will re-enable outgoing key share requests
[session.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil];
}
}
else if (session.state == MXSessionStateRunning)
{
[self unregisterSessionStateChangeNotification];
if (session.crypto.crossSigning)
{
[session.crypto.crossSigning refreshStateWithSuccess:^(BOOL stateUpdated) {
NSLog(@"[AuthenticationVC] sessionStateDidChange: crossSigning.state: %@", @(session.crypto.crossSigning.state));
@ -1600,14 +1605,13 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0;
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId
{
// Set outgoing key requests back
[coordinatorBridgePresenter.session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidCancel:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
{
// Set outgoing key requests back
[coordinatorBridgePresenter.session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
[self dismiss];
}

View file

@ -1,58 +0,0 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <UIKit/UIKit.h>
#import <MatrixSDK/MatrixSDK.h>
#import <MatrixKit/MatrixKit.h>
/**
The `RoomKeyRequestViewController` display a modal dialog at the top of the
application asking the user if he wants to share room keys with a user's device.
For the moment, the user is himself.
*/
@interface RoomKeyRequestViewController : NSObject
/**
The UIAlertController instance which handles the dialog.
*/
@property (nonatomic, readonly) UIAlertController *alertController;
@property (nonatomic, readonly) MXSession *mxSession;
@property (nonatomic, readonly) MXDeviceInfo *device;
/**
Initialise an `RoomKeyRequestViewController` instance.
@param deviceInfo the device to share keys to.
@param wasNewDevice flag indicating whether this is the first time we meet the device.
@param session the related matrix session.
@param onComplete a block called when the the dialog is closed.
@return the newly created instance.
*/
- (instancetype)initWithDeviceInfo:(MXDeviceInfo*)deviceInfo wasNewDevice:(BOOL)wasNewDevice andMatrixSession:(MXSession*)session onComplete:(void (^)(void))onComplete;
/**
Show the dialog in a modal way.
*/
- (void)show;
/**
Hide the dialog.
*/
- (void)hide;
@end

View file

@ -1,187 +0,0 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "RoomKeyRequestViewController.h"
#import "Riot-Swift.h"
@interface RoomKeyRequestViewController () <KeyVerificationCoordinatorBridgePresenterDelegate>
{
void (^onComplete)(void);
KeyVerificationCoordinatorBridgePresenter *keyVerificationCoordinatorBridgePresenter;
BOOL wasNewDevice;
}
@end
@implementation RoomKeyRequestViewController
- (instancetype)initWithDeviceInfo:(MXDeviceInfo *)deviceInfo wasNewDevice:(BOOL)theWasNewDevice andMatrixSession:(MXSession *)session onComplete:(void (^)(void))onCompleteBlock
{
self = [super init];
if (self)
{
_mxSession = session;
_device = deviceInfo;
wasNewDevice = theWasNewDevice;
onComplete = onCompleteBlock;
}
return self;
}
- (void)show
{
// Show it modally on the root view controller
UIViewController *rootViewController = [AppDelegate theDelegate].window.rootViewController;
if (rootViewController)
{
NSString *title = NSLocalizedStringFromTable(@"e2e_room_key_request_title", @"Vector", nil);
NSString *message;
if (wasNewDevice)
{
message = [NSString stringWithFormat:NSLocalizedStringFromTable(@"e2e_room_key_request_message_new_device", @"Vector", nil), _device.displayName];
}
else
{
message = [NSString stringWithFormat:NSLocalizedStringFromTable(@"e2e_room_key_request_message", @"Vector", nil), _device.displayName];
}
_alertController = [UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
__weak typeof(self) weakSelf = self;
[_alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"e2e_room_key_request_start_verification", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->_alertController = nil;
[self showVerificationView];
}
}]];
[_alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"e2e_room_key_request_share_without_verifying", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->_alertController = nil;
// Accept the received requests from this device
[self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{
onComplete();
}];
}
}]];
[_alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"e2e_room_key_request_ignore_request", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->_alertController = nil;
// Ignore all pending requests from this device
[self.mxSession.crypto ignoreAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{
onComplete();
}];
}
}]];
[rootViewController presentViewController:_alertController animated:YES completion:nil];
}
}
- (void)hide
{
if (_alertController)
{
[_alertController dismissViewControllerAnimated:YES completion:nil];
_alertController = nil;
}
}
- (void)showVerificationView
{
// Show it modally on the root view controller
UIViewController *rootViewController = [AppDelegate theDelegate].window.rootViewController;
if (rootViewController)
{
keyVerificationCoordinatorBridgePresenter = [[KeyVerificationCoordinatorBridgePresenter alloc] initWithSession:_mxSession];
keyVerificationCoordinatorBridgePresenter.delegate = self;
[keyVerificationCoordinatorBridgePresenter presentFrom:rootViewController otherUserId:_device.userId otherDeviceId:_device.deviceId animated:YES];
}
}
#pragma mark - DeviceVerificationCoordinatorBridgePresenterDelegate
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter *)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId
{
[self dismissKeyVerificationCoordinatorBridgePresenter];
}
- (void)keyVerificationCoordinatorBridgePresenterDelegateDidCancel:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
{
[self dismissKeyVerificationCoordinatorBridgePresenter];
}
- (void)dismissKeyVerificationCoordinatorBridgePresenter
{
[keyVerificationCoordinatorBridgePresenter dismissWithAnimated:YES completion:nil];
keyVerificationCoordinatorBridgePresenter = nil;
// Check device new status
[self.mxSession.crypto downloadKeys:@[self.device.userId] forceDownload:NO success:^(MXUsersDevicesMap<MXDeviceInfo *> *usersDevicesInfoMap, NSDictionary<NSString *,MXCrossSigningInfo *> *crossSigningKeysMap) {
MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:self.device.deviceId forUser:self.device.userId];
if (deviceInfo && deviceInfo.trustLevel.localVerificationStatus == MXDeviceVerified)
{
// Accept the received requests from this device
// As the device is now verified, all other key requests will be automatically accepted.
[self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{
onComplete();
}];
}
else
{
// Come back to self.alertController - ie, reopen it
[self show];
}
} failure:^(NSError *error) {
// Should not happen (the device is in the crypto db)
[self show];
}];
}
@end

View file

@ -405,6 +405,15 @@
- (void)onMatrixSessionStateDidChange:(NSNotification *)notif
{
MXSession *session = (MXSession*)notif.object;
if (session.state == MXSessionStateStoreDataReady)
{
if (session.crypto.crossSigning && session.crypto.crossSigning.state == MXCrossSigningStateCrossSigningExists)
{
[session.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil];
}
}
[self refreshTabBarBadges];
}