Merge branch 'charlesmchen/selfSync'

pull/1/head
Matthew Chen 7 years ago
commit 1b94207452

@ -263,7 +263,7 @@ CHECKOUT OPTIONS:
:commit: ff0b95770520133b83a4bd7b26bc2c90b51abc4d :commit: ff0b95770520133b83a4bd7b26bc2c90b51abc4d
:git: https://github.com/signalapp/SignalCoreKit.git :git: https://github.com/signalapp/SignalCoreKit.git
SignalMetadataKit: SignalMetadataKit:
:commit: b0e664410dd3d709355bfdb9d464ae02644aeb74 :commit: beb10a358db0202228b8d67bcb466d877fefb405
:git: https://github.com/signalapp/SignalMetadataKit :git: https://github.com/signalapp/SignalMetadataKit
SocketRocket: SocketRocket:
:commit: 9f9563a83cd8960503074aa8de72206f83fb7a69 :commit: 9f9563a83cd8960503074aa8de72206f83fb7a69

@ -19,7 +19,9 @@ public class OWS111UDAttributesMigration: OWSDatabaseMigration {
// increment a similar constant for each migration. // increment a similar constant for each migration.
@objc @objc
class func migrationId() -> String { class func migrationId() -> String {
return "111" // NOTE: Changes were made to the service after this migration was initially
// merged, so we need to re-migrate any developer devices.
return "111.1"
} }
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) { override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {

@ -111,6 +111,12 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
object:nil]; object:nil];
} }
#pragma mark - Dependencies
- (TSAccountManager *)tsAccountManager {
return TSAccountManager.sharedInstance;
}
- (AFHTTPSessionManager *)avatarHTTPManager - (AFHTTPSessionManager *)avatarHTTPManager
{ {
return [OWSSignalService sharedInstance].CDNSessionManager; return [OWSSignalService sharedInstance].CDNSessionManager;
@ -491,7 +497,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
{ {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();
NSString *_Nullable localNumber = [TSAccountManager sharedInstance].localNumber; NSString *_Nullable localNumber = self.tsAccountManager.localNumber;
if (!localNumber) { if (!localNumber) {
return; return;
} }
@ -676,7 +682,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
- (void)logUserProfiles - (void)logUserProfiles
{ {
[self.dbConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.dbConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) {
OWSLogError(@"logUserProfiles: %zd", [transaction numberOfKeysInCollection:OWSUserProfile.collection]); OWSLogError(@"logUserProfiles: %ld", (unsigned long) [transaction numberOfKeysInCollection:OWSUserProfile.collection]);
[transaction [transaction
enumerateKeysAndObjectsInCollection:OWSUserProfile.collection enumerateKeysAndObjectsInCollection:OWSUserProfile.collection
usingBlock:^(NSString *_Nonnull key, id _Nonnull object, BOOL *_Nonnull stop) { usingBlock:^(NSString *_Nonnull key, id _Nonnull object, BOOL *_Nonnull stop) {
@ -730,9 +736,11 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
- (nullable OWSAES256Key *)profileKeyForRecipientId:(NSString *)recipientId - (nullable OWSAES256Key *)profileKeyForRecipientId:(NSString *)recipientId
{ {
OWSAssertDebug(recipientId.length > 0); OWSAssertDebug(recipientId.length > 0);
OWSUserProfile *userProfile = // For "local reads", use the local user profile.
[OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]; OWSUserProfile *userProfile = ([self.tsAccountManager.localNumber isEqualToString:recipientId]
? self.localUserProfile
: [OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]);
OWSAssertDebug(userProfile); OWSAssertDebug(userProfile);
return userProfile.profileKey; return userProfile.profileKey;
@ -742,8 +750,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
{ {
OWSAssertDebug(recipientId.length > 0); OWSAssertDebug(recipientId.length > 0);
OWSUserProfile *userProfile = // For "local reads", use the local user profile.
[OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]; OWSUserProfile *userProfile = ([self.tsAccountManager.localNumber isEqualToString:recipientId]
? self.localUserProfile
: [OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]);
return userProfile.profileName; return userProfile.profileName;
} }
@ -752,8 +762,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
{ {
OWSAssertDebug(recipientId.length > 0); OWSAssertDebug(recipientId.length > 0);
OWSUserProfile *userProfile = // For "local reads", use the local user profile.
[OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]; OWSUserProfile *userProfile = ([self.tsAccountManager.localNumber isEqualToString:recipientId]
? self.localUserProfile
: [OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]);
if (userProfile.avatarFileName.length > 0) { if (userProfile.avatarFileName.length > 0) {
return [self loadProfileAvatarWithFilename:userProfile.avatarFileName]; return [self loadProfileAvatarWithFilename:userProfile.avatarFileName];
@ -770,8 +782,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
{ {
OWSAssertDebug(recipientId.length > 0); OWSAssertDebug(recipientId.length > 0);
OWSUserProfile *userProfile = // For "local reads", use the local user profile.
[OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]; OWSUserProfile *userProfile = ([self.tsAccountManager.localNumber isEqualToString:recipientId]
? self.localUserProfile
: [OWSUserProfile getOrBuildUserProfileForRecipientId:recipientId dbConnection:self.dbConnection]);
if (userProfile.avatarFileName.length > 0) { if (userProfile.avatarFileName.length > 0) {
return [self loadProfileDataWithFilename:userProfile.avatarFileName]; return [self loadProfileDataWithFilename:userProfile.avatarFileName];
@ -862,7 +876,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
// If we're updating the profile that corresponds to our local number, // If we're updating the profile that corresponds to our local number,
// update the local profile as well. // update the local profile as well.
NSString *_Nullable localNumber = [TSAccountManager sharedInstance].localNumber; NSString *_Nullable localNumber = self.tsAccountManager.localNumber;
if (localNumber && [localNumber isEqualToString:userProfile.recipientId]) { if (localNumber && [localNumber isEqualToString:userProfile.recipientId]) {
OWSUserProfile *localUserProfile = self.localUserProfile; OWSUserProfile *localUserProfile = self.localUserProfile;
OWSAssertDebug(localUserProfile); OWSAssertDebug(localUserProfile);
@ -919,7 +933,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
// If we're updating the profile that corresponds to our local number, // If we're updating the profile that corresponds to our local number,
// update the local profile as well. // update the local profile as well.
NSString *_Nullable localNumber = [TSAccountManager sharedInstance].localNumber; NSString *_Nullable localNumber = self.tsAccountManager.localNumber;
if (localNumber && [localNumber isEqualToString:recipientId]) { if (localNumber && [localNumber isEqualToString:recipientId]) {
OWSUserProfile *localUserProfile = self.localUserProfile; OWSUserProfile *localUserProfile = self.localUserProfile;
OWSAssertDebug(localUserProfile); OWSAssertDebug(localUserProfile);

@ -3,6 +3,7 @@
// //
#import "SignalRecipient.h" #import "SignalRecipient.h"
#import "OWSDevice.h"
#import "TSAccountManager.h" #import "TSAccountManager.h"
#import <YapDatabase/YapDatabaseConnection.h> #import <YapDatabase/YapDatabaseConnection.h>
@ -52,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
// //
// OWSMessageSender will correct this if it is wrong the next time // OWSMessageSender will correct this if it is wrong the next time
// we send a message to this recipient. // we send a message to this recipient.
_devices = [NSOrderedSet orderedSetWithObject:@(1)]; _devices = [NSOrderedSet orderedSetWithObject:@(OWSDevicePrimaryDeviceId)];
} }
return self; return self;
@ -69,7 +70,8 @@ NS_ASSUME_NONNULL_BEGIN
_devices = [NSOrderedSet new]; _devices = [NSOrderedSet new];
} }
if ([self.uniqueId isEqual:[TSAccountManager localNumber]] && [self.devices containsObject:@(1)]) { if ([self.uniqueId isEqual:[TSAccountManager localNumber]] &&
[self.devices containsObject:@(OWSDevicePrimaryDeviceId)]) {
OWSFailDebug(@"self as recipient device"); OWSFailDebug(@"self as recipient device");
} }
@ -89,8 +91,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)addDevices:(NSSet *)devices - (void)addDevices:(NSSet *)devices
{ {
OWSAssertDebug(devices.count > 0); OWSAssertDebug(devices.count > 0);
if ([self.uniqueId isEqual:[TSAccountManager localNumber]] && [devices containsObject:@(1)]) { if ([self.uniqueId isEqual:[TSAccountManager localNumber]] &&
[devices containsObject:@(OWSDevicePrimaryDeviceId)]) {
OWSFailDebug(@"adding self as recipient device"); OWSFailDebug(@"adding self as recipient device");
return; return;
} }

@ -10,12 +10,15 @@
#import "ProfileManagerProtocol.h" #import "ProfileManagerProtocol.h"
#import "SSKEnvironment.h" #import "SSKEnvironment.h"
#import "SignalAccount.h" #import "SignalAccount.h"
#import "TSAccountManager.h"
#import "TSAttachment.h" #import "TSAttachment.h"
#import "TSAttachmentStream.h" #import "TSAttachmentStream.h"
#import "TSContactThread.h" #import "TSContactThread.h"
#import <SignalCoreKit/NSDate+OWS.h> #import <SignalCoreKit/NSDate+OWS.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h> #import <SignalServiceKit/SignalServiceKit-Swift.h>
@import Contacts;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface OWSSyncContactsMessage () @interface OWSSyncContactsMessage ()
@ -49,6 +52,18 @@ NS_ASSUME_NONNULL_BEGIN
return [super initWithCoder:coder]; return [super initWithCoder:coder];
} }
#pragma mark - Dependencies
- (id<ContactsManagerProtocol>)contactsManager {
return SSKEnvironment.shared.contactsManager;
}
- (TSAccountManager *)tsAccountManager {
return TSAccountManager.sharedInstance;
}
#pragma mark -
- (nullable SSKProtoSyncMessageBuilder *)syncMessageBuilder - (nullable SSKProtoSyncMessageBuilder *)syncMessageBuilder
{ {
if (self.attachmentIds.count != 1) { if (self.attachmentIds.count != 1) {
@ -79,7 +94,22 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSData *)buildPlainTextAttachmentDataWithTransaction:(YapDatabaseReadTransaction *)transaction - (nullable NSData *)buildPlainTextAttachmentDataWithTransaction:(YapDatabaseReadTransaction *)transaction
{ {
id<ContactsManagerProtocol> contactsManager = SSKEnvironment.shared.contactsManager; NSMutableArray<SignalAccount *> *signalAccounts = [self.signalAccounts mutableCopy];
NSString *_Nullable localNumber = self.tsAccountManager.localNumber;
OWSAssertDebug(localNumber);
if (localNumber) {
BOOL hasLocalNumber = NO;
for (SignalAccount *signalAccount in signalAccounts) {
hasLocalNumber |= [signalAccount.recipientId isEqualToString:localNumber];
}
if (!hasLocalNumber) {
SignalAccount *signalAccount = [[SignalAccount alloc] initWithRecipientId:localNumber];
// OWSContactsOutputStream requires all signalAccount to have a contact.
signalAccount.contact = [[Contact alloc] initWithSystemContact:[CNContact new]];
[signalAccounts addObject:signalAccount];
}
}
// TODO use temp file stream to avoid loading everything into memory at once // TODO use temp file stream to avoid loading everything into memory at once
// First though, we need to re-engineer our attachment process to accept streams (encrypting with stream, // First though, we need to re-engineer our attachment process to accept streams (encrypting with stream,
@ -89,12 +119,11 @@ NS_ASSUME_NONNULL_BEGIN
OWSContactsOutputStream *contactsOutputStream = OWSContactsOutputStream *contactsOutputStream =
[[OWSContactsOutputStream alloc] initWithOutputStream:dataOutputStream]; [[OWSContactsOutputStream alloc] initWithOutputStream:dataOutputStream];
for (SignalAccount *signalAccount in self.signalAccounts) { for (SignalAccount *signalAccount in signalAccounts) {
OWSRecipientIdentity *_Nullable recipientIdentity = OWSRecipientIdentity *_Nullable recipientIdentity =
[self.identityManager recipientIdentityForRecipientId:signalAccount.recipientId]; [self.identityManager recipientIdentityForRecipientId:signalAccount.recipientId];
NSData *_Nullable profileKeyData = [self.profileManager profileKeyDataForRecipientId:signalAccount.recipientId]; NSData *_Nullable profileKeyData = [self.profileManager profileKeyDataForRecipientId:signalAccount.recipientId];
OWSDisappearingMessagesConfiguration *_Nullable disappearingMessagesConfiguration; OWSDisappearingMessagesConfiguration *_Nullable disappearingMessagesConfiguration;
NSString *conversationColorName; NSString *conversationColorName;
@ -109,11 +138,11 @@ NS_ASSUME_NONNULL_BEGIN
[contactsOutputStream writeSignalAccount:signalAccount [contactsOutputStream writeSignalAccount:signalAccount
recipientIdentity:recipientIdentity recipientIdentity:recipientIdentity
profileKeyData:profileKeyData profileKeyData:profileKeyData
contactsManager:contactsManager contactsManager:self.contactsManager
conversationColorName:conversationColorName conversationColorName:conversationColorName
disappearingMessagesConfiguration:disappearingMessagesConfiguration]; disappearingMessagesConfiguration:disappearingMessagesConfiguration];
} }
[dataOutputStream close]; [dataOutputStream close];
if (contactsOutputStream.hasError) { if (contactsOutputStream.hasError) {

@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly, nullable) NSData *plaintextData; @property (nonatomic, readonly, nullable) NSData *plaintextData;
@property (nonatomic, readonly) NSString *source; @property (nonatomic, readonly) NSString *source;
@property (nonatomic, readonly) UInt32 sourceDevice; @property (nonatomic, readonly) UInt32 sourceDevice;
@property (nonatomic, readonly) BOOL isUDMessage;
@end @end

@ -8,6 +8,7 @@
#import "NotificationsProtocol.h" #import "NotificationsProtocol.h"
#import "OWSAnalytics.h" #import "OWSAnalytics.h"
#import "OWSBlockingManager.h" #import "OWSBlockingManager.h"
#import "OWSDevice.h"
#import "OWSError.h" #import "OWSError.h"
#import "OWSIdentityManager.h" #import "OWSIdentityManager.h"
#import "OWSPrimaryStorage+PreKeyStore.h" #import "OWSPrimaryStorage+PreKeyStore.h"
@ -46,6 +47,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
@property (nonatomic, nullable) NSData *plaintextData; @property (nonatomic, nullable) NSData *plaintextData;
@property (nonatomic) NSString *source; @property (nonatomic) NSString *source;
@property (nonatomic) UInt32 sourceDevice; @property (nonatomic) UInt32 sourceDevice;
@property (nonatomic) BOOL isUDMessage;
@end @end
@ -57,6 +59,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
plaintextData:(nullable NSData *)plaintextData plaintextData:(nullable NSData *)plaintextData
source:(NSString *)source source:(NSString *)source
sourceDevice:(UInt32)sourceDevice sourceDevice:(UInt32)sourceDevice
isUDMessage:(BOOL)isUDMessage
{ {
OWSAssertDebug(envelopeData); OWSAssertDebug(envelopeData);
OWSAssertDebug(source.length > 0); OWSAssertDebug(source.length > 0);
@ -67,6 +70,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
result.plaintextData = plaintextData; result.plaintextData = plaintextData;
result.source = source; result.source = source;
result.sourceDevice = sourceDevice; result.sourceDevice = sourceDevice;
result.isUDMessage = isUDMessage;
return result; return result;
} }
@ -134,6 +138,11 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
return [self.blockingManager.blockedPhoneNumbers containsObject:envelope.source]; return [self.blockingManager.blockedPhoneNumbers containsObject:envelope.source];
} }
- (TSAccountManager *)tsAccountManager
{
return TSAccountManager.sharedInstance;
}
#pragma mark - Decryption #pragma mark - Decryption
- (void)decryptEnvelope:(SSKProtoEnvelope *)envelope - (void)decryptEnvelope:(SSKProtoEnvelope *)envelope
@ -157,11 +166,19 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
}); });
}; };
NSString *localRecipientId = self.tsAccountManager.localNumber;
uint32_t localDeviceId = OWSDevicePrimaryDeviceId;
DecryptSuccessBlock successBlock = ^( DecryptSuccessBlock successBlock = ^(
OWSMessageDecryptResult *result, YapDatabaseReadWriteTransaction *transaction) { OWSMessageDecryptResult *result, YapDatabaseReadWriteTransaction *transaction) {
// Ensure all blocked messages are discarded. // Ensure all blocked messages are discarded.
if ([self isEnvelopeSenderBlocked:envelope]) { if ([self isEnvelopeSenderBlocked:envelope]) {
OWSLogInfo(@"ignoring blocked envelope: %@", envelope.source); OWSLogInfo(@"Ignoring blocked envelope: %@", envelope.source);
return failureBlock();
}
if ([result.source isEqualToString:localRecipientId] && result.sourceDevice == localDeviceId) {
// Self-sent messages should be discarded during the decryption process.
OWSFailDebug(@"Unexpected self-sent sync message.");
return failureBlock(); return failureBlock();
} }
@ -237,7 +254,8 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
[OWSMessageDecryptResult resultWithEnvelopeData:envelopeData [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
plaintextData:nil plaintextData:nil
source:envelope.source source:envelope.source
sourceDevice:envelope.sourceDevice]; sourceDevice:envelope.sourceDevice
isUDMessage:NO];
successBlock(result, transaction); successBlock(result, transaction);
}]; }];
// Return to avoid double-acknowledging. // Return to avoid double-acknowledging.
@ -361,11 +379,11 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
// plaintextData may be nil for some envelope types. // plaintextData may be nil for some envelope types.
NSData *_Nullable plaintextData = NSData *_Nullable plaintextData =
[[cipher decrypt:cipherMessage protocolContext:transaction] removePadding]; [[cipher decrypt:cipherMessage protocolContext:transaction] removePadding];
OWSMessageDecryptResult *result = OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
[OWSMessageDecryptResult resultWithEnvelopeData:envelopeData plaintextData:plaintextData
plaintextData:plaintextData source:envelope.source
source:envelope.source sourceDevice:envelope.sourceDevice
sourceDevice:envelope.sourceDevice]; isUDMessage:NO];
successBlock(result, transaction); successBlock(result, transaction);
} @catch (NSException *exception) { } @catch (NSException *exception) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -414,6 +432,9 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
id<SMKCertificateValidator> certificateValidator = id<SMKCertificateValidator> certificateValidator =
[[SMKCertificateDefaultValidator alloc] initWithTrustRoot:self.udManager.trustRoot]; [[SMKCertificateDefaultValidator alloc] initWithTrustRoot:self.udManager.trustRoot];
NSString *localRecipientId = self.tsAccountManager.localNumber;
uint32_t localDeviceId = OWSDevicePrimaryDeviceId;
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try { @try {
NSError *error; NSError *error;
@ -433,9 +454,17 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
[cipher decryptMessageWithCertificateValidator:certificateValidator [cipher decryptMessageWithCertificateValidator:certificateValidator
cipherTextData:encryptedData cipherTextData:encryptedData
timestamp:serverTimestamp timestamp:serverTimestamp
localRecipientId:localRecipientId
localDeviceId:localDeviceId
protocolContext:transaction protocolContext:transaction
error:&error]; error:&error];
if (error || !decryptResult) { if (error || !decryptResult) {
if ([error.domain isEqualToString:@"SignalMetadataKit.SMKSecretSessionCipherError"]
&& error.code == SMKSecretSessionCipherErrorSelfSentMessage) {
// Self-sent messages can be safely discarded.
return failureBlock(error);
}
OWSFailDebug(@"Could not decrypt UD message: %@", error); OWSFailDebug(@"Could not decrypt UD message: %@", error);
error = EnsureDecryptError(error, @"Could not decrypt UD message"); error = EnsureDecryptError(error, @"Could not decrypt UD message");
return failureBlock(error); return failureBlock(error);
@ -471,7 +500,8 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:newEnvelopeData OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:newEnvelopeData
plaintextData:plaintextData plaintextData:plaintextData
source:source source:source
sourceDevice:(uint32_t)sourceDeviceId]; sourceDevice:(uint32_t)sourceDeviceId
isUDMessage:YES];
successBlock(result, transaction); successBlock(result, transaction);
} @catch (NSException *exception) { } @catch (NSException *exception) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -517,7 +547,12 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
return; return;
} else { } else {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorCorruptMessage], envelope); OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorCorruptMessage], envelope);
errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction]; if (envelope.source.length > 0) {
errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction];
} else {
// TODO: Find another way to surface undecryptable UD messages to the user.
return;
}
} }
OWSAssertDebug(errorMessage); OWSAssertDebug(errorMessage);

@ -1324,7 +1324,19 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSLogDebug( OWSLogDebug(
@"built message: %@ plainTextData.length: %lu", [messageSend.message class], (unsigned long)plainText.length); @"built message: %@ plainTextData.length: %lu", [messageSend.message class], (unsigned long)plainText.length);
for (NSNumber *deviceNumber in messageSend.recipient.devices) { OWSLogDebug(@"recipient.devices: %@", recipient.devices);
[DDLog flushLog];
NSMutableArray<NSNumber *> *deviceIds = [recipient.devices mutableCopy];
OWSAssertDebug(deviceIds);
if (messageSend.isUDSend && messageSend.isLocalNumber) {
OWSAssertDebug(![deviceIds containsObject:@(OWSDevicePrimaryDeviceId)]);
[deviceIds addObject:@(OWSDevicePrimaryDeviceId)];
}
for (NSNumber *deviceId in deviceIds) {
@try { @try {
__block NSDictionary *messageDict; __block NSDictionary *messageDict;
__block NSException *encryptionException; __block NSException *encryptionException;
@ -1332,7 +1344,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try { @try {
messageDict = [self encryptedMessageForMessageSend:messageSend messageDict = [self encryptedMessageForMessageSend:messageSend
deviceId:deviceNumber deviceId:deviceId
plainText:plainText plainText:plainText
transaction:transaction]; transaction:transaction];
} @catch (NSException *exception) { } @catch (NSException *exception) {
@ -1353,7 +1365,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} @catch (NSException *exception) { } @catch (NSException *exception) {
if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) { if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient removeDevicesFromRecipient:[NSSet setWithObject:deviceNumber] transaction:transaction]; [recipient removeDevicesFromRecipient:[NSSet setWithObject:deviceId] transaction:transaction];
}]; }];
} else { } else {
@throw exception; @throw exception;

@ -94,10 +94,17 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
return SSKEnvironment.shared.profileManager return SSKEnvironment.shared.profileManager
} }
private var tsAccountManager: TSAccountManager {
return TSAccountManager.sharedInstance()
}
// MARK: - Recipient state // MARK: - Recipient state
@objc @objc
public func supportsUnidentifiedDelivery(recipientId: String) -> Bool { public func supportsUnidentifiedDelivery(recipientId: String) -> Bool {
if tsAccountManager.localNumber() == recipientId {
return true
}
return dbConnection.bool(forKey: recipientId, inCollection: kUDRecipientModeCollection, defaultValue: false) return dbConnection.bool(forKey: recipientId, inCollection: kUDRecipientModeCollection, defaultValue: false)
} }

@ -13,32 +13,37 @@ NS_ASSUME_NONNULL_BEGIN
@implementation ProtoUtils @implementation ProtoUtils
#pragma mark - Dependencies
+ (id<ProfileManagerProtocol>)profileManager {
return SSKEnvironment.shared.profileManager;
}
+ (OWSAES256Key *)localProfileKey
{
return self.profileManager.localProfileKey;
}
#pragma mark -
+ (BOOL)shouldMessageHaveLocalProfileKey:(TSThread *)thread recipientId:(NSString *_Nullable)recipientId + (BOOL)shouldMessageHaveLocalProfileKey:(TSThread *)thread recipientId:(NSString *_Nullable)recipientId
{ {
OWSAssertDebug(thread); OWSAssertDebug(thread);
id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager;
// For 1:1 threads, we want to include the profile key IFF the // For 1:1 threads, we want to include the profile key IFF the
// contact is in the whitelist. // contact is in the whitelist.
// //
// For Group threads, we want to include the profile key IFF the // For Group threads, we want to include the profile key IFF the
// recipient OR the group is in the whitelist. // recipient OR the group is in the whitelist.
if (recipientId.length > 0 && [profileManager isUserInProfileWhitelist:recipientId]) { if (recipientId.length > 0 && [self.profileManager isUserInProfileWhitelist:recipientId]) {
return YES; return YES;
} else if ([profileManager isThreadInProfileWhitelist:thread]) { } else if ([self.profileManager isThreadInProfileWhitelist:thread]) {
return YES; return YES;
} }
return NO; return NO;
} }
+ (OWSAES256Key *)localProfileKey
{
id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager;
return profileManager.localProfileKey;
}
+ (void)addLocalProfileKeyIfNecessary:(TSThread *)thread + (void)addLocalProfileKeyIfNecessary:(TSThread *)thread
recipientId:(NSString *_Nullable)recipientId recipientId:(NSString *_Nullable)recipientId
dataMessageBuilder:(SSKProtoDataMessageBuilder *)dataMessageBuilder dataMessageBuilder:(SSKProtoDataMessageBuilder *)dataMessageBuilder
@ -52,10 +57,9 @@ NS_ASSUME_NONNULL_BEGIN
if (recipientId.length > 0) { if (recipientId.length > 0) {
// Once we've shared our profile key with a user (perhaps due to being // Once we've shared our profile key with a user (perhaps due to being
// a member of a whitelisted group), make sure they're whitelisted. // a member of a whitelisted group), make sure they're whitelisted.
id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager;
// FIXME PERF avoid this dispatch. It's going to happen for *each* recipient in a group message. // FIXME PERF avoid this dispatch. It's going to happen for *each* recipient in a group message.
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[profileManager addUserToProfileWhitelist:recipientId]; [self.profileManager addUserToProfileWhitelist:recipientId];
}); });
} }
} }
@ -81,10 +85,9 @@ NS_ASSUME_NONNULL_BEGIN
// Once we've shared our profile key with a user (perhaps due to being // Once we've shared our profile key with a user (perhaps due to being
// a member of a whitelisted group), make sure they're whitelisted. // a member of a whitelisted group), make sure they're whitelisted.
id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager;
// FIXME PERF avoid this dispatch. It's going to happen for *each* recipient in a group message. // FIXME PERF avoid this dispatch. It's going to happen for *each* recipient in a group message.
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[profileManager addUserToProfileWhitelist:recipientId]; [self.profileManager addUserToProfileWhitelist:recipientId];
}); });
} }
} }

Loading…
Cancel
Save