-
Notifications
You must be signed in to change notification settings - Fork 530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Certificate rejection via ConnectionCertificateValidationComplete leads to connection timeout. #4132
Comments
I think I know what is going on. As per RFC 9001
This means the mistake is in the client sending the CONNECTION_CLOSE on 1-RTT level. There is also this comment msquic/src/core/packet_builder.c Lines 529 to 537 in ae3db5c
I don't know how to go about sending the CONNECTION_CLOSE/PING frames on two protection levels, but in this specific scenario the code does not get into that block anyway because of msquic/src/core/packet_builder.c Lines 496 to 503 in ae3db5c
In the working (synchronous) case, there was data (ACKs) to be sent on the Handshake level, so the CONNECTION_CLOSE piggybacked on top of that. I had some success with fixing it in PacketBuilder diff --git a/src/core/packet_builder.c b/src/core/packet_builder.c
index 84d1a2705..52704b836 100644
--- a/src/core/packet_builder.c
+++ b/src/core/packet_builder.c
@@ -479,8 +479,22 @@ QuicPacketBuilderGetPacketTypeAndKeyForControlFrames(
CXPLAT_DBG_ASSERT(SendFlags != 0);
QuicSendValidate(&Builder->Connection->Send);
+ QUIC_PACKET_KEY_TYPE MaxKeyType = Connection->Crypto.TlsState.WriteKey;
+
+ if (QuicConnIsClient(Connection) &&
+ !Connection->State.HandshakeConfirmed &&
+ MaxKeyType == QUIC_PACKET_KEY_1_RTT &&
+ (SendFlags & QUIC_CONN_SEND_FLAG_CONNECTION_CLOSE)) {
+ //
+ // Server is not allowed to process 1-RTT packets until the handshake is confirmed and since we are
+ // closing the connection, the handshake is unlikely to complete. Ensure the CONNECTION_CLOSE is sent
+ // in a packet which server can process.
+ //
+ MaxKeyType = QUIC_PACKET_KEY_HANDSHAKE;
+ }
+
for (QUIC_PACKET_KEY_TYPE KeyType = 0;
- KeyType <= Connection->Crypto.TlsState.WriteKey;
+ KeyType <= MaxKeyType;
++KeyType) {
if (KeyType == QUIC_PACKET_KEY_0_RTT) {
@@ -538,7 +552,7 @@ QuicPacketBuilderGetPacketTypeAndKeyForControlFrames(
if (Connection->Crypto.TlsState.WriteKey == QUIC_PACKET_KEY_0_RTT) {
*PacketKeyType = QUIC_PACKET_KEY_INITIAL;
} else {
- *PacketKeyType = Connection->Crypto.TlsState.WriteKey;
+ *PacketKeyType = MaxKeyType;
}
return TRUE;
} |
@nibanks does the fix above sound reasonable? Should I open a PR? |
Go ahead and create the PR. We can go from there. Let's see if all the tests still pass. |
* Allow switching execution profiles using env vars * Quick and dirty version to enable benchmarking * Don't call callbacks from MsQuic threads * Remove unintentional changes * Offload parsing to threadpool as well * Customize TLS ALERT code * Code review feedback * Apply suggestions from code review Co-authored-by: Marie Píchová <[email protected]> * use ConfigureAwaitOptions.ForceYielding * Version check to work around microsoft/msquic#4132 * Use configure await to yield to threadpool * Fix functionality on older msquic versions --------- Co-authored-by: Marie Píchová <[email protected]>
Describe the bug
I am offloading computation-heavy certificate validation to a non-MsQuic thread in System.Net.Quic, and a unit test where the cert is rejected keeps failing.
Wireshark capture of when the
ConnectionCertificateValidationComplete
function is invoked from inside thePEER_CERTIFICATE_RECEIVED
handler:Notably, the Connection Close frame is sent at the Handshake protection level. This works fine.
When the invocation is moved to be done later from another thread:
Note that this time, the Connection Close is sent at 1RTT level, which seems to get ignored by the server. The connection attempt times out and get's closed by the server (the last line). The capture is attached below, together with sslkeylogfile to decrypt it.
quic-cert-validation.zip
Affected OS
Additional OS information
Reproduced on Windows, didn't try other OSes
MsQuic version
main
Steps taken to reproduce bug
Use
ConnectionCertificateValidationComplete
to reject certificate from another thread.Expected behavior
The server-side connection receives TLS alert which was sent by the client.
Actual outcome
The connection attempt times out
Additional details
No response
The text was updated successfully, but these errors were encountered: