diff --git a/Podfile.lock b/Podfile.lock index 69667daec..a23e3c1a8 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -268,7 +268,7 @@ CHECKOUT OPTIONS: :commit: b60dc7d58dfc93ca6eafbb3ea5300c6d67ebc69a :git: https://github.com/signalapp/SignalCoreKit.git SignalMetadataKit: - :commit: b493b7b0db57902dc766a50ca97d2202453ba512 + :commit: 56f28fc3a6e35d548d034ef7d0009f233ca0aa62 :git: https://github.com/signalapp/SignalMetadataKit SocketRocket: :commit: 9f9563a83cd8960503074aa8de72206f83fb7a69 diff --git a/Pods b/Pods index 5fface14b..afb050136 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 5fface14b1bed97e4b7686947f1a24953700ac26 +Subproject commit afb050136acfdaec83e2e88e25f56db9af771e2c diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 79b4a1e04..1ae6b2805 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -537,12 +537,18 @@ NS_ASSUME_NONNULL_BEGIN } // Send delivery receipts for "valid data" messages received via UD. - BOOL wasReceivedByUD = envelope.type == SSKProtoEnvelopeTypeUnidentifiedSender; + BOOL wasReceivedByUD = [self wasReceivedByUD:envelope]; if (wasReceivedByUD) { [self.outgoingReceiptManager enqueueDeliveryReceiptForEnvelope:envelope]; } } +- (BOOL)wasReceivedByUD:(SSKProtoEnvelope *)envelope +{ + return ( + envelope.type == SSKProtoEnvelopeTypeUnidentifiedSender && (!envelope.hasSource || envelope.source.length < 1)); +} + - (void)sendGroupInfoRequest:(NSData *)groupId envelope:(SSKProtoEnvelope *)envelope transaction:(YapDatabaseReadWriteTransaction *)transaction @@ -1149,7 +1155,7 @@ NS_ASSUME_NONNULL_BEGIN NSData *groupId = dataMessage.group ? dataMessage.group.id : nil; OWSContact *_Nullable contact = [OWSContacts contactForDataMessage:dataMessage transaction:transaction]; NSNumber *_Nullable serverTimestamp = (envelope.hasServerTimestamp ? @(envelope.serverTimestamp) : nil); - BOOL wasReceivedByUD = envelope.type == SSKProtoEnvelopeTypeUnidentifiedSender; + BOOL wasReceivedByUD = [self wasReceivedByUD:envelope]; if (dataMessage.group.type == SSKProtoGroupContextTypeRequestInfo) { [self handleGroupInfoRequest:envelope dataMessage:dataMessage transaction:transaction]; diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index cc1307622..ea0182de1 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -1044,6 +1044,25 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } } + for (NSDictionary *deviceMessage in deviceMessages) { + NSNumber *_Nullable messageType = deviceMessage[@"type"]; + OWSAssertDebug(messageType); + BOOL hasValidMessageType; + if (messageSend.isUDSend) { + hasValidMessageType = [messageType isEqualToNumber:@(TSUnidentifiedSenderMessageType)]; + } else { + hasValidMessageType = ([messageType isEqualToNumber:@(TSEncryptedWhisperMessageType)] || + [messageType isEqualToNumber:@(TSPreKeyWhisperMessageType)]); + } + + if (!hasValidMessageType) { + OWSFailDebug(@"Invalid message type: %@", messageType); + NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); + [error setIsRetryable:NO]; + return messageSend.failure(error); + } + } + if (deviceMessages.count == 0) { // This might happen: // @@ -1061,15 +1080,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; OWSLogWarn(@"Sending a message with no device messages."); } - // NOTE: canFailoverUDAuth depends on whether or not we're sending a - // sync message because sync messages use different device lists - // for UD-auth and Non-UD-auth requests. - // - // Therefore, for sync messages, we can't use OWSRequestMaker's - // retry/failover logic; we need to use the message sender's retry - // logic that will build a new set of device messages. - BOOL isSyncMessageSend = messageSend.isLocalNumber; - BOOL canFailoverUDAuth = !isSyncMessageSend; OWSRequestMaker *requestMaker = [[OWSRequestMaker alloc] initWithLabel:@"Message Send" requestFactoryBlock:^(SMKUDAccessKey *_Nullable udAccessKey) { return [OWSRequestFactory submitMessageRequestWithRecipient:recipient.recipientId @@ -1089,7 +1099,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } recipientId:recipient.recipientId udAccess:messageSend.udAccess - canFailoverUDAuth:canFailoverUDAuth]; + canFailoverUDAuth:NO]; [[requestMaker makeRequestObjc] .then(^(OWSRequestMakerResult *result) { dispatch_async([OWSDispatch sendingQueue], ^{ @@ -1437,7 +1447,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; // we open a transaction. [self throws_ensureRecipientHasSessionForMessageSend:messageSend deviceId:deviceId]; - __block NSDictionary *messageDict; + __block NSDictionary *_Nullable messageDict; __block NSException *encryptionException; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { @@ -1605,10 +1615,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; }) retainUntilComplete]; } -- (NSDictionary *)throws_encryptedMessageForMessageSend:(OWSMessageSend *)messageSend - deviceId:(NSNumber *)deviceId - plainText:(NSData *)plainText - transaction:(YapDatabaseReadWriteTransaction *)transaction +- (nullable NSDictionary *)throws_encryptedMessageForMessageSend:(OWSMessageSend *)messageSend + deviceId:(NSNumber *)deviceId + plainText:(NSData *)plainText + transaction:(YapDatabaseReadWriteTransaction *)transaction { OWSAssertDebug(messageSend); OWSAssertDebug(deviceId); @@ -1658,6 +1668,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; protocolContext:transaction error:&error]; SCKRaiseIfExceptionWrapperError(error); + if (!serializedMessage || error) { + OWSFailDebug(@"error while UD encrypting message: %@", error); + return nil; + } messageType = TSUnidentifiedSenderMessageType; } else { // This may throw an exception. diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index 94e7448f9..9af915388 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -27,6 +27,7 @@ BOOL IsNSErrorNetworkFailure(NSError *_Nullable error) // This property should only be accessed on udSerialQueue. @property (atomic, readonly) AFHTTPSessionManager *udSessionManager; +@property (atomic, readonly) NSDictionary *udSessionManagerDefaultHeaders; @property (atomic, readonly) dispatch_queue_t udSerialQueue; @@ -139,9 +140,12 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); - (AFHTTPSessionManager *)udSessionManager { if (!_udSessionManager) { - _udSessionManager = [OWSSignalService sharedInstance].signalServiceSessionManager; - _udSessionManager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + AFHTTPSessionManager *udSessionManager = [OWSSignalService sharedInstance].signalServiceSessionManager; + udSessionManager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // NOTE: We could enable HTTPShouldUsePipelining here. + _udSessionManager = udSessionManager; + // Make a copy of the default headers for this session manager. + _udSessionManagerDefaultHeaders = [udSessionManager.requestSerializer.HTTPRequestHeaders copy]; } return _udSessionManager; @@ -169,10 +173,16 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); AFHTTPSessionManager *sessionManager = self.udSessionManager; - // Honor the request's headers. + // Clear all headers so that we don't retain headers from previous requests. for (NSString *headerField in sessionManager.requestSerializer.HTTPRequestHeaders.allKeys.copy) { [sessionManager.requestSerializer setValue:nil forHTTPHeaderField:headerField]; } + // Apply the default headers for this session manager. + for (NSString *headerField in self.udSessionManagerDefaultHeaders) { + NSString *headerValue = self.udSessionManagerDefaultHeaders[headerField]; + [sessionManager.requestSerializer setValue:headerValue forHTTPHeaderField:headerField]; + } + // Honor the request's headers. for (NSString *headerField in request.allHTTPHeaderFields) { NSString *headerValue = request.allHTTPHeaderFields[headerField]; [sessionManager.requestSerializer setValue:headerValue forHTTPHeaderField:headerField];