This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 0ec4d39707285d12608e6597671747c541ba245d
Author: Andrew Stitcher <[email protected]>
AuthorDate: Mon Aug 24 21:43:15 2026 -0400

    PROTON-2970: Validate the SASL state before handling a frame
    
    Each SASL body handler checked that the frame was one its role could 
receive - but not that it was one it was expecting at this point in the 
protocol exchange.
    
    Check the state of the exchange as well. A server takes an init only once it
    has posted its mechanisms, and a response only once it has posted a
    challenge. A client takes a mechanisms frame only before it has posted
    anything, and a challenge or an outcome only once it has posted an init or a
    response. Anything else is PN_ERR, as a frame arriving at the wrong role
    already was.
    
    The state tested is desired_state rather than last_state. A pipelining peer
    can legitimately send its next frame before we have actually written our 
own,
    so last_state can still be lagging behind the frame we have already 
committed
    to sending.
    
    Assisted-By: Claude Opus 5 <[email protected]>
---
 c/src/sasl/sasl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/c/src/sasl/sasl.c b/c/src/sasl/sasl.c
index 3e639de58..d757c8adc 100644
--- a/c/src/sasl/sasl.c
+++ b/c/src/sasl/sasl.c
@@ -904,6 +904,10 @@ int pn_do_init(pn_transport_t *transport, uint8_t 
frame_type, uint16_t channel,
 
   // We should only receive this if we are a sasl server
   if (sasl->client) return PN_ERR;
+  // Check the protocol state using desired_state not last_state: a pipelining 
peer can
+  // legitimately send its next frame before we've actually written out our 
own, so
+  // last_state can still be lagging behind the frame we've already committed 
to sending.
+  if (sasl->desired_state != SASL_POSTED_MECHANISMS) return PN_ERR;
 
   pn_bytes_t mech;
   pn_bytes_t recv;
@@ -936,6 +940,7 @@ int pn_do_mechanisms(pn_transport_t *transport, uint8_t 
frame_type, uint16_t cha
 
   // We should only receive this if we are a sasl client
   if (!sasl->client) return PN_ERR;
+  if (sasl->desired_state != SASL_NONE) return PN_ERR;
 
   pn_string_t *mechs = pn_string("");
 
@@ -1004,6 +1009,7 @@ int pn_do_challenge(pn_transport_t *transport, uint8_t 
frame_type, uint16_t chan
 
   // We should only receive this if we are a sasl client
   if (!sasl->client) return PN_ERR;
+  if (sasl->desired_state != SASL_POSTED_INIT && sasl->desired_state != 
SASL_POSTED_RESPONSE) return PN_ERR;
 
   pn_bytes_t recv;
 
@@ -1025,6 +1031,7 @@ int pn_do_response(pn_transport_t *transport, uint8_t 
frame_type, uint16_t chann
 
   // We should only receive this if we are a sasl server
   if (sasl->client) return PN_ERR;
+  if (sasl->desired_state != SASL_POSTED_CHALLENGE) return PN_ERR;
 
   pn_bytes_t recv;
 
@@ -1046,6 +1053,7 @@ int pn_do_outcome(pn_transport_t *transport, uint8_t 
frame_type, uint16_t channe
 
   // We should only receive this if we are a sasl client
   if (!sasl->client) return PN_ERR;
+  if (sasl->desired_state != SASL_POSTED_INIT && sasl->desired_state != 
SASL_POSTED_RESPONSE) return PN_ERR;
 
   uint8_t outcome;
   pn_bytes_t recv;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to