@@ -1390,6 +1390,7 @@ QuicErrorCodeToStatus(
1390
1390
case QUIC_ERROR_NO_ERROR : return QUIC_STATUS_SUCCESS ;
1391
1391
case QUIC_ERROR_CONNECTION_REFUSED : return QUIC_STATUS_CONNECTION_REFUSED ;
1392
1392
case QUIC_ERROR_PROTOCOL_VIOLATION : return QUIC_STATUS_PROTOCOL_ERROR ;
1393
+ case QUIC_ERROR_APPLICATION_ERROR :
1393
1394
case QUIC_ERROR_CRYPTO_USER_CANCELED : return QUIC_STATUS_USER_CANCELED ;
1394
1395
case QUIC_ERROR_CRYPTO_HANDSHAKE_FAILURE : return QUIC_STATUS_HANDSHAKE_FAILURE ;
1395
1396
case QUIC_ERROR_CRYPTO_NO_APPLICATION_PROTOCOL : return QUIC_STATUS_ALPN_NEG_FAILURE ;
@@ -1450,27 +1451,6 @@ QuicConnTryClose(
1450
1451
}
1451
1452
}
1452
1453
1453
- if (!ClosedRemotely ) {
1454
-
1455
- if ((Flags & QUIC_CLOSE_APPLICATION ) &&
1456
- Connection -> Crypto .TlsState .WriteKey < QUIC_PACKET_KEY_1_RTT ) {
1457
- //
1458
- // Application close can only happen if we are using 1-RTT keys.
1459
- // Otherwise we have to send "user_canceled" TLS error code as a
1460
- // connection close. Overwrite all application provided parameters.
1461
- //
1462
- Flags &= ~QUIC_CLOSE_APPLICATION ;
1463
- ErrorCode = QUIC_ERROR_CRYPTO_USER_CANCELED ;
1464
- RemoteReasonPhrase = NULL ;
1465
- RemoteReasonPhraseLength = 0 ;
1466
-
1467
- QuicTraceLogConnInfo (
1468
- CloseUserCanceled ,
1469
- Connection ,
1470
- "Connection close using user canceled error" );
1471
- }
1472
- }
1473
-
1474
1454
BOOLEAN ResultQuicStatus = !!(Flags & QUIC_CLOSE_QUIC_STATUS );
1475
1455
1476
1456
BOOLEAN IsFirstCloseForConnection = TRUE;
@@ -3694,6 +3674,15 @@ QuicConnGetKeyOrDeferDatagram(
3694
3674
return FALSE;
3695
3675
}
3696
3676
3677
+ if (QuicConnIsServer (Connection ) && !Connection -> State .HandshakeConfirmed &&
3678
+ Packet -> KeyType == QUIC_PACKET_KEY_1_RTT ) {
3679
+ //
3680
+ // A server MUST NOT process incoming 1-RTT protected packets before the TLS
3681
+ // handshake is complete.
3682
+ //
3683
+ return FALSE;
3684
+ }
3685
+
3697
3686
_Analysis_assume_ (Packet -> KeyType >= 0 && Packet -> KeyType < QUIC_PACKET_KEY_COUNT );
3698
3687
if (Connection -> Crypto .TlsState .ReadKeys [Packet -> KeyType ] == NULL ) {
3699
3688
//
@@ -5090,12 +5079,33 @@ QuicConnRecvFrames(
5090
5079
if (Frame .ApplicationClosed ) {
5091
5080
Flags |= QUIC_CLOSE_APPLICATION ;
5092
5081
}
5093
- QuicConnTryClose (
5094
- Connection ,
5095
- Flags ,
5096
- Frame .ErrorCode ,
5097
- Frame .ReasonPhrase ,
5098
- (uint16_t )Frame .ReasonPhraseLength );
5082
+
5083
+ if (!Frame .ApplicationClosed && Frame .ErrorCode == QUIC_ERROR_APPLICATION_ERROR ) {
5084
+ //
5085
+ // The APPLICATION_ERROR transport error should be sent only
5086
+ // when closing the connection before the handshake is
5087
+ // confirmed. In such case, we can also expect peer to send the
5088
+ // application CONNECTION_CLOSE frame in a 1-RTT packet
5089
+ // (presumably also in the same UDP datagram).
5090
+ //
5091
+ // We want to prioritize reporting the application-layer error
5092
+ // code to the application, so we postpone the call to
5093
+ // QuicConnTryClose and check again after processing incoming
5094
+ // datagrams in case it does not arrive.
5095
+ //
5096
+ QuicTraceEvent (
5097
+ ConnDelayCloseApplicationError ,
5098
+ "[conn][%p] Received APPLICATION_ERROR error, delaying close in expectation of a 1-RTT CONNECTION_CLOSE frame." ,
5099
+ Connection );
5100
+ Connection -> State .DelayedApplicationError = TRUE;
5101
+ } else {
5102
+ QuicConnTryClose (
5103
+ Connection ,
5104
+ Flags ,
5105
+ Frame .ErrorCode ,
5106
+ Frame .ReasonPhrase ,
5107
+ (uint16_t )Frame .ReasonPhraseLength );
5108
+ }
5099
5109
5100
5110
AckEliciting = TRUE;
5101
5111
Packet -> HasNonProbingFrame = TRUE;
@@ -5126,7 +5136,7 @@ QuicConnRecvFrames(
5126
5136
HandshakeConfirmedFrame ,
5127
5137
Connection ,
5128
5138
"Handshake confirmed (frame)" );
5129
- QuicCryptoHandshakeConfirmed (& Connection -> Crypto );
5139
+ QuicCryptoHandshakeConfirmed (& Connection -> Crypto , TRUE );
5130
5140
}
5131
5141
5132
5142
AckEliciting = TRUE;
@@ -5628,9 +5638,7 @@ QuicConnRecvDatagrams(
5628
5638
Packet -> BufferLength - (uint16_t )(Packet -> AvailBuffer - Packet -> Buffer );
5629
5639
}
5630
5640
5631
- if (Connection -> Crypto .CertValidationPending ||
5632
- Connection -> Crypto .TicketValidationPending ||
5633
- !QuicConnRecvHeader (
5641
+ if (!QuicConnRecvHeader (
5634
5642
Connection ,
5635
5643
Packet ,
5636
5644
Cipher + BatchCount * CXPLAT_HP_SAMPLE_LENGTH )) {
@@ -5737,6 +5745,20 @@ QuicConnRecvDatagrams(
5737
5745
BatchCount = 0 ; // cppcheck-suppress unreadVariable; NOLINT
5738
5746
}
5739
5747
5748
+ if (Connection -> State .DelayedApplicationError && Connection -> CloseStatus == 0 ) {
5749
+ //
5750
+ // We received transport APPLICATION_ERROR, but didn't receive the expected
5751
+ // CONNECTION_ERROR frame, so close the connection with originally postponed
5752
+ // APPLICATION_ERROR.
5753
+ //
5754
+ QuicConnTryClose (
5755
+ Connection ,
5756
+ QUIC_CLOSE_REMOTE | QUIC_CLOSE_SEND_NOTIFICATION ,
5757
+ QUIC_ERROR_APPLICATION_ERROR ,
5758
+ NULL ,
5759
+ (uint16_t )0 );
5760
+ }
5761
+
5740
5762
if (RecvState .ResetIdleTimeout ) {
5741
5763
QuicConnResetIdleTimeout (Connection );
5742
5764
}
0 commit comments