diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m index ec66c4a93..6ffea00b7 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m @@ -6,6 +6,7 @@ #import "Environment.h" #import "OWSCountryMetadata.h" #import "OWSTableViewController.h" +#import "RegistrationViewController.h" #import "Signal-Swift.h" #import "ThreadUtil.h" #import @@ -21,6 +22,12 @@ NS_ASSUME_NONNULL_BEGIN +@interface TSAccountManager (Debug) + +- (void)resetForRegistration; + +@end + @implementation DebugUIMisc #pragma mark - Logging @@ -61,9 +68,38 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIMisc clearHasDismissedOffers]; }]]; + + [items addObject:[OWSTableItem + itemWithTitle:@"Re-register" + actionBlock:^{ + + [OWSAlerts + showConfirmationAlertWithTitle:@"Re-register?" + message:@"If you proceed, you will not lose any of your " + @"current messages, but your account will be " + @"deactivated until you complete re-registration." + proceedTitle:@"Proceed" + proceedAction:^(UIAlertAction *_Nonnull action) { + [self reregister]; + }]; + }]]; + return [OWSTableSection sectionWithTitle:self.name items:items]; } +- (void)reregister +{ + DDLogInfo(@"%@ re-registering.", self.tag); + [[TSAccountManager sharedInstance] resetForRegistration]; + + RegistrationViewController *viewController = [RegistrationViewController new]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:viewController]; + navigationController.navigationBarHidden = YES; + + [UIApplication sharedApplication].delegate.window.rootViewController = navigationController; +} + + (void)setManualCensorshipCircumventionEnabled:(BOOL)isEnabled { OWSCountryMetadata *countryMetadata = nil; diff --git a/Signal/src/ViewControllers/SafetyNumberConfirmationAlert.swift b/Signal/src/ViewControllers/SafetyNumberConfirmationAlert.swift index e50c6eeed..044f02b66 100644 --- a/Signal/src/ViewControllers/SafetyNumberConfirmationAlert.swift +++ b/Signal/src/ViewControllers/SafetyNumberConfirmationAlert.swift @@ -74,7 +74,7 @@ class SafetyNumberConfirmationAlert: NSObject { } actionSheetController.addAction(showSafetyNumberAction) - actionSheetController.addAction(OWSAlerts.cancelAction()) + actionSheetController.addAction(OWSAlerts.cancelAction) UIApplication.shared.frontmostViewController?.present(actionSheetController, animated: true) return true diff --git a/Signal/src/views/OWSAlerts.swift b/Signal/src/views/OWSAlerts.swift index df4d1fcaa..1b46de176 100644 --- a/Signal/src/views/OWSAlerts.swift +++ b/Signal/src/views/OWSAlerts.swift @@ -33,14 +33,26 @@ import Foundation public class func showAlert(withTitle title: String, message: String? = nil, buttonTitle: String? = nil) { assert(title.characters.count > 0) - let actionTitle = (buttonTitle != nil ? buttonTitle : NSLocalizedString("OK", comment: "")) + let actionTitle = buttonTitle ?? NSLocalizedString("OK", comment: "") let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: actionTitle, style: .default, handler: nil)) UIApplication.shared.frontmostViewController?.present(alert, animated: true, completion: nil) } - public class func cancelAction() -> UIAlertAction { + public class func showConfirmationAlert(withTitle title: String, message: String? = nil, proceedTitle: String? = nil, proceedAction: @escaping (UIAlertAction) -> Void) { + assert(title.characters.count > 0) + + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(self.cancelAction) + + let actionTitle = proceedTitle ?? NSLocalizedString("OK", comment: "") + alert.addAction(UIAlertAction(title: actionTitle, style: .default, handler: proceedAction)) + + UIApplication.shared.frontmostViewController?.present(alert, animated: true, completion: nil) + } + + public class var cancelAction: UIAlertAction { let action = UIAlertAction(title: CommonStrings.cancelButton, style: .cancel) { _ in Logger.debug("Cancel item") // Do nothing. diff --git a/SignalServiceKit/src/Account/TSAccountManager.h b/SignalServiceKit/src/Account/TSAccountManager.h index ae7e7ed92..a80e5c12a 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.h +++ b/SignalServiceKit/src/Account/TSAccountManager.h @@ -42,6 +42,22 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange; + (nullable NSString *)localNumber; - (nullable NSString *)localNumber; +/** + * Symmetric key that's used to encrypt message payloads from the server, + * + * @return signaling key + */ ++ (nullable NSString *)signalingKey; +- (nullable NSString *)signalingKey; + +/** + * The server auth token allows the Signal client to connect to the Signal server + * + * @return server authentication token + */ ++ (nullable NSString *)serverAuthToken; +- (nullable NSString *)serverAuthToken; + /** * The registration ID is unique to an installation of TextSecure, it allows to know if the app was reinstalled * diff --git a/SignalServiceKit/src/Account/TSAccountManager.m b/SignalServiceKit/src/Account/TSAccountManager.m index dc5b61604..1b050cdd9 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.m +++ b/SignalServiceKit/src/Account/TSAccountManager.m @@ -12,7 +12,8 @@ #import "TSNetworkManager.h" #import "TSPreKeyManager.h" #import "TSSocketManager.h" -#import "TSStorageManager+keyingMaterial.h" +#import "TSStorageManager+SessionStore.h" +#import "YapDatabaseConnection+OWS.h" NS_ASSUME_NONNULL_BEGIN @@ -24,6 +25,10 @@ NSString *const kNSNotificationName_LocalNumberDidChange = @"kNSNotificationName NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey"; NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId"; +NSString *const TSAccountManager_UserAccountCollection = @"TSStorageUserAccountCollection"; +NSString *const TSAccountManager_ServerAuthToken = @"TSStorageServerAuthToken"; +NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignalingKey"; + @interface TSAccountManager () @property (nonatomic, readonly) BOOL isRegistered; @@ -76,6 +81,20 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist userInfo:nil]; } +- (void)resetForRegistration +{ + @synchronized(self) + { + _isRegistered = NO; + _cachedLocalNumber = nil; + _phoneNumberAwaitingVerification = nil; + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection]; + }]; + } + [[TSStorageManager sharedManager] resetSessionStore]; +} + + (BOOL)isRegistered { return [[self sharedInstance] isRegistered]; @@ -141,7 +160,7 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist { @synchronized (self) { return [self.dbConnection stringForKey:TSAccountManager_RegisteredNumberKey - inCollection:TSStorageUserAccountCollection]; + inCollection:TSAccountManager_UserAccountCollection]; } } @@ -150,7 +169,7 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist @synchronized (self) { [self.dbConnection setObject:localNumber forKey:TSAccountManager_RegisteredNumberKey - inCollection:TSStorageUserAccountCollection]; + inCollection:TSAccountManager_UserAccountCollection]; } } @@ -161,19 +180,22 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist - (uint32_t)getOrGenerateRegistrationId { - uint32_t registrationID = [[self.dbConnection objectForKey:TSAccountManager_LocalRegistrationIdKey - inCollection:TSStorageUserAccountCollection] unsignedIntValue]; + @synchronized(self) + { + uint32_t registrationID = + [[self.dbConnection objectForKey:TSAccountManager_LocalRegistrationIdKey + inCollection:TSAccountManager_UserAccountCollection] unsignedIntValue]; - if (registrationID == 0) { - registrationID = (uint32_t)arc4random_uniform(16380) + 1; - DDLogWarn(@"%@ Generated a new registrationID: %u", self.tag, registrationID); + if (registrationID == 0) { + registrationID = (uint32_t)arc4random_uniform(16380) + 1; + DDLogWarn(@"%@ Generated a new registrationID: %u", self.tag, registrationID); - [self.dbConnection setObject:[NSNumber numberWithUnsignedInteger:registrationID] - forKey:TSAccountManager_LocalRegistrationIdKey - inCollection:TSStorageUserAccountCollection]; + [self.dbConnection setObject:[NSNumber numberWithUnsignedInteger:registrationID] + forKey:TSAccountManager_LocalRegistrationIdKey + inCollection:TSAccountManager_UserAccountCollection]; + } + return registrationID; } - - return registrationID; } - (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken @@ -314,7 +336,7 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist case 200: case 204: { DDLogInfo(@"%@ Verification code accepted.", self.tag); - [TSStorageManager storeServerToken:authToken signalingKey:signalingKey]; + [self storeServerAuthToken:authToken signalingKey:signalingKey]; [TSPreKeyManager registerPreKeysWithMode:RefreshPreKeysMode_SignedAndOneTime success:successBlock failure:failureBlock]; @@ -367,6 +389,41 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist return signalingKeyTokenPrint; } ++ (nullable NSString *)signalingKey +{ + return [[self sharedInstance] signalingKey]; +} + +- (nullable NSString *)signalingKey +{ + return [self.dbConnection stringForKey:TSAccountManager_ServerSignalingKey + inCollection:TSAccountManager_UserAccountCollection]; +} + ++ (nullable NSString *)serverAuthToken +{ + return [[self sharedInstance] serverAuthToken]; +} + +- (nullable NSString *)serverAuthToken +{ + return [self.dbConnection stringForKey:TSAccountManager_ServerAuthToken + inCollection:TSAccountManager_UserAccountCollection]; +} + +- (void)storeServerAuthToken:(NSString *)authToken signalingKey:(NSString *)signalingKey +{ + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [transaction setObject:authToken + forKey:TSAccountManager_ServerAuthToken + inCollection:TSAccountManager_UserAccountCollection]; + [transaction setObject:signalingKey + forKey:TSAccountManager_ServerSignalingKey + inCollection:TSAccountManager_UserAccountCollection]; + + }]; +} + + (void)unregisterTextSecureWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failureBlock { [[TSNetworkManager sharedManager] makeRequest:[[TSUnregisterAccountRequest alloc] init] diff --git a/SignalServiceKit/src/Account/TSAttributes.m b/SignalServiceKit/src/Account/TSAttributes.m index ad1053d4a..9e0889c5b 100644 --- a/SignalServiceKit/src/Account/TSAttributes.m +++ b/SignalServiceKit/src/Account/TSAttributes.m @@ -4,7 +4,6 @@ #import "TSAttributes.h" #import "TSAccountManager.h" -#import "TSStorageManager+keyingMaterial.h" NS_ASSUME_NONNULL_BEGIN @@ -12,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSDictionary *)attributesFromStorageWithManualMessageFetching:(BOOL)isEnabled { - return [self attributesWithSignalingKey:[TSStorageManager signalingKey] - serverAuthToken:[TSStorageManager serverAuthToken] + return [self attributesWithSignalingKey:TSAccountManager.signalingKey + serverAuthToken:TSAccountManager.serverAuthToken manualMessageFetching:isEnabled]; } diff --git a/SignalServiceKit/src/Network/API/Requests/TSRequest.m b/SignalServiceKit/src/Network/API/Requests/TSRequest.m index 8922ad353..06b0f7fa7 100644 --- a/SignalServiceKit/src/Network/API/Requests/TSRequest.m +++ b/SignalServiceKit/src/Network/API/Requests/TSRequest.m @@ -3,9 +3,8 @@ // #import "TSRequest.h" - +#import "TSAccountManager.h" #import "TSConstants.h" -#import "TSStorageManager+keyingMaterial.h" @implementation TSRequest @@ -37,7 +36,8 @@ #pragma clang diagnostic pop - (void)makeAuthenticatedRequest { - [self.parameters addEntriesFromDictionary:@{ @"Authorization" : [TSStorageManager serverAuthToken] }]; + OWSAssert([TSAccountManager serverAuthToken]); + [self.parameters addEntriesFromDictionary:@{ @"Authorization" : [TSAccountManager serverAuthToken] }]; } @end diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index d8853ca6e..9979758d3 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -6,7 +6,6 @@ #import "NSURLSessionDataTask+StatusCode.h" #import "OWSSignalService.h" #import "TSAccountManager.h" -#import "TSStorageManager+keyingMaterial.h" #import "TSVerifyCodeRequest.h" #import @@ -74,7 +73,7 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); if (![request isKindOfClass:[TSRequestVerificationCodeRequest class]]) { [sessionManager.requestSerializer setAuthorizationHeaderFieldWithUsername:[TSAccountManager localNumber] - password:[TSStorageManager serverAuthToken]]; + password:[TSAccountManager serverAuthToken]]; } if ([request.HTTPMethod isEqualToString:@"GET"]) { diff --git a/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m b/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m index 648741169..29515c6ee 100644 --- a/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m +++ b/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m @@ -14,7 +14,6 @@ #import "SubProtocol.pb.h" #import "TSAccountManager.h" #import "TSConstants.h" -#import "TSStorageManager+keyingMaterial.h" #import "Threading.h" static const CGFloat kSocketHeartbeatPeriodSeconds = 30.f; @@ -384,7 +383,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *decryptedPayload = - [Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSStorageManager.signalingKey]; + [Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSAccountManager.signalingKey]; if (!decryptedPayload) { DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.tag); @@ -485,7 +484,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_ - (NSString *)webSocketAuthenticationString { return [NSString stringWithFormat:@"?login=%@&password=%@", [[TSAccountManager localNumber] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"], - [TSStorageManager serverAuthToken]]; + [TSAccountManager serverAuthToken]]; } #pragma mark - Socket LifeCycle diff --git a/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.h b/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.h index 741146204..5dff6712b 100644 --- a/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.h +++ b/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.h @@ -11,6 +11,7 @@ #pragma mark - debug +- (void)resetSessionStore; - (void)printAllSessions; @end diff --git a/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.m b/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.m index 466a3a70c..062ca2e64 100644 --- a/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.m +++ b/SignalServiceKit/src/Storage/AxolotlStore/TSStorageManager+SessionStore.m @@ -189,6 +189,14 @@ void AssertIsOnSessionStoreQueue() #pragma mark - debug +- (void)resetSessionStore +{ + DDLogWarn(@"%@ resetting session store", self.tag); + [self.sessionDBConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [transaction removeAllObjectsInCollection:TSStorageManagerSessionStoreCollection]; + }]; +} + - (void)printAllSessions { AssertIsOnSessionStoreQueue(); diff --git a/SignalServiceKit/src/Storage/TSStorageKeys.h b/SignalServiceKit/src/Storage/TSStorageKeys.h index f969915e6..b18a8205f 100644 --- a/SignalServiceKit/src/Storage/TSStorageKeys.h +++ b/SignalServiceKit/src/Storage/TSStorageKeys.h @@ -5,13 +5,6 @@ #ifndef TextSecureKit_TSStorageKeys_h #define TextSecureKit_TSStorageKeys_h -#pragma mark User Account Keys - -#define TSStorageUserAccountCollection @"TSStorageUserAccountCollection" - -#define TSStorageServerAuthToken @"TSStorageServerAuthToken" -#define TSStorageServerSignalingKey @"TSStorageServerSignalingKey" - /** * Preferences exposed to the user */ diff --git a/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.h b/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.h deleted file mode 100644 index 390f85cb0..000000000 --- a/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" - -@interface TSStorageManager (keyingMaterial) - -#pragma mark Server Credentials - -/** - * The server signaling key that's used to encrypt push payloads - * - * @return signaling key - */ - -+ (NSString *)signalingKey; - -/** - * The server auth token allows the TextSecure client to connect to the server - * - * @return server authentication token - */ - -+ (NSString *)serverAuthToken; - -+ (void)storeServerToken:(NSString *)authToken signalingKey:(NSString *)signalingKey; - -@end diff --git a/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.m b/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.m deleted file mode 100644 index bc0703c2c..000000000 --- a/SignalServiceKit/src/Storage/TSStorageManager+keyingMaterial.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+keyingMaterial.h" - -// TODO merge this category extension's functionality into TSAccountManager -@implementation TSStorageManager (keyingMaterial) - -+ (NSString *)signalingKey { - return [[self sharedManager] stringForKey:TSStorageServerSignalingKey inCollection:TSStorageUserAccountCollection]; -} - -+ (NSString *)serverAuthToken { - return [[self sharedManager] stringForKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection]; -} - -+ (void)storeServerToken:(NSString *)authToken signalingKey:(NSString *)signalingKey { - TSStorageManager *sharedManager = self.sharedManager; - [sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection]; - [transaction setObject:signalingKey - forKey:TSStorageServerSignalingKey - inCollection:TSStorageUserAccountCollection]; - - }]; -} - -#pragma mark - Logging - -+ (NSString *)logTag -{ - return [NSString stringWithFormat:@"[%@]", self.class]; -} - -- (NSString *)logTag -{ - return self.class.logTag; -} - -@end