From dcae781923136b07a9afedf58f070e5f6e85c0fa Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 4 Apr 2023 10:18:43 +1000 Subject: [PATCH] Fixed a crash due to database reentrancy when generating the users blinded public key --- .../Conversations/ConversationViewModel.swift | 1 + Session/Notifications/AppNotifications.swift | 1 + .../Database/Models/SessionThread.swift | 58 ++++++++++--------- SessionMessagingKit/Messages/Message.swift | 1 + .../SessionThreadViewModel.swift | 2 + 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Session/Conversations/ConversationViewModel.swift b/Session/Conversations/ConversationViewModel.swift index d21d932d0..a5c30bed7 100644 --- a/Session/Conversations/ConversationViewModel.swift +++ b/Session/Conversations/ConversationViewModel.swift @@ -146,6 +146,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { .map { $0.with(recentReactionEmoji: recentReactionEmoji) } .map { viewModel -> SessionThreadViewModel in viewModel.populatingCurrentUserBlindedKey( + db, currentUserBlindedPublicKeyForThisThread: self?.threadData.currentUserBlindedPublicKey ) } diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index 7667d2806..9a8b97a2b 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -236,6 +236,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { let userPublicKey: String = getUserHexEncodedPublicKey(db) let userBlindedKey: String? = SessionThread.getUserHexEncodedBlindedKey( + db, threadId: thread.id, threadVariant: thread.variant ) diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift index f5d743acf..dd7a49528 100644 --- a/SessionMessagingKit/Database/Models/SessionThread.swift +++ b/SessionMessagingKit/Database/Models/SessionThread.swift @@ -317,42 +317,46 @@ public extension SessionThread { } static func getUserHexEncodedBlindedKey( + _ db: Database? = nil, threadId: String, threadVariant: Variant ) -> String? { + guard threadVariant == .openGroup else { return nil } + guard let db: Database = db else { + return Storage.shared.read { db in + getUserHexEncodedBlindedKey(db, threadId: threadId, threadVariant: threadVariant) + } + } + + // Retrieve the relevant open group info + struct OpenGroupInfo: Decodable, FetchableRecord { + let publicKey: String + let server: String + } + guard - threadVariant == .openGroup, - let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?, capabilities: Set) = Storage.shared.read({ db in - struct OpenGroupInfo: Decodable, FetchableRecord { - let publicKey: String? - let server: String? - } - let openGroupInfo: OpenGroupInfo? = try OpenGroup - .filter(id: threadId) - .select(.publicKey, .server) - .asRequest(of: OpenGroupInfo.self) - .fetchOne(db) - - return ( - Identity.fetchUserEd25519KeyPair(db), - openGroupInfo?.publicKey, - (try? Capability - .select(.variant) - .filter(Capability.Columns.openGroupServer == openGroupInfo?.server?.lowercased()) - .asRequest(of: Capability.Variant.self) - .fetchSet(db)) - .defaulting(to: []) - ) - }), - let userEdKeyPair: Box.KeyPair = blindingInfo.edkeyPair, - let publicKey: String = blindingInfo.publicKey, - blindingInfo.capabilities.isEmpty || blindingInfo.capabilities.contains(.blind) + let userEdKeyPair: Box.KeyPair = Identity.fetchUserEd25519KeyPair(db), + let openGroupInfo: OpenGroupInfo = try? OpenGroup + .filter(id: threadId) + .select(.publicKey, .server) + .asRequest(of: OpenGroupInfo.self) + .fetchOne(db) else { return nil } + // Check the capabilities to ensure the SOGS is blinded (or whether we have no capabilities) + let capabilities: Set = (try? Capability + .select(.variant) + .filter(Capability.Columns.openGroupServer == openGroupInfo.server.lowercased()) + .asRequest(of: Capability.Variant.self) + .fetchSet(db)) + .defaulting(to: []) + + guard capabilities.isEmpty || capabilities.contains(.blind) else { return nil } + let sodium: Sodium = Sodium() let blindedKeyPair: Box.KeyPair? = sodium.blindedKeyPair( - serverPublicKey: publicKey, + serverPublicKey: openGroupInfo.publicKey, edKeyPair: userEdKeyPair, genericHash: sodium.getGenericHash() ) diff --git a/SessionMessagingKit/Messages/Message.swift b/SessionMessagingKit/Messages/Message.swift index c6e4555db..d66d85c4f 100644 --- a/SessionMessagingKit/Messages/Message.swift +++ b/SessionMessagingKit/Messages/Message.swift @@ -370,6 +370,7 @@ public extension Message { let userPublicKey: String = getUserHexEncodedPublicKey(db) let blindedUserPublicKey: String? = SessionThread .getUserHexEncodedBlindedKey( + db, threadId: openGroupId, threadVariant: .openGroup ) diff --git a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift index 02e614aeb..022b87893 100644 --- a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift +++ b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift @@ -360,6 +360,7 @@ public extension SessionThreadViewModel { } func populatingCurrentUserBlindedKey( + _ db: Database? = nil, currentUserBlindedPublicKeyForThisThread: String? = nil ) -> SessionThreadViewModel { return SessionThreadViewModel( @@ -411,6 +412,7 @@ public extension SessionThreadViewModel { currentUserBlindedPublicKey: ( currentUserBlindedPublicKeyForThisThread ?? SessionThread.getUserHexEncodedBlindedKey( + db, threadId: self.threadId, threadVariant: self.threadVariant )