Handle malformed protos.

This commit is contained in:
Matthew Chen 2018-04-16 14:48:29 -04:00
parent b925f913bd
commit 5ce39337ed
9 changed files with 106 additions and 29 deletions

View File

@ -222,6 +222,7 @@
34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */; };
34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */; };
34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0F1EFC2684007F6822 /* DebugUIPage.m */; };
34E8A8D12085238A00B272B1 /* ProtoParsingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E8A8D02085238900B272B1 /* ProtoParsingTest.m */; };
34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */; };
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m */; };
4503F1BE20470A5B00CEE724 /* classic-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BB20470A5B00CEE724 /* classic-quiet.aifc */; };
@ -860,6 +861,7 @@
34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIDiskUsage.m; sourceTree = "<group>"; };
34E3EF0E1EFC2684007F6822 /* DebugUIPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUIPage.h; sourceTree = "<group>"; };
34E3EF0F1EFC2684007F6822 /* DebugUIPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIPage.m; sourceTree = "<group>"; };
34E8A8D02085238900B272B1 /* ProtoParsingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProtoParsingTest.m; sourceTree = "<group>"; };
34F308A01ECB469700BB7697 /* OWSBezierPathView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBezierPathView.h; sourceTree = "<group>"; };
34F308A11ECB469700BB7697 /* OWSBezierPathView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBezierPathView.m; sourceTree = "<group>"; };
34FD936E1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWSAnyTouchGestureRecognizer.h; path = views/OWSAnyTouchGestureRecognizer.h; sourceTree = "<group>"; };
@ -2191,10 +2193,11 @@
34DB0BEB2011548A007B313F /* OWSDatabaseConverterTest.h */,
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */,
45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */,
34E8A8D02085238900B272B1 /* ProtoParsingTest.m */,
45360B8F1F9527DA00FA666C /* SearcherTest.swift */,
452D1AF02081059C00A67F7F /* StringAdditionsTest.swift */,
B660F6B31C29868000687D6E /* UtilTest.h */,
B660F6B41C29868000687D6E /* UtilTest.m */,
452D1AF02081059C00A67F7F /* StringAdditionsTest.swift */,
);
path = util;
sourceTree = "<group>";
@ -3360,6 +3363,7 @@
B660F6BB1C29868000687D6E /* OWSContactsManagerTest.m in Sources */,
B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */,
455AC69E1F4F8B0300134004 /* ImageCacheTest.swift in Sources */,
34E8A8D12085238A00B272B1 /* ProtoParsingTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -391,8 +391,13 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
aborted = YES;
return completion(NO);
}
OWSSignaliOSProtosBackupSnapshot *_Nullable entities =
[OWSSignaliOSProtosBackupSnapshot parseFromData:uncompressedData];
OWSSignaliOSProtosBackupSnapshot *_Nullable entities;
@try {
entities = [OWSSignaliOSProtosBackupSnapshot parseFromData:uncompressedData];
} @catch (NSException *exception) {
OWSProdLogAndFail(@"%@ Could not parse proto: %@", self.logTag, exception.debugDescription);
// TODO: Add analytics.
}
if (!entities || entities.entity.count < 1) {
DDLogError(@"%@ missing entities.", self.logTag);
// Database-related errors are unrecoverable.

View File

@ -0,0 +1,41 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSSignalServiceProtos.pb.h"
#import <XCTest/XCTest.h>
@interface ProtoParsingTest : XCTestCase
@end
#pragma mark -
@implementation ProtoParsingTest
- (void)testProtoParsing_nil
{
OWSSignalServiceProtosEnvelope *_Nullable envelope = [OWSSignalServiceProtosEnvelope parseFromData:nil];
XCTAssertNotNil(envelope);
}
- (void)testProtoParsing_empty
{
NSData *data = [NSData new];
OWSSignalServiceProtosEnvelope *_Nullable envelope = [OWSSignalServiceProtosEnvelope parseFromData:data];
XCTAssertNotNil(envelope);
}
- (void)testProtoParsing_wrong1
{
@try {
NSData *data = [@"test" dataUsingEncoding:NSUTF8StringEncoding];
[OWSSignalServiceProtosEnvelope parseFromData:data];
XCTFail(@"Missing expected exception");
} @catch (NSException *exception) {
// Exception is expected.
NSLog(@"Caught expected exception: %@", [exception class]);
}
}
@end

View File

@ -62,7 +62,12 @@ NS_ASSUME_NONNULL_BEGIN
- (OWSSignalServiceProtosEnvelope *)envelope
{
if (!_envelope) {
_envelope = [OWSSignalServiceProtosEnvelope parseFromData:self.envelopeData];
@try {
_envelope = [OWSSignalServiceProtosEnvelope parseFromData:self.envelopeData];
} @catch (NSException *exception) {
OWSProdLogAndFail(@"%@ Could not parse proto: %@", self.logTag, exception.debugDescription);
// TODO: Add analytics.
}
}
return _envelope;
}

View File

@ -375,9 +375,14 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo
NSMutableArray<OWSMessageContentJob *> *processedJobs = [NSMutableArray new];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSMessageContentJob *job in jobs) {
[self.messagesManager processEnvelope:job.envelopeProto
plaintextData:job.plaintextData
transaction:transaction];
@try {
[self.messagesManager processEnvelope:job.envelopeProto
plaintextData:job.plaintextData
transaction:transaction];
} @catch (NSException *exception) {
OWSProdLogAndFail(@"%@ Received an invalid envelope: %@", self.logTag, exception.debugDescription);
// TODO: Add analytics.
}
[processedJobs addObject:job];
if (self.isAppInBackground) {

View File

@ -106,16 +106,17 @@ NS_ASSUME_NONNULL_BEGIN
failureBlockParameter();
});
};
DDLogInfo(@"%@ decrypting envelope: %@", self.logTag, [self descriptionForEnvelope:envelope]);
OWSAssert(envelope.source.length > 0);
if ([self isEnvelopeBlocked:envelope]) {
DDLogInfo(@"%@ ignoring blocked envelope: %@", self.logTag, envelope.source);
failureBlock();
return;
}
@try {
DDLogInfo(@"%@ decrypting envelope: %@", self.logTag, [self descriptionForEnvelope:envelope]);
OWSAssert(envelope.source.length > 0);
if ([self isEnvelopeBlocked:envelope]) {
DDLogInfo(@"%@ ignoring blocked envelope: %@", self.logTag, envelope.source);
failureBlock();
return;
}
switch (envelope.type) {
case OWSSignalServiceProtosEnvelopeTypeCiphertext: {
[self decryptSecureMessage:envelope
@ -167,7 +168,7 @@ NS_ASSUME_NONNULL_BEGIN
break;
}
} @catch (NSException *exception) {
DDLogError(@"Received an incorrectly formatted protocol buffer: %@", exception.debugDescription);
OWSProdLogAndFail(@"%@ Received an invalid envelope: %@", self.logTag, exception.debugDescription);
OWSProdFail([OWSAnalyticsEvents messageManagerErrorInvalidProtocolMessage]);
}

View File

@ -200,7 +200,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(!plaintextData);
[self handleDeliveryReceipt:envelope transaction:transaction];
break;
// Other messages are just dismissed for now.
// Other messages are just dismissed for now.
case OWSSignalServiceProtosEnvelopeTypeKeyExchange:
DDLogWarn(@"Received Key Exchange Message, not supported");
break;

View File

@ -316,7 +316,18 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
AssertOnDispatchQueue(self.serialQueue);
OWSAssert(job);
OWSSignalServiceProtosEnvelope *envelope = job.envelopeProto;
OWSSignalServiceProtosEnvelope *_Nullable envelope = nil;
@try {
envelope = job.envelopeProto;
} @catch (NSException *exception) {
OWSProdLogAndFail(@"%@ Could not parse proto: %@", self.logTag, exception.debugDescription);
// TODO: Add analytics.
dispatch_async(self.serialQueue, ^{
completion(NO);
});
return;
}
[self.messageDecrypter decryptEnvelope:envelope
successBlock:^(NSData *_Nullable plaintextData, YapDatabaseReadWriteTransaction *transaction) {
OWSAssert(transaction);

View File

@ -385,21 +385,26 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
__block OWSBackgroundTask *backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@try {
NSData *decryptedPayload = [Cryptography decryptAppleMessagePayload:message.body
withSignalingKey:TSAccountManager.signalingKey];
NSData *decryptedPayload =
[Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSAccountManager.signalingKey];
if (!decryptedPayload) {
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag);
[self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil;
return;
}
if (!decryptedPayload) {
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag);
[self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil;
return;
OWSSignalServiceProtosEnvelope *envelope =
[OWSSignalServiceProtosEnvelope parseFromData:decryptedPayload];
[self.messageReceiver handleReceivedEnvelope:envelope];
} @catch (NSException *exception) {
OWSProdLogAndFail(@"%@ Received an invalid envelope: %@", self.logTag, exception.debugDescription);
// TODO: Add analytics.
}
OWSSignalServiceProtosEnvelope *envelope = [OWSSignalServiceProtosEnvelope parseFromData:decryptedPayload];
[self.messageReceiver handleReceivedEnvelope:envelope];
dispatch_async(dispatch_get_main_queue(), ^{
[self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil;