You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TLS peer-close handling does not follow the negotiated protocol version #177
When TLS receive reaches authenticated peer close_notify, HIO records only generic receive cutoff. It does not consult SSLSocket.version(), even though TLS 1.2 and TLS 1.3 require different treatment of the local transmit direction.
Using one policy for both versions either discards valid TLS 1.3 output or permits output that TLS 1.2 requires the recipient to abandon. Missing or unsupported negotiated versions also need an explicit fail-closed outcome rather than silently inheriting the permissive TLS 1.3 path.
This issue starts only after #173 has distinguished authenticated close_notify from abrupt TCP EOF.
Protocol contract
TLS 1.2 requires the recipient of close_notify to send its own notification, close immediately, and discard pending writes.
TLS 1.3 changes that rule. Peer close_notify closes the peer's write direction but has no effect on the local write direction. Accepted local output may continue before local closure.
The policy must use the version negotiated for this connection, returned by SSLSocket.version(), not the versions enabled on the context. A return value of None after authenticated closure indicates inconsistent endpoint state; an unknown value has no defined HIO policy. Both must fail closed.
Required behavior
TLS 1.3
Mark local receive closed.
Keep transmit available.
Preserve and continue sending accepted output.
Do not start local TLS shutdown solely because the peer sent close_notify.
Record no transport error.
TLS 1.2
Mark both directions terminal for application I/O.
Preserve queued bytes for inspection.
If bytes are stranded, retain a TransmitClosedError with the exact count.
The exact state names may differ, but the negotiated-version decision, directional behavior, exact stranded-byte accounting, and retained failure must remain observable.
Buffered plaintext and WANT_READ recurrence belong to #176. The close service must drain pending plaintext before the first local unwrap() and wait for receive processing to consume peer close_notify before retrying it.
Output accounting
TLS 1.2's required discard is an application-transmit decision, not permission to erase diagnostics. Bytes already accepted into txbs should remain available for inspection even though they can no longer be sent. The retained error must report the exact byte count so owners can distinguish clean reciprocal closure from accepted output loss.
Problem
When TLS receive reaches authenticated peer
close_notify, HIO records only generic receive cutoff. It does not consultSSLSocket.version(), even though TLS 1.2 and TLS 1.3 require different treatment of the local transmit direction.Using one policy for both versions either discards valid TLS 1.3 output or permits output that TLS 1.2 requires the recipient to abandon. Missing or unsupported negotiated versions also need an explicit fail-closed outcome rather than silently inheriting the permissive TLS 1.3 path.
This issue starts only after #173 has distinguished authenticated
close_notifyfrom abrupt TCP EOF.Protocol contract
TLS 1.2 requires the recipient of
close_notifyto send its own notification, close immediately, and discard pending writes.TLS 1.3 changes that rule. Peer
close_notifycloses the peer's write direction but has no effect on the local write direction. Accepted local output may continue before local closure.The policy must use the version negotiated for this connection, returned by
SSLSocket.version(), not the versions enabled on the context. A return value ofNoneafter authenticated closure indicates inconsistent endpoint state; an unknown value has no defined HIO policy. Both must fail closed.Required behavior
TLS 1.3
close_notify.TLS 1.2
TransmitClosedErrorwith the exact count.Missing or unsupported version
VersionErroridentifying the missing or unsupported value.Reproduction
close_notify.mainrecords only generic receive cutoff instead of abandoning application transmission and starting reciprocal shutdown.version()returningNoneand an unsupported value.Equivalent regressions are required for
ClientTlsandRemoterTls, including zero and nonzero queued-output cases.Proposed direction
Route authenticated peer closure through a version-aware handler:
The exact state names may differ, but the negotiated-version decision, directional behavior, exact stranded-byte accounting, and retained failure must remain observable.
Buffered plaintext and WANT_READ recurrence belong to #176. The close service must drain pending plaintext before the first local
unwrap()and wait for receive processing to consume peerclose_notifybefore retrying it.Output accounting
TLS 1.2's required discard is an application-transmit decision, not permission to erase diagnostics. Bytes already accepted into
txbsshould remain available for inspection even though they can no longer be sent. The retained error must report the exact byte count so owners can distinguish clean reciprocal closure from accepted output loss.Dependencies
Acceptance criteria
SSLSocket.version().VersionError.