From adbefc1187796f53d161fda609d4f5d12bca8e39 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 26 Jan 2021 17:33:05 +0100 Subject: [PATCH 01/15] Avoid megolm share requests if the device is not verified --- CHANGES.rst | 2 +- Riot.xcodeproj/project.pbxproj | 14 -- Riot/Modules/Application/LegacyAppDelegate.m | 82 ++------ .../AuthenticationViewController.m | 20 +- .../RoomKeyRequestViewController.h | 58 ------ .../RoomKeyRequestViewController.m | 187 ------------------ Riot/Modules/TabBar/MasterTabBarController.m | 9 + 7 files changed, 36 insertions(+), 336 deletions(-) delete mode 100644 Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h delete mode 100644 Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m diff --git a/CHANGES.rst b/CHANGES.rst index 1913a5a3e..6ceee50dd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -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). diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 5a3be7138..c2a724622 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -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 = ""; }; B1B556FB20EE6C4C00210D55 /* AuthenticationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AuthenticationViewController.xib; sourceTree = ""; }; B1B556FC20EE6C4C00210D55 /* AuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthenticationViewController.m; sourceTree = ""; }; - B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomKeyRequestViewController.m; sourceTree = ""; }; - B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomKeyRequestViewController.h; sourceTree = ""; }; B1B5570E20EE6C4C00210D55 /* HomeMessagesSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeMessagesSearchViewController.h; sourceTree = ""; }; B1B5570F20EE6C4C00210D55 /* HomeMessagesSearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeMessagesSearchViewController.m; sourceTree = ""; }; B1B5571020EE6C4C00210D55 /* UnifiedSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnifiedSearchViewController.h; sourceTree = ""; }; @@ -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 = ""; }; - B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */ = { - isa = PBXGroup; - children = ( - B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */, - B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */, - ); - path = RoomKeyRequest; - sourceTree = ""; - }; 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 */, diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 21bb7c98c..d51efea8d 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -33,7 +33,6 @@ #import "ContactDetailsViewController.h" #import "BugReportViewController.h" -#import "RoomKeyRequestViewController.h" #import "DecryptionFailureTracker.h" #import @@ -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 *> *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 *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 *usersDevicesInfoMap, NSDictionary *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]; } diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 76667cb58..527b2bf28 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -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]; } diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h deleted file mode 100644 index 92358b5a8..000000000 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h +++ /dev/null @@ -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 - -#import -#import - -/** - 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 diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m deleted file mode 100644 index 40c44964a..000000000 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m +++ /dev/null @@ -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 () -{ - 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 *usersDevicesInfoMap, NSDictionary *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 diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 2b3d68aa6..0d047c611 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -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]; } From 372e93f1a0bfb3a2ad4b2635053adf1e4245820d Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 27 Jan 2021 09:38:11 +0100 Subject: [PATCH 02/15] reintroduced RoomKeyRequestViewController for the case of the cross signing is not available --- Riot.xcodeproj/project.pbxproj | 14 ++ Riot/Modules/Application/LegacyAppDelegate.m | 87 +++++++- .../RoomKeyRequestViewController.h | 58 ++++++ .../RoomKeyRequestViewController.m | 187 ++++++++++++++++++ 4 files changed, 339 insertions(+), 7 deletions(-) create mode 100644 Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h create mode 100644 Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index c2a724622..5a3be7138 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -454,6 +454,7 @@ 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 */; }; @@ -1608,6 +1609,8 @@ B1B556FA20EE6C4C00210D55 /* AuthenticationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthenticationViewController.h; sourceTree = ""; }; B1B556FB20EE6C4C00210D55 /* AuthenticationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AuthenticationViewController.xib; sourceTree = ""; }; B1B556FC20EE6C4C00210D55 /* AuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthenticationViewController.m; sourceTree = ""; }; + B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomKeyRequestViewController.m; sourceTree = ""; }; + B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomKeyRequestViewController.h; sourceTree = ""; }; B1B5570E20EE6C4C00210D55 /* HomeMessagesSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeMessagesSearchViewController.h; sourceTree = ""; }; B1B5570F20EE6C4C00210D55 /* HomeMessagesSearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeMessagesSearchViewController.m; sourceTree = ""; }; B1B5571020EE6C4C00210D55 /* UnifiedSearchViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnifiedSearchViewController.h; sourceTree = ""; }; @@ -3536,6 +3539,7 @@ B1C3361A22F328AE0021BA8D /* Camera */, B1B556E420EE6C4C00210D55 /* UserDevices */, B1B5596B20EFA85C00210D55 /* EncryptionInfo */, + B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */, B1B556B020EE6C4C00210D55 /* BugReport */, B1098BE921ECFE64000DDA48 /* KeyBackup */, B1550FCF242148FA00CE097B /* KeyVerification */, @@ -3971,6 +3975,15 @@ path = Authentication; sourceTree = ""; }; + B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */ = { + isa = PBXGroup; + children = ( + B1B556FF20EE6C4C00210D55 /* RoomKeyRequestViewController.h */, + B1B556FE20EE6C4C00210D55 /* RoomKeyRequestViewController.m */, + ); + path = RoomKeyRequest; + sourceTree = ""; + }; B1B5570C20EE6C4C00210D55 /* GlobalSearch */ = { isa = PBXGroup; children = ( @@ -6798,6 +6811,7 @@ 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 */, diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index d51efea8d..e33c60c3d 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -33,6 +33,7 @@ #import "ContactDetailsViewController.h" #import "BugReportViewController.h" +#import "RoomKeyRequestViewController.h" #import "DecryptionFailureTracker.h" #import @@ -128,6 +129,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni id roomKeyRequestObserver; id roomKeyRequestCancellationObserver; + /** + If any the currently displayed sharing key dialog + */ + RoomKeyRequestViewController *roomKeyRequestViewController; + /** Incoming key verification requests observers */ @@ -3720,28 +3726,95 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni return; } + MXWeakify(self); [mxSession.crypto pendingKeyRequests:^(MXUsersDevicesMap *> *pendingKeyRequests) { - NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: pendingKeyRequests.count: %lu", - pendingKeyRequests.count); + MXStrongifyAndReturnIfNil(self); + NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: pendingKeyRequests.count: %@. Already displayed: %@", + @(pendingKeyRequests.count), + self->roomKeyRequestViewController ? @"YES" : @"NO"); - if (pendingKeyRequests.count) + if (!mxSession.crypto.crossSigning) + { + if (self->roomKeyRequestViewController) + { + // Check if the current RoomKeyRequestViewController is still valid + MXSession *currentMXSession = self->roomKeyRequestViewController.mxSession; + NSString *currentUser = self->roomKeyRequestViewController.device.userId; + NSString *currentDevice = self->roomKeyRequestViewController.device.deviceId; + + NSArray *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 + [self->roomKeyRequestViewController hide]; + self->roomKeyRequestViewController = nil; + } + } + } + + if (!self->roomKeyRequestViewController && 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 + MXWeakify(self); [mxSession.crypto downloadKeys:@[userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { + + MXStrongifyAndReturnIfNil(self); MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:deviceId forUser:userId]; - if (deviceInfo && deviceInfo.trustLevel.isVerified) + if (deviceInfo) { - [mxSession.crypto acceptAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ - [self checkPendingRoomKeyRequests]; - }]; + if (!mxSession.crypto.crossSigning) + { + BOOL wasNewDevice = (deviceInfo.trustLevel.localVerificationStatus == MXDeviceUnknown); + + void (^openDialog)(void) = ^void() + { + NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Open dialog for %@", deviceInfo); + + self->roomKeyRequestViewController = [[RoomKeyRequestViewController alloc] initWithDeviceInfo:deviceInfo wasNewDevice:wasNewDevice andMatrixSession:mxSession onComplete:^{ + + self->roomKeyRequestViewController = nil; + + // Check next pending key request, if any + [self checkPendingRoomKeyRequests]; + }]; + + [self->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 if (deviceInfo.trustLevel.isVerified) + { + [mxSession.crypto acceptAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ + [self checkPendingRoomKeyRequests]; + }]; + } + else + { + [mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ + [self checkPendingRoomKeyRequests]; + }]; + } } else { + NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: No details found for device %@:%@", userId, deviceId); [mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ [self checkPendingRoomKeyRequests]; }]; diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h new file mode 100644 index 000000000..92358b5a8 --- /dev/null +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h @@ -0,0 +1,58 @@ +/* + 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 + +#import +#import + +/** + 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 diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m new file mode 100644 index 000000000..40c44964a --- /dev/null +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m @@ -0,0 +1,187 @@ +/* + 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 () +{ + 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 *usersDevicesInfoMap, NSDictionary *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 From aa52bddc36b80f140da31c026fd0c6bb182a6f11 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 28 Jan 2021 11:32:54 +0100 Subject: [PATCH 03/15] Fixed cross-signing detection in LegacyAppDelegate --- Riot/Modules/Application/LegacyAppDelegate.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index e33c60c3d..1fb368f55 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -3734,7 +3734,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni @(pendingKeyRequests.count), self->roomKeyRequestViewController ? @"YES" : @"NO"); - if (!mxSession.crypto.crossSigning) + if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state != MXCrossSigningStateCrossSigningExists) { if (self->roomKeyRequestViewController) { @@ -3770,7 +3770,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:deviceId forUser:userId]; if (deviceInfo) { - if (!mxSession.crypto.crossSigning) + if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state != MXCrossSigningStateCrossSigningExists) { BOOL wasNewDevice = (deviceInfo.trustLevel.localVerificationStatus == MXDeviceUnknown); From 9fb503acf2d3d7173ad6362c7b061c68397274bf Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 28 Jan 2021 14:47:12 +0100 Subject: [PATCH 04/15] Update Riot/Modules/Application/LegacyAppDelegate.m Co-authored-by: manuroe --- Riot/Modules/Application/LegacyAppDelegate.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 1fb368f55..3f042ffbb 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -3734,7 +3734,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni @(pendingKeyRequests.count), self->roomKeyRequestViewController ? @"YES" : @"NO"); - if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state != MXCrossSigningStateCrossSigningExists) + if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) { if (self->roomKeyRequestViewController) { From d254339e9beef8033e44f9fb4cc8394f2b198e81 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 28 Jan 2021 14:48:23 +0100 Subject: [PATCH 05/15] Update Riot/Modules/Application/LegacyAppDelegate.m Co-authored-by: manuroe --- Riot/Modules/Application/LegacyAppDelegate.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 3f042ffbb..d0f8c74fe 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -3770,7 +3770,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:deviceId forUser:userId]; if (deviceInfo) { - if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state != MXCrossSigningStateCrossSigningExists) + if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) { BOOL wasNewDevice = (deviceInfo.trustLevel.localVerificationStatus == MXDeviceUnknown); From a58f83acea8f874299134328aef9aae4ae918cbf Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 28 Jan 2021 19:53:20 +0100 Subject: [PATCH 06/15] Modifications after review --- Riot/Modules/Application/LegacyAppDelegate.m | 10 ++++++++-- Riot/Modules/TabBar/MasterTabBarController.m | 9 --------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index d0f8c74fe..02933f209 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2333,6 +2333,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni case MXSessionStateSyncInProgress: // Stay in launching during the first server sync if the store is empty. isLaunching = (mainSession.rooms.count == 0 && launchAnimationContainerView); + + if (mainSession.crypto.crossSigning && mainSession.crypto.crossSigning.state == MXCrossSigningStateCrossSigningExists) + { + [mainSession.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil]; + } break; default: isLaunching = NO; @@ -3730,8 +3735,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [mxSession.crypto pendingKeyRequests:^(MXUsersDevicesMap *> *pendingKeyRequests) { MXStrongifyAndReturnIfNil(self); - NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: pendingKeyRequests.count: %@. Already displayed: %@", - @(pendingKeyRequests.count), + NSLog(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: cross-signing state: %ld, pendingKeyRequests.count: %@. Already displayed: %@", + mxSession.crypto.crossSigning.state, + @(pendingKeyRequests.count), self->roomKeyRequestViewController ? @"YES" : @"NO"); if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 0d047c611..2b3d68aa6 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -405,15 +405,6 @@ - (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]; } From 3c126cddc1ce35f01628c55bb51598538371e378 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 1 Feb 2021 09:53:17 +0100 Subject: [PATCH 07/15] Update after review --- Riot/Modules/Application/LegacyAppDelegate.m | 7 ++++++- .../Modules/Authentication/AuthenticationViewController.m | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 02933f209..cd11cd70a 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -3996,7 +3996,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter *)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId { - [coordinatorBridgePresenter.session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; + MXCrypto *crypto = coordinatorBridgePresenter.session.crypto; + if (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled) + { + NSLog(@"[AppDelegate][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys"); + [crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; + } [self dismissKeyVerificationCoordinatorBridgePresenter]; } diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 0a9cfbf72..f769c5e48 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -1624,8 +1624,12 @@ 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]; + MXCrypto *crypto = coordinatorBridgePresenter.session.crypto; + if (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled) + { + NSLog(@"[AuthenticationVC][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys"); + [crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; + } [self dismiss]; } From 8febbdc6defd1e9de1806e5e61ced8fa51462064 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 2 Feb 2021 11:31:21 +0100 Subject: [PATCH 08/15] Force device verification on user share key re-request if device is not verified. --- Riot/Modules/Room/RoomViewController.m | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 27b14118f..65f156d32 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -121,6 +121,9 @@ #import "EventFormatter.h" #import +#import "SettingsViewController.h" +#import "SecurityViewController.h" + #import "Riot-Swift.h" @interface RoomViewController () Date: Tue, 2 Feb 2021 16:24:32 +0100 Subject: [PATCH 09/15] matrix.to: Cannot open links with query parameters #3990 The string can come percent encoded but we parse it with ascii chars ("?", "&", ...). So, remove one layer of encoding to fix the bug. --- CHANGES.rst | 1 + Riot/Modules/Application/LegacyAppDelegate.m | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index befac451d..c81e55ade 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,7 @@ Changes to be released in next version 🐛 Bugfix * Push: Fix PushKit crashes due to undecryptable call invites (#3986). + * matrix.to: Cannot open links with query parameters (#3990). ⚠️ API Changes * diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 21bb7c98c..3fb7de7d4 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1255,6 +1255,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni NSLog(@"[AppDelegate] Universal link: handleUniversalLinkFragment: %@", fragment); + // Make sure we have plain utf8 character for separators + fragment = [fragment stringByRemovingPercentEncoding]; + NSLog(@"[AppDelegate] Universal link: handleUniversalLinkFragment: %@", fragment); + // The app manages only one universal link at a time // Discard any pending one [self resetPendingUniversalLink]; From fe474fda48f26af9a48d1da32d2321f3b1067db5 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 2 Feb 2021 17:07:12 +0100 Subject: [PATCH 10/15] matrix.to: Cannot open/preview a new room given by alias #3991 Add a patch to try to build the right string and to avoid to loop forever --- CHANGES.rst | 1 + Riot/Modules/Application/LegacyAppDelegate.m | 22 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c81e55ade..d435db2aa 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Changes to be released in next version 🐛 Bugfix * Push: Fix PushKit crashes due to undecryptable call invites (#3986). * matrix.to: Cannot open links with query parameters (#3990). + * matrix.to: Cannot open/preview a new room given by alias (#3991). ⚠️ API Changes * diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 3fb7de7d4..ba0e306cc 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1380,9 +1380,27 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni withString:[MXTools encodeURIComponent:roomId] ]; - universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias}; + // The previous operation can fail because of percent encoding + // TBH we are not clean on data inputs. For the moment, just give another try with no encoding + // TODO: Have a dedicated module and tests to handle universal links (matrix.to, email link, etc) + if ([newUniversalLinkFragment isEqualToString:fragment]) + { + newUniversalLinkFragment = + [fragment stringByReplacingOccurrencesOfString:roomIdOrAlias + withString:[MXTools encodeURIComponent:roomId]]; + } - [self handleUniversalLinkFragment:newUniversalLinkFragment]; + if (![newUniversalLinkFragment isEqualToString:fragment]) + { + universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias}; + + [self handleUniversalLinkFragment:newUniversalLinkFragment]; + } + else + { + // Do not continue. Else we will loop forever + NSLog(@"[AppDelegate] Universal link: Error: Cannot resolve alias in %@ to the room id %@", fragment, roomId); + } } } failure:^(NSError *error) { From 13d01dee0ba1efcbabd1aa23b96e095f3bb774d2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 2 Feb 2021 17:13:01 +0100 Subject: [PATCH 11/15] matrix.to: Support room preview when the permalink has parameters (like "via=") It works. There is no reason for not doing it --- CHANGES.rst | 1 + Riot/Modules/Application/LegacyAppDelegate.m | 48 ++++++++------------ 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d435db2aa..175587e81 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Changes to be released in next version 🙌 Improvements * Social login: Handle new identity provider brand field in order to customize buttons (#3980). * Widgets: Support $matrix_room_id and $matrix_widget_id parameters (#3987). + * matrix.to: Support room preview when the permalink has parameters (like "via="). 🐛 Bugfix * Push: Fix PushKit crashes due to undecryptable call invites (#3986). diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index ba0e306cc..0a9c48783 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1444,40 +1444,32 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // FIXME: In case of multi-account, ask the user which one to use MXKAccount* account = accountManager.activeAccounts.firstObject; - RoomPreviewData *roomPreviewData; + RoomPreviewData *roomPreviewData = [[RoomPreviewData alloc] initWithRoomId:roomIdOrAlias + andSession:account.mxSession]; if (queryParams) { + roomPreviewData.viaServers = queryParams[@"via"]; + } + + // Is it a link to an event of a room? + // If yes, the event will be displayed once the room is joined + roomPreviewData.eventId = (pathParams.count >= 3) ? pathParams[2] : nil; + + // Try to get more information about the room before opening its preview + [roomPreviewData peekInRoom:^(BOOL succeeded) { + // Note: the activity indicator will not disappear if the session is not ready [homeViewController stopActivityIndicator]; - roomPreviewData = [[RoomPreviewData alloc] initWithRoomId:roomIdOrAlias emailInvitationParams:queryParams andSession:account.mxSession]; - roomPreviewData.viaServers = queryParams[@"via"]; + // If no data is available for this room, we name it with the known room alias (if any). + if (!succeeded && universalLinkFragmentPendingRoomAlias[roomIdOrAlias]) + { + roomPreviewData.roomName = universalLinkFragmentPendingRoomAlias[roomIdOrAlias]; + } + universalLinkFragmentPendingRoomAlias = nil; + [self showRoomPreview:roomPreviewData]; - } - else - { - roomPreviewData = [[RoomPreviewData alloc] initWithRoomId:roomIdOrAlias andSession:account.mxSession]; - - // Is it a link to an event of a room? - // If yes, the event will be displayed once the room is joined - roomPreviewData.eventId = (pathParams.count >= 3) ? pathParams[2] : nil; - - // Try to get more information about the room before opening its preview - [roomPreviewData peekInRoom:^(BOOL succeeded) { - - // Note: the activity indicator will not disappear if the session is not ready - [homeViewController stopActivityIndicator]; - - // If no data is available for this room, we name it with the known room alias (if any). - if (!succeeded && universalLinkFragmentPendingRoomAlias[roomIdOrAlias]) - { - roomPreviewData.roomName = universalLinkFragmentPendingRoomAlias[roomIdOrAlias]; - } - universalLinkFragmentPendingRoomAlias = nil; - - [self showRoomPreview:roomPreviewData]; - }]; - } + }]; } } From ee3ebc179267d2bcbe143bcec8caffafe48143e9 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 2 Feb 2021 17:59:39 +0100 Subject: [PATCH 12/15] matrix.to: The app does not open a permalink from matrix.to #3993 --- CHANGES.rst | 1 + Riot/Modules/Application/LegacyAppDelegate.m | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 175587e81..1b5ec3c8d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,7 @@ Changes to be released in next version * Push: Fix PushKit crashes due to undecryptable call invites (#3986). * matrix.to: Cannot open links with query parameters (#3990). * matrix.to: Cannot open/preview a new room given by alias (#3991). + * matrix.to: The app does not open a permalink from matrix.to (#3993). ⚠️ API Changes * diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 0a9c48783..5ea802c1a 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1146,9 +1146,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [[NSNotificationCenter defaultCenter] postNotificationName:AppDelegateUniversalLinkDidChangeNotification object:nil]; } - if ([webURL.path isEqualToString:@"/"]) + if ([self handleServerProvionningLink:webURL]) { - return [self handleServerProvionningLink:webURL]; + return YES; } NSString *validateEmailSubmitTokenPath = @"validate/email/submitToken"; From 64c6f4c66ff1622e2e02d1f672f38de3ca98bff8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 3 Feb 2021 12:12:28 +0100 Subject: [PATCH 13/15] Logs: Add a size limitation so that we can upload them in bug reports #3903 --- CHANGES.rst | 1 + Riot/Modules/Application/LegacyAppDelegate.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 92ff64870..5678ba20e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,7 @@ Changes to be released in next version * matrix.to: Cannot open links with query parameters (#3990). * matrix.to: Cannot open/preview a new room given by alias (#3991). * matrix.to: The app does not open a permalink from matrix.to (#3993). + * Logs: Add a size limitation so that we can upload them in bug reports (#3903). ⚠️ API Changes * diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 57cfca11f..0fbf36cd1 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -254,7 +254,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Redirect NSLogs to files only if we are not debugging if (!isatty(STDERR_FILENO)) { - [MXLogger redirectNSLogToFiles:YES numberOfFiles:50]; + [MXLogger redirectNSLogToFiles:YES numberOfFiles:50 sizeLimit:(100 * 1024 * 1024)]; } NSLog(@"[AppDelegate] initialize: Done"); From 30052144e940028a97cd5608fe322a7137f77bda Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 3 Feb 2021 12:14:33 +0100 Subject: [PATCH 14/15] Push notifications: Keep more life cycles logs but with a size limit This should be temporary until we fix crashes in NSE --- RiotNSE/NotificationService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 2fdef058b..0a30bda54 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -126,7 +126,7 @@ class NotificationService: UNNotificationServiceExtension { if !NotificationService.isLoggerInitialized { if isatty(STDERR_FILENO) == 0 { MXLogger.setSubLogName("nse") - MXLogger.redirectNSLog(toFiles: true) + MXLogger.redirectNSLog(toFiles: true, numberOfFiles: 100, sizeLimit: 10 * 1024 * 1024) } NotificationService.isLoggerInitialized = true } From 59e4903b746ce694386b914930098bc8d2dc0869 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 3 Feb 2021 15:59:06 +0100 Subject: [PATCH 15/15] Push notifications: Keep more life cycles logs but with a size limit Fix Gil's comments --- Riot/Modules/Application/LegacyAppDelegate.m | 3 ++- RiotNSE/NotificationService.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 0fbf36cd1..1ab6cc0da 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -254,7 +254,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Redirect NSLogs to files only if we are not debugging if (!isatty(STDERR_FILENO)) { - [MXLogger redirectNSLogToFiles:YES numberOfFiles:50 sizeLimit:(100 * 1024 * 1024)]; + NSUInteger sizeLimit = 100 * 1024 * 1024; // 100MB + [MXLogger redirectNSLogToFiles:YES numberOfFiles:50 sizeLimit:sizeLimit]; } NSLog(@"[AppDelegate] initialize: Done"); diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 0a30bda54..b0ac5e6b0 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -126,7 +126,8 @@ class NotificationService: UNNotificationServiceExtension { if !NotificationService.isLoggerInitialized { if isatty(STDERR_FILENO) == 0 { MXLogger.setSubLogName("nse") - MXLogger.redirectNSLog(toFiles: true, numberOfFiles: 100, sizeLimit: 10 * 1024 * 1024) + let sizeLimit: UInt = 10 * 1024 * 1024; // 10MB + MXLogger.redirectNSLog(toFiles: true, numberOfFiles: 100, sizeLimit: sizeLimit) } NotificationService.isLoggerInitialized = true }