diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 29bd11e94..e7ef19ec0 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -29,6 +29,7 @@ #import #import #import +#import #import #import #import @@ -816,6 +817,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; // If there were any messages in our local queue which we hadn't yet processed. [[OWSMessageReceiver sharedInstance] handleAnyUnprocessedEnvelopesAsync]; + // [[OWSMessageDecrypter sharedInstance] handleAnyUnprocessedEnvelopesAsync]; [OWSProfileManager.sharedManager fetchLocalUsersProfile]; } diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.m b/SignalServiceKit/src/Messages/OWSMessageReceiver.m index db975f76b..eb2e4a00b 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.m +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.m @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Persisted data model + @class OWSSignalServiceProtosEnvelope; @interface OWSMessageProcessingJob : TSYapDatabaseObject @@ -27,12 +28,16 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - + @interface OWSMessageProcessingJob () @property (nonatomic, readonly) NSData *envelopeData; @end +#pragma mark - + @implementation OWSMessageProcessingJob - (instancetype)initWithEnvelope:(OWSSignalServiceProtosEnvelope *)envelope @@ -70,12 +75,16 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces @end +#pragma mark - + @interface OWSMessageProcessingJobFinder () @property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @end +#pragma mark - + @implementation OWSMessageProcessingJobFinder - (instancetype)initWithDBConnection:(YapDatabaseConnection *)dbConnection @@ -118,7 +127,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces }]; } -+ (YapDatabaseView *)databaseExension ++ (YapDatabaseView *)databaseExtension { YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction, @@ -175,7 +184,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces // already initialized return; } - [database registerExtension:[self databaseExension] withName:OWSMessageProcessingJobFinderExtensionName]; + [database registerExtension:[self databaseExtension] withName:OWSMessageProcessingJobFinderExtensionName]; } @end @@ -194,6 +203,8 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces @end +#pragma mark - + @implementation OWSMessageProcessingQueue - (instancetype)initWithMessagesManager:(TSMessagesManager *)messagesManager @@ -248,17 +259,25 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces DDLogVerbose(@"%@ completed job. %lu jobs left.", self.tag, (unsigned long)[OWSMessageProcessingJob numberOfKeysInCollection]); + [self.finder removeJobWithId:job.uniqueId]; [self drainQueueWorkStep]; }]; } - (void)processJob:(OWSMessageProcessingJob *)job completion:(void (^)())completion { - [self.messagesManager processEnvelope:job.envelopeProto - completion:^{ - [self.finder removeJobWithId:job.uniqueId]; - completion(); - }]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self.messagesManager decryptEnvelope:job.envelopeProto + successBlock:^(NSData *_Nullable plaintextData) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.messagesManager processEnvelope:job.envelopeProto plaintextData:plaintextData]; + completion(); + }); + } + failureBlock:^{ + completion(); + }]; + }); } #pragma mark Logging @@ -284,6 +303,8 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces @end +#pragma mark - + @implementation OWSMessageReceiver - (instancetype)initWithDBConnection:(YapDatabaseConnection *)dbConnection diff --git a/SignalServiceKit/src/Messages/TSMessagesManager.h b/SignalServiceKit/src/Messages/TSMessagesManager.h index e45e73737..bf83d0d0b 100644 --- a/SignalServiceKit/src/Messages/TSMessagesManager.h +++ b/SignalServiceKit/src/Messages/TSMessagesManager.h @@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN @protocol ContactsManagerProtocol; @protocol OWSCallMessageHandler; +typedef void (^DecryptSuccessBlock)(NSData *_Nullable plaintextData); +typedef void (^DecryptFailureBlock)(); typedef void (^MessageManagerCompletionBlock)(); @interface TSMessagesManager : NSObject @@ -28,8 +30,13 @@ typedef void (^MessageManagerCompletionBlock)(); @property (nonatomic, readonly) TSNetworkManager *networkManager; @property (nonatomic, readonly) ContactsUpdater *contactsUpdater; -- (void)processEnvelope:(OWSSignalServiceProtosEnvelope *)envelope - completion:(nullable MessageManagerCompletionBlock)completion; +// decryptEnvelope: can be called from any thread. +// successBlock & failureBlock may be called on any thread. +- (void)decryptEnvelope:(OWSSignalServiceProtosEnvelope *)envelope + successBlock:(DecryptSuccessBlock)successBlock + failureBlock:(DecryptFailureBlock)failureBlock; + +- (void)processEnvelope:(OWSSignalServiceProtosEnvelope *)envelope plaintextData:(NSData *_Nullable)plaintextData; - (NSUInteger)unreadMessagesCount; - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread; diff --git a/SignalServiceKit/src/Messages/TSMessagesManager.m b/SignalServiceKit/src/Messages/TSMessagesManager.m index 4be17b91a..abd7b185e 100644 --- a/SignalServiceKit/src/Messages/TSMessagesManager.m +++ b/SignalServiceKit/src/Messages/TSMessagesManager.m @@ -260,84 +260,89 @@ NS_ASSUME_NONNULL_BEGIN return description; } -#pragma mark - message handling +#pragma mark - Blocking -- (void)processEnvelope:(OWSSignalServiceProtosEnvelope *)envelope - completion:(nullable MessageManagerCompletionBlock)completionHandler +- (BOOL)isEnvelopeBlocked:(OWSSignalServiceProtosEnvelope *)envelope { - OWSAssert([NSThread isMainThread]); + OWSAssert(envelope); + + return [_blockingManager.blockedPhoneNumbers containsObject:envelope.source]; +} + +#pragma mark - Decryption + +- (void)decryptEnvelope:(OWSSignalServiceProtosEnvelope *)envelope + successBlock:(DecryptSuccessBlock)successBlockParameter + failureBlock:(DecryptFailureBlock)failureBlockParameter +{ + OWSAssert(envelope); + OWSAssert(successBlockParameter); + OWSAssert(failureBlockParameter); OWSAssert([TSAccountManager isRegistered]); - // Ensure that completionHandler is called on the main thread, - // and handle the nil case. - MessageManagerCompletionBlock completion = ^{ - dispatch_async(dispatch_get_main_queue(), ^{ - if (completionHandler) { - completionHandler(); - } + // Ensure that successBlock and failureBlock are called on a worker queue. + DecryptSuccessBlock successBlock = ^(NSData *_Nullable plaintextData) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + successBlockParameter(plaintextData); }); }; - - DDLogInfo(@"%@ received envelope: %@", self.tag, [self descriptionForEnvelope:envelope]); + DecryptFailureBlock failureBlock = ^() { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + failureBlockParameter(); + }); + }; + DDLogInfo(@"%@ decrypting envelope: %@", self.tag, [self descriptionForEnvelope:envelope]); OWSAssert(envelope.source.length > 0); - BOOL isEnvelopeBlocked = [_blockingManager.blockedPhoneNumbers containsObject:envelope.source]; - if (isEnvelopeBlocked) { + if ([self isEnvelopeBlocked:envelope]) { DDLogInfo(@"%@ ignoring blocked envelope: %@", self.tag, envelope.source); - completion(); + failureBlock(); return; } @try { switch (envelope.type) { case OWSSignalServiceProtosEnvelopeTypeCiphertext: { - [self handleSecureMessageAsync:envelope - completion:^(NSError *_Nullable error) { - DDLogDebug(@"%@ handled secure message.", self.tag); - if (error) { - DDLogError( - @"%@ handling secure message from address: %@ failed with error: %@", - self.tag, - envelopeAddress(envelope), - error); - OWSProdError( - [OWSAnalyticsEvents messageManagerErrorCouldNotHandleSecureMessage]); - } - completion(); - }]; + [self decryptSecureMessage:envelope + successBlock:^(NSData *_Nullable plaintextData) { + DDLogDebug(@"%@ decrypted secure message.", self.tag); + successBlock(plaintextData); + } + failureBlock:^(NSError *_Nullable error) { + DDLogError(@"%@ decrypting secure message from address: %@ failed with error: %@", + self.tag, + envelopeAddress(envelope), + error); + OWSProdError([OWSAnalyticsEvents messageManagerErrorCouldNotHandleSecureMessage]); + failureBlock(); + }]; // Return to avoid double-acknowledging. return; } case OWSSignalServiceProtosEnvelopeTypePrekeyBundle: { - [self handlePreKeyBundleAsync:envelope - completion:^(NSError *_Nullable error) { - DDLogDebug(@"%@ handled pre-key whisper message", self.tag); - if (error) { - DDLogError(@"%@ handling pre-key whisper message from address: %@ failed " - @"with error: %@", - self.tag, - envelopeAddress(envelope), - error); - OWSProdError( - [OWSAnalyticsEvents messageManagerErrorCouldNotHandlePrekeyBundle]); - } - completion(); - }]; + [self decryptPreKeyBundle:envelope + successBlock:^(NSData *_Nullable plaintextData) { + DDLogDebug(@"%@ decrypted pre-key whisper message", self.tag); + successBlock(plaintextData); + } + failureBlock:^(NSError *_Nullable error) { + DDLogError(@"%@ decrypting pre-key whisper message from address: %@ failed " + @"with error: %@", + self.tag, + envelopeAddress(envelope), + error); + OWSProdError([OWSAnalyticsEvents messageManagerErrorCouldNotHandlePrekeyBundle]); + failureBlock(); + }]; // Return to avoid double-acknowledging. return; } case OWSSignalServiceProtosEnvelopeTypeReceipt: - [self handleDeliveryReceipt:envelope]; - break; - - // Other messages are just dismissed for now. - case OWSSignalServiceProtosEnvelopeTypeKeyExchange: - DDLogWarn(@"Received Key Exchange Message, not supported"); - break; case OWSSignalServiceProtosEnvelopeTypeUnknown: - DDLogWarn(@"Received an unknown message type"); - break; + successBlock(nil); + // Return to avoid double-acknowledging. + return; default: DDLogWarn(@"Received unhandled envelope type: %d", (int)envelope.type); break; @@ -347,13 +352,140 @@ NS_ASSUME_NONNULL_BEGIN OWSProdFail([OWSAnalyticsEvents messageManagerErrorInvalidProtocolMessage]); } - completion(); + failureBlock(); +} + +- (void)decryptSecureMessage:(OWSSignalServiceProtosEnvelope *)messageEnvelope + successBlock:(DecryptSuccessBlock)successBlock + failureBlock:(void (^)(NSError *_Nullable error))failureBlock +{ + OWSAssert(messageEnvelope); + OWSAssert(successBlock); + OWSAssert(failureBlock); + + TSStorageManager *storageManager = [TSStorageManager sharedManager]; + NSString *recipientId = messageEnvelope.source; + int deviceId = messageEnvelope.sourceDevice; + dispatch_async([OWSDispatch sessionStoreQueue], ^{ + // DEPRECATED - Remove after all clients have been upgraded. + NSData *encryptedData = messageEnvelope.hasContent ? messageEnvelope.content : messageEnvelope.legacyMessage; + if (!encryptedData) { + OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]); + failureBlock(nil); + return; + } + + @try { + WhisperMessage *message = [[WhisperMessage alloc] initWithData:encryptedData]; + SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager + preKeyStore:storageManager + signedPreKeyStore:storageManager + identityKeyStore:self.identityManager + recipientId:recipientId + deviceId:deviceId]; + + NSData *plaintextData = [[cipher decrypt:message] removePadding]; + successBlock(plaintextData); + } @catch (NSException *exception) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self processException:exception envelope:messageEnvelope]; + NSString *errorDescription = + [NSString stringWithFormat:@"Exception while decrypting: %@", exception.description]; + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription); + failureBlock(error); + }); + } + }); +} + +- (void)decryptPreKeyBundle:(OWSSignalServiceProtosEnvelope *)preKeyEnvelope + successBlock:(DecryptSuccessBlock)successBlock + failureBlock:(void (^)(NSError *_Nullable error))failureBlock +{ + OWSAssert(preKeyEnvelope); + OWSAssert(successBlock); + OWSAssert(failureBlock); + + TSStorageManager *storageManager = [TSStorageManager sharedManager]; + NSString *recipientId = preKeyEnvelope.source; + int deviceId = preKeyEnvelope.sourceDevice; + + // DEPRECATED - Remove after all clients have been upgraded. + NSData *encryptedData = preKeyEnvelope.hasContent ? preKeyEnvelope.content : preKeyEnvelope.legacyMessage; + if (!encryptedData) { + OWSProdFail([OWSAnalyticsEvents messageManagerErrorPrekeyBundleEnvelopeHasNoContent]); + failureBlock(nil); + return; + } + + dispatch_async([OWSDispatch sessionStoreQueue], ^{ + @try { + // Check whether we need to refresh our PreKeys every time we receive a PreKeyWhisperMessage. + [TSPreKeyManager checkPreKeys]; + + PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:encryptedData]; + SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager + preKeyStore:storageManager + signedPreKeyStore:storageManager + identityKeyStore:self.identityManager + recipientId:recipientId + deviceId:deviceId]; + + NSData *plaintextData = [[cipher decrypt:message] removePadding]; + successBlock(plaintextData); + } @catch (NSException *exception) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self processException:exception envelope:preKeyEnvelope]; + NSString *errorDescription = + [NSString stringWithFormat:@"Exception while decrypting PreKey Bundle: %@", exception.description]; + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription); + failureBlock(error); + }); + } + }); +} + +#pragma mark - message handling + +// TODO: Add transaction parameter. +- (void)processEnvelope:(OWSSignalServiceProtosEnvelope *)envelope plaintextData:(NSData *_Nullable)plaintextData +{ + OWSAssert([TSAccountManager isRegistered]); + + DDLogInfo(@"%@ received envelope: %@", self.tag, [self descriptionForEnvelope:envelope]); + + OWSAssert(envelope.source.length > 0); + OWSAssert(![self isEnvelopeBlocked:envelope]); + + switch (envelope.type) { + case OWSSignalServiceProtosEnvelopeTypeCiphertext: + case OWSSignalServiceProtosEnvelopeTypePrekeyBundle: + if (plaintextData) { + [self handleEnvelope:envelope plaintextData:plaintextData]; + } else { + OWSFail( + @"%@ missing decrypted data for envelope: %@", self.tag, [self descriptionForEnvelope:envelope]); + } + break; + case OWSSignalServiceProtosEnvelopeTypeReceipt: + OWSAssert(!plaintextData); + [self handleDeliveryReceipt:envelope]; + break; + // Other messages are just dismissed for now. + case OWSSignalServiceProtosEnvelopeTypeKeyExchange: + DDLogWarn(@"Received Key Exchange Message, not supported"); + break; + case OWSSignalServiceProtosEnvelopeTypeUnknown: + DDLogWarn(@"Received an unknown message type"); + break; + default: + DDLogWarn(@"Received unhandled envelope type: %d", (int)envelope.type); + break; + } } - (void)handleDeliveryReceipt:(OWSSignalServiceProtosEnvelope *)envelope { - OWSAssert([NSThread isMainThread]); - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { TSInteraction *interaction = [TSInteraction interactionForTimestamp:envelope.timestamp withTransaction:transaction]; @@ -364,110 +496,8 @@ NS_ASSUME_NONNULL_BEGIN }]; } -- (void)handleSecureMessageAsync:(OWSSignalServiceProtosEnvelope *)messageEnvelope - completion:(void (^)(NSError *_Nullable error))completion -{ - OWSAssert([NSThread isMainThread]); - - @synchronized(self) { - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - NSString *recipientId = messageEnvelope.source; - int deviceId = messageEnvelope.sourceDevice; - dispatch_async([OWSDispatch sessionStoreQueue], ^{ - // DEPRECATED - Remove after all clients have been upgraded. - NSData *encryptedData - = messageEnvelope.hasContent ? messageEnvelope.content : messageEnvelope.legacyMessage; - if (!encryptedData) { - OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]); - completion(nil); - return; - } - - NSData *plaintextData; - - @try { - WhisperMessage *message = [[WhisperMessage alloc] initWithData:encryptedData]; - SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager - preKeyStore:storageManager - signedPreKeyStore:storageManager - identityKeyStore:self.identityManager - recipientId:recipientId - deviceId:deviceId]; - - plaintextData = [[cipher decrypt:message] removePadding]; - } @catch (NSException *exception) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self processException:exception envelope:messageEnvelope]; - NSString *errorDescription = - [NSString stringWithFormat:@"Exception while decrypting: %@", exception.description]; - NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription); - completion(error); - }); - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleEnvelope:messageEnvelope plaintextData:plaintextData]; - completion(nil); - }); - }); - } -} - -- (void)handlePreKeyBundleAsync:(OWSSignalServiceProtosEnvelope *)preKeyEnvelope - completion:(void (^)(NSError *_Nullable error))completion -{ - OWSAssert([NSThread isMainThread]); - - @synchronized(self) { - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - NSString *recipientId = preKeyEnvelope.source; - int deviceId = preKeyEnvelope.sourceDevice; - - // DEPRECATED - Remove after all clients have been upgraded. - NSData *encryptedData = preKeyEnvelope.hasContent ? preKeyEnvelope.content : preKeyEnvelope.legacyMessage; - if (!encryptedData) { - OWSProdFail([OWSAnalyticsEvents messageManagerErrorPrekeyBundleEnvelopeHasNoContent]); - completion(nil); - return; - } - - dispatch_async([OWSDispatch sessionStoreQueue], ^{ - NSData *plaintextData; - @try { - // Check whether we need to refresh our PreKeys every time we receive a PreKeyWhisperMessage. - [TSPreKeyManager checkPreKeys]; - - PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:encryptedData]; - SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager - preKeyStore:storageManager - signedPreKeyStore:storageManager - identityKeyStore:self.identityManager - recipientId:recipientId - deviceId:deviceId]; - - plaintextData = [[cipher decrypt:message] removePadding]; - } @catch (NSException *exception) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self processException:exception envelope:preKeyEnvelope]; - NSString *errorDescription = [NSString stringWithFormat:@"Exception while decrypting PreKey Bundle: %@", exception.description]; - NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription); - completion(error); - }); - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleEnvelope:preKeyEnvelope plaintextData:plaintextData]; - completion(nil); - }); - }); - } -} - - (void)handleEnvelope:(OWSSignalServiceProtosEnvelope *)envelope plaintextData:(NSData *)plaintextData { - OWSAssert([NSThread isMainThread]); OWSAssert(envelope.hasTimestamp && envelope.timestamp > 0); OWSAssert(envelope.hasSource && envelope.source.length > 0); OWSAssert(envelope.hasSourceDevice && envelope.sourceDevice > 0); @@ -1120,6 +1150,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)processException:(NSException *)exception envelope:(OWSSignalServiceProtosEnvelope *)envelope { OWSAssert([NSThread isMainThread]); + DDLogError(@"%@ Got exception: %@ of type: %@ with reason: %@", self.tag, exception.description, @@ -1128,40 +1159,40 @@ NS_ASSUME_NONNULL_BEGIN __block TSErrorMessage *errorMessage; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - if ([exception.name isEqualToString:NoSessionException]) { - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorNoSession], envelope); - errorMessage = [TSErrorMessage missingSessionWithEnvelope:envelope withTransaction:transaction]; - } else if ([exception.name isEqualToString:InvalidKeyException]) { - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKey], envelope); - errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; - } else if ([exception.name isEqualToString:InvalidKeyIdException]) { - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKeyId], envelope); - errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; - } else if ([exception.name isEqualToString:DuplicateMessageException]) { - // Duplicate messages are dismissed - return; - } else if ([exception.name isEqualToString:InvalidVersionException]) { - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidMessageVersion], envelope); - errorMessage = [TSErrorMessage invalidVersionWithEnvelope:envelope withTransaction:transaction]; - } else if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { - // Should no longer get here, since we now record the new identity for incoming messages. - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorUntrustedIdentityKeyException], envelope); - OWSFail(@"%@ Failed to trust identity on incoming message from: %@", self.tag, envelopeAddress(envelope)); - return; - } else { - OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorCorruptMessage], envelope); - errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction]; - } + if ([exception.name isEqualToString:NoSessionException]) { + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorNoSession], envelope); + errorMessage = [TSErrorMessage missingSessionWithEnvelope:envelope withTransaction:transaction]; + } else if ([exception.name isEqualToString:InvalidKeyException]) { + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKey], envelope); + errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; + } else if ([exception.name isEqualToString:InvalidKeyIdException]) { + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKeyId], envelope); + errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction]; + } else if ([exception.name isEqualToString:DuplicateMessageException]) { + // Duplicate messages are dismissed + return; + } else if ([exception.name isEqualToString:InvalidVersionException]) { + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidMessageVersion], envelope); + errorMessage = [TSErrorMessage invalidVersionWithEnvelope:envelope withTransaction:transaction]; + } else if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { + // Should no longer get here, since we now record the new identity for incoming messages. + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorUntrustedIdentityKeyException], envelope); + OWSFail(@"%@ Failed to trust identity on incoming message from: %@", self.tag, envelopeAddress(envelope)); + return; + } else { + OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorCorruptMessage], envelope); + errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction]; + } - [errorMessage saveWithTransaction:transaction]; + [errorMessage saveWithTransaction:transaction]; }]; if (errorMessage != nil) { - [self notififyForErrorMessage:errorMessage withEnvelope:envelope]; + [self notifyForErrorMessage:errorMessage withEnvelope:envelope]; } } -- (void)notififyForErrorMessage:(TSErrorMessage *)errorMessage withEnvelope:(OWSSignalServiceProtosEnvelope *)envelope +- (void)notifyForErrorMessage:(TSErrorMessage *)errorMessage withEnvelope:(OWSSignalServiceProtosEnvelope *)envelope { TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:envelope.source]; [[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForErrorMessage:errorMessage inThread:contactThread]; diff --git a/SignalServiceKit/src/Storage/TSStorageManager.m b/SignalServiceKit/src/Storage/TSStorageManager.m index d24250850..ca923ff3e 100644 --- a/SignalServiceKit/src/Storage/TSStorageManager.m +++ b/SignalServiceKit/src/Storage/TSStorageManager.m @@ -18,6 +18,7 @@ #import "TSThread.h" #import <25519/Randomness.h> #import +#import #import #import @@ -305,6 +306,7 @@ void setDatabaseInitialized() [TSDatabaseView registerUnreadDatabaseView]; [self.database registerExtension:[TSDatabaseSecondaryIndexes registerTimeStampIndex] withName:@"idx"]; [OWSMessageReceiver syncRegisterDatabaseExtension:self.database]; + // [OWSMessageDecrypter syncRegisterDatabaseExtension:self.database]; // See comments on OWSDatabaseConnection. //