Skip to content

Commit ecd89cf

Browse files
committed
namespace: accept RSLV direct (non-forwarded) in addition to PFWD
RSLV was previously rejected by the server unless forwarded via PFWD, making the agent's direct fallback unreachable. Relax the server-side guard so RSLV is accepted both forwarded (preferred - hides client IP from the resolver) and direct (faster, exposes client IP). Mode choice is delegated to the client and the operator network config. - Server: drop the forwarded-only check on SResolver in verifyQueueTransmission. - Protocol: give SResolver a client role (SRMessaging) so SMPClient can connect in the Resolver role. checkRole accepts this because RSLV clients have no service binding (falls through to True). - Client: add directResolveName mirroring proxyResolveName via sendProtocolCommand with no auth and no entity (RSLV is noAuthCmd). - Agent: wire the direct path through sendOrProxySMPCommand so the PFWD-or-direct selection works the same as other commands.
1 parent 90de60e commit ecd89cf

4 files changed

Lines changed: 24 additions & 14 deletions

File tree

src/Simplex/Messaging/Agent/Client.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,16 +1993,16 @@ getQueueLink c nm userId server lnkId =
19931993
getViaProxy smp proxySess = proxyGetSMPQueueLink smp nm proxySess lnkId
19941994
getDirectly smp = getSMPQueueLink smp nm lnkId
19951995

1996-
-- | RSLV is proxy-only at the protocol level (SResolver has no direct client
1997-
-- role), so the direct fallback used by sendOrProxySMPCommand cannot succeed.
1998-
-- Surface a transport error if the network config (SPMNever, or no proxy
1999-
-- available for the destination) routes us to the direct path.
1996+
-- | Resolve a public-namespace name. Prefers PFWD (hides client IP from the
1997+
-- resolver) and falls back to a direct send when the proxy is unavailable
1998+
-- (faster but exposes the client IP). Mode selection is delegated to
1999+
-- `sendOrProxySMPCommand`, which honours the network config (SPMNever etc.).
20002000
resolveName :: AgentClient -> NetworkRequestMode -> UserId -> SMPServer -> NameOwner -> Text -> AM NameRecord
20012001
resolveName c nm userId server contract name =
20022002
snd <$> sendOrProxySMPCommand c nm userId server "" "RSLV" NoEntity resolveViaProxy resolveDirectly
20032003
where
20042004
resolveViaProxy smp proxySess = proxyResolveName smp nm proxySess contract name
2005-
resolveDirectly _ = throwE $ PCETransportError TENoServerAuth
2005+
resolveDirectly smp = directResolveName smp nm contract name
20062006

20072007
enableQueueNotifications :: AgentClient -> RcvQueue -> SMP.NtfPublicAuthKey -> SMP.RcvNtfPublicDhKey -> AM (SMP.NotifierId, SMP.RcvNtfPublicDhKey)
20082008
enableQueueNotifications c rq@RcvQueue {rcvId, rcvPrivateKey} notifierKey rcvNtfPublicDhKey =

src/Simplex/Messaging/Client.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ module Simplex.Messaging.Client
7474
connectSMPProxiedRelay,
7575
proxySMPMessage,
7676
proxyResolveName,
77+
directResolveName,
7778
forwardSMPTransmission,
7879
getSMPQueueInfo,
7980
sendProtocolCommand,
@@ -1047,17 +1048,26 @@ sendSMPMessage c nm spKey sId flags msg =
10471048
proxySMPMessage :: SMPClient -> NetworkRequestMode -> ProxiedRelay -> Maybe SndPrivateAuthKey -> SenderId -> MsgFlags -> MsgBody -> ExceptT SMPClientError IO (Either ProxyClientError ())
10481049
proxySMPMessage c nm proxiedRelay spKey sId flags msg = proxyOKSMPCommand c nm proxiedRelay spKey sId (SEND flags msg)
10491050

1050-
-- | Resolve a public-namespace name via PFWD. RSLV is forwarded-only on the
1051-
-- server, so this is the only client-side path. Mirrors `proxySMPMessage`'s
1052-
-- shape; routes through `proxySMPCommand` and pattern-matches the expected
1053-
-- NAME response.
1051+
-- | Resolve a public-namespace name via PFWD. Preferred path - hides the
1052+
-- client IP from the resolver. Mirrors `proxySMPMessage`'s shape; routes
1053+
-- through `proxySMPCommand` and pattern-matches the expected NAME response.
10541054
proxyResolveName :: SMPClient -> NetworkRequestMode -> ProxiedRelay -> NameOwner -> Text -> ExceptT SMPClientError IO (Either ProxyClientError NameRecord)
10551055
proxyResolveName c nm proxiedRelay contract name =
10561056
proxySMPCommand c nm proxiedRelay Nothing NoEntity (RSLV RslvRequest {name, contract}) >>= \case
10571057
Right (NAME nr) -> pure $ Right nr
10581058
Right r -> throwE $ unexpectedResponse r
10591059
Left e -> pure $ Left e
10601060

1061+
-- | Direct (non-PFWD) name resolution. Exposes the client IP to the resolver;
1062+
-- callers that want anonymity should use `proxyResolveName` via the standard
1063+
-- proxy fallback in the agent. RSLV requires no entity ID or authorization
1064+
-- (see `noAuthCmd` in Protocol.hs).
1065+
directResolveName :: SMPClient -> NetworkRequestMode -> NameOwner -> Text -> ExceptT SMPClientError IO NameRecord
1066+
directResolveName c nm contract name =
1067+
sendProtocolCommand c nm Nothing NoEntity (Cmd SResolver (RSLV RslvRequest {name, contract})) >>= \case
1068+
NAME nr -> pure nr
1069+
r -> throwE $ unexpectedResponse r
1070+
10611071
-- | Acknowledge message delivery (server deletes the message).
10621072
--
10631073
-- https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#acknowledge-message-delivery

src/Simplex/Messaging/Protocol.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ partyClientRole = \case
488488
SSenderLink -> Just SRMessaging
489489
SProxiedClient -> Just SRMessaging
490490
SProxyService -> Just SRProxy
491-
SResolver -> Nothing
491+
SResolver -> Just SRMessaging
492492
{-# INLINE partyClientRole #-}
493493

494494
partyServiceRole :: ServiceParty p => SParty p -> SMPServiceRole

src/Simplex/Messaging/Server.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ verifyLoadedQueue forwarded service thAuth t@(tAuth, authorized, (corrId, _, _))
12501250
Left e -> VRFailed e
12511251

12521252
verifyQueueTransmission :: forall s. Bool -> Maybe THPeerClientService -> Maybe (THandleAuth 'TServer) -> SignedTransmission Cmd -> Maybe (StoreQueue s, QueueRec) -> VerificationResult s
1253-
verifyQueueTransmission forwarded service thAuth (tAuth, authorized, (corrId, entId, command@(Cmd p cmd))) q_
1253+
verifyQueueTransmission _forwarded service thAuth (tAuth, authorized, (corrId, entId, command@(Cmd p cmd))) q_
12541254
| not checkRole = VRFailed $ CMD PROHIBITED
12551255
| not verifyServiceSig = VRFailed SERVICE
12561256
| otherwise = vc p cmd
@@ -1270,9 +1270,9 @@ verifyQueueTransmission forwarded service thAuth (tAuth, authorized, (corrId, en
12701270
vc SNotifierService NSUBS {} = verifyServiceCmd
12711271
vc SProxiedClient _ = VRVerified Nothing
12721272
vc SProxyService (RFWD _) = VRVerified Nothing
1273-
vc SResolver (RSLV _)
1274-
| forwarded = VRVerified Nothing
1275-
| otherwise = VRFailed $ CMD PROHIBITED
1273+
-- RSLV is accepted both forwarded (via PFWD, preferred - hides client IP from resolver)
1274+
-- and direct (client->resolver, faster, exposes client IP). Mode is chosen by the client.
1275+
vc SResolver (RSLV _) = VRVerified Nothing
12761276
checkRole = case (service, partyClientRole p) of
12771277
(Just THClientService {serviceRole}, Just role) -> serviceRole == role
12781278
_ -> True

0 commit comments

Comments
 (0)