diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index 067031899..c5f57cdd9 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -1325,7 +1325,7 @@ newRcvConnSrv c nm userId connId enableNtfs cMode userLinkData_ clientData pqIni Just d -> do (nonce, qUri, cReq, qd) <- prepareLinkData addrKeys_ (setLinkDataRatchetKeys addrKeys_ d) $ fst e2eKeys (rq, qUri') <- createRcvQueue c nm userId connId srvWithAuth enableNtfs subMode (Just nonce) qd e2eKeys - connReqWithShortLink qUri cReq qUri' (shortLink rq) + connReqWithShortLink pqInitKeys qUri cReq qUri' rq Nothing -> do let qd = case cMode of SCMContact -> CQRContact Nothing; SCMInvitation -> CQRMessaging Nothing (_rq, qUri) <- createRcvQueue c nm userId connId srvWithAuth enableNtfs subMode Nothing qd e2eKeys @@ -1372,23 +1372,19 @@ newRcvConnSrv c nm userId connId enableNtfs cMode userLinkData_ clientData pqIni srvData <- liftError id $ SL.encryptLinkData g k linkData pure $ CQRMessaging $ Just CQRData {linkKey, privSigKey, srvReq = (sndId, srvData)} pure (nonce, qUri, connReq, qd) - connReqWithShortLink :: SMPQueueUri -> ConnectionRequestUri c -> SMPQueueUri -> Maybe ShortLinkCreds -> AM (CreatedConnLink c) - connReqWithShortLink qUri cReq qUri' shortLink = case shortLink of - Just ShortLinkCreds {shortLinkId, shortLinkKey} - | qUri == qUri' -> pure $ case cReq of - CRContactUri _ _ -> CCLink cReq $ Just $ CSLContact SLSServer CCTContact srv shortLinkKey - CRInvitationUri crData (CR.E2ERatchetParamsUri vr k1 k2 _) -> - let cReq' = case pqInitKeys of - CR.IKPQOn -> CRInvitationUri crData $ CR.E2ERatchetParamsUri vr k1 k2 Nothing -- remove PQ keys - _ -> cReq -- either PQ is disabled, or disabled for initial request because there is no short link - in CCLink cReq' $ Just $ CSLInvitation SLSServer srv shortLinkId shortLinkKey - | otherwise -> throwE $ INTERNAL "different rcv queue address" - Nothing -> - let updated (ConnReqUriData _ vr _ _) = (ConnReqUriData SSSimplex vr [qUri'] clientData) - cReq' = case cReq of - CRContactUri crData rk -> CRContactUri (updated crData) rk - CRInvitationUri crData e2eParams -> CRInvitationUri (updated crData) e2eParams - in pure $ CCLink cReq' Nothing + +connReqWithShortLink :: CR.InitialKeys -> SMPQueueUri -> ConnectionRequestUri c -> SMPQueueUri -> RcvQueue -> AM (CreatedConnLink c) +connReqWithShortLink pqInitKeys qUri cReq qUri' RcvQueue {server = srv, shortLink} = case shortLink of + Just ShortLinkCreds {shortLinkId, shortLinkKey} + | qUri == qUri' -> pure $ case cReq of + CRContactUri _ _ -> CCLink cReq $ Just $ CSLContact SLSServer CCTContact srv shortLinkKey + CRInvitationUri crData (CR.E2ERatchetParamsUri vr k1 k2 _) -> + let cReq' = case pqInitKeys of + CR.IKPQOn -> CRInvitationUri crData $ CR.E2ERatchetParamsUri vr k1 k2 Nothing -- remove PQ keys + _ -> cReq -- either PQ is disabled, or disabled for initial request because there is no short link + in CCLink cReq' $ Just $ CSLInvitation SLSServer srv shortLinkId shortLinkKey + | otherwise -> throwE $ INTERNAL "different rcv queue address" + Nothing -> throwE $ INTERNAL "no short link credentials" newQueueNtfServer :: AM (Maybe NtfServer) newQueueNtfServer = fmap ntfServer_ . readTVarIO . ntfTkn =<< asks ntfSupervisor diff --git a/src/Simplex/Messaging/Agent/Client.hs b/src/Simplex/Messaging/Agent/Client.hs index 655470385..4488c5b6b 100644 --- a/src/Simplex/Messaging/Agent/Client.hs +++ b/src/Simplex/Messaging/Agent/Client.hs @@ -311,7 +311,7 @@ import Simplex.Messaging.Session import Simplex.Messaging.SystemTime import Simplex.Messaging.TMap (TMap) import qualified Simplex.Messaging.TMap as TM -import Simplex.Messaging.Transport (HandshakeError (..), SMPServiceRole (..), SMPVersion, ServiceCredentials (..), SessionId, THClientService' (..), THandleAuth (..), THandleParams (sessionId, thAuth, thVersion, serverInfo), TransportError (..), TransportPeer (..), shortLinksSMPVersion, newNtfCredsSMPVersion) +import Simplex.Messaging.Transport (HandshakeError (..), SMPServiceRole (..), SMPVersion, ServiceCredentials (..), SessionId, THClientService' (..), THandleAuth (..), THandleParams (sessionId, thAuth, thVersion, serverInfo), TransportError (..), newNtfCredsSMPVersion) import Simplex.Messaging.Transport.Client (TransportHost (..)) import Simplex.Messaging.Transport.Credentials import Simplex.Messaging.Util @@ -1498,7 +1498,7 @@ newRcvQueue_ c nm userId connId (ProtoServerWithAuth srv auth) vRange cqrd enabl let sessServiceId = (\THClientService {serviceId = sId} -> sId) <$> (clientService =<< thAuth thParams') when (isJust serviceId && serviceId /= sessServiceId) $ logError "incorrect service ID in NEW response" liftIO . logServer "<--" c srv NoEntity $ B.unwords ["IDS", logSecret rcvId, logSecret sndId] - shortLink <- mkShortLinkCreds thParams' qik + shortLink <- mkShortLinkCreds qik let rq = RcvQueue { userId, @@ -1539,8 +1539,8 @@ newRcvQueue_ c nm userId connId (ProtoServerWithAuth srv auth) vRange cqrd enabl (Just ((ntfPublicKey, ntfPrivateKey), dhpk), Just (ServerNtfCreds notifierId dhk')) -> Just ClientNtfCreds {ntfPublicKey, ntfPrivateKey, notifierId, rcvNtfDhSecret = C.dh' dhk' dhpk} _ -> Nothing - mkShortLinkCreds :: THandleParams SMPVersion 'TClient -> QueueIdsKeys -> AM (Maybe ShortLinkCreds) - mkShortLinkCreds thParams' QIK {sndId, queueMode, linkId} = case (cqrd, queueMode) of + mkShortLinkCreds :: QueueIdsKeys -> AM (Maybe ShortLinkCreds) + mkShortLinkCreds QIK {sndId, queueMode, linkId} = case (cqrd, queueMode) of (CQRMessaging ld, Just QMMessaging) -> withLinkData ld $ \lnkId CQRData {linkKey, privSigKey, srvReq = (sndId', d)} -> if sndId == sndId' @@ -1554,11 +1554,9 @@ newRcvQueue_ c nm userId connId (ProtoServerWithAuth srv auth) vRange cqrd enabl (_, Nothing) -> newErr "unexpected link ID" _ -> newErr "unexpected queue mode" where - v = thVersion thParams' withLinkData :: Maybe d -> (SMP.LinkId -> d -> AM (Maybe ShortLinkCreds)) -> AM (Maybe ShortLinkCreds) withLinkData ld_ mkLink = case (ld_, linkId) of (Just ld, Just lnkId) -> mkLink lnkId ld - (Just _, Nothing) | v < shortLinksSMPVersion -> pure Nothing (Nothing, Nothing) -> pure Nothing _ -> newErr "unexpected or absent link ID" newErr :: String -> AM (Maybe ShortLinkCreds) diff --git a/src/Simplex/Messaging/Protocol.hs b/src/Simplex/Messaging/Protocol.hs index a62e84224..ab0f362f4 100644 --- a/src/Simplex/Messaging/Protocol.hs +++ b/src/Simplex/Messaging/Protocol.hs @@ -1824,8 +1824,7 @@ instance PartyI p => ProtocolEncoding SMPVersion ErrorType (Command p) where encodeProtocol v = \case NEW NewQueueReq {rcvAuthKey = rKey, rcvDhKey = dhKey, auth_, subMode, queueReqData, ntfCreds} | v >= newNtfCredsSMPVersion -> new <> e (subMode, queueReqData, ntfCreds) - | v >= shortLinksSMPVersion -> new <> e (subMode, queueReqData) - | otherwise -> new <> e (subMode, senderCanSecure (queueReqMode <$> queueReqData)) + | otherwise -> new <> e (subMode, queueReqData) where new = e (NEW_, ' ', rKey, dhKey, auth_) SUB -> e SUB_ @@ -1912,20 +1911,18 @@ instance ProtocolEncoding SMPVersion ErrorType Cmd where CT SCreator NEW_ -> Cmd SCreator <$> newCmd where newCmd - | v >= newNtfCredsSMPVersion = new smpP smpP - | v >= shortLinksSMPVersion = new smpP nothing - | otherwise = new (qReq <$> smpP) nothing + | v >= newNtfCredsSMPVersion = new smpP + | otherwise = new nothing where nothing = pure Nothing - new p2 p3 = NEW <$> do + new p3 = NEW <$> do rcvAuthKey <- _smpP rcvDhKey <- smpP auth_ <- smpP subMode <- smpP - queueReqData <- p2 + queueReqData <- smpP ntfCreds <- p3 pure NewQueueReq {rcvAuthKey, rcvDhKey, auth_, subMode, queueReqData, ntfCreds} - qReq sndSecure = Just $ if sndSecure then QRMessaging Nothing else QRContact Nothing CT SRecipient tag -> Cmd SRecipient <$> case tag of SUB_ -> pure SUB @@ -1976,8 +1973,7 @@ instance ProtocolEncoding SMPVersion ErrorType BrokerMsg where IDS QIK {rcvId, sndId, rcvPublicDhKey = srvDh, queueMode, linkId, serviceId, serverNtfCreds} | v >= newNtfCredsSMPVersion -> ids <> e (queueMode, linkId, serviceId, serverNtfCreds) | v >= serviceCertsSMPVersion -> ids <> e (queueMode, linkId, serviceId) - | v >= shortLinksSMPVersion -> ids <> e (queueMode, linkId) - | otherwise -> ids <> e (senderCanSecure queueMode) + | otherwise -> ids <> e (queueMode, linkId) where ids = e (IDS_, ' ', rcvId, sndId, srvDh) LNK sId d -> e (LNK_, ' ', sId, d) @@ -2028,19 +2024,17 @@ instance ProtocolEncoding SMPVersion ErrorType BrokerMsg where bodyP = EncRcvMsgBody . unTail <$> smpP ALLS_ -> pure ALLS IDS_ - | v >= newNtfCredsSMPVersion -> ids smpP smpP smpP smpP - | v >= serviceCertsSMPVersion -> ids smpP smpP smpP nothing - | v >= shortLinksSMPVersion -> ids smpP smpP nothing nothing - | otherwise -> ids (qm <$> smpP) nothing nothing nothing + | v >= newNtfCredsSMPVersion -> ids smpP smpP + | v >= serviceCertsSMPVersion -> ids smpP nothing + | otherwise -> ids nothing nothing where - qm sndSecure = Just $ if sndSecure then QMMessaging else QMContact nothing = pure Nothing - ids p1 p2 p3 p4 = do + ids p3 p4 = do rcvId <- _smpP sndId <- smpP rcvPublicDhKey <- smpP - queueMode <- p1 - linkId <- p2 + queueMode <- smpP + linkId <- smpP serviceId <- p3 serverNtfCreds <- p4 pure $ IDS QIK {rcvId, sndId, rcvPublicDhKey, queueMode, linkId, serviceId, serverNtfCreds} diff --git a/src/Simplex/Messaging/Transport.hs b/src/Simplex/Messaging/Transport.hs index 0a082a388..32e33ad1a 100644 --- a/src/Simplex/Messaging/Transport.hs +++ b/src/Simplex/Messaging/Transport.hs @@ -46,7 +46,6 @@ module Simplex.Messaging.Transport minServerSMPRelayVersion, currentClientSMPRelayVersion, currentServerSMPRelayVersion, - shortLinksSMPVersion, serviceCertsSMPVersion, newNtfCredsSMPVersion, clientNoticesSMPVersion, @@ -191,11 +190,8 @@ type VersionRangeSMP = VersionRange SMPVersion pattern VersionSMP :: Word16 -> VersionSMP pattern VersionSMP v = Version v -_proxyServerHandshakeSMPVersion :: VersionSMP -_proxyServerHandshakeSMPVersion = VersionSMP 14 - -shortLinksSMPVersion :: VersionSMP -shortLinksSMPVersion = VersionSMP 15 +_shortLinksSMPVersion :: VersionSMP +_shortLinksSMPVersion = VersionSMP 15 serviceCertsSMPVersion :: VersionSMP serviceCertsSMPVersion = VersionSMP 16 @@ -224,10 +220,10 @@ fwdNoncesSMPVersion :: VersionSMP fwdNoncesSMPVersion = VersionSMP 23 minClientSMPRelayVersion :: VersionSMP -minClientSMPRelayVersion = VersionSMP 14 +minClientSMPRelayVersion = VersionSMP 15 minServerSMPRelayVersion :: VersionSMP -minServerSMPRelayVersion = VersionSMP 14 +minServerSMPRelayVersion = VersionSMP 15 currentClientSMPRelayVersion :: VersionSMP currentClientSMPRelayVersion = VersionSMP 23 @@ -245,7 +241,7 @@ currentServerSMPRelayVersion = VersionSMP 23 proxiedSMPRelayVersion :: VersionSMP proxiedSMPRelayVersion = VersionSMP 23 --- minimal supported protocol version is 14 +-- minimal supported protocol version is 15 supportedClientSMPRelayVRange :: VersionRangeSMP supportedClientSMPRelayVRange = mkVersionRange minClientSMPRelayVersion currentClientSMPRelayVersion diff --git a/tests/AgentTests/FunctionalAPITests.hs b/tests/AgentTests/FunctionalAPITests.hs index 6ab503866..7b2481a60 100644 --- a/tests/AgentTests/FunctionalAPITests.hs +++ b/tests/AgentTests/FunctionalAPITests.hs @@ -112,7 +112,7 @@ import Simplex.Messaging.Server.Information (ServerPublicInfo (..)) import Simplex.Messaging.Server.MsgStore.Types (SMSType (..), SQSType (..)) import Simplex.Messaging.Server.QueueStore.QueueInfo import Simplex.Messaging.Server.StoreLog (StoreLogRecord (..)) -import Simplex.Messaging.Transport (ASrvTransport, SMPVersion, VersionSMP, currentServerSMPRelayVersion, minClientSMPRelayVersion, minServerSMPRelayVersion, alpnSupportedSMPHandshakes, supportedServerSMPRelayVRange) +import Simplex.Messaging.Transport (ASrvTransport, SMPVersion, VersionSMP, currentServerSMPRelayVersion, minClientSMPRelayVersion, minServerSMPRelayVersion, alpnSupportedSMPHandshakes) import Simplex.Messaging.Transport.Server (TransportServerConfig (..)) import Simplex.Messaging.Util (bshow, diffToMicroseconds) import Simplex.Messaging.Version (VersionRange (..)) @@ -413,7 +413,6 @@ functionalAPITests ps = do describe "should connect via 1-time short link with async join" $ testProxyMatrix ps testInvitationShortLinkAsync describe "should connect via contact short link" $ testProxyMatrix ps testContactShortLink describe "should add short link to existing contact and connect" $ testProxyMatrix ps testAddContactShortLink - xdescribe "try to create 1-time short link with prev versions" $ testProxyMatrixWithPrev ps testInvitationShortLinkPrev describe "server restart" $ do it "should get 1-time link data after restart" $ testInvitationShortLinkRestart ps it "should connect via contact short link after restart" $ testContactShortLinkRestart ps @@ -675,19 +674,6 @@ testProxyMatrix ps runTest = do it "2 servers, directly" $ withSmpServers2 ps $ withAgentClientsServers2 (agentCfg, initAgentServers) (agentCfg, initAgentServers2) $ runTest False it "2 servers, via proxy" $ withSmpServersProxy2 ps $ withAgentClientsServers2 (agentCfg, initAgentServersProxy) (agentCfg, initAgentServersProxy2) $ runTest True -testProxyMatrixWithPrev :: HasCallStack => (ASrvTransport, AStoreType) -> (Bool -> Bool -> AgentClient -> AgentClient -> IO ()) -> Spec -testProxyMatrixWithPrev ps@(t, msType@(ASType qs _ms)) runTest = do - it "2 servers, directly, curr clients, prev servers" $ withSmpServers2Prev $ withAgentClientsServers2 (agentCfg, initAgentServers) (agentCfg, initAgentServers2) $ runTest False True - it "2 servers, via proxy, curr clients, prev servers" $ withSmpServersProxy2Prev $ withAgentClientsServers2 (agentCfg, initAgentServersProxy) (agentCfg, initAgentServersProxy2) $ runTest True True - it "2 servers, directly, prev clients, curr servers" $ withSmpServers2 ps $ withAgentClientsServers2 (agentCfgVPrevPQ, initAgentServers) (agentCfgVPrevPQ, initAgentServers2) $ runTest False False - it "2 servers, via proxy, prev clients, curr servers" $ withSmpServersProxy2 ps $ withAgentClientsServers2 (agentCfgVPrevPQ, initAgentServersProxy) (agentCfgVPrevPQ, initAgentServersProxy2) $ runTest True False - where - prev cfg' = updateCfg cfg' $ \cfg_ -> cfg_ {smpServerVRange = prevRange supportedServerSMPRelayVRange} - withSmpServers2Prev a = withServers2 (prev $ cfgMS msType) (prev $ cfgS2QS qs) a - withSmpServersProxy2Prev a = withServers2 (prev $ proxyCfgMS msType) (prev $ proxyCfgS2QS qs) a - withServers2 cfg1 cfg2 a = - withSmpServerConfigOn t cfg1 testPort $ \_ -> withSmpServerConfigOn t cfg2 testPort2 $ \_ -> a - testPQMatrix2 :: HasCallStack => (ASrvTransport, AStoreType) -> (HasCallStack => (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> AgentMsgId -> IO ()) -> Spec testPQMatrix2 = pqMatrix2_ True @@ -1789,14 +1775,6 @@ testJoinConn_ viaProxy sndSecure a bId b connReq = do get b ##> ("", aId, CON) exchangeGreetingsViaProxy viaProxy a bId b aId -testInvitationShortLinkPrev :: HasCallStack => Bool -> Bool -> AgentClient -> AgentClient -> IO () -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 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"