diff --git a/src/Simplex/Messaging/Client.hs b/src/Simplex/Messaging/Client.hs index 313dc329d..e89e1f8c2 100644 --- a/src/Simplex/Messaging/Client.hs +++ b/src/Simplex/Messaging/Client.hs @@ -195,6 +195,7 @@ data PClient v err msg = PClient transportHost :: TransportHost, tcpConnectTimeout :: NetworkTimeout, tcpTimeout :: NetworkTimeout, + proxiedRelayVRange :: VersionRange v, sendPings :: TVar Bool, lastReceived :: TVar UTCTime, timeoutErrorCount :: TVar Int, @@ -240,6 +241,7 @@ smpClientStub g sessionId thVersion thAuth = do transportHost = "localhost", tcpConnectTimeout, tcpTimeout, + proxiedRelayVRange = supportedClientSMPRelayVRange, sendPings, lastReceived, timeoutErrorCount, @@ -477,6 +479,7 @@ data ProtocolClientConfig v = ProtocolClientConfig serviceCredentials :: Maybe ServiceCredentials, -- | client-server protocol version range serverVRange :: VersionRange v, + proxiedRelayVRange :: VersionRange v, -- | agree shared session secret (used in SMP proxy for additional encryption layer) agreeSecret :: Bool, -- | Whether connecting client is a proxy server. See comment in ClientHandshake @@ -495,6 +498,7 @@ defaultClientConfig clientALPN useSNI serverVRange = clientALPN, serviceCredentials = Nothing, serverVRange, + proxiedRelayVRange = serverVRange, agreeSecret = False, proxyServer = False, useSNI @@ -505,6 +509,7 @@ defaultSMPClientConfig :: ProtocolClientConfig SMPVersion defaultSMPClientConfig = (defaultClientConfig (Just alpnSupportedSMPHandshakes) False supportedClientSMPRelayVRange) { defaultTransport = (show defaultSMPPort, transport @TLS), + proxiedRelayVRange = supportedClientSMPRelayVRange, agreeSecret = True } {-# INLINE defaultSMPClientConfig #-} @@ -568,7 +573,7 @@ type SMPTransportSession = TransportSession BrokerMsg -- A single queue can be used for multiple 'SMPClient' instances, -- as 'SMPServerTransmission' includes server information. getProtocolClient :: forall v err msg. Protocol v err msg => TVar ChaChaDRG -> NetworkRequestMode -> TransportSession msg -> ProtocolClientConfig v -> [HostName] -> Maybe (TBQueue (ServerTransmissionBatch v err msg)) -> UTCTime -> (ProtocolClient v err msg -> IO ()) -> IO (Either (ProtocolClientError err) (ProtocolClient v err msg)) -getProtocolClient g nm transportSession@(_, srv, _) cfg@ProtocolClientConfig {qSize, networkConfig, clientALPN, serviceCredentials, serverVRange, agreeSecret, proxyServer, useSNI} presetDomains msgQ proxySessTs disconnected = do +getProtocolClient g nm transportSession@(_, srv, _) cfg@ProtocolClientConfig {qSize, networkConfig, clientALPN, serviceCredentials, serverVRange, proxiedRelayVRange, agreeSecret, proxyServer, useSNI} presetDomains msgQ proxySessTs disconnected = do case chooseTransportHost networkConfig (host srv) of Right useHost -> (getCurrentTime >>= mkProtocolClient useHost >>= runClient useTransport useHost) @@ -593,6 +598,7 @@ getProtocolClient g nm transportSession@(_, srv, _) cfg@ProtocolClientConfig {qS transportHost, tcpConnectTimeout, tcpTimeout, + proxiedRelayVRange, sendPings, lastReceived, timeoutErrorCount, @@ -1115,10 +1121,10 @@ deleteSMPQueues = okSMPCommands DEL -- send PRXY :: SMPServer -> Maybe BasicAuth -> Command Sender -- receives PKEY :: SessionId -> X.CertificateChain -> X.SignedExact X.PubKey -> BrokerMsg connectSMPProxiedRelay :: SMPClient -> NetworkRequestMode -> SMPServer -> Maybe BasicAuth -> ExceptT SMPClientError IO ProxiedRelay -connectSMPProxiedRelay c@ProtocolClient {thParams = THandleParams {thServerVRange}, client_ = PClient {tcpConnectTimeout, tcpTimeout}} nm relayServ@ProtocolServer {port = relayPort, keyHash = C.KeyHash kh} proxyAuth = +connectSMPProxiedRelay c@ProtocolClient {client_ = PClient {tcpConnectTimeout, tcpTimeout, proxiedRelayVRange}} nm relayServ@ProtocolServer {port = relayPort, keyHash = C.KeyHash kh} proxyAuth = sendProtocolCommand_ c nm Nothing tOut Nothing NoEntity (Cmd SProxiedClient (PRXY relayServ proxyAuth)) >>= \case PKEY sId vr (CertChainPubKey chain key) -> - case thServerVRange `compatibleVersion` vr of + case proxiedRelayVRange `compatibleVersion` vr of Nothing -> throwE $ transportErr TEVersion Just (Compatible v) -> do relayKey <- liftEitherWith (const $ transportErr $ TEHandshake IDENTITY) =<< liftIO (runExceptT $ validateRelay chain key) diff --git a/tests/AgentTests/FunctionalAPITests.hs b/tests/AgentTests/FunctionalAPITests.hs index 319f885ea..8194e9ccd 100644 --- a/tests/AgentTests/FunctionalAPITests.hs +++ b/tests/AgentTests/FunctionalAPITests.hs @@ -231,7 +231,11 @@ pattern Rcvd' :: AgentMsgId -> AgentMsgId -> AEvent 'AEConn pattern Rcvd' aMsgId rcvdMsgId <- RCVD MsgMeta {integrity = MsgOk, recipient = (aMsgId, _)} [MsgReceipt {agentMsgId = rcvdMsgId, msgRcptStatus = MROk}] smpCfgVPrev :: ProtocolClientConfig SMPVersion -smpCfgVPrev = (smpCfg agentCfg) {serverVRange = prevRange $ serverVRange $ smpCfg agentCfg} +smpCfgVPrev = + (smpCfg agentCfg) + { serverVRange = prevRange $ serverVRange $ smpCfg agentCfg, + proxiedRelayVRange = prevRange $ proxiedRelayVRange $ smpCfg agentCfg + } -- ntfCfgVPrev :: ProtocolClientConfig NTFVersion -- ntfCfgVPrev = (ntfCfg agentCfg) {clientALPN = Nothing, serverVRange = V.mkVersionRange (VersionNTF 1) (VersionNTF 1)} diff --git a/tests/SMPClient.hs b/tests/SMPClient.hs index 43aa22a76..f1d5af1db 100644 --- a/tests/SMPClient.hs +++ b/tests/SMPClient.hs @@ -349,6 +349,16 @@ proxyCfgShortTimeout = nt = NetworkTimeout {backgroundTimeout = 4_000000, interactiveTimeout = 4_000000} in cfg' {smpAgentCfg = aCfg {smpCfg = cCfg {networkConfig = (networkConfig cCfg) {tcpConnectTimeout = nt}}}} +proxyCfgVPrev :: AStoreType -> AServerConfig +proxyCfgVPrev msType = + updateCfg (proxyCfgMS msType) $ \cfg' -> + let aCfg = smpAgentCfg cfg' + cCfg = smpCfg aCfg + in cfg' + { smpServerVRange = prevRange $ smpServerVRange cfg', + smpAgentCfg = aCfg {smpCfg = cCfg {serverVRange = prevRange $ serverVRange cCfg}} + } + withSmpServerStoreMsgLogOn :: HasCallStack => (ASrvTransport, AStoreType) -> ServiceName -> (HasCallStack => ThreadId -> IO a) -> IO a withSmpServerStoreMsgLogOn (t, msType) = withSmpServerConfigOn t $ updateCfg (cfgMS msType) $ \cfg' -> cfg' {storeNtfsFile = Just testStoreNtfsFile, serverStatsBackupFile = Just testServerStatsBackupFile} diff --git a/tests/SMPProxyTests.hs b/tests/SMPProxyTests.hs index eca9fc5eb..91bae09a6 100644 --- a/tests/SMPProxyTests.hs +++ b/tests/SMPProxyTests.hs @@ -162,7 +162,7 @@ smpProxyTests = do twoServersFirstProxy test msType = twoServers_ (proxyCfgMS msType) (updateCfg (cfgMS msType) $ \cfg_ -> cfg_ {msgQueueQuota = 128, maxJournalMsgCount = 256}) test msType twoServersMoreConc test msType = twoServers_ (updateCfg (proxyCfgMS msType) $ \cfg_ -> cfg_ {serverClientConcurrency = 128}) (updateCfg (cfgMS msType) $ \cfg_ -> cfg_ {msgQueueQuota = 128, maxJournalMsgCount = 256}) test msType twoServersNoConc test msType = twoServers_ (updateCfg (proxyCfgMS msType) $ \cfg_ -> cfg_ {serverClientConcurrency = 1}) (updateCfg (cfgMS msType) $ \cfg_ -> cfg_ {msgQueueQuota = 128, maxJournalMsgCount = 256}) test msType - twoServersPrevProxy test msType = twoServers_ (prevServerVRange $ proxyCfgMS msType) (cfgMS msType) test msType + twoServersPrevProxy test msType = twoServers_ (proxyCfgVPrev msType) (cfgMS msType) test msType twoServersPrevRelay test msType = twoServers_ (proxyCfgMS msType) (prevServerVRange $ cfgMS msType) test msType prevServerVRange cfg' = updateCfg cfg' $ \cfg_ -> cfg_ {smpServerVRange = prevRange $ smpServerVRange cfg_} twoServers_ :: AServerConfig -> AServerConfig -> IO () -> AStoreType -> IO () @@ -184,7 +184,7 @@ deliverMessagesViaProxyVR clientVR proxyServ relayServ alg unsecuredMsgs secured g <- C.newRandom -- set up proxy ts <- getCurrentTime - pc' <- getProtocolClient g NRMInteractive (1, proxyServ, Nothing) defaultSMPClientConfig {serverVRange = clientVR} [] Nothing ts (\_ -> pure ()) + pc' <- getProtocolClient g NRMInteractive (1, proxyServ, Nothing) defaultSMPClientConfig {serverVRange = clientVR, proxiedRelayVRange = clientVR} [] Nothing ts (\_ -> pure ()) pc <- either (fail . show) pure pc' THAuthClient {} <- maybe (fail "getProtocolClient returned no thAuth") pure $ thAuth $ thParams pc -- set up relay