From d2d834ad1617b4740125a8c9202e41810a98228b Mon Sep 17 00:00:00 2001 From: Evgeny Date: Mon, 9 Mar 2026 12:22:42 +0000 Subject: [PATCH 1/3] agent: validate destination relay certificate, allow 3-4 certificate chains (#1717) Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> --- src/Simplex/Messaging/Client.hs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Simplex/Messaging/Client.hs b/src/Simplex/Messaging/Client.hs index 27840b092..3ffdda145 100644 --- a/src/Simplex/Messaging/Client.hs +++ b/src/Simplex/Messaging/Client.hs @@ -167,6 +167,7 @@ import Simplex.Messaging.Transport import Simplex.Messaging.Transport.Client (SocksAuth (..), SocksProxyWithAuth (..), TransportClientConfig (..), TransportHost (..), defaultSMPPort, runTransportClient) import Simplex.Messaging.Transport.HTTP2 (httpALPN11) import Simplex.Messaging.Transport.KeepAlive +import Simplex.Messaging.Transport.Shared (ChainCertificates (..), chainIdCaCerts, x509validate) import Simplex.Messaging.Util import Simplex.Messaging.Version import System.Mem.Weak (Weak, deRefWeak) @@ -1066,26 +1067,30 @@ 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 {client_ = PClient {tcpConnectTimeout, tcpTimeout}} nm relayServ@ProtocolServer {keyHash = C.KeyHash kh} proxyAuth +connectSMPProxiedRelay c@ProtocolClient {client_ = PClient {tcpConnectTimeout, tcpTimeout}} nm relayServ@ProtocolServer {port = relayPort, keyHash = C.KeyHash kh} proxyAuth | thVersion (thParams c) >= sendingProxySMPVersion = sendProtocolCommand_ c nm Nothing tOut Nothing NoEntity (Cmd SProxiedClient (PRXY relayServ proxyAuth)) >>= \case PKEY sId vr (CertChainPubKey chain key) -> case supportedClientSMPRelayVRange `compatibleVersion` vr of Nothing -> throwE $ transportErr TEVersion - Just (Compatible v) -> liftEitherWith (const $ transportErr $ TEHandshake IDENTITY) $ ProxiedRelay sId v proxyAuth <$> validateRelay chain key + Just (Compatible v) -> do + relayKey <- liftEitherWith (const $ transportErr $ TEHandshake IDENTITY) =<< liftIO (runExceptT $ validateRelay chain key) + pure $ ProxiedRelay sId v proxyAuth relayKey r -> throwE $ unexpectedResponse r | otherwise = throwE $ PCETransportError TEVersion where tOut = Just $ netTimeoutInt tcpConnectTimeout nm + netTimeoutInt tcpTimeout nm transportErr = PCEProtocolError . PROXY . BROKER . TRANSPORT - validateRelay :: X.CertificateChain -> X.SignedExact X.PubKey -> Either String C.PublicKeyX25519 - validateRelay (X.CertificateChain cert) exact = do - serverKey <- case cert of - [leaf, ca] - | XV.Fingerprint kh == XV.getFingerprint ca X.HashSHA256 -> - C.x509ToPublic' $ X.certPubKey $ X.signedObject $ X.getSigned leaf - _ -> throwError "bad certificate" - C.x509ToPublic' =<< C.verifyX509 serverKey exact + hostName = B.unpack $ strEncode $ transportHost' c + validateRelay :: X.CertificateChain -> X.SignedExact X.PubKey -> ExceptT String IO C.PublicKeyX25519 + validateRelay chain exact = case chainIdCaCerts chain of + CCValid {leafCert, idCert, caCert} + | XV.Fingerprint kh == XV.getFingerprint idCert X.HashSHA256 -> do + errs <- liftIO $ x509validate caCert (hostName, B.pack relayPort) chain + unless (null errs) $ throwError "bad certificate" + serverKey <- liftEither $ C.x509ToPublic' $ X.certPubKey $ X.signedObject $ X.getSigned leafCert + liftEither $ C.x509ToPublic' =<< C.verifyX509 serverKey exact + _ -> throwError "bad certificate" data ProxiedRelay = ProxiedRelay { prSessionId :: SessionId, From 3a627a95990678fa89828da0336597552296cb5e Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:23:03 +0000 Subject: [PATCH 2/3] tests: use correct web CA certificate in CLI static files test (#1727) --- tests/CLITests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CLITests.hs b/tests/CLITests.hs index 798b3e939..66af74ab8 100644 --- a/tests/CLITests.hs +++ b/tests/CLITests.hs @@ -159,7 +159,7 @@ smpServerTestStatic = do html <- BL.readFile $ webPath <> "/index.html" -- "external" CA signing HTTP credentials - Fingerprint fpHTTP <- loadFileFingerprint "tests/fixtures/ca.crt" + Fingerprint fpHTTP <- loadFileFingerprint "tests/fixtures/web_ca.crt" let caHTTP = C.KeyHash fpHTTP manager <- H1.newManager H1.defaultManagerSettings H1.responseBody <$> H1.httpLbs "http://127.0.0.1:8000" manager `shouldReturn` html From 1449e6418ce2cbe49644a73aa01ccc3308983b6f Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 9 Mar 2026 12:25:08 +0000 Subject: [PATCH 3/3] 6.5.0.10 --- simplexmq.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplexmq.cabal b/simplexmq.cabal index 5dac440c0..41997e5d3 100644 --- a/simplexmq.cabal +++ b/simplexmq.cabal @@ -1,7 +1,7 @@ cabal-version: 1.12 name: simplexmq -version: 6.5.0.9 +version: 6.5.0.10 synopsis: SimpleXMQ message broker description: This package includes <./docs/Simplex-Messaging-Server.html server>, <./docs/Simplex-Messaging-Client.html client> and