pull/228/head
nielsandriesse 5 years ago
parent e7e6023542
commit b89fb68a56

@ -26,16 +26,6 @@ public class DotNetAPI : NSObject {
/// To be overridden by subclasses. /// To be overridden by subclasses.
internal class var authTokenCollection: String { preconditionFailure("authTokenCollection is abstract and must be overridden.") } internal class var authTokenCollection: String { preconditionFailure("authTokenCollection is abstract and must be overridden.") }
private static func getAuthTokenFromDatabase(for server: String) -> String? {
var result: String? = nil
storage.dbReadConnection.read { transaction in
if transaction.hasObject(forKey: server, inCollection: authTokenCollection) {
result = transaction.object(forKey: server, inCollection: authTokenCollection) as? String
}
}
return result
}
internal static func getAuthToken(for server: String) -> Promise<String> { internal static func getAuthToken(for server: String) -> Promise<String> {
if let token = getAuthTokenFromDatabase(for: server) { if let token = getAuthTokenFromDatabase(for: server) {
return Promise.value(token) return Promise.value(token)
@ -49,6 +39,16 @@ public class DotNetAPI : NSObject {
} }
} }
private static func getAuthTokenFromDatabase(for server: String) -> String? {
var result: String? = nil
storage.dbReadConnection.read { transaction in
if transaction.hasObject(forKey: server, inCollection: authTokenCollection) {
result = transaction.object(forKey: server, inCollection: authTokenCollection) as? String
}
}
return result
}
private static func setAuthToken(for server: String, to newValue: String, in transaction: YapDatabaseReadWriteTransaction) { private static func setAuthToken(for server: String, to newValue: String, in transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(newValue, forKey: server, inCollection: authTokenCollection) transaction.setObject(newValue, forKey: server, inCollection: authTokenCollection)
} }

@ -8,12 +8,14 @@ public final class FileServerAPI : DotNetAPI {
private static let attachmentType = "net.app.core.oembed" private static let attachmentType = "net.app.core.oembed"
public static let maxFileSize = 10_000_000 // 10 MB public static let maxFileSize = 10_000_000 // 10 MB
@objc public static let server = "https://file.getsession.org" @objc public static let server = "https://file.getsession.org"
// MARK: Storage // MARK: Storage
override internal class var authTokenCollection: String { return "LokiStorageAuthTokenCollection" } override internal class var authTokenCollection: String { return "LokiStorageAuthTokenCollection" }
// MARK: Device Links // MARK: Device Links
/// - Note: Deprecated.
@objc(getDeviceLinksAssociatedWithHexEncodedPublicKey:) @objc(getDeviceLinksAssociatedWithHexEncodedPublicKey:)
public static func objc_getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> AnyPromise { public static func objc_getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> AnyPromise {
return AnyPromise.from(getDeviceLinks(associatedWith: hexEncodedPublicKey)) return AnyPromise.from(getDeviceLinks(associatedWith: hexEncodedPublicKey))
@ -21,10 +23,13 @@ public final class FileServerAPI : DotNetAPI {
/// Gets the device links associated with the given hex encoded public key from the /// Gets the device links associated with the given hex encoded public key from the
/// server and stores and returns the valid ones. /// server and stores and returns the valid ones.
///
/// - Note: Deprecated.
public static func getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> Promise<Set<DeviceLink>> { public static func getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> Promise<Set<DeviceLink>> {
return getDeviceLinks(associatedWith: [ hexEncodedPublicKey ]) return getDeviceLinks(associatedWith: [ hexEncodedPublicKey ])
} }
/// - Note: Deprecated.
@objc(getDeviceLinksAssociatedWithHexEncodedPublicKeys:) @objc(getDeviceLinksAssociatedWithHexEncodedPublicKeys:)
public static func objc_getDeviceLinks(associatedWith hexEncodedPublicKeys: Set<String>) -> AnyPromise { public static func objc_getDeviceLinks(associatedWith hexEncodedPublicKeys: Set<String>) -> AnyPromise {
return AnyPromise.from(getDeviceLinks(associatedWith: hexEncodedPublicKeys)) return AnyPromise.from(getDeviceLinks(associatedWith: hexEncodedPublicKeys))
@ -32,6 +37,8 @@ public final class FileServerAPI : DotNetAPI {
/// Gets the device links associated with the given hex encoded public keys from the /// Gets the device links associated with the given hex encoded public keys from the
/// server and stores and returns the valid ones. /// server and stores and returns the valid ones.
///
/// - Note: Deprecated.
public static func getDeviceLinks(associatedWith hexEncodedPublicKeys: Set<String>) -> Promise<Set<DeviceLink>> { public static func getDeviceLinks(associatedWith hexEncodedPublicKeys: Set<String>) -> Promise<Set<DeviceLink>> {
let hexEncodedPublicKeysDescription = "[ \(hexEncodedPublicKeys.joined(separator: ", ")) ]" let hexEncodedPublicKeysDescription = "[ \(hexEncodedPublicKeys.joined(separator: ", ")) ]"
print("[Loki] Getting device links for: \(hexEncodedPublicKeysDescription).") print("[Loki] Getting device links for: \(hexEncodedPublicKeysDescription).")
@ -87,7 +94,8 @@ public final class FileServerAPI : DotNetAPI {
} }
}.handlingInvalidAuthTokenIfNeeded(for: server) }.handlingInvalidAuthTokenIfNeeded(for: server)
} }
/// - Note: Deprecated.
public static func setDeviceLinks(_ deviceLinks: Set<DeviceLink>) -> Promise<Void> { public static func setDeviceLinks(_ deviceLinks: Set<DeviceLink>) -> Promise<Void> {
print("[Loki] Updating device links.") print("[Loki] Updating device links.")
return getAuthToken(for: server).then2 { token -> Promise<Void> in return getAuthToken(for: server).then2 { token -> Promise<Void> in
@ -109,6 +117,8 @@ public final class FileServerAPI : DotNetAPI {
} }
/// Adds the given device link to the user's device mapping on the server. /// Adds the given device link to the user's device mapping on the server.
///
/// - Note: Deprecated.
public static func addDeviceLink(_ deviceLink: DeviceLink) -> Promise<Void> { public static func addDeviceLink(_ deviceLink: DeviceLink) -> Promise<Void> {
var deviceLinks: Set<DeviceLink> = [] var deviceLinks: Set<DeviceLink> = []
storage.dbReadConnection.read { transaction in storage.dbReadConnection.read { transaction in
@ -121,6 +131,8 @@ public final class FileServerAPI : DotNetAPI {
} }
/// Removes the given device link from the user's device mapping on the server. /// Removes the given device link from the user's device mapping on the server.
///
/// - Note: Deprecated.
public static func removeDeviceLink(_ deviceLink: DeviceLink) -> Promise<Void> { public static func removeDeviceLink(_ deviceLink: DeviceLink) -> Promise<Void> {
var deviceLinks: Set<DeviceLink> = [] var deviceLinks: Set<DeviceLink> = []
storage.dbReadConnection.read { transaction in storage.dbReadConnection.read { transaction in

@ -14,6 +14,7 @@ public enum OnionRequestAPI {
// MARK: Settings // MARK: Settings
/// The number of snodes (including the guard snode) in a path. /// The number of snodes (including the guard snode) in a path.
private static let pathSize: UInt = 3 private static let pathSize: UInt = 3
public static let pathCount: UInt = 2 public static let pathCount: UInt = 2
private static var guardSnodeCount: UInt { return pathCount } // One per path private static var guardSnodeCount: UInt { return pathCount } // One per path

@ -15,6 +15,7 @@ public final class PublicChatAPI : DotNetAPI {
private static let maxRetryCount: UInt = 4 private static let maxRetryCount: UInt = 4
public static let profilePictureType = "network.loki.messenger.avatar" public static let profilePictureType = "network.loki.messenger.avatar"
@objc public static let publicChatMessageType = "network.loki.messenger.publicChat" @objc public static let publicChatMessageType = "network.loki.messenger.publicChat"
// MARK: Convenience // MARK: Convenience

@ -38,7 +38,7 @@
SSKProtoContentBuilder *contentBuilder = [super prepareCustomContentBuilder:recipient]; SSKProtoContentBuilder *contentBuilder = [super prepareCustomContentBuilder:recipient];
NSError *error; NSError *error;
if (self.kind == LKDeviceLinkMessageKindRequest) { if (self.kind == LKDeviceLinkMessageKindRequest) {
// The slave device attaches a pre key bundle with the request it sends, so that a // The slave device attaches a pre key bundle with the request it sends so that a
// session can be established with the master device. // session can be established with the master device.
PreKeyBundle *preKeyBundle = [OWSPrimaryStorage.sharedManager generatePreKeyBundleForContact:recipient.recipientId]; PreKeyBundle *preKeyBundle = [OWSPrimaryStorage.sharedManager generatePreKeyBundleForContact:recipient.recipientId];
SSKProtoPrekeyBundleMessageBuilder *preKeyBundleMessageBuilder = [SSKProtoPrekeyBundleMessage builderFromPreKeyBundle:preKeyBundle]; SSKProtoPrekeyBundleMessageBuilder *preKeyBundleMessageBuilder = [SSKProtoPrekeyBundleMessage builderFromPreKeyBundle:preKeyBundle];
@ -51,7 +51,7 @@
} }
} else { } else {
// The master device attaches its display name and profile picture URL to the device link // The master device attaches its display name and profile picture URL to the device link
// authorization message, so that the slave device is in sync with these things as soon // authorization message so that the slave device is in sync with these things as soon
// as possible. // as possible.
id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager; id<ProfileManagerProtocol> profileManager = SSKEnvironment.shared.profileManager;
NSString *displayName = profileManager.localProfileName; NSString *displayName = profileManager.localProfileName;

@ -2,8 +2,6 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
// TODO: This is just an ephemeral message with a flag set. Not sure if it needs to be its own type.
NS_SWIFT_NAME(UnlinkDeviceMessage) NS_SWIFT_NAME(UnlinkDeviceMessage)
@interface LKUnlinkDeviceMessage : TSOutgoingMessage @interface LKUnlinkDeviceMessage : TSOutgoingMessage

@ -14,16 +14,16 @@ public class LokiSessionResetImplementation : NSObject, SessionResetProtocol {
public func validatePreKeyForFriendRequestAcceptance(for recipientID: String, whisperMessage: CipherMessage, protocolContext: Any?) throws { public func validatePreKeyForFriendRequestAcceptance(for recipientID: String, whisperMessage: CipherMessage, protocolContext: Any?) throws {
guard let transaction = protocolContext as? YapDatabaseReadTransaction else { guard let transaction = protocolContext as? YapDatabaseReadTransaction else {
print("[Loki] Couldn't verify friend request accepted message because an invalid transaction was provided.") print("[Loki] Invalid transaction.")
return return
} }
guard let preKeyMessage = whisperMessage as? PreKeyWhisperMessage else { return } guard let preKeyMessage = whisperMessage as? PreKeyWhisperMessage else { return }
guard let storedPreKey = storage.getPreKeyRecord(forContact: recipientID, transaction: transaction) else { guard let storedPreKey = storage.getPreKeyRecord(forContact: recipientID, transaction: transaction) else {
print("[Loki] Received a friend request accepted message from a public key for which no pre key bundle was created.") print("[Loki] Missing pre key bundle.")
return return
} }
guard storedPreKey.id == preKeyMessage.prekeyID else { guard storedPreKey.id == preKeyMessage.prekeyID else {
print("[Loki] Received a `PreKeyWhisperMessage` (friend request accepted message) from an unknown source.") print("[Loki] Received a `PreKeyWhisperMessage` from an unknown source.")
throw Error.preKeyIDsDontMatch throw Error.preKeyIDsDontMatch
} }
} }

@ -457,6 +457,7 @@ NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSMessageContentJo
} }
} }
} error:nil]; } error:nil];
return processedJobs; return processedJobs;
} }

@ -220,11 +220,11 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
[self decryptFallbackMessage:envelope [self decryptFallbackMessage:envelope
envelopeData:envelopeData envelopeData:envelopeData
successBlock:^(OWSMessageDecryptResult *result) { successBlock:^(OWSMessageDecryptResult *result) {
OWSLogDebug(@"Decrypted friend request message."); OWSLogDebug(@"Decrypted fallback message.");
successBlock(result, transaction); successBlock(result, transaction);
} }
failureBlock:^(NSError * _Nullable error) { failureBlock:^(NSError * _Nullable error) {
OWSLogError(@"Decrypting friend request message from: %@ failed with error: %@.", OWSLogError(@"Decrypting fallback message from: %@ failed with error: %@.",
envelopeAddress(envelope), envelopeAddress(envelope),
error); error);
failureBlock(); failureBlock();
@ -328,8 +328,8 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
OWSAssertDebug(successBlock); OWSAssertDebug(successBlock);
OWSAssertDebug(failureBlock); OWSAssertDebug(failureBlock);
NSData *encryptedData = envelope.content; NSData *ivAndCiphertext = envelope.content;
if (!encryptedData) { if (ivAndCiphertext == nil) {
OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]); OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]);
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, @"Envelope has no content."); NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, @"Envelope has no content.");
return failureBlock(error); return failureBlock(error);
@ -339,15 +339,15 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
ECKeyPair *identityKeyPair = self.identityManager.identityKeyPair; ECKeyPair *identityKeyPair = self.identityManager.identityKeyPair;
FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientPublicKey:recipientId privateKey:identityKeyPair.privateKey]; FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientPublicKey:recipientId privateKey:identityKeyPair.privateKey];
NSData *_Nullable plaintextData = [[cipher decrypt:encryptedData] removePadding]; NSData *_Nullable plaintext = [[cipher decrypt:ivAndCiphertext] removePadding];
if (!plaintextData) { if (plaintext == nil) {
NSString *errorString = [NSString stringWithFormat:@"Failed to decrypt fallback message from: %@.", recipientId]; NSString *errorDescription = [NSString stringWithFormat:@"Failed to decrypt fallback message from: %@.", recipientId];
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorString); NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorDescription);
return failureBlock(error); return failureBlock(error);
} }
OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
plaintextData:plaintextData plaintextData:plaintext
source:envelope.source source:envelope.source
sourceDevice:envelope.sourceDevice sourceDevice:envelope.sourceDevice
isUDMessage:NO]; isUDMessage:NO];

@ -1284,10 +1284,8 @@ NS_ASSUME_NONNULL_BEGIN
// ======== // ========
} }
// Loki: Handle profile key update if needed
[LKSessionMetaProtocol updateProfileKeyIfNeededForPublicKey:senderMasterPublicKey using:dataMessage]; [LKSessionMetaProtocol updateProfileKeyIfNeededForPublicKey:senderMasterPublicKey using:dataMessage];
// Loki: Handle display name update if needed
[LKSessionMetaProtocol updateDisplayNameIfNeededForPublicKey:senderMasterPublicKey using:dataMessage transaction:transaction]; [LKSessionMetaProtocol updateDisplayNameIfNeededForPublicKey:senderMasterPublicKey using:dataMessage transaction:transaction];
switch (dataMessage.group.type) { switch (dataMessage.group.type) {

@ -398,7 +398,6 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
successBlock:^(OWSMessageDecryptResult *result, YapDatabaseReadWriteTransaction *transaction) { successBlock:^(OWSMessageDecryptResult *result, YapDatabaseReadWriteTransaction *transaction) {
OWSAssertDebug(transaction); OWSAssertDebug(transaction);
// Loki: Don't process any messages from ourself
if ([LKSessionMetaProtocol shouldSkipMessageDecryptResult:result wrappedIn:envelope]) { if ([LKSessionMetaProtocol shouldSkipMessageDecryptResult:result wrappedIn:envelope]) {
dispatch_async(self.serialQueue, ^{ dispatch_async(self.serialQueue, ^{
completion(YES); completion(YES);
@ -448,6 +447,7 @@ NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessin
OWSSingletonAssert(); OWSSingletonAssert();
self = [super init]; self = [super init];
if (!self) { if (!self) {
return self; return self;
} }

@ -790,31 +790,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[sendPromise retainUntilComplete]; [sendPromise retainUntilComplete];
} }
- (void)unregisteredRecipient:(SignalRecipient *)recipient
message:(TSOutgoingMessage *)message
thread:(TSThread *)thread
{
[LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (thread.isGroupThread) {
// Mark as "skipped" group members who no longer have signal accounts.
[message updateWithSkippedRecipient:recipient.recipientId transaction:transaction];
}
if (![SignalRecipient isRegisteredRecipient:recipient.recipientId transaction:transaction]) {
return;
}
[SignalRecipient markRecipientAsUnregistered:recipient.recipientId transaction:transaction];
[[TSInfoMessage userNotRegisteredMessageInThread:thread recipientId:recipient.recipientId]
saveWithTransaction:transaction];
// TODO: Should we deleteAllSessionsForContact here?
// If so, we'll need to avoid doing a prekey fetch every
// time we try to send a message to an unregistered user.
} error:nil];
}
- (nullable NSArray<NSDictionary *> *)deviceMessagesForMessageSend:(OWSMessageSend *)messageSend - (nullable NSArray<NSDictionary *> *)deviceMessagesForMessageSend:(OWSMessageSend *)messageSend
error:(NSError **)errorHandle error:(NSError **)errorHandle
{ {
@ -1243,27 +1218,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}); });
}; };
void (^handle404)(void) = ^{
OWSLogWarn(@"Unregistered recipient: %@.", recipient.uniqueId);
dispatch_async(OWSDispatch.sendingQueue, ^{
if (![messageSend.message isKindOfClass:[OWSOutgoingSyncMessage class]]) {
TSThread *_Nullable thread = messageSend.thread;
OWSAssertDebug(thread);
[self unregisteredRecipient:recipient message:message thread:thread];
}
NSError *error = OWSErrorMakeNoSuchSignalRecipientError();
// No need to retry if the recipient is not registered.
[error setIsRetryable:NO];
// If one member of a group deletes their account,
// the group should ignore errors when trying to send
// messages to this ex-member.
[error setShouldBeIgnoredForGroups:YES];
messageSend.failure(error);
});
};
switch (statusCode) { switch (statusCode) {
case 0: { // Loki case 0: { // Loki
NSError *error; NSError *error;
@ -1285,10 +1239,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[error setIsRetryable:NO]; [error setIsRetryable:NO];
return messageSend.failure(error); return messageSend.failure(error);
} }
case 404: {
handle404();
return;
}
default: default:
retrySend(); retrySend();
break; break;

Loading…
Cancel
Save