Generate new registrationId on re-register

In order for others to know they should start a new session with us, we
need to change our registration id.

To achieve this, I consolidated all the Account related attributes on
TSAccountManager - luckily they were already in the proper collection, I
just moved the API to hang on the AccountManager instead of a TSStorage
category extension.

Also:

@synchronize access to `registrationId`

// FREEBIE
This commit is contained in:
Michael Kirk 2017-10-10 15:06:45 -04:00
parent 58d4c95362
commit 0706edf42a
9 changed files with 81 additions and 112 deletions

View file

@ -42,6 +42,22 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange;
+ (nullable NSString *)localNumber; + (nullable NSString *)localNumber;
- (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 * The registration ID is unique to an installation of TextSecure, it allows to know if the app was reinstalled
* *

View file

@ -13,7 +13,7 @@
#import "TSPreKeyManager.h" #import "TSPreKeyManager.h"
#import "TSSocketManager.h" #import "TSSocketManager.h"
#import "TSStorageManager+SessionStore.h" #import "TSStorageManager+SessionStore.h"
#import "TSStorageManager+keyingMaterial.h" #import "YapDatabaseConnection+OWS.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -25,6 +25,10 @@ NSString *const kNSNotificationName_LocalNumberDidChange = @"kNSNotificationName
NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey"; NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey";
NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId"; NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId";
NSString *const TSAccountManager_UserAccountCollection = @"TSStorageUserAccountCollection";
NSString *const TSAccountManager_ServerAuthToken = @"TSStorageServerAuthToken";
NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignalingKey";
@interface TSAccountManager () @interface TSAccountManager ()
@property (nonatomic, readonly) BOOL isRegistered; @property (nonatomic, readonly) BOOL isRegistered;
@ -84,7 +88,9 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
_isRegistered = NO; _isRegistered = NO;
_cachedLocalNumber = nil; _cachedLocalNumber = nil;
_phoneNumberAwaitingVerification = nil; _phoneNumberAwaitingVerification = nil;
[self removeStoredLocalNumber]; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection];
}];
} }
[[TSStorageManager sharedManager] resetSessionStore]; [[TSStorageManager sharedManager] resetSessionStore];
} }
@ -150,20 +156,11 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
return self.cachedLocalNumber; return self.cachedLocalNumber;
} }
- (void)removeStoredLocalNumber
{
@synchronized(self)
{
[self.dbConnection removeObjectForKey:TSAccountManager_RegisteredNumberKey
inCollection:TSStorageUserAccountCollection];
}
}
- (nullable NSString *)storedLocalNumber - (nullable NSString *)storedLocalNumber
{ {
@synchronized (self) { @synchronized (self) {
return [self.dbConnection stringForKey:TSAccountManager_RegisteredNumberKey return [self.dbConnection stringForKey:TSAccountManager_RegisteredNumberKey
inCollection:TSStorageUserAccountCollection]; inCollection:TSAccountManager_UserAccountCollection];
} }
} }
@ -172,7 +169,7 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
@synchronized (self) { @synchronized (self) {
[self.dbConnection setObject:localNumber [self.dbConnection setObject:localNumber
forKey:TSAccountManager_RegisteredNumberKey forKey:TSAccountManager_RegisteredNumberKey
inCollection:TSStorageUserAccountCollection]; inCollection:TSAccountManager_UserAccountCollection];
} }
} }
@ -183,19 +180,22 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
- (uint32_t)getOrGenerateRegistrationId - (uint32_t)getOrGenerateRegistrationId
{ {
uint32_t registrationID = [[self.dbConnection objectForKey:TSAccountManager_LocalRegistrationIdKey @synchronized(self)
inCollection:TSStorageUserAccountCollection] unsignedIntValue]; {
uint32_t registrationID =
[[self.dbConnection objectForKey:TSAccountManager_LocalRegistrationIdKey
inCollection:TSAccountManager_UserAccountCollection] unsignedIntValue];
if (registrationID == 0) { if (registrationID == 0) {
registrationID = (uint32_t)arc4random_uniform(16380) + 1; registrationID = (uint32_t)arc4random_uniform(16380) + 1;
DDLogWarn(@"%@ Generated a new registrationID: %u", self.tag, registrationID); DDLogWarn(@"%@ Generated a new registrationID: %u", self.tag, registrationID);
[self.dbConnection setObject:[NSNumber numberWithUnsignedInteger:registrationID] [self.dbConnection setObject:[NSNumber numberWithUnsignedInteger:registrationID]
forKey:TSAccountManager_LocalRegistrationIdKey forKey:TSAccountManager_LocalRegistrationIdKey
inCollection:TSStorageUserAccountCollection]; inCollection:TSAccountManager_UserAccountCollection];
}
return registrationID;
} }
return registrationID;
} }
- (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken - (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken
@ -336,7 +336,7 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
case 200: case 200:
case 204: { case 204: {
DDLogInfo(@"%@ Verification code accepted.", self.tag); DDLogInfo(@"%@ Verification code accepted.", self.tag);
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey]; [self storeServerToken:authToken signalingKey:signalingKey];
[TSPreKeyManager registerPreKeysWithMode:RefreshPreKeysMode_SignedAndOneTime [TSPreKeyManager registerPreKeysWithMode:RefreshPreKeysMode_SignedAndOneTime
success:successBlock success:successBlock
failure:failureBlock]; failure:failureBlock];
@ -389,6 +389,41 @@ NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegist
return signalingKeyTokenPrint; 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)storeServerToken:(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 + (void)unregisterTextSecureWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failureBlock
{ {
[[TSNetworkManager sharedManager] makeRequest:[[TSUnregisterAccountRequest alloc] init] [[TSNetworkManager sharedManager] makeRequest:[[TSUnregisterAccountRequest alloc] init]

View file

@ -4,7 +4,6 @@
#import "TSAttributes.h" #import "TSAttributes.h"
#import "TSAccountManager.h" #import "TSAccountManager.h"
#import "TSStorageManager+keyingMaterial.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN

View file

@ -3,9 +3,8 @@
// //
#import "TSRequest.h" #import "TSRequest.h"
#import "TSAccountManager.h"
#import "TSConstants.h" #import "TSConstants.h"
#import "TSStorageManager+keyingMaterial.h"
@implementation TSRequest @implementation TSRequest
@ -37,7 +36,8 @@
#pragma clang diagnostic pop #pragma clang diagnostic pop
- (void)makeAuthenticatedRequest { - (void)makeAuthenticatedRequest {
[self.parameters addEntriesFromDictionary:@{ @"Authorization" : [TSStorageManager serverAuthToken] }]; OWSAssert([TSAccountManager serverAuthToken]);
[self.parameters addEntriesFromDictionary:@{ @"Authorization" : [TSAccountManager serverAuthToken] }];
} }
@end @end

View file

@ -6,7 +6,6 @@
#import "NSURLSessionDataTask+StatusCode.h" #import "NSURLSessionDataTask+StatusCode.h"
#import "OWSSignalService.h" #import "OWSSignalService.h"
#import "TSAccountManager.h" #import "TSAccountManager.h"
#import "TSStorageManager+keyingMaterial.h"
#import "TSVerifyCodeRequest.h" #import "TSVerifyCodeRequest.h"
#import <AFNetworking/AFNetworking.h> #import <AFNetworking/AFNetworking.h>
@ -74,7 +73,7 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error);
if (![request isKindOfClass:[TSRequestVerificationCodeRequest class]]) { if (![request isKindOfClass:[TSRequestVerificationCodeRequest class]]) {
[sessionManager.requestSerializer [sessionManager.requestSerializer
setAuthorizationHeaderFieldWithUsername:[TSAccountManager localNumber] setAuthorizationHeaderFieldWithUsername:[TSAccountManager localNumber]
password:[TSStorageManager serverAuthToken]]; password:[TSAccountManager serverAuthToken]];
} }
if ([request.HTTPMethod isEqualToString:@"GET"]) { if ([request.HTTPMethod isEqualToString:@"GET"]) {

View file

@ -14,7 +14,6 @@
#import "SubProtocol.pb.h" #import "SubProtocol.pb.h"
#import "TSAccountManager.h" #import "TSAccountManager.h"
#import "TSConstants.h" #import "TSConstants.h"
#import "TSStorageManager+keyingMaterial.h"
#import "Threading.h" #import "Threading.h"
static const CGFloat kSocketHeartbeatPeriodSeconds = 30.f; static const CGFloat kSocketHeartbeatPeriodSeconds = 30.f;
@ -380,11 +379,9 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
[self requestSocketAliveForAtLeastSeconds:kBackgroundKeepSocketAliveDurationSeconds]; [self requestSocketAliveForAtLeastSeconds:kBackgroundKeepSocketAliveDurationSeconds];
if ([message.path isEqualToString:@"/api/v1/message"] && [message.verb isEqualToString:@"PUT"]) { if ([message.path isEqualToString:@"/api/v1/message"] && [message.verb isEqualToString:@"PUT"]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *decryptedPayload = NSData *decryptedPayload =
[Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSStorageManager.signalingKey]; [Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSAccountManager.signalingKey];
if (!decryptedPayload) { if (!decryptedPayload) {
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.tag); DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.tag);
@ -485,7 +482,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
- (NSString *)webSocketAuthenticationString { - (NSString *)webSocketAuthenticationString {
return [NSString stringWithFormat:@"?login=%@&password=%@", return [NSString stringWithFormat:@"?login=%@&password=%@",
[[TSAccountManager localNumber] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"], [[TSAccountManager localNumber] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"],
[TSStorageManager serverAuthToken]]; [TSAccountManager serverAuthToken]];
} }
#pragma mark - Socket LifeCycle #pragma mark - Socket LifeCycle

View file

@ -5,13 +5,6 @@
#ifndef TextSecureKit_TSStorageKeys_h #ifndef TextSecureKit_TSStorageKeys_h
#define 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 * Preferences exposed to the user
*/ */

View file

@ -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

View file

@ -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