mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-10-05 23:07:22 +00:00
agent: use double ratchet from the first message in contact addresses, request rejection, RPC (#1831)
* agent: initialize double ratchet from the invitation via contact address (#1829) * rfc: agent support for PRC pattern without duplex connection * update rfc, plan * corrections Co-authored-by: Evgeny <evgeny@poberezkin.com> * split rfcs, add plan * update rfc * update rfc and plan * update plan * add double ratchet keys to address * agent schema * fix version in test * change ContactRequest encoding * fix tests * update plan * tests, refactor * fix compilation * refactor * refactor more * fix * add export * fix * refactor * refactor * update schema * rename * refactor * refactor 2 * comment, type * type * rename * refactor more * move type * refactor * remove comment * diff * refactor * comment * puns * get correct key * rename * add autoincrement * refactor * move * move back * simplify * rename * refactor * tuple * comment * split decryption * refactor * rename * refactor * move * remove createSndQueue * remove comment * remove JoinInvitationReq * simplify * rename * fix * type synonim * getConnData * simplify * move * encoding * version * async join with ratchet keys * fix encoding * rotate address ratchet keys * rename, parameter order * refactor, include ratchet keys into ConnectionRequestUri * simplify * remove records * refactor * rename, encoding * clean up * refactor * compatible * addrKeysE2EVersion * support IKUsePQ for contact addresses * comments, refactor condition * typos --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * agent: contact request rejection and service requests (#1833) * agent: request rejection * implement RPC requests/responses * simplify rpc, test, async * renames * clean up * fix * fix query * set flag at creation * move * command type, schema * rename * refactor * typo Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com> * allow overriding the service request timeout per request * fixes * use SSENT event for service replies * AgentServiceError encoding * sign service requests * add bad signature error * update the plan * clean up * refactor * empty line Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com> * add indices --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com> * update schemas * tryAllErrors * combine queries --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Evgeny @ SimpleX Chat
simplex-chat-agent[bot]
parent
066a93861b
commit
e4e5ce75fa
@@ -18,6 +18,7 @@ module AgentTests.ConnectionRequestTests
|
||||
invConnRequest,
|
||||
) where
|
||||
|
||||
import AgentTests.EqInstances ()
|
||||
import Data.ByteString (ByteString)
|
||||
import Network.HTTP.Types (urlEncode)
|
||||
import Simplex.Messaging.Agent.Protocol
|
||||
@@ -25,7 +26,7 @@ import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.Ratchet
|
||||
import Simplex.Messaging.Encoding
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Protocol (EntityId (..), ProtocolServer (..), QueueMode (..), currentSMPClientVersion, supportedSMPClientVRange, pattern VersionSMPC)
|
||||
import Simplex.Messaging.Protocol (EntityId (..), ProtocolServer (..), QueueMode (..), SubscriptionMode (..), currentSMPClientVersion, supportedSMPClientVRange, pattern VersionSMPC)
|
||||
import Simplex.Messaging.ServiceScheme (ServiceScheme (..))
|
||||
import Simplex.Messaging.Version
|
||||
import Test.Hspec hiding (fit, it)
|
||||
@@ -176,7 +177,7 @@ connectionRequestNoQM :: AConnectionRequestUri
|
||||
connectionRequestNoQM = ACR SCMInvitation $ CRInvitationUri connReqDataNoQM testE2ERatchetParams
|
||||
|
||||
connectionRequestContact :: AConnectionRequestUri
|
||||
connectionRequestContact = ACR SCMContact $ CRContactUri connReqDataContact
|
||||
connectionRequestContact = ACR SCMContact $ CRContactUri connReqDataContact Nothing
|
||||
|
||||
connectionRequestV1 :: AConnectionRequestUri
|
||||
connectionRequestV1 = ACR SCMInvitation $ CRInvitationUri connReqDataV1 testE2ERatchetParams
|
||||
@@ -194,13 +195,16 @@ contactAddress :: AConnectionRequestUri
|
||||
contactAddress = ACR SCMContact $ contactConnRequest
|
||||
|
||||
contactConnRequest :: ConnectionRequestUri 'CMContact
|
||||
contactConnRequest = CRContactUri connReqData
|
||||
contactConnRequest = CRContactUri connReqData Nothing
|
||||
|
||||
contactAddressDR :: AConnectionRequestUri
|
||||
contactAddressDR = ACR SCMContact $ CRContactUri connReqData (Just (RatchetKeyId "0123456789abcdef", testE2ERatchetParams))
|
||||
|
||||
contactAddressV2 :: AConnectionRequestUri
|
||||
contactAddressV2 = ACR SCMContact $ CRContactUri connReqDataV2
|
||||
contactAddressV2 = ACR SCMContact $ CRContactUri connReqDataV2 Nothing
|
||||
|
||||
contactAddressNew :: AConnectionRequestUri
|
||||
contactAddressNew = ACR SCMContact $ CRContactUri connReqDataNew
|
||||
contactAddressNew = ACR SCMContact $ CRContactUri connReqDataNew Nothing
|
||||
|
||||
connectionRequest2queues :: AConnectionRequestUri
|
||||
connectionRequest2queues = ACR SCMInvitation $ CRInvitationUri connReqData {crSmpQueues = [queue, queue]} testE2ERatchetParams
|
||||
@@ -209,16 +213,20 @@ connectionRequest2queuesNew :: AConnectionRequestUri
|
||||
connectionRequest2queuesNew = ACR SCMInvitation $ CRInvitationUri connReqDataNew {crSmpQueues = [queueNew, queueNew]} testE2ERatchetParams
|
||||
|
||||
contactAddress2queues :: AConnectionRequestUri
|
||||
contactAddress2queues = ACR SCMContact $ CRContactUri connReqData {crSmpQueues = [queue, queue]}
|
||||
contactAddress2queues = ACR SCMContact $ CRContactUri connReqData {crSmpQueues = [queue, queue]} Nothing
|
||||
|
||||
contactAddress2queuesNew :: AConnectionRequestUri
|
||||
contactAddress2queuesNew = ACR SCMContact $ CRContactUri connReqDataNew {crSmpQueues = [queueNew, queueNew]}
|
||||
contactAddress2queuesNew = ACR SCMContact $ CRContactUri connReqDataNew {crSmpQueues = [queueNew, queueNew]} Nothing
|
||||
|
||||
connectionRequestClientDataEmpty :: AConnectionRequestUri
|
||||
connectionRequestClientDataEmpty = ACR SCMInvitation $ CRInvitationUri connReqData {crClientData = Just "{}"} testE2ERatchetParams
|
||||
|
||||
contactAddressClientData :: AConnectionRequestUri
|
||||
contactAddressClientData = ACR SCMContact $ CRContactUri connReqData {crClientData = Just "{\"type\":\"group_link\", \"group_link_id\":\"abc\"}"}
|
||||
contactAddressClientData = ACR SCMContact $ CRContactUri connReqData {crClientData = Just "{\"type\":\"group_link\", \"group_link_id\":\"abc\"}"} Nothing
|
||||
|
||||
-- binary encoding is defined only for BinaryConnectionRequestUri; drop the address keys for the round-trip
|
||||
aBinaryConnReq :: AConnectionRequestUri -> ABinaryConnectionRequestUri
|
||||
aBinaryConnReq (ACR m cr) = ABCR m (binaryConnReq cr)
|
||||
|
||||
url :: ByteString -> ByteString
|
||||
url = urlEncode True
|
||||
@@ -267,6 +275,7 @@ connectionRequestTests =
|
||||
connectionRequestV1 #== ("https://simplex.chat/invitation#/?v=1&smp=" <> url queueStr <> "&e2e=" <> testE2ERatchetParamsStrUri)
|
||||
connectionRequestClientDataEmpty #==# ("simplex:/invitation#/?v=2-7&smp=" <> url queueStr <> "&e2e=" <> testE2ERatchetParamsStrUri <> "&data=" <> url "{}")
|
||||
contactAddress #==# ("simplex:/contact#/?v=2-7&smp=" <> url queueStr)
|
||||
contactAddressDR #==# ("simplex:/contact#/?v=2-7&smp=" <> url queueStr <> "&e2e=" <> testE2ERatchetParamsStrUri <> "&rk=MDEyMzQ1Njc4OWFiY2RlZg%3D%3D")
|
||||
contactAddress #== ("https://simplex.chat/contact#/?v=2-7&smp=" <> url queueStr)
|
||||
contactAddress2queues #==# ("simplex:/contact#/?v=2-7&smp=" <> url (queueStr <> ";" <> queueStr))
|
||||
contactAddressNew #==# ("simplex:/contact#/?v=2-7&smp=" <> url queueNewStr)
|
||||
@@ -287,21 +296,21 @@ connectionRequestTests =
|
||||
smpEncodingTest queueNew1NoPort
|
||||
smpEncodingTest queueV1
|
||||
smpEncodingTest queueV1NoPort
|
||||
smpEncodingTest connectionRequest
|
||||
smpEncodingTest (aBinaryConnReq connectionRequest)
|
||||
-- smpEncodingTest connectionRequestNoQM -- this fails, because of queue mode patch
|
||||
smpEncodingTest connectionRequestContact -- this passes because of queue mode patch in ConnReqUriData encoding
|
||||
smpEncodingTest connectionRequest1
|
||||
smpEncodingTest connectionRequest2queues
|
||||
smpEncodingTest connectionRequestNew
|
||||
smpEncodingTest connectionRequestNew1
|
||||
smpEncodingTest connectionRequest2queuesNew
|
||||
smpEncodingTest connectionRequestClientDataEmpty
|
||||
smpEncodingTest contactAddress
|
||||
smpEncodingTest contactAddress2queues
|
||||
smpEncodingTest contactAddressNew
|
||||
smpEncodingTest contactAddress2queuesNew
|
||||
smpEncodingTest contactAddressV2
|
||||
smpEncodingTest contactAddressClientData
|
||||
smpEncodingTest (aBinaryConnReq connectionRequestContact) -- this passes because of queue mode patch in ConnReqUriData encoding
|
||||
smpEncodingTest (aBinaryConnReq connectionRequest1)
|
||||
smpEncodingTest (aBinaryConnReq connectionRequest2queues)
|
||||
smpEncodingTest (aBinaryConnReq connectionRequestNew)
|
||||
smpEncodingTest (aBinaryConnReq connectionRequestNew1)
|
||||
smpEncodingTest (aBinaryConnReq connectionRequest2queuesNew)
|
||||
smpEncodingTest (aBinaryConnReq connectionRequestClientDataEmpty)
|
||||
smpEncodingTest (aBinaryConnReq contactAddress)
|
||||
smpEncodingTest (aBinaryConnReq contactAddress2queues)
|
||||
smpEncodingTest (aBinaryConnReq contactAddressNew)
|
||||
smpEncodingTest (aBinaryConnReq contactAddress2queuesNew)
|
||||
smpEncodingTest (aBinaryConnReq contactAddressV2)
|
||||
smpEncodingTest (aBinaryConnReq contactAddressClientData)
|
||||
it "should serialize / parse short links" $ do
|
||||
CSLContact SLSServer CCTContact srv (LinkKey "0123456789abcdef0123456789abcdef") #==# "https://smp.simplex.im/a#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
|
||||
CSLContact SLSServer CCTGroup srv (LinkKey "0123456789abcdef0123456789abcdef") #==# "https://smp.simplex.im/g#MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY?h=jjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&p=5223&c=1234-w"
|
||||
@@ -343,6 +352,11 @@ connectionRequestTests =
|
||||
Right (inv' :: ConnShortLink 'CMInvitation) <- pure $ strDecode "https://localhost/i#tnUaHYp8saREmyEHR93SBpl8ySHBchOt/LJ1ZQUzxH9Udb0jw5wmJACv5o6oe8e7BsX_hUCUMTSY"
|
||||
shortenShortLink [presetSrv] inv `shouldBe` inv'
|
||||
restoreShortLink [presetSrv] inv' `shouldBe` inv
|
||||
it "should serialize and parse service RPC agent messages" $ do
|
||||
let qInfo = SMPQueueInfo currentSMPClientVersion queueAddr
|
||||
smpEncodingTest $ AgentServiceRequest [qInfo] Nothing "service request payload"
|
||||
smpEncodingTest $ AgentServiceResponse "service response payload"
|
||||
smpEncodingTest $ AgentRejection "rejected: not allowed"
|
||||
where
|
||||
smpEncodingTest :: (Encoding a, Eq a, Show a, HasCallStack) => a -> Expectation
|
||||
smpEncodingTest a = smpDecode (smpEncode a) `shouldBe` Right a
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
module AgentTests.EqInstances where
|
||||
|
||||
import Data.Type.Equality
|
||||
import Simplex.Messaging.Agent.Protocol (ShortLinkCreds (..))
|
||||
import Simplex.Messaging.Agent.Protocol (ABinaryConnectionRequestUri (..), AMessage (..), AMessageReceipt (..), AgentMessage (..), APrivHeader (..), ShortLinkCreds (..))
|
||||
import Simplex.Messaging.Agent.Store
|
||||
import Simplex.Messaging.Client (ProxiedRelay (..))
|
||||
|
||||
@@ -31,3 +31,18 @@ deriving instance Eq ShortLinkCreds
|
||||
deriving instance Show ProxiedRelay
|
||||
|
||||
deriving instance Eq ProxiedRelay
|
||||
|
||||
instance Eq ABinaryConnectionRequestUri where
|
||||
ABCR m cr == ABCR m' cr' = case testEquality m m' of
|
||||
Just Refl -> cr == cr'
|
||||
_ -> False
|
||||
|
||||
deriving instance Show ABinaryConnectionRequestUri
|
||||
|
||||
deriving instance Eq APrivHeader
|
||||
|
||||
deriving instance Eq AMessageReceipt
|
||||
|
||||
deriving instance Eq AMessage
|
||||
|
||||
deriving instance Eq AgentMessage
|
||||
|
||||
@@ -200,7 +200,7 @@ pattern INFO :: ConnInfo -> AEvent 'AEConn
|
||||
pattern INFO connInfo = A.INFO PQSupportOn connInfo
|
||||
|
||||
pattern REQ :: InvitationId -> NonEmpty SMPServer -> ConnInfo -> AEvent e
|
||||
pattern REQ invId srvs connInfo <- A.REQ invId PQSupportOn srvs connInfo
|
||||
pattern REQ invId srvs connInfo <- A.REQ invId PQSupportOn srvs connInfo _
|
||||
|
||||
pattern CON :: AEvent 'AEConn
|
||||
pattern CON = A.CON PQEncOn
|
||||
@@ -283,7 +283,7 @@ inAnyOrder g rs = withFrozenCallStack $ do
|
||||
|
||||
createConnection :: ConnectionModeI c => AgentClient -> UserId -> Bool -> SConnectionMode c -> Maybe CRClientData -> SubscriptionMode -> AE (ConnId, ConnectionRequestUri c)
|
||||
createConnection c userId enableNtfs cMode clientData subMode = do
|
||||
(connId, CCLink cReq _) <- A.createConnection c NRMInteractive userId enableNtfs True cMode Nothing clientData IKPQOn subMode
|
||||
(connId, CCLink cReq _) <- A.createConnection c NRMInteractive userId enableNtfs True cMode Nothing clientData IKPQOn False subMode
|
||||
pure (connId, cReq)
|
||||
|
||||
joinConnection :: AgentClient -> UserId -> Bool -> ConnectionRequestUri c -> ConnInfo -> SubscriptionMode -> AE (ConnId, SndQueueSecured)
|
||||
@@ -310,11 +310,11 @@ deleteConnection c = A.deleteConnection c NRMInteractive
|
||||
deleteConnections :: AgentClient -> [ConnId] -> AE (M.Map ConnId (Either AgentErrorType ()))
|
||||
deleteConnections c = A.deleteConnections c NRMInteractive
|
||||
|
||||
getConnShortLink :: AgentClient -> UserId -> ConnShortLink c -> AE (FixedLinkData c, ConnLinkData c)
|
||||
getConnShortLink :: AgentClient -> UserId -> ConnShortLink c -> AE (FixedLinkData c, ConnLinkData c, ConnectionRequestUri c)
|
||||
getConnShortLink c = A.getConnShortLink c NRMInteractive
|
||||
|
||||
setConnShortLink :: AgentClient -> ConnId -> SConnectionMode c -> UserConnLinkData c -> Maybe CRClientData -> AE (ConnShortLink c)
|
||||
setConnShortLink c = A.setConnShortLink c NRMInteractive
|
||||
setConnShortLink c connId cMode uld cd = A.setConnShortLink c NRMInteractive connId cMode uld cd False Nothing
|
||||
|
||||
suspendConnection :: AgentClient -> ConnId -> AE ()
|
||||
suspendConnection c = A.suspendConnection c NRMInteractive
|
||||
@@ -346,8 +346,40 @@ functionalAPITests ps = do
|
||||
testRatchetMatrix2 ps runAgentClientContactTest
|
||||
describe "Establish duplex connection via contact address, different PQ settings (3 clients)" $ do
|
||||
testPQMatrix3 ps $ runAgentClientContactTestPQ3 True
|
||||
it "should support rejecting contact request" $
|
||||
withSmpServer ps testRejectContactRequest
|
||||
describe "contact address with DR" $ do
|
||||
describe "Establish duplex connection via contact address with DR" $
|
||||
testContactDRMatrix ps
|
||||
describe "Establish duplex connection creating contact address with DR" $ do
|
||||
it "createConnection, IKPQOn" $ runCreateConnectionDRTest_ False IKPQOn PQSupportOn ps
|
||||
it "createConnection, IKUsePQ" $ runCreateConnectionDRTest_ False IKUsePQ PQSupportOn ps
|
||||
it "createConnectionAsync, IKPQOn" $ runCreateConnectionDRTest_ True IKPQOn PQSupportOn ps
|
||||
it "createConnectionAsync, IKUsePQ" $ runCreateConnectionDRTest_ True IKUsePQ PQSupportOn ps
|
||||
it "should preserve address DR keys when the link data is updated" $
|
||||
testAddressUpdatePreservesDRKeys ps
|
||||
it "should rotate address DR keys, keeping old keys for stale requesters until pruned" $
|
||||
testAddressKeyRotation ps
|
||||
it "should add DR keys to an existing address via setConnShortLink" $
|
||||
testAddDRViaSetConnShortLink ps
|
||||
it "should resume DR accept after a transient failure (reuse the send queue and ratchet)" $
|
||||
testAcceptContactDRResumeAfterOffline ps
|
||||
it "should support rejecting contact request" $
|
||||
withSmpServer ps testRejectContactRequest
|
||||
it "should communicate rejection reason via double ratchet" $
|
||||
withSmpServer ps testRejectContactRequestDR
|
||||
it "should communicate rejection reason via double ratchet (async)" $
|
||||
withSmpServer ps testRejectContactRequestDRAsync
|
||||
it "should send a service request and receive the response" $
|
||||
withSmpServer ps testServiceRequestResponse
|
||||
it "should send a service request and receive the response (async reply)" $
|
||||
withSmpServer ps testServiceRequestResponseAsync
|
||||
it "should reject a service request with a reason" $
|
||||
withSmpServer ps testServiceRequestRejected
|
||||
it "should verify a signed service request" $
|
||||
withSmpServer ps testSignedServiceRequest
|
||||
it "should verify a signed service request (async)" $
|
||||
withSmpServer ps testSignedServiceRequestAsync
|
||||
it "should deliver a service response across server outages" $
|
||||
testServiceRequestResilient ps
|
||||
describe "Changing connection user id" $ do
|
||||
it "should change user id for new connections" $ do
|
||||
withSmpServer ps testUpdateConnectionUserId
|
||||
@@ -714,7 +746,7 @@ runAgentClientTest pqSupport sqSecured viaProxy alice bob baseId =
|
||||
runAgentClientTestPQ :: HasCallStack => SndQueueSecured -> Bool -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> AgentMsgId -> IO ()
|
||||
runAgentClientTestPQ sqSecured viaProxy (alice, aPQ) (bob, bPQ) baseId =
|
||||
runRight_ $ do
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing aPQ SMSubscribe
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing aPQ False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True qInfo bPQ
|
||||
sqSecured' <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe
|
||||
liftIO $ sqSecured' `shouldBe` sqSecured
|
||||
@@ -943,11 +975,11 @@ runAgentClientContactTest pqSupport sqSecured viaProxy alice bob baseId =
|
||||
runAgentClientContactTestPQ :: HasCallStack => SndQueueSecured -> Bool -> PQSupport -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> AgentMsgId -> IO ()
|
||||
runAgentClientContactTestPQ sqSecured viaProxy reqPQSupport (alice, aPQ) (bob, bPQ) baseId =
|
||||
runRight_ $ do
|
||||
(_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe
|
||||
(_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True qInfo bPQ
|
||||
sqSecuredJoin <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe
|
||||
liftIO $ sqSecuredJoin `shouldBe` False -- joining via contact address connection
|
||||
("", _, A.REQ invId pqSup' _ "bob's connInfo") <- get alice
|
||||
("", _, A.REQ invId pqSup' _ "bob's connInfo" _) <- get alice
|
||||
liftIO $ pqSup' `shouldBe` reqPQSupport
|
||||
bobId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ)
|
||||
sqSecured' <- acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption aPQ) SMSubscribe
|
||||
@@ -985,9 +1017,218 @@ runAgentClientContactTestPQ sqSecured viaProxy reqPQSupport (alice, aPQ) (bob, b
|
||||
where
|
||||
msgId = subtract baseId . fst
|
||||
|
||||
allowConfirmGreet :: HasCallStack => AgentClient -> ConnId -> AgentClient -> ConnId -> ConfirmationId -> InitialKeys -> PQEncryption -> ExceptT AgentErrorType IO ()
|
||||
allowConfirmGreet alice bobId bob aliceId confId addrIK pqEnc = do
|
||||
allowConnection bob aliceId confId "bob's connInfo"
|
||||
get alice ##> ("", bobId, A.INFO (CR.connPQEncryption addrIK) "bob's connInfo")
|
||||
get alice ##> ("", bobId, A.CON pqEnc)
|
||||
get bob ##> ("", aliceId, A.CON pqEnc)
|
||||
exchangeGreetings_ pqEnc alice bobId bob aliceId
|
||||
|
||||
-- DR-advertising contact address, across accept/join modes, InitialKeys, and joiner PQ
|
||||
runAgentClientContactDRTest_ :: HasCallStack => Bool -> Bool -> InitialKeys -> Bool -> PQSupport -> (ASrvTransport, AStoreType) -> IO ()
|
||||
runAgentClientContactDRTest_ asyncAccept asyncJoin addrIK useDR bPQ ps = withSmpServer ps $ withAgentClients2 $ \alice bob -> do
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
let userCtData = UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
userLinkData = UserContactLinkData userCtData
|
||||
pqEnc = PQEncryption $ pqConnectionMode addrIK bPQ
|
||||
runRight_ $ do
|
||||
(ccLink@(CCLink _ (Just shortLink)), preparedParams) <- A.prepareConnectionLink alice 1 rootKey linkEntId True Nothing addrIK True Nothing
|
||||
_ <- A.createConnectionForLink alice NRMInteractive 1 True ccLink preparedParams userLinkData SMSubscribe
|
||||
(_, ContactLinkData _ userCtData', connReq') <- getConnShortLink bob 1 shortLink
|
||||
-- the advertised bundle carries a KEM only for IKUsePQ (PQ from message 1)
|
||||
liftIO $ case ratchetKeys userCtData' of
|
||||
Just (_, CR.E2ERatchetParamsUri _ _ _ kem_) ->
|
||||
isJust kem_ `shouldBe` supportPQ (CR.initialPQEncryption False addrIK)
|
||||
Nothing -> expectationFailure "address must advertise DR ratchet keys"
|
||||
-- classic (non-DR) join drops the address keys from the request
|
||||
let connReqJoin = if useDR then connReq' else case connReq' of CRContactUri d _ -> CRContactUri d Nothing
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True connReqJoin bPQ
|
||||
if asyncJoin
|
||||
then do
|
||||
A.joinConnectionAsync bob "join" False aliceId True connReqJoin "bob's connInfo" bPQ SMSubscribe
|
||||
get bob =##> \case ("join", c, A.JOINED sqSecured) -> c == aliceId && not sqSecured; _ -> False
|
||||
else do
|
||||
sqSecuredJoin <- A.joinConnection bob NRMInteractive 1 aliceId True connReqJoin "bob's connInfo" bPQ SMSubscribe
|
||||
liftIO $ sqSecuredJoin `shouldBe` False
|
||||
("", _, A.REQ invId reqPQ _ "bob's connInfo" _) <- get alice
|
||||
liftIO $ reqPQ `shouldBe` PQSupportOn
|
||||
bobId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption addrIK)
|
||||
if asyncAccept
|
||||
then do
|
||||
acceptContactAsync alice "accept" bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
get alice =##> \case ("accept", c, A.JOINED _) -> c == bobId; _ -> False
|
||||
else void $ acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
("", _, A.CONF confId confPQ _ "alice's connInfo") <- get bob
|
||||
liftIO $ confPQ `shouldBe` bPQ
|
||||
allowConfirmGreet alice bobId bob aliceId confId addrIK pqEnc
|
||||
|
||||
-- DR advertising via createConnection (sync) and createConnectionAsync (async NEW), reaching newRcvConnSrv
|
||||
runCreateConnectionDRTest_ :: HasCallStack => Bool -> InitialKeys -> PQSupport -> (ASrvTransport, AStoreType) -> IO ()
|
||||
runCreateConnectionDRTest_ asyncNew addrIK bPQ ps = withSmpServer ps $ withAgentClients2 $ \alice bob -> do
|
||||
let userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
pqEnc = PQEncryption $ pqConnectionMode addrIK bPQ
|
||||
runRight_ $ do
|
||||
connReq <-
|
||||
if asyncNew
|
||||
then do
|
||||
addrConnId <- prepareConnectionToCreate alice 1 True SCMContact (CR.connPQEncryption addrIK)
|
||||
createConnectionAsync alice "1" addrConnId True SCMContact addrIK True SMSubscribe
|
||||
("1", _, INV (ACR SCMContact cReq)) <- get alice
|
||||
pure cReq
|
||||
else do
|
||||
(_, CCLink cReq _) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just userLinkData) Nothing addrIK True SMSubscribe
|
||||
pure cReq
|
||||
let CRContactUri _ addrKeys_ = connReq
|
||||
liftIO $ case addrKeys_ of
|
||||
Just (_, CR.E2ERatchetParamsUri _ _ _ kem_) -> isJust kem_ `shouldBe` supportPQ (CR.initialPQEncryption False addrIK)
|
||||
Nothing -> expectationFailure "createConnection must advertise DR ratchet keys"
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True connReq bPQ
|
||||
void $ A.joinConnection bob NRMInteractive 1 aliceId True connReq "bob's connInfo" bPQ SMSubscribe
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
bobId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption addrIK)
|
||||
void $ acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
("", _, A.CONF confId _ _ "alice's connInfo") <- get bob
|
||||
allowConfirmGreet alice bobId bob aliceId confId addrIK pqEnc
|
||||
|
||||
testContactDRMatrix :: HasCallStack => (ASrvTransport, AStoreType) -> Spec
|
||||
testContactDRMatrix ps = do
|
||||
describe "DR join (ratchet from the invitation)" $ drRows False True False
|
||||
describe "classic join, ratchet keys ignored" $ drRows False False False
|
||||
describe "DR join, async accept (JOIN command)" $ drRows True True False
|
||||
describe "DR join, async join (JOIN command)" $ drRows False True True
|
||||
where
|
||||
drRows asyncAccept useDR asyncJoin = do
|
||||
it "IKPQOff, dh join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKPQOff useDR PQSupportOff ps
|
||||
it "IKPQOff, pq join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKPQOff useDR PQSupportOn ps
|
||||
it "IKPQOn, dh join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKPQOn useDR PQSupportOff ps
|
||||
it "IKPQOn, pq join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKPQOn useDR PQSupportOn ps
|
||||
it "IKUsePQ, dh join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKUsePQ useDR PQSupportOff ps
|
||||
it "IKUsePQ, pq join" $ runAgentClientContactDRTest_ asyncAccept asyncJoin IKUsePQ useDR PQSupportOn ps
|
||||
|
||||
joinContactDR :: HasCallStack => AgentClient -> AgentClient -> ConnectionRequestUri 'CMContact -> InitialKeys -> PQEncryption -> ExceptT AgentErrorType IO ()
|
||||
joinContactDR alice requester connReq addrIK pqEnc = do
|
||||
aliceId <- A.prepareConnectionToJoin requester 1 True connReq PQSupportOn
|
||||
void $ A.joinConnection requester NRMInteractive 1 aliceId True connReq "bob's connInfo" PQSupportOn SMSubscribe
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
reqId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption addrIK)
|
||||
void $ acceptContact alice 1 reqId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
("", _, A.CONF confId _ _ "alice's connInfo") <- get requester
|
||||
allowConfirmGreet alice reqId requester aliceId confId addrIK pqEnc
|
||||
|
||||
testAddressKeyRotation :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testAddressKeyRotation ps = withSmpServer ps $ withAgentClients3 $ \alice bob carol -> do
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
let addrIK = IKPQOn
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
connIK = IKLinkPQ (CR.connPQEncryption addrIK)
|
||||
pqEnc = PQEncryption $ pqConnectionMode addrIK PQSupportOn
|
||||
runRight_ $ do
|
||||
(ccLink@(CCLink _ (Just shortLink)), preparedParams) <- A.prepareConnectionLink alice 1 rootKey linkEntId True Nothing connIK True Nothing
|
||||
addrConnId <- A.createConnectionForLink alice NRMInteractive 1 True ccLink preparedParams userLinkData SMSubscribe
|
||||
(_, ContactLinkData _ ctData1, connReq1) <- getConnShortLink bob 1 shortLink
|
||||
let key1 = ratchetKeys ctData1
|
||||
liftIO $ key1 `shouldSatisfy` isJust
|
||||
void $ A.setConnShortLink alice NRMInteractive addrConnId SCMContact userLinkData Nothing True (Just addrIK)
|
||||
(_, ContactLinkData _ ctData2, connReq2) <- getConnShortLink carol 1 shortLink
|
||||
let key2 = ratchetKeys ctData2
|
||||
liftIO $ (key1 == key2) `shouldBe` False
|
||||
joinContactDR alice bob connReq1 addrIK pqEnc
|
||||
joinContactDR alice carol connReq2 addrIK pqEnc
|
||||
void $ A.setConnShortLink alice NRMInteractive addrConnId SCMContact userLinkData Nothing True (Just addrIK)
|
||||
void $ A.setConnShortLink alice NRMInteractive addrConnId SCMContact userLinkData Nothing True (Just addrIK)
|
||||
aId <- A.prepareConnectionToJoin bob 1 True connReq1 PQSupportOn
|
||||
void $ A.joinConnection bob NRMInteractive 1 aId True connReq1 "bob's connInfo" PQSupportOn SMSubscribe
|
||||
get alice =##> \case ("", _, A.ERR _) -> True; _ -> False
|
||||
|
||||
testAddDRViaSetConnShortLink :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testAddDRViaSetConnShortLink ps = withSmpServer ps $ withAgentClients2 $ \alice bob -> do
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
let addrIK = IKPQOn
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
connIK = IKLinkPQ (CR.connPQEncryption addrIK)
|
||||
runRight_ $ do
|
||||
(ccLink@(CCLink _ (Just shortLink)), preparedParams) <- A.prepareConnectionLink alice 1 rootKey linkEntId True Nothing connIK False Nothing
|
||||
addrConnId <- A.createConnectionForLink alice NRMInteractive 1 True ccLink preparedParams userLinkData SMSubscribe
|
||||
(_, ContactLinkData _ cd0, _) <- getConnShortLink bob 1 shortLink
|
||||
liftIO $ ratchetKeys cd0 `shouldBe` Nothing
|
||||
void $ A.setConnShortLink alice NRMInteractive addrConnId SCMContact userLinkData Nothing False (Just addrIK)
|
||||
(_, ContactLinkData _ cd1, _) <- getConnShortLink bob 1 shortLink
|
||||
liftIO $ ratchetKeys cd1 `shouldSatisfy` isJust
|
||||
|
||||
-- updating a DR address's link data must preserve the stored ratchet keys
|
||||
testAddressUpdatePreservesDRKeys :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testAddressUpdatePreservesDRKeys ps = withSmpServer ps $ withAgentClients2 $ \alice bob -> do
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
let addrIK = IKPQOn
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "original", ratchetKeys = Nothing}
|
||||
connIK = IKLinkPQ (CR.connPQEncryption addrIK)
|
||||
bPQ = PQSupportOn
|
||||
pqEnc = PQEncryption $ pqConnectionMode addrIK bPQ
|
||||
runRight_ $ do
|
||||
(ccLink@(CCLink _ (Just shortLink)), preparedParams) <- A.prepareConnectionLink alice 1 rootKey linkEntId True Nothing connIK True Nothing
|
||||
addrConnId <- A.createConnectionForLink alice NRMInteractive 1 True ccLink preparedParams (UserContactLinkData userCtData) SMSubscribe
|
||||
(_, ContactLinkData _ published, _) <- getConnShortLink bob 1 shortLink
|
||||
liftIO $ ratchetKeys published `shouldSatisfy` isJust
|
||||
-- update passing ratchetKeys = Nothing; the stored keys must be preserved
|
||||
let updatedCtData = userCtData {userData = UserLinkData "updated", ratchetKeys = Nothing}
|
||||
shortLink' <- setConnShortLink alice addrConnId SCMContact (UserContactLinkData updatedCtData) Nothing
|
||||
liftIO $ shortLink' `shouldBe` shortLink
|
||||
(_, ContactLinkData _ updated, connReq') <- getConnShortLink bob 1 shortLink
|
||||
liftIO $ ratchetKeys updated `shouldBe` ratchetKeys published
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True connReq' bPQ
|
||||
sqSecuredJoin <- A.joinConnection bob NRMInteractive 1 aliceId True connReq' "bob's connInfo" bPQ SMSubscribe
|
||||
liftIO $ sqSecuredJoin `shouldBe` False
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
bobId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption addrIK)
|
||||
_ <- acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
("", _, A.CONF confId _ _ "alice's connInfo") <- get bob
|
||||
allowConfirmGreet alice bobId bob aliceId confId addrIK pqEnc
|
||||
|
||||
-- a DR accept that fails at the network step after committing send queue + ratchet must resume on retry
|
||||
testAcceptContactDRResumeAfterOffline :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testAcceptContactDRResumeAfterOffline ps = withAgentClients2 $ \alice bob -> do
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
let addrIK = IKPQOn
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "u", ratchetKeys = Nothing}
|
||||
connIK = IKLinkPQ (CR.connPQEncryption addrIK)
|
||||
pqEnc = PQEncryption $ pqConnectionMode addrIK PQSupportOn
|
||||
-- set up the DR address, bob joins, alice receives REQ and pre-creates the accept connection (server up)
|
||||
(bobId, invId, aliceId) <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $ do
|
||||
(ccLink@(CCLink _ (Just shortLink)), preparedParams) <- A.prepareConnectionLink alice 1 rootKey linkEntId True Nothing connIK True Nothing
|
||||
_ <- A.createConnectionForLink alice NRMInteractive 1 True ccLink preparedParams (UserContactLinkData userCtData) SMSubscribe
|
||||
(_, _, connReq') <- getConnShortLink bob 1 shortLink
|
||||
aId <- A.prepareConnectionToJoin bob 1 True connReq' PQSupportOn
|
||||
_ <- A.joinConnection bob NRMInteractive 1 aId True connReq' "bob's connInfo" PQSupportOn SMSubscribe
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
bId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption addrIK)
|
||||
pure (bId, invId, aId)
|
||||
("", "", DOWN _ _) <- nGet alice
|
||||
("", "", DOWN _ _) <- nGet bob
|
||||
-- server is down: the accept commits the send queue + ratchet (DB-local) then fails at the network step
|
||||
Left (BROKER _ (NETWORK _)) <- runExceptT $ acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
-- server is back: retrying the same accept must reuse the committed state and complete the handshake
|
||||
withSmpServerStoreLogOn ps testPort $ \_ -> runRight_ $ do
|
||||
("", "", UP _ _) <- nGet alice
|
||||
("", "", UP _ _) <- nGet bob
|
||||
liftIO $ threadDelay 250000
|
||||
_ <- acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption addrIK) SMSubscribe
|
||||
("", _, A.CONF confId _ _ "alice's connInfo") <- get bob
|
||||
allowConfirmGreet alice bobId bob aliceId confId addrIK pqEnc
|
||||
|
||||
runAgentClientContactTestPQ3 :: HasCallStack => Bool -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> (AgentClient, PQSupport) -> AgentMsgId -> IO ()
|
||||
runAgentClientContactTestPQ3 viaProxy (alice, aPQ) (bob, bPQ) (tom, tPQ) baseId = runRight_ $ do
|
||||
(_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe
|
||||
(_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ False SMSubscribe
|
||||
(bAliceId, bobId, abPQEnc) <- connectViaContact bob bPQ qInfo
|
||||
sentMessages abPQEnc alice bobId bob bAliceId
|
||||
(tAliceId, tomId, atPQEnc) <- connectViaContact tom tPQ qInfo
|
||||
@@ -998,7 +1239,7 @@ runAgentClientContactTestPQ3 viaProxy (alice, aPQ) (bob, bPQ) (tom, tPQ) baseId
|
||||
aId <- A.prepareConnectionToJoin b 1 True qInfo pq
|
||||
sqSecuredJoin <- A.joinConnection b NRMInteractive 1 aId True qInfo "bob's connInfo" pq SMSubscribe
|
||||
liftIO $ sqSecuredJoin `shouldBe` False -- joining via contact address connection
|
||||
("", _, A.REQ invId pqSup' _ "bob's connInfo") <- get alice
|
||||
("", _, A.REQ invId pqSup' _ "bob's connInfo" _) <- get alice
|
||||
liftIO $ pqSup' `shouldBe` PQSupportOn
|
||||
bId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ)
|
||||
sqSecuredAccept <- acceptContact alice 1 bId True invId "alice's connInfo" (CR.connPQEncryption aPQ) SMSubscribe
|
||||
@@ -1040,14 +1281,141 @@ noMessages_ ingoreQCONT c err = tryGet `shouldReturn` ()
|
||||
testRejectContactRequest :: HasCallStack => IO ()
|
||||
testRejectContactRequest =
|
||||
withAgentClients2 $ \alice bob -> runRight_ $ do
|
||||
(_addrConnId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
(_addrConnId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn
|
||||
sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe
|
||||
liftIO $ sqSecured `shouldBe` False -- joining via contact address connection
|
||||
("", _, A.REQ invId PQSupportOn _ "bob's connInfo") <- get alice
|
||||
rejectContact alice invId
|
||||
("", _, A.REQ invId PQSupportOn _ "bob's connInfo" _) <- get alice
|
||||
Left (A.CMD PROHIBITED _) <- tryError $ rejectContact alice NRMInteractive 1 invId (Just "no rejection without double ratchet")
|
||||
rejectContact alice NRMInteractive 1 invId Nothing
|
||||
liftIO $ noMessages bob "nothing delivered to bob"
|
||||
|
||||
testRejectContactRequestDR :: HasCallStack => IO ()
|
||||
testRejectContactRequestDR =
|
||||
withAgentClients2 $ \alice bob -> runRight_ $ do
|
||||
let userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just userLinkData) Nothing IKPQOn True SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True connReq PQSupportOn
|
||||
void $ A.joinConnection bob NRMInteractive 1 aliceId True connReq "bob's connInfo" PQSupportOn SMSubscribe
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
rejectContact alice NRMInteractive 1 invId (Just "not now")
|
||||
("", _, A.RJCT "not now") <- get bob
|
||||
pure ()
|
||||
|
||||
testRejectContactRequestDRAsync :: HasCallStack => IO ()
|
||||
testRejectContactRequestDRAsync =
|
||||
withAgentClients2 $ \alice bob -> runRight_ $ do
|
||||
let userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just userLinkData) Nothing IKPQOn True SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True connReq PQSupportOn
|
||||
void $ A.joinConnection bob NRMInteractive 1 aliceId True connReq "bob's connInfo" PQSupportOn SMSubscribe
|
||||
("", _, A.REQ invId _ _ "bob's connInfo" _) <- get alice
|
||||
rejectContactAsync alice "1" 1 invId (Just "not now")
|
||||
("", _, A.RJCT "not now") <- get bob
|
||||
pure ()
|
||||
|
||||
serviceUserLinkData :: UserConnLinkData 'CMContact
|
||||
serviceUserLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = UserLinkData "test user data", ratchetKeys = Nothing}
|
||||
|
||||
testServiceRequestResponse :: HasCallStack => IO ()
|
||||
testServiceRequestResponse =
|
||||
withAgentClients2 $ \service client -> runRight_ $ do
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
resp <- liftIO $ fst <$> concurrently
|
||||
(runRight $ sendServiceRequest client NRMInteractive 1 connReq Nothing Nothing "service request")
|
||||
(runRight_ $ do
|
||||
("", _, SREQ invId _ "service request") <- get service
|
||||
replyConnId <- sendServiceReply service NRMInteractive 1 invId "service response"
|
||||
("", sentConnId, A.SSENT _ _) <- get service
|
||||
liftIO $ sentConnId `shouldBe` replyConnId)
|
||||
liftIO $ resp `shouldBe` "service response"
|
||||
liftIO $ threadDelay 250000 -- let the async teardown of the reply queues settle before dispose
|
||||
|
||||
testServiceRequestResponseAsync :: HasCallStack => IO ()
|
||||
testServiceRequestResponseAsync =
|
||||
withAgentClients2 $ \service client -> runRight_ $ do
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
resp <- liftIO $ fst <$> concurrently
|
||||
(runRight $ sendServiceRequest client NRMInteractive 1 connReq Nothing Nothing "service request")
|
||||
(runRight_ $ do
|
||||
("", _, SREQ invId _ "service request") <- get service
|
||||
replyConnId <- sendServiceReplyAsync service "1" 1 invId "service response"
|
||||
("", sentConnId, A.SSENT _ _) <- get service
|
||||
liftIO $ sentConnId `shouldBe` replyConnId)
|
||||
liftIO $ resp `shouldBe` "service response"
|
||||
liftIO $ threadDelay 250000 -- let the async teardown of the reply queues settle before dispose
|
||||
|
||||
testServiceRequestRejected :: HasCallStack => IO ()
|
||||
testServiceRequestRejected =
|
||||
withAgentClients2 $ \service client -> runRight_ $ do
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
resp <- liftIO $ fst <$> concurrently
|
||||
(runExceptT $ sendServiceRequest client NRMInteractive 1 connReq Nothing Nothing "service request")
|
||||
(runRight_ $ do
|
||||
("", _, SREQ invId _ "service request") <- get service
|
||||
rejectServiceRequest service NRMInteractive 1 invId (Just "not allowed"))
|
||||
liftIO $ resp `shouldBe` Left (AGENT (A_SERVICE (ASERejected "not allowed")))
|
||||
liftIO $ threadDelay 250000 -- let the async teardown of the reply queues settle before dispose
|
||||
|
||||
testSignedServiceRequest :: HasCallStack => IO ()
|
||||
testSignedServiceRequest =
|
||||
withAgentClients2 $ \service client -> runRight_ $ do
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
g <- liftIO C.newRandom
|
||||
(signPub, signPriv) <- liftIO $ atomically $ C.generateKeyPair g
|
||||
resp <- liftIO $ fst <$> concurrently
|
||||
(runRight $ sendServiceRequest client NRMInteractive 1 connReq Nothing (Just signPriv) "signed request")
|
||||
(runRight_ $ do
|
||||
("", _, SREQ invId sigKey_ "signed request") <- get service
|
||||
liftIO $ sigKey_ `shouldBe` Just signPub
|
||||
void $ sendServiceReply service NRMInteractive 1 invId "service response")
|
||||
liftIO $ resp `shouldBe` "service response"
|
||||
liftIO $ threadDelay 250000 -- let the async teardown of the reply queues settle before dispose
|
||||
|
||||
testSignedServiceRequestAsync :: HasCallStack => IO ()
|
||||
testSignedServiceRequestAsync =
|
||||
withAgentClients2 $ \service client -> runRight_ $ do
|
||||
(_addrConnId, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
g <- liftIO C.newRandom
|
||||
(signPub, signPriv) <- liftIO $ atomically $ C.generateKeyPair g
|
||||
resp <- liftIO $ fst <$> concurrently
|
||||
(runRight $ sendServiceRequestAsync client 1 connReq Nothing (Just signPriv) "signed request")
|
||||
(runRight_ $ do
|
||||
("", _, SREQ invId sigKey_ "signed request") <- get service
|
||||
liftIO $ sigKey_ `shouldBe` Just signPub
|
||||
void $ sendServiceReply service NRMInteractive 1 invId "service response")
|
||||
liftIO $ resp `shouldBe` "service response"
|
||||
liftIO $ threadDelay 250000 -- let the async teardown of the reply queues settle before dispose
|
||||
|
||||
-- server down, send, up, receive, down, reply, up, receive response.
|
||||
-- The request send retries the outage (bounded by serviceRequestTimeout) until the server is back; the reply is
|
||||
-- queued while the server is down and delivered on reconnect (async reply via ICReplyDel); the blocking call receives it.
|
||||
testServiceRequestResilient :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testServiceRequestResilient ps = withAgentClients2 $ \service client -> do
|
||||
-- server up: create the service address
|
||||
connReq <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $ do
|
||||
(_, CCLink connReq _) <- A.createConnection service NRMInteractive 1 True True SCMContact (Just serviceUserLinkData) Nothing IKPQOn True SMSubscribe
|
||||
pure connReq
|
||||
("", "", DOWN _ _) <- nGet service
|
||||
-- server down: the async send is enqueued as a retried JOIN command and blocks for the response
|
||||
reqAsync <- async $ runExceptT $ sendServiceRequestAsync client 1 connReq Nothing Nothing "resilient request"
|
||||
threadDelay 500000 -- let the enqueued send retry against the down server before bringing it up
|
||||
-- server up: the request is delivered and the service receives it
|
||||
invId <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $ do
|
||||
("", "", UP _ _) <- nGet service
|
||||
("", _, SREQ invId _ "resilient request") <- get service
|
||||
pure invId :: ExceptT AgentErrorType IO InvitationId
|
||||
("", "", DOWN _ _) <- nGet service
|
||||
-- server down: the service replies; the async reply is enqueued and retried until the server is back
|
||||
replyConnId <- runRight $ sendServiceReplyAsync service "1" 1 invId "resilient response"
|
||||
-- server up: the reply is delivered, the requester's blocking call returns the response, the service gets SENT
|
||||
resp <- withSmpServerStoreLogOn ps testPort $ \_ -> do
|
||||
("", "", UP _ _) <- nGet service
|
||||
("", sentConnId, A.SSENT _ _) <- get service
|
||||
sentConnId `shouldBe` replyConnId
|
||||
wait reqAsync
|
||||
resp `shouldBe` Right "resilient response"
|
||||
|
||||
testUpdateConnectionUserId :: HasCallStack => IO ()
|
||||
testUpdateConnectionUserId =
|
||||
withAgentClients2 $ \alice bob -> runRight_ $ do
|
||||
@@ -1305,7 +1673,7 @@ testContactErrors ps restart = do
|
||||
Right r -> error $ "unexpected result " <> show r
|
||||
Left _ -> putStrLn "retrying send" >> threadDelay 200000 >> loopSend
|
||||
loopSend
|
||||
("", _, A.REQ invId PQSupportOn _ "bob's connInfo") <- get a
|
||||
("", _, A.REQ invId PQSupportOn _ "bob's connInfo" _) <- get a
|
||||
pure invId
|
||||
("", "", DOWN _ [_]) <- nGet a
|
||||
bId <- runRight $ A.prepareConnectionToAccept a 1 True invId PQSupportOn
|
||||
@@ -1367,13 +1735,13 @@ testInvitationShortLink viaProxy a b =
|
||||
withAgent 3 agentCfg initAgentServers testDB3 $ \c -> do
|
||||
let userData = UserLinkData "some user data"
|
||||
newLinkData = UserInvLinkData userData
|
||||
(bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe
|
||||
(FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ False SMSubscribe
|
||||
(_, connData', connReq') <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
linkUserData connData' `shouldBe` userData
|
||||
-- same user can get invitation link again
|
||||
(FixedLinkData {linkConnReq = connReq2}, connData2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
(_, connData2, connReq2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
connReq2 `shouldBe` connReq
|
||||
linkUserData connData2 `shouldBe` userData
|
||||
-- another user cannot get the same invitation link
|
||||
@@ -1403,15 +1771,15 @@ testInvitationShortLinkPrev viaProxy sndSecure a b = runRight_ $ do
|
||||
let userData = UserLinkData "some user data"
|
||||
newLinkData = UserInvLinkData userData
|
||||
-- can't create short link with previous version
|
||||
(bId, CCLink connReq Nothing) <- A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKPQOn SMSubscribe
|
||||
(bId, CCLink connReq Nothing) <- A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKPQOn False SMSubscribe
|
||||
testJoinConn_ viaProxy sndSecure a bId b connReq
|
||||
|
||||
testInvitationShortLinkAsync :: HasCallStack => Bool -> AgentClient -> AgentClient -> IO ()
|
||||
testInvitationShortLinkAsync viaProxy a b = do
|
||||
let userData = UserLinkData "some user data"
|
||||
newLinkData = UserInvLinkData userData
|
||||
(bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe
|
||||
(FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ False SMSubscribe
|
||||
(_, connData', connReq') <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
linkUserData connData' `shouldBe` userData
|
||||
@@ -1436,20 +1804,22 @@ testContactShortLink :: HasCallStack => Bool -> AgentClient -> AgentClient -> IO
|
||||
testContactShortLink viaProxy a b =
|
||||
withAgent 3 agentCfg initAgentServers testDB3 $ \c -> do
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
(contactId, CCLink connReq0 (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMSubscribe
|
||||
Right connReq <- pure $ smpDecode (smpEncode connReq0)
|
||||
(FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(contactId, CCLink connReq0 (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn False SMSubscribe
|
||||
-- normalize through binary fixed-data encoding (queue mode patch); the extended type has no binary encoding
|
||||
Right connReqBin <- pure $ smpDecode (smpEncode (binaryConnReq connReq0))
|
||||
let connReq = connReqWithKeys connReqBin Nothing
|
||||
(_, ContactLinkData _ userCtData', connReq') <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
userCtData' `shouldBe` userCtData
|
||||
-- same user can get contact link again
|
||||
(FixedLinkData {linkConnReq = connReq2}, ContactLinkData _ userCtData2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
(_, ContactLinkData _ userCtData2, connReq2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
connReq2 `shouldBe` connReq
|
||||
userCtData2 `shouldBe` userCtData
|
||||
-- another user can get the same contact link
|
||||
(FixedLinkData {linkConnReq = connReq3}, ContactLinkData _ userCtData3) <- runRight $ getConnShortLink c 1 shortLink
|
||||
(_, ContactLinkData _ userCtData3, connReq3) <- runRight $ getConnShortLink c 1 shortLink
|
||||
connReq3 `shouldBe` connReq
|
||||
userCtData3 `shouldBe` userCtData
|
||||
runRight $ do
|
||||
@@ -1467,11 +1837,11 @@ testContactShortLink viaProxy a b =
|
||||
exchangeGreetingsViaProxy viaProxy a bId b aId
|
||||
-- update user data
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData, ratchetKeys = Nothing}
|
||||
userLinkData' = UserContactLinkData updatedCtData
|
||||
shortLink' <- runRight $ setConnShortLink a contactId SCMContact userLinkData' Nothing
|
||||
shortLink' `shouldBe` shortLink
|
||||
(FixedLinkData {linkConnReq = connReq4}, ContactLinkData _ updatedCtData') <- runRight $ getConnShortLink c 1 shortLink
|
||||
(_, ContactLinkData _ updatedCtData', connReq4) <- runRight $ getConnShortLink c 1 shortLink
|
||||
connReq4 `shouldBe` connReq
|
||||
updatedCtData' `shouldBe` updatedCtData
|
||||
-- one more time
|
||||
@@ -1485,22 +1855,24 @@ testContactShortLink viaProxy a b =
|
||||
testAddContactShortLink :: HasCallStack => Bool -> AgentClient -> AgentClient -> IO ()
|
||||
testAddContactShortLink viaProxy a b =
|
||||
withAgent 3 agentCfg initAgentServers testDB3 $ \c -> do
|
||||
(contactId, CCLink connReq0 Nothing) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
Right connReq <- pure $ smpDecode (smpEncode connReq0) --
|
||||
(contactId, CCLink connReq0 Nothing) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
-- normalize through binary fixed-data encoding (queue mode patch); the extended type has no binary encoding
|
||||
Right connReqBin <- pure $ smpDecode (smpEncode (binaryConnReq connReq0))
|
||||
let connReq = connReqWithKeys connReqBin Nothing
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
shortLink <- runRight $ setConnShortLink a contactId SCMContact newLinkData Nothing
|
||||
(FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(_, ContactLinkData _ userCtData', connReq') <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
userCtData' `shouldBe` userCtData
|
||||
-- same user can get contact link again
|
||||
(FixedLinkData {linkConnReq = connReq2}, ContactLinkData _ userCtData2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
(_, ContactLinkData _ userCtData2, connReq2) <- runRight $ getConnShortLink b 1 shortLink
|
||||
connReq2 `shouldBe` connReq
|
||||
userCtData2 `shouldBe` userCtData
|
||||
-- another user can get the same contact link
|
||||
(FixedLinkData {linkConnReq = connReq3}, ContactLinkData _ userCtData3) <- runRight $ getConnShortLink c 1 shortLink
|
||||
(_, ContactLinkData _ userCtData3, connReq3) <- runRight $ getConnShortLink c 1 shortLink
|
||||
connReq3 `shouldBe` connReq
|
||||
userCtData3 `shouldBe` userCtData
|
||||
runRight $ do
|
||||
@@ -1518,11 +1890,11 @@ testAddContactShortLink viaProxy a b =
|
||||
exchangeGreetingsViaProxy viaProxy a bId b aId
|
||||
-- update user data
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData, ratchetKeys = Nothing}
|
||||
userLinkData' = UserContactLinkData updatedCtData
|
||||
shortLink' <- runRight $ setConnShortLink a contactId SCMContact userLinkData' Nothing
|
||||
shortLink' `shouldBe` shortLink
|
||||
(FixedLinkData {linkConnReq = connReq4}, ContactLinkData _ updatedCtData') <- runRight $ getConnShortLink c 1 shortLink
|
||||
(_, ContactLinkData _ updatedCtData', connReq4) <- runRight $ getConnShortLink c 1 shortLink
|
||||
connReq4 `shouldBe` connReq
|
||||
updatedCtData' `shouldBe` updatedCtData
|
||||
|
||||
@@ -1531,10 +1903,10 @@ testInvitationShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
let userData = UserLinkData "some user data"
|
||||
newLinkData = UserInvLinkData userData
|
||||
(bId, CCLink connReq (Just shortLink)) <- withSmpServer ps $
|
||||
runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMOnlyCreate
|
||||
runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ False SMOnlyCreate
|
||||
withSmpServer ps $ do
|
||||
runRight_ $ subscribeConnection a bId
|
||||
(FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(_, connData', connReq') <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
linkUserData connData' `shouldBe` userData
|
||||
@@ -1542,16 +1914,16 @@ testInvitationShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
testContactShortLinkRestart :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testContactShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
(contactId, CCLink connReq0 (Just shortLink)) <- withSmpServer ps $
|
||||
runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMOnlyCreate
|
||||
Right connReq <- pure $ smpDecode (smpEncode connReq0)
|
||||
runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn False SMOnlyCreate
|
||||
Right connReq <- pure $ smpDecode (smpEncode (binaryConnReq connReq0))
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData, ratchetKeys = Nothing}
|
||||
updatedLinkData = UserContactLinkData updatedCtData
|
||||
withSmpServer ps $ do
|
||||
(fd', ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(fd', ContactLinkData _ userCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
linkConnReq fd' `shouldBe` connReq
|
||||
userCtData' `shouldBe` userCtData
|
||||
@@ -1559,24 +1931,24 @@ testContactShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
shortLink' <- runRight $ setConnShortLink a contactId SCMContact updatedLinkData Nothing
|
||||
shortLink' `shouldBe` shortLink
|
||||
withSmpServer ps $ do
|
||||
(fd4, ContactLinkData _ updatedCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(fd4, ContactLinkData _ updatedCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
linkConnReq fd4 `shouldBe` connReq
|
||||
updatedCtData' `shouldBe` updatedCtData
|
||||
|
||||
testAddContactShortLinkRestart :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testAddContactShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
((contactId, CCLink connReq0 Nothing), shortLink) <- withSmpServer ps $ runRight $ do
|
||||
r@(contactId, _) <- A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate
|
||||
r@(contactId, _) <- A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn False SMOnlyCreate
|
||||
(r,) <$> setConnShortLink a contactId SCMContact newLinkData Nothing
|
||||
Right connReq <- pure $ smpDecode (smpEncode connReq0)
|
||||
Right connReq <- pure $ smpDecode (smpEncode (binaryConnReq connReq0))
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData, ratchetKeys = Nothing}
|
||||
updatedLinkData = UserContactLinkData updatedCtData
|
||||
withSmpServer ps $ do
|
||||
(fd', ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(fd', ContactLinkData _ userCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
linkConnReq fd' `shouldBe` connReq
|
||||
userCtData' `shouldBe` userCtData
|
||||
@@ -1584,14 +1956,14 @@ testAddContactShortLinkRestart ps = withAgentClients2 $ \a b -> do
|
||||
shortLink' <- runRight $ setConnShortLink a contactId SCMContact updatedLinkData Nothing
|
||||
shortLink' `shouldBe` shortLink
|
||||
withSmpServer ps $ do
|
||||
(fd4, ContactLinkData _ updatedCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(fd4, ContactLinkData _ updatedCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
linkConnReq fd4 `shouldBe` connReq
|
||||
updatedCtData' `shouldBe` updatedCtData
|
||||
|
||||
testOldContactQueueShortLink :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testOldContactQueueShortLink ps@(_, msType) = withAgentClients2 $ \a b -> do
|
||||
(contactId, CCLink connReq Nothing) <- withSmpServer ps $ runRight $
|
||||
A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate
|
||||
A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn False SMOnlyCreate
|
||||
-- make it an "old" queue
|
||||
let updateStoreLog f = replaceSubstringInFile f " queue_mode=C" ""
|
||||
#if defined(dbServerPostgres)
|
||||
@@ -1620,22 +1992,22 @@ testOldContactQueueShortLink ps@(_, msType) = withAgentClients2 $ \a b -> do
|
||||
|
||||
withSmpServer ps $ do
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
userLinkData = UserContactLinkData userCtData
|
||||
shortLink <- runRight $ setConnShortLink a contactId SCMContact userLinkData Nothing
|
||||
(FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
(FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ userCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
connReq' `shouldBe` connReq
|
||||
connReq' `shouldBe` binaryConnReq connReq
|
||||
userCtData' `shouldBe` userCtData
|
||||
-- update user data
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData, ratchetKeys = Nothing}
|
||||
userLinkData' = UserContactLinkData updatedCtData
|
||||
shortLink' <- runRight $ setConnShortLink a contactId SCMContact userLinkData' Nothing
|
||||
shortLink' `shouldBe` shortLink
|
||||
-- check updated
|
||||
(FixedLinkData {linkConnReq = connReq''}, ContactLinkData _ updatedCtData') <- runRight $ getConnShortLink b 1 shortLink
|
||||
connReq'' `shouldBe` connReq
|
||||
(FixedLinkData {linkConnReq = connReq''}, ContactLinkData _ updatedCtData', _) <- runRight $ getConnShortLink b 1 shortLink
|
||||
connReq'' `shouldBe` binaryConnReq connReq
|
||||
updatedCtData' `shouldBe` updatedCtData
|
||||
|
||||
replaceSubstringInFile :: FilePath -> T.Text -> T.Text -> IO ()
|
||||
@@ -1647,19 +2019,20 @@ replaceSubstringInFile filePath oldText newText = do
|
||||
testPrepareCreateConnectionLink :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testPrepareCreateConnectionLink ps = withSmpServer ps $ withAgentClients2 $ \a b -> do
|
||||
let userData = UserLinkData "test user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
userLinkData = UserContactLinkData userCtData
|
||||
g <- C.newRandom
|
||||
rootKey <- atomically $ C.generateKeyPair g
|
||||
linkEntId <- atomically $ C.randomBytes 32 g
|
||||
runRight $ do
|
||||
(ccLink@(CCLink connReq (Just shortLink)), preparedParams) <-
|
||||
A.prepareConnectionLink a 1 rootKey linkEntId True Nothing Nothing
|
||||
A.prepareConnectionLink a 1 rootKey linkEntId True Nothing CR.IKPQOn False Nothing
|
||||
liftIO $ strDecode (strEncode shortLink) `shouldBe` Right shortLink
|
||||
_ <- A.createConnectionForLink a NRMInteractive 1 True ccLink preparedParams userLinkData CR.IKPQOn SMSubscribe
|
||||
(FixedLinkData {linkConnReq = connReq', linkEntityId}, ContactLinkData _ userCtData') <- getConnShortLink b 1 shortLink
|
||||
_ <- A.createConnectionForLink a NRMInteractive 1 True ccLink preparedParams userLinkData SMSubscribe
|
||||
(FixedLinkData {linkEntityId}, ContactLinkData _ userCtData', connReq') <- getConnShortLink b 1 shortLink
|
||||
liftIO $ Just linkEntId `shouldBe` linkEntityId
|
||||
Right connReqDecoded <- pure $ smpDecode (smpEncode connReq)
|
||||
Right connReqBin <- pure $ smpDecode (smpEncode (binaryConnReq connReq))
|
||||
let connReqDecoded = connReqWithKeys connReqBin Nothing
|
||||
liftIO $ connReq' `shouldBe` connReqDecoded
|
||||
liftIO $ userCtData' `shouldBe` userCtData
|
||||
(bId, sndSecure) <- joinConnection b 1 True connReq' "bob's connInfo" SMSubscribe
|
||||
@@ -1675,6 +2048,11 @@ testPrepareCreateConnectionLink ps = withSmpServer ps $ withAgentClients2 $ \a b
|
||||
get b ##> ("", bId, CON)
|
||||
exchangeGreetings a aId b bId
|
||||
|
||||
connReqWithKeys :: BinaryConnectionRequestUri m -> Maybe AddressRatchetKeys -> ConnectionRequestUri m
|
||||
connReqWithKeys cr rk = case cr of
|
||||
BCRInvitationUri crData e2eParams -> CRInvitationUri crData e2eParams
|
||||
BCRContactUri crData -> CRContactUri crData rk
|
||||
|
||||
testIncreaseConnAgentVersion :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testIncreaseConnAgentVersion ps = do
|
||||
alice <- getSMPAgentClient' 1 agentCfg {smpAgentVRange = mkVersionRange 1 2} initAgentServers testDB
|
||||
@@ -2362,7 +2740,7 @@ makeConnectionForUsers = makeConnectionForUsers_ PQSupportOn True
|
||||
|
||||
makeConnectionForUsers_ :: HasCallStack => PQSupport -> SndQueueSecured -> AgentClient -> UserId -> AgentClient -> UserId -> ExceptT AgentErrorType IO (ConnId, ConnId)
|
||||
makeConnectionForUsers_ pqSupport sqSecured alice aliceUserId bob bobUserId = do
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive aliceUserId True True SCMInvitation Nothing Nothing (IKLinkPQ pqSupport) SMSubscribe
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive aliceUserId True True SCMInvitation Nothing Nothing (IKLinkPQ pqSupport) False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob bobUserId True qInfo pqSupport
|
||||
sqSecured' <- A.joinConnection bob NRMInteractive bobUserId aliceId True qInfo "bob's connInfo" pqSupport SMSubscribe
|
||||
liftIO $ sqSecured' `shouldBe` sqSecured
|
||||
@@ -2642,7 +3020,7 @@ testAsyncCommands :: SndQueueSecured -> AgentClient -> AgentClient -> AgentMsgId
|
||||
testAsyncCommands sqSecured alice bob baseId =
|
||||
runRight_ $ do
|
||||
bobId <- prepareConnectionToCreate alice 1 True SCMInvitation PQSupportOn
|
||||
createConnectionAsync alice "1" bobId True SCMInvitation IKPQOn SMSubscribe
|
||||
createConnectionAsync alice "1" bobId True SCMInvitation IKPQOn False SMSubscribe
|
||||
("1", bobId', INV (ACR _ qInfo)) <- get alice
|
||||
liftIO $ bobId' `shouldBe` bobId
|
||||
aliceId <- prepareConnectionToJoin bob 1 True qInfo PQSupportOn
|
||||
@@ -2695,22 +3073,22 @@ testSetConnShortLinkAsync :: (ASrvTransport, AStoreType) -> IO ()
|
||||
testSetConnShortLinkAsync ps = withAgentClients2 $ \alice bob ->
|
||||
withSmpServerStoreLogOn ps testPort $ \_ -> runRight_ $ do
|
||||
let userData = UserLinkData "test user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
(cId, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe
|
||||
(cId, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn False SMSubscribe
|
||||
-- verify initial link data
|
||||
(_, ContactLinkData _ userCtData') <- getConnShortLink bob 1 shortLink
|
||||
(_, ContactLinkData _ userCtData', _) <- getConnShortLink bob 1 shortLink
|
||||
liftIO $ userCtData' `shouldBe` userCtData
|
||||
-- update link data async
|
||||
let updatedData = UserLinkData "updated user data"
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [], userData = updatedData}
|
||||
updatedCtData = UserContactData {direct = False, owners = [], relays = [], userData = updatedData, ratchetKeys = Nothing}
|
||||
setConnShortLinkAsync alice "1" cId (UserContactLinkData updatedCtData) Nothing
|
||||
("1", cId', LINK shortLink' (UserContactLinkData updatedCtData')) <- get alice
|
||||
liftIO $ cId' `shouldBe` cId
|
||||
liftIO $ shortLink' `shouldBe` shortLink
|
||||
liftIO $ updatedCtData' `shouldBe` updatedCtData
|
||||
-- verify updated link data
|
||||
(_, ContactLinkData _ updatedCtData'') <- getConnShortLink bob 1 shortLink'
|
||||
(_, ContactLinkData _ updatedCtData'', _) <- getConnShortLink bob 1 shortLink'
|
||||
liftIO $ updatedCtData'' `shouldBe` updatedCtData
|
||||
-- complete connection via contact address
|
||||
(aliceId, _) <- joinConnection bob 1 True qInfo "bob's connInfo" SMSubscribe
|
||||
@@ -2727,17 +3105,17 @@ testGetConnShortLinkAsync :: (ASrvTransport, AStoreType) -> IO ()
|
||||
testGetConnShortLinkAsync ps = withAgentClients2 $ \alice bob ->
|
||||
withSmpServerStoreLogOn ps testPort $ \_ -> runRight_ $ do
|
||||
let userData = UserLinkData "test user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
newLinkData = UserContactLinkData userCtData
|
||||
(_, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe
|
||||
(_, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn False SMSubscribe
|
||||
-- get link data async - creates new connection for bob
|
||||
newId <- getConnShortLinkAsync bob 1 "1" Nothing shortLink
|
||||
("1", newId', LDATA FixedLinkData {linkConnReq = qInfo'} (ContactLinkData _ userCtData')) <- get bob
|
||||
("1", newId', LDATA FixedLinkData {linkConnReq = qInfo'} (ContactLinkData _ userCtData') connReq') <- get bob
|
||||
liftIO $ newId' `shouldBe` newId
|
||||
liftIO $ qInfo' `shouldBe` qInfo
|
||||
liftIO $ qInfo' `shouldBe` binaryConnReq qInfo
|
||||
liftIO $ userCtData' `shouldBe` userCtData
|
||||
-- join connection async using connId from getConnShortLinkAsync
|
||||
joinConnectionAsync bob "2" True newId True qInfo' "bob's connInfo" PQSupportOn SMSubscribe
|
||||
-- join connection async using connId from getConnShortLinkAsync and the merged connReq from LDATA
|
||||
joinConnectionAsync bob "2" True newId True connReq' "bob's connInfo" PQSupportOn SMSubscribe
|
||||
let aliceId = newId
|
||||
("2", aliceId', JOINED False) <- get bob
|
||||
liftIO $ aliceId' `shouldBe` aliceId
|
||||
@@ -2756,7 +3134,7 @@ testAsyncCommandsRestore ps = do
|
||||
alice <- getSMPAgentClient' 1 agentCfg initAgentServers testDB
|
||||
bobId <- runRight $ do
|
||||
connId <- prepareConnectionToCreate alice 1 True SCMInvitation PQSupportOn
|
||||
createConnectionAsync alice "1" connId True SCMInvitation IKPQOn SMSubscribe
|
||||
createConnectionAsync alice "1" connId True SCMInvitation IKPQOn False SMSubscribe
|
||||
pure connId
|
||||
liftIO $ noMessages alice "alice doesn't receive INV because server is down"
|
||||
disposeAgentClient alice
|
||||
@@ -3046,7 +3424,7 @@ testJoinConnectionAsyncReplyError ps@(t, ASType qsType _) = do
|
||||
withAgent 2 agentCfg initAgentServersSrv2 testDB2 $ \b -> do
|
||||
(aId, bId) <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $ do
|
||||
bId <- prepareConnectionToCreate a 1 True SCMInvitation PQSupportOn
|
||||
createConnectionAsync a "1" bId True SCMInvitation IKPQOn SMSubscribe
|
||||
createConnectionAsync a "1" bId True SCMInvitation IKPQOn False SMSubscribe
|
||||
("1", bId', INV (ACR _ qInfo)) <- get a
|
||||
liftIO $ bId' `shouldBe` bId
|
||||
aId <- prepareConnectionToJoin b 1 True qInfo PQSupportOn
|
||||
@@ -4351,7 +4729,7 @@ testClientNotice :: HasCallStack => (ASrvTransport, AStoreType) -> IO ()
|
||||
testClientNotice ps = do
|
||||
withAgent 1 agentCfg initAgentServers testDB $ \c -> do
|
||||
(cId, _) <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $
|
||||
A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
("", "", DOWN _ [_]) <- nGet c
|
||||
|
||||
addNotice c cId $ Just 1
|
||||
@@ -4360,7 +4738,7 @@ testClientNotice ps = do
|
||||
subscribedWithErrors c 1
|
||||
testNotice c True
|
||||
threadDelay 1000000
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
("", "", DOWN _ [_]) <- nGet c
|
||||
|
||||
addNotice c cId' $ Just 1
|
||||
@@ -4371,7 +4749,7 @@ testClientNotice ps = do
|
||||
threadDelay 1000000
|
||||
testNotice c True
|
||||
threadDelay 1000000
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
|
||||
addNotice c cId'' $ Just 1
|
||||
|
||||
@@ -4383,7 +4761,7 @@ testClientNotice ps = do
|
||||
threadDelay 2000000
|
||||
testNotice c True
|
||||
threadDelay 1000000
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
("", "", DOWN _ [_]) <- nGet c
|
||||
|
||||
addNotice c cId3 Nothing
|
||||
@@ -4398,7 +4776,7 @@ testClientNotice ps = do
|
||||
withSmpServerStoreLogOn ps testPort $ \_ -> do
|
||||
runRight_ $ subscribeAllConnections c False Nothing
|
||||
subscribedWithErrors c 4
|
||||
void $ runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
void $ runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
where
|
||||
addNotice c cId ttl = logNotice c cId $ Just ClientNotice {ttl}
|
||||
removeNotice c cId = logNotice c cId Nothing
|
||||
@@ -4414,7 +4792,7 @@ testClientNotice ps = do
|
||||
r -> expectationFailure $ "unexpected event: " <> show r
|
||||
testNotice :: HasCallStack => AgentClient -> Bool -> IO ()
|
||||
testNotice c willExpire = do
|
||||
NOTICE "localhost" False expiresAt_ <- runLeft $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe
|
||||
NOTICE "localhost" False expiresAt_ <- runLeft $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn False SMSubscribe
|
||||
isJust expiresAt_ `shouldBe` willExpire
|
||||
|
||||
noNetworkDelay :: AgentClient -> IO ()
|
||||
|
||||
@@ -198,7 +198,8 @@ cData1 =
|
||||
lastExternalSndId = 0,
|
||||
deleted = False,
|
||||
ratchetSyncState = RSOk,
|
||||
pqSupport = CR.PQSupportOn
|
||||
pqSupport = CR.PQSupportOn,
|
||||
serviceRequestExpiresAt = Nothing
|
||||
}
|
||||
|
||||
testPrivateAuthKey :: C.APrivateAuthKey
|
||||
@@ -696,7 +697,7 @@ testGetPendingServerCommand st = do
|
||||
Right (Just PendingCommand {corrId = corrId'}) <- getPendingServerCommand db connId (Just smpServer1)
|
||||
corrId' `shouldBe` "4"
|
||||
where
|
||||
command = AClientCommand $ NEW True (ACM SCMInvitation) IKPQOn SMSubscribe
|
||||
command = AClientCommand $ NEW True (ACM SCMInvitation) IKPQOn SMSubscribe False
|
||||
corruptCmd :: DB.Connection -> ByteString -> ConnId -> IO ()
|
||||
corruptCmd db corrId connId = DB.execute db "UPDATE commands SET command = cast('bad' as blob) WHERE conn_id = ? AND corr_id = ?" (connId, corrId)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ testInvShortLink = do
|
||||
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
||||
-- decrypt
|
||||
Right (FixedLinkData {linkConnReq = connReq}, connData') <- pure $ SL.decryptLinkData linkKey k srvData
|
||||
connReq `shouldBe` invConnRequest
|
||||
connReq `shouldBe` binaryConnReq invConnRequest
|
||||
linkUserData connData' `shouldBe` userData
|
||||
|
||||
testInvShortLinkBadDataHash :: IO ()
|
||||
@@ -80,14 +80,14 @@ testContactShortLink = do
|
||||
g <- C.newRandom
|
||||
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
userLinkData = UserContactLinkData userCtData
|
||||
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest Nothing userLinkData
|
||||
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
||||
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
||||
-- decrypt
|
||||
Right (FixedLinkData {linkConnReq = connReq}, ContactLinkData _ userCtData') <- pure $ SL.decryptLinkData @'CMContact linkKey k srvData
|
||||
connReq `shouldBe` contactConnRequest
|
||||
connReq `shouldBe` binaryConnReq contactConnRequest
|
||||
userCtData' `shouldBe` userCtData
|
||||
|
||||
testUpdateContactShortLink :: IO ()
|
||||
@@ -96,20 +96,20 @@ testUpdateContactShortLink = do
|
||||
g <- C.newRandom
|
||||
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let userData = UserLinkData "some user data"
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userCtData = UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
userLinkData = UserContactLinkData userCtData
|
||||
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest Nothing userLinkData
|
||||
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
||||
Right (fd, _ud) <- runExceptT $ SL.encryptLinkData g k linkData
|
||||
-- encrypt updated user data
|
||||
let updatedUserData = UserLinkData "updated user data"
|
||||
userCtData' = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedUserData}
|
||||
userCtData' = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedUserData, ratchetKeys = Nothing}
|
||||
userLinkData' = UserContactLinkData userCtData'
|
||||
signed = SL.encodeSignUserData SCMContact (snd sigKeys) supportedSMPAgentVRange userLinkData'
|
||||
Right ud' <- runExceptT $ SL.encryptUserData g k signed
|
||||
-- decrypt
|
||||
Right (FixedLinkData {linkConnReq = connReq}, ContactLinkData _ userCtData'') <- pure $ SL.decryptLinkData @'CMContact linkKey k (fd, ud')
|
||||
connReq `shouldBe` contactConnRequest
|
||||
connReq `shouldBe` binaryConnReq contactConnRequest
|
||||
userCtData'' `shouldBe` userCtData'
|
||||
|
||||
testContactShortLinkBadDataHash :: IO ()
|
||||
@@ -118,7 +118,7 @@ testContactShortLinkBadDataHash = do
|
||||
g <- C.newRandom
|
||||
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let userData = UserLinkData "some user data"
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
(_linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest Nothing userLinkData
|
||||
-- different key
|
||||
linkKey <- LinkKey <$> atomically (C.randomBytes 32 g)
|
||||
@@ -134,13 +134,13 @@ testContactShortLinkBadSignature = do
|
||||
g <- C.newRandom
|
||||
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let userData = UserLinkData "some user data"
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest Nothing userLinkData
|
||||
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
||||
Right (fd, _ud) <- runExceptT $ SL.encryptLinkData g k linkData
|
||||
-- encrypt updated user data
|
||||
let updatedUserData = UserLinkData "updated user data"
|
||||
userLinkData' = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = updatedUserData}
|
||||
userLinkData' = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData = updatedUserData, ratchetKeys = Nothing}
|
||||
-- another signature key
|
||||
(_, pk) <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let signed = SL.encodeSignUserData SCMContact pk supportedSMPAgentVRange userLinkData'
|
||||
@@ -156,7 +156,7 @@ testContactShortLinkOwner = do
|
||||
(pk, lnk) <- encryptLink g
|
||||
-- encrypt updated user data
|
||||
(ownerPK, owner) <- authNewOwner g pk
|
||||
let ud = UserContactData {direct = True, owners = [owner], relays = [], userData = UserLinkData "updated user data"}
|
||||
let ud = UserContactData {direct = True, owners = [owner], relays = [], userData = UserLinkData "updated user data", ratchetKeys = Nothing}
|
||||
testEncDec g pk lnk ud
|
||||
testEncDec g ownerPK lnk ud
|
||||
(_, wrongKey) <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
@@ -166,7 +166,7 @@ encryptLink :: TVar ChaChaDRG -> IO (C.PrivateKeyEd25519, (EncFixedDataBytes, Li
|
||||
encryptLink g = do
|
||||
sigKeys@(_, pk) <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
||||
let userData = UserLinkData "some user data"
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData}
|
||||
userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData, ratchetKeys = Nothing}
|
||||
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest Nothing userLinkData
|
||||
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
||||
Right (fd, _ud) <- runExceptT $ SL.encryptLinkData g k linkData
|
||||
@@ -184,7 +184,7 @@ testEncDec g pk (fd, linkKey, k) ctData = do
|
||||
let signed = SL.encodeSignUserData SCMContact pk supportedSMPAgentVRange $ UserContactLinkData ctData
|
||||
Right ud <- runExceptT $ SL.encryptUserData g k signed
|
||||
Right (FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ ctData') <- pure $ SL.decryptLinkData @'CMContact linkKey k (fd, ud)
|
||||
connReq' `shouldBe` contactConnRequest
|
||||
connReq' `shouldBe` binaryConnReq contactConnRequest
|
||||
ctData' `shouldBe` ctData
|
||||
|
||||
testContactShortLinkManyOwners :: IO ()
|
||||
@@ -199,7 +199,7 @@ testContactShortLinkManyOwners = do
|
||||
(ownerPK4, owner4) <- authNewOwner g ownerPK1
|
||||
(ownerPK5, owner5) <- authNewOwner g ownerPK3
|
||||
let owners = [owner1, owner2, owner3, owner4, owner5]
|
||||
ud = UserContactData {direct = True, owners, relays = [], userData = UserLinkData "updated user data"}
|
||||
ud = UserContactData {direct = True, owners, relays = [], userData = UserLinkData "updated user data", ratchetKeys = Nothing}
|
||||
testEncDec g pk lnk ud
|
||||
testEncDec g ownerPK1 lnk ud
|
||||
testEncDec g ownerPK2 lnk ud
|
||||
@@ -216,7 +216,7 @@ testContactShortLinkInvalidOwners = do
|
||||
(pk, lnk) <- encryptLink g
|
||||
-- encrypt updated user data
|
||||
(ownerPK, owner) <- authNewOwner g pk
|
||||
let mkCtData owners = UserContactData {direct = True, owners, relays = [], userData = UserLinkData "updated user data"}
|
||||
let mkCtData owners = UserContactData {direct = True, owners, relays = [], userData = UserLinkData "updated user data", ratchetKeys = Nothing}
|
||||
-- decryption fails: owner uses root key
|
||||
let ud = mkCtData [owner {ownerKey = C.publicKey pk}]
|
||||
err = A_LINK $ "owner key for ID " <> ownerIdStr owner <> " matches root key"
|
||||
|
||||
@@ -228,7 +228,7 @@ agentDeliverMessageViaProxy :: (C.AlgorithmI a, C.AuthAlgorithm a) => (NonEmpty
|
||||
agentDeliverMessageViaProxy aTestCfg@(aSrvs, _, aViaProxy) bTestCfg@(bSrvs, _, bViaProxy) alg msg1 msg2 baseId =
|
||||
withAgent 1 aCfg (servers aTestCfg) testDB $ \alice ->
|
||||
withAgent 2 aCfg (servers bTestCfg) testDB2 $ \bob -> runRight_ $ do
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn
|
||||
sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe
|
||||
liftIO $ sqSecured `shouldBe` True
|
||||
@@ -284,7 +284,7 @@ agentDeliverMessagesViaProxyConc agentServers msgs =
|
||||
-- agent connections have to be set up in advance
|
||||
-- otherwise the CONF messages would get mixed with MSG
|
||||
prePair alice bob = do
|
||||
(bobId, CCLink qInfo Nothing) <- runExceptT' $ A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
(bobId, CCLink qInfo Nothing) <- runExceptT' $ A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
aliceId <- runExceptT' $ A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn
|
||||
sqSecured <- runExceptT' $ A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe
|
||||
liftIO $ sqSecured `shouldBe` True
|
||||
@@ -343,7 +343,7 @@ agentViaProxyRetryOffline = do
|
||||
let pqEnc = CR.PQEncOn
|
||||
withServer $ \_ -> do
|
||||
(aliceId, bobId) <- withServer2 $ \_ -> runRight $ do
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
(bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn
|
||||
sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe
|
||||
liftIO $ sqSecured `shouldBe` True
|
||||
@@ -504,14 +504,14 @@ testAgentClientReconnectAfterCancel :: IO ()
|
||||
testAgentClientReconnectAfterCancel =
|
||||
withAgent 1 agentCfg agentServersLeak testDB $ \a -> do
|
||||
withStallingServerOn testPort2 $ do
|
||||
t <- async $ runExceptT $ A.createConnection a NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
t <- async $ runExceptT $ A.createConnection a NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
threadDelay 1000000 -- let the connect to the stalling relay start, then kill it mid-flight
|
||||
cancel t
|
||||
withSmpServerConfigOn (transport @TLS) cfgJ2 testPort2 $ \_ -> do
|
||||
testSMPClient_ "127.0.0.1" testPort2 supportedServerSMPRelayVRange Nothing $ \(th :: THandleSMP TLS 'TClient) -> do
|
||||
(_, _, reply) <- sendRecv th (Nothing, "0", NoEntity, SMP.PING)
|
||||
reply `shouldBe` Right SMP.PONG -- the relay is up and reachable, so a timeout can only be the poisoned var
|
||||
r <- timeout 8000000 $ runExceptT $ A.createConnection a NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe
|
||||
r <- timeout 8000000 $ runExceptT $ A.createConnection a NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn False SMSubscribe
|
||||
case r of
|
||||
Just (Right _) -> pure ()
|
||||
_ -> expectationFailure $ "agent failed to connect after a cancelled connect; got: " <> show r
|
||||
|
||||
Reference in New Issue
Block a user