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 */; }; 34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E3E5671EC4B19400495BAC /* AudioProgressView.swift */; };
34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */; }; 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0C1EFC235B007F6822 /* DebugUIDiskUsage.m */; };
34E3EF101EFC2684007F6822 /* DebugUIPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E3EF0F1EFC2684007F6822 /* DebugUIPage.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 */; }; 34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */; };
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FD936F1E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.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 */; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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 */, 34DB0BEB2011548A007B313F /* OWSDatabaseConverterTest.h */,
34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */, 34DB0BEC2011548B007B313F /* OWSDatabaseConverterTest.m */,
45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */, 45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */,
34E8A8D02085238900B272B1 /* ProtoParsingTest.m */,
45360B8F1F9527DA00FA666C /* SearcherTest.swift */, 45360B8F1F9527DA00FA666C /* SearcherTest.swift */,
452D1AF02081059C00A67F7F /* StringAdditionsTest.swift */,
B660F6B31C29868000687D6E /* UtilTest.h */, B660F6B31C29868000687D6E /* UtilTest.h */,
B660F6B41C29868000687D6E /* UtilTest.m */, B660F6B41C29868000687D6E /* UtilTest.m */,
452D1AF02081059C00A67F7F /* StringAdditionsTest.swift */,
); );
path = util; path = util;
sourceTree = "<group>"; sourceTree = "<group>";
@ -3360,6 +3363,7 @@
B660F6BB1C29868000687D6E /* OWSContactsManagerTest.m in Sources */, B660F6BB1C29868000687D6E /* OWSContactsManagerTest.m in Sources */,
B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */, B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */,
455AC69E1F4F8B0300134004 /* ImageCacheTest.swift in Sources */, 455AC69E1F4F8B0300134004 /* ImageCacheTest.swift in Sources */,
34E8A8D12085238A00B272B1 /* ProtoParsingTest.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View file

@ -391,8 +391,13 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
aborted = YES; aborted = YES;
return completion(NO); return completion(NO);
} }
OWSSignaliOSProtosBackupSnapshot *_Nullable entities = OWSSignaliOSProtosBackupSnapshot *_Nullable entities;
[OWSSignaliOSProtosBackupSnapshot parseFromData:uncompressedData]; @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) { if (!entities || entities.entity.count < 1) {
DDLogError(@"%@ missing entities.", self.logTag); DDLogError(@"%@ missing entities.", self.logTag);
// Database-related errors are unrecoverable. // 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 - (OWSSignalServiceProtosEnvelope *)envelope
{ {
if (!_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; return _envelope;
} }

View file

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

View file

@ -106,16 +106,17 @@ NS_ASSUME_NONNULL_BEGIN
failureBlockParameter(); 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 { @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) { switch (envelope.type) {
case OWSSignalServiceProtosEnvelopeTypeCiphertext: { case OWSSignalServiceProtosEnvelopeTypeCiphertext: {
[self decryptSecureMessage:envelope [self decryptSecureMessage:envelope
@ -167,7 +168,7 @@ NS_ASSUME_NONNULL_BEGIN
break; break;
} }
} @catch (NSException *exception) { } @catch (NSException *exception) {
DDLogError(@"Received an incorrectly formatted protocol buffer: %@", exception.debugDescription); OWSProdLogAndFail(@"%@ Received an invalid envelope: %@", self.logTag, exception.debugDescription);
OWSProdFail([OWSAnalyticsEvents messageManagerErrorInvalidProtocolMessage]); OWSProdFail([OWSAnalyticsEvents messageManagerErrorInvalidProtocolMessage]);
} }

View file

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

View file

@ -316,7 +316,18 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
AssertOnDispatchQueue(self.serialQueue); AssertOnDispatchQueue(self.serialQueue);
OWSAssert(job); 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 [self.messageDecrypter decryptEnvelope:envelope
successBlock:^(NSData *_Nullable plaintextData, YapDatabaseReadWriteTransaction *transaction) { successBlock:^(NSData *_Nullable plaintextData, YapDatabaseReadWriteTransaction *transaction) {
OWSAssert(transaction); OWSAssert(transaction);

View file

@ -385,21 +385,26 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
__block OWSBackgroundTask *backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__]; __block OWSBackgroundTask *backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@try {
NSData *decryptedPayload = [Cryptography decryptAppleMessagePayload:message.body
withSignalingKey:TSAccountManager.signalingKey];
NSData *decryptedPayload = if (!decryptedPayload) {
[Cryptography decryptAppleMessagePayload:message.body withSignalingKey:TSAccountManager.signalingKey]; DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag);
[self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil;
return;
}
if (!decryptedPayload) { OWSSignalServiceProtosEnvelope *envelope =
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag); [OWSSignalServiceProtosEnvelope parseFromData:decryptedPayload];
[self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil; [self.messageReceiver handleReceivedEnvelope:envelope];
return; } @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(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self sendWebSocketMessageAcknowledgement:message]; [self sendWebSocketMessageAcknowledgement:message];
backgroundTask = nil; backgroundTask = nil;