From 83e2fbe28c72e44070c4ab89db9ce2ab917aeb94 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 4 Aug 2017 09:33:56 -0400 Subject: [PATCH] Rework where profile key is attached in photos. // FREEBIE --- .../OWSOutgoingSentMessageTranscript.m | 4 +- .../DeviceSyncing/OWSOutgoingSyncMessage.m | 6 +- .../Messages/Interactions/TSOutgoingMessage.h | 5 -- .../Messages/Interactions/TSOutgoingMessage.m | 46 ++-------- .../src/Messages/OWSOutgoingCallMessage.m | 11 ++- .../src/Messages/OWSOutgoingNullMessage.m | 2 - .../src/Messages/TSMessagesManager.m | 35 ++++++-- .../src/Protocols/ProfileManagerProtocol.h | 2 + SignalServiceKit/src/Protocols/ProtoBuf+OWS.h | 39 ++++++++ SignalServiceKit/src/Protocols/ProtoBuf+OWS.m | 88 +++++++++++++++++++ 10 files changed, 179 insertions(+), 59 deletions(-) create mode 100644 SignalServiceKit/src/Protocols/ProtoBuf+OWS.h create mode 100644 SignalServiceKit/src/Protocols/ProtoBuf+OWS.m diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSentMessageTranscript.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSentMessageTranscript.m index 5819de6e2..11e25a15f 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSentMessageTranscript.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSentMessageTranscript.m @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN * Normally this is private, but we need to embed this * data structure within our own. */ -- (OWSSignalServiceProtosDataMessage *)buildDataMessage; +- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *)recipientId; @end @@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN OWSSignalServiceProtosSyncMessageSentBuilder *sentBuilder = [OWSSignalServiceProtosSyncMessageSentBuilder new]; [sentBuilder setTimestamp:self.message.timestamp]; [sentBuilder setDestination:self.message.recipientIdentifier]; - [sentBuilder setMessage:[self.message buildDataMessage]]; + [sentBuilder setMessage:[self.message buildDataMessage:self.message.recipientIdentifier]]; [sentBuilder setExpirationStartTimestamp:self.message.timestamp]; [syncMessageBuilder setSentBuilder:sentBuilder]; diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m index c780eea7a..6f6ea96a0 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSOutgoingSyncMessage.m @@ -5,6 +5,7 @@ #import "OWSOutgoingSyncMessage.h" #import "Cryptography.h" #import "OWSSignalServiceProtos.pb.h" +#import "ProtoBuf+OWS.h" NS_ASSUME_NONNULL_BEGIN @@ -30,7 +31,9 @@ NS_ASSUME_NONNULL_BEGIN // Add a random 1-512 bytes to obscure sync message type size_t paddingBytesLength = arc4random_uniform(512) + 1; builder.padding = [Cryptography generateRandomBytes:paddingBytesLength]; - + + [builder addLocalProfileKey]; + return [builder build]; } @@ -44,7 +47,6 @@ NS_ASSUME_NONNULL_BEGIN { OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new]; [contentBuilder setSyncMessage:[self buildSyncMessage]]; - [self addLocalProfileKeyIfNecessary:contentBuilder recipient:recipient]; return [[contentBuilder build] data]; } diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h index fbff68ae5..ee1c870ed 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.h @@ -178,11 +178,6 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) { - (void)updateWithSentRecipient:(NSString *)contactId transaction:(YapDatabaseReadWriteTransaction *)transaction; - (void)updateWithSentRecipient:(NSString *)contactId; -#pragma mark - - -- (void)addLocalProfileKeyIfNecessary:(OWSSignalServiceProtosContentBuilder *)contentBuilder - recipient:(SignalRecipient *)recipient; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m index 80b8682b1..0a2d0e6e1 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m @@ -7,6 +7,7 @@ #import "OWSOutgoingSyncMessage.h" #import "OWSSignalServiceProtos.pb.h" #import "ProfileManagerProtocol.h" +#import "ProtoBuf+OWS.h" #import "SignalRecipient.h" #import "TSAttachmentStream.h" #import "TSContactThread.h" @@ -454,51 +455,20 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec return builder; } -- (OWSSignalServiceProtosDataMessage *)buildDataMessage +- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *)recipientId { - return [[self dataMessageBuilder] build]; -} - -- (void)addLocalProfileKeyIfNecessary:(OWSSignalServiceProtosContentBuilder *)contentBuilder - recipient:(SignalRecipient *)recipient -{ - OWSAssert(contentBuilder); - OWSAssert(recipient); + OWSAssert(self.thread); + OWSAssert(recipientId.length > 0); - id profileManager = [TextSecureKitEnv sharedEnv].profileManager; - NSData *localProfileKey = profileManager.localProfileKey; - - OWSAssert(localProfileKey.length > 0); - BOOL shouldIncludeProfileKey = NO; - - if ([self isKindOfClass:[OWSOutgoingSyncMessage class]]) { - // Always sync the profile key to linked devices. - shouldIncludeProfileKey = YES; - } else { - OWSAssert(self.thread); - - // For 1:1 threads, we want to include the profile key IFF the - // contact is in the whitelist. - // - // For Group threads, we want to include the profile key IFF the - // recipient OR the group is in the whitelist. - if ([profileManager isUserInProfileWhitelist:recipient.recipientId]) { - shouldIncludeProfileKey = YES; - } else if ([profileManager isThreadInProfileWhitelist:self.thread]) { - shouldIncludeProfileKey = YES; - } - } - - if (shouldIncludeProfileKey) { - [contentBuilder setProfileKey:localProfileKey]; - } + OWSSignalServiceProtosDataMessageBuilder *builder = [self dataMessageBuilder]; + [builder addLocalProfileKeyIfNecessary:self.thread recipientId:recipientId]; + return [builder build]; } - (NSData *)buildPlainTextData:(SignalRecipient *)recipient { OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new]; - contentBuilder.dataMessage = [self buildDataMessage]; - [self addLocalProfileKeyIfNecessary:contentBuilder recipient:recipient]; + contentBuilder.dataMessage = [self buildDataMessage:recipient.recipientId]; return [[contentBuilder build] data]; } diff --git a/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m b/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m index 5e11b23b4..153558dca 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingCallMessage.m @@ -10,6 +10,8 @@ #import "OWSCallIceUpdateMessage.h" #import "OWSCallOfferMessage.h" #import "OWSSignalServiceProtos.pb.h" +#import "ProtoBuf+OWS.h" +#import "SignalRecipient.h" #import "TSContactThread.h" NS_ASSUME_NONNULL_BEGIN @@ -123,13 +125,14 @@ NS_ASSUME_NONNULL_BEGIN - (NSData *)buildPlainTextData:(SignalRecipient *)recipient { + OWSAssert(recipient); + OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new]; - [contentBuilder setCallMessage:[self asProtobuf]]; - [self addLocalProfileKeyIfNecessary:contentBuilder recipient:recipient]; + [contentBuilder setCallMessage:[self buildCallMessage:recipient.recipientId]]; return [[contentBuilder build] data]; } -- (OWSSignalServiceProtosCallMessage *)asProtobuf +- (OWSSignalServiceProtosCallMessage *)buildCallMessage:(NSString *)recipientId { OWSSignalServiceProtosCallMessageBuilder *builder = [OWSSignalServiceProtosCallMessageBuilder new]; @@ -155,6 +158,8 @@ NS_ASSUME_NONNULL_BEGIN [builder setBusy:[self.busyMessage asProtobuf]]; } + [builder addLocalProfileKeyIfNecessary:self.thread recipientId:recipientId]; + return [builder build]; } diff --git a/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m b/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m index 7b6284165..45f8044ac 100644 --- a/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m +++ b/SignalServiceKit/src/Messages/OWSOutgoingNullMessage.m @@ -57,8 +57,6 @@ NS_ASSUME_NONNULL_BEGIN contentBuilder.nullMessage = [nullMessageBuilder build]; - [self addLocalProfileKeyIfNecessary:contentBuilder recipient:recipient]; - return [contentBuilder build].data; } diff --git a/SignalServiceKit/src/Messages/TSMessagesManager.m b/SignalServiceKit/src/Messages/TSMessagesManager.m index 759d4a259..7b53a0938 100644 --- a/SignalServiceKit/src/Messages/TSMessagesManager.m +++ b/SignalServiceKit/src/Messages/TSMessagesManager.m @@ -484,13 +484,6 @@ NS_ASSUME_NONNULL_BEGIN if (envelope.hasContent) { OWSSignalServiceProtosContent *content = [OWSSignalServiceProtosContent parseFromData:plaintextData]; DDLogInfo(@"%@ handling content: ", self.tag, [self descriptionForContent:content]); - - if ([content hasProfileKey]) { - NSData *profileKey = [content profileKey]; - NSString *recipientId = envelope.source; - id profileManager = [TextSecureKitEnv sharedEnv].profileManager; - [profileManager setProfileKey:profileKey forRecipientId:recipientId]; - } if (content.hasSyncMessage) { [self handleIncomingEnvelope:envelope withSyncMessage:content.syncMessage]; @@ -507,6 +500,7 @@ NS_ASSUME_NONNULL_BEGIN OWSSignalServiceProtosDataMessage *dataMessage = [OWSSignalServiceProtosDataMessage parseFromData:plaintextData]; DDLogInfo(@"%@ handling dataMessage: %@", self.tag, [self descriptionForDataMessage:dataMessage]); + [self handleIncomingEnvelope:envelope withDataMessage:dataMessage]; } else { OWSProdInfoWEnvelope([OWSAnalyticsEvents messageManagerErrorEnvelopeNoActionablePayload], envelope); @@ -518,6 +512,13 @@ NS_ASSUME_NONNULL_BEGIN { OWSAssert([NSThread isMainThread]); + if ([dataMessage hasProfileKey]) { + NSData *profileKey = [dataMessage profileKey]; + NSString *recipientId = incomingEnvelope.source; + id profileManager = [TextSecureKitEnv sharedEnv].profileManager; + [profileManager setProfileKey:profileKey forRecipientId:recipientId]; + } + if (dataMessage.hasGroup) { __block BOOL ignoreMessage = NO; [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { @@ -575,6 +576,16 @@ NS_ASSUME_NONNULL_BEGIN - (void)handleIncomingEnvelope:(OWSSignalServiceProtosEnvelope *)incomingEnvelope withCallMessage:(OWSSignalServiceProtosCallMessage *)callMessage { + OWSAssert(incomingEnvelope); + OWSAssert(callMessage); + + if ([callMessage hasProfileKey]) { + NSData *profileKey = [callMessage profileKey]; + NSString *recipientId = incomingEnvelope.source; + id profileManager = [TextSecureKitEnv sharedEnv].profileManager; + [profileManager setProfileKey:profileKey forRecipientId:recipientId]; + } + if (callMessage.hasOffer) { [self.callMessageHandler receivedOffer:callMessage.offer fromCallerId:incomingEnvelope.source]; } else if (callMessage.hasAnswer) { @@ -683,6 +694,16 @@ NS_ASSUME_NONNULL_BEGIN messageSender:self.messageSender networkManager:self.networkManager]; + OWSSignalServiceProtosDataMessage *dataMessage = syncMessage.sent.message; + OWSAssert(dataMessage); + NSString *destination = syncMessage.sent.destination; + if (dataMessage && destination.length > 0 && [dataMessage hasProfileKey]) { + // If we observe a linked device sending our profile key to another + // user, we can infer that that user belongs in our profile whitelist. + id profileManager = [TextSecureKitEnv sharedEnv].profileManager; + [profileManager addUserToProfileWhitelist:destination]; + } + if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message]) { [recordJob runWithAttachmentHandler:^(TSAttachmentStream *attachmentStream) { TSGroupThread *groupThread = diff --git a/SignalServiceKit/src/Protocols/ProfileManagerProtocol.h b/SignalServiceKit/src/Protocols/ProfileManagerProtocol.h index ac1b750ee..897460c6b 100644 --- a/SignalServiceKit/src/Protocols/ProfileManagerProtocol.h +++ b/SignalServiceKit/src/Protocols/ProfileManagerProtocol.h @@ -14,4 +14,6 @@ - (BOOL)isThreadInProfileWhitelist:(TSThread *)thread; +- (void)addUserToProfileWhitelist:(NSString *)recipientId; + @end diff --git a/SignalServiceKit/src/Protocols/ProtoBuf+OWS.h b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.h new file mode 100644 index 000000000..b614090ec --- /dev/null +++ b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "OWSSignalServiceProtos.pb.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TSThread; + +@interface PBGeneratedMessageBuilder (OWS) + +@end + +#pragma mark - + +@interface OWSSignalServiceProtosDataMessageBuilder (OWS) + +- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId; + +@end + +#pragma mark - + +@interface OWSSignalServiceProtosCallMessageBuilder (OWS) + +- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId; + +@end + +#pragma mark - + +@interface OWSSignalServiceProtosSyncMessageBuilder (OWS) + +- (void)addLocalProfileKey; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m new file mode 100644 index 000000000..62431895e --- /dev/null +++ b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "ProfileManagerProtocol.h" +#import "ProtoBuf+OWS.h" +#import "SignalRecipient.h" +#import "TSThread.h" +#import "TextSecureKitEnv.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation PBGeneratedMessageBuilder (OWS) + +- (BOOL)shouldMessageHaveLocalProfileKey:(TSThread *)thread recipientId:(NSString *)recipientId +// recipient:(SignalRecipient *)recipient +{ + OWSAssert(thread); + OWSAssert(recipientId.length > 0); + + id profileManager = [TextSecureKitEnv sharedEnv].profileManager; + + // For 1:1 threads, we want to include the profile key IFF the + // contact is in the whitelist. + // + // For Group threads, we want to include the profile key IFF the + // recipient OR the group is in the whitelist. + if ([profileManager isUserInProfileWhitelist:recipientId]) { + return YES; + } else if ([profileManager isThreadInProfileWhitelist:thread]) { + return YES; + } + + return NO; +} + +- (NSData *)localProfileKey +{ + id profileManager = [TextSecureKitEnv sharedEnv].profileManager; + return profileManager.localProfileKey; +} + +@end + +#pragma mark - + +@implementation OWSSignalServiceProtosDataMessageBuilder (OWS) + +- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId +{ + OWSAssert(thread); + OWSAssert(recipientId.length > 0); + + if ([self shouldMessageHaveLocalProfileKey:thread recipientId:recipientId]) { + [self setProfileKey:self.localProfileKey]; + } +} + +@end + +#pragma mark - + +@implementation OWSSignalServiceProtosCallMessageBuilder (OWS) + +- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId +{ + OWSAssert(thread); + OWSAssert(recipientId.length > 0); + + if ([self shouldMessageHaveLocalProfileKey:thread recipientId:recipientId]) { + [self setProfileKey:self.localProfileKey]; + } +} + +@end + +#pragma mark - + +@implementation OWSSignalServiceProtosSyncMessageBuilder (OWS) + +- (void)addLocalProfileKey +{ + [self setProfileKey:self.localProfileKey]; +} + +@end + +NS_ASSUME_NONNULL_END