mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-09 10:00:57 +03:00
Reviewed By: mjoras Differential Revision: D15293208 fbshipit-source-id: 4ea5bf6c2c335a5c034341086f9348451bed827e
410 lines
15 KiB
C++
410 lines
15 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*/
|
|
|
|
#include <quic/server/handshake/DefaultAppTokenValidator.h>
|
|
|
|
#include <quic/QuicConstants.h>
|
|
#include <quic/api/test/Mocks.h>
|
|
#include <quic/server/state/ServerStateMachine.h>
|
|
|
|
#include <fizz/server/ResumptionState.h>
|
|
#include <folly/Optional.h>
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <cstdint>
|
|
|
|
using namespace fizz;
|
|
using namespace fizz::server;
|
|
using namespace quic;
|
|
using namespace testing;
|
|
|
|
namespace quic {
|
|
namespace test {
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestValidParams) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_TRUE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(
|
|
DefaultAppTokenValidatorTest,
|
|
TestValidUnequalParamsUpdateTransportSettings) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
auto initialMaxData =
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize;
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
initialMaxData - 1,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_TRUE(validator.validate(resState));
|
|
|
|
EXPECT_EQ(
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
initialMaxData - 1);
|
|
EXPECT_EQ(conn.flowControlState.windowSize, initialMaxData - 1);
|
|
EXPECT_EQ(conn.flowControlState.advertisedMaxOffset, initialMaxData - 1);
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidNullAppToken) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
ResumptionState resState;
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidVersionMismatch) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::QUIC_DRAFT;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
QuicVersion::MVFST,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidEmptyTransportParams) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams.negotiated_version = *conn.version;
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidMissingParams) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams.negotiated_version = *conn.version;
|
|
auto& params = appToken.transportParams;
|
|
params.parameters.push_back(encodeIntegerParameter(
|
|
TransportParameterId::initial_max_stream_data_bidi_local,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize));
|
|
params.parameters.push_back(encodeIntegerParameter(
|
|
TransportParameterId::initial_max_stream_data_bidi_remote,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize));
|
|
params.parameters.push_back(encodeIntegerParameter(
|
|
TransportParameterId::initial_max_stream_data_uni,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize));
|
|
params.parameters.push_back(encodeIntegerParameter(
|
|
TransportParameterId::ack_delay_exponent,
|
|
conn.transportSettings.ackDelayExponent));
|
|
params.parameters.push_back(encodeIntegerParameter(
|
|
TransportParameterId::max_packet_size,
|
|
conn.transportSettings.maxRecvPacketSize));
|
|
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidRedundantParameter) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
appToken.transportParams.parameters.push_back(
|
|
encodeIntegerParameter(TransportParameterId::idle_timeout, 100));
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidDecreasedInitialMaxStreamData) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize + 1,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize + 1,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize + 1,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestChangedIdleTimeout) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count() + 100,
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
TEST(DefaultAppTokenValidatorTest, TestDecreasedInitialMaxStreams) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialMaxStreamsBidi + 1,
|
|
conn.transportSettings.advertisedInitialMaxStreamsUni + 1);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
|
|
/* TODO junqiw change validateEarlyAppParam to folly::Function
|
|
TEST(DefaultAppTokenValidatorTest, TestInvalidAppParams) {
|
|
QuicServerConnectionState conn;
|
|
conn.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn.version = QuicVersion::MVFST;
|
|
|
|
MockConnectionCallback connCallback;
|
|
|
|
AppToken appToken;
|
|
appToken.transportParams = createTicketTransportParameters(
|
|
*conn.version,
|
|
conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn.transportSettings.idleTimeout.count(),
|
|
conn.transportSettings.maxRecvPacketSize,
|
|
conn.transportSettings.ackDelayExponent);
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken);
|
|
|
|
DefaultAppTokenValidator validator(&conn, &connCallback);
|
|
EXPECT_FALSE(validator.validate(resState));
|
|
}
|
|
*/
|
|
|
|
class SourceAddressTokenTest : public Test {
|
|
public:
|
|
void SetUp() override {
|
|
conn_.peerAddress = folly::SocketAddress("1.2.3.4", 443);
|
|
conn_.version = QuicVersion::MVFST;
|
|
|
|
appToken_.transportParams = createTicketTransportParameters(
|
|
*conn_.version,
|
|
conn_.transportSettings.idleTimeout.count(),
|
|
conn_.transportSettings.maxRecvPacketSize,
|
|
conn_.transportSettings.advertisedInitialConnectionWindowSize,
|
|
conn_.transportSettings.advertisedInitialBidiLocalStreamWindowSize,
|
|
conn_.transportSettings.advertisedInitialBidiRemoteStreamWindowSize,
|
|
conn_.transportSettings.advertisedInitialUniStreamWindowSize,
|
|
conn_.transportSettings.advertisedInitialMaxStreamsBidi,
|
|
conn_.transportSettings.advertisedInitialMaxStreamsUni);
|
|
}
|
|
|
|
void encodeAndValidate(bool acceptZeroRtt = true) {
|
|
ResumptionState resState;
|
|
resState.appToken = encodeAppToken(appToken_);
|
|
|
|
DefaultAppTokenValidator validator(&conn_);
|
|
EXPECT_EQ(validator.validate(resState), acceptZeroRtt);
|
|
}
|
|
|
|
protected:
|
|
QuicServerConnectionState conn_;
|
|
AppToken appToken_;
|
|
};
|
|
|
|
TEST_F(SourceAddressTokenTest, EmptySourceToken) {
|
|
encodeAndValidate();
|
|
|
|
EXPECT_EQ(
|
|
conn_.writableBytesLimit.value(),
|
|
conn_.transportSettings.limitedCwndInMss * conn_.udpSendPacketLen);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
TEST_F(SourceAddressTokenTest, OneSourceTokensNoMatch) {
|
|
appToken_.sourceAddresses = {folly::IPAddress("1.2.3.5")};
|
|
encodeAndValidate();
|
|
|
|
EXPECT_EQ(
|
|
conn_.writableBytesLimit.value(),
|
|
conn_.transportSettings.limitedCwndInMss * conn_.udpSendPacketLen);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(
|
|
folly::IPAddress("1.2.3.5"), conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
TEST_F(SourceAddressTokenTest, MaxNumSourceTokensNoMatch) {
|
|
appToken_.sourceAddresses = {folly::IPAddress("1.2.3.5"),
|
|
folly::IPAddress("1.2.3.6"),
|
|
folly::IPAddress("1.2.3.7")};
|
|
encodeAndValidate();
|
|
|
|
EXPECT_EQ(
|
|
conn_.writableBytesLimit.value(),
|
|
conn_.transportSettings.limitedCwndInMss * conn_.udpSendPacketLen);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(
|
|
folly::IPAddress("1.2.3.6"),
|
|
folly::IPAddress("1.2.3.7"),
|
|
conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
TEST_F(SourceAddressTokenTest, OneSourceTokensMatch) {
|
|
appToken_.sourceAddresses = {folly::IPAddress("1.2.3.4")};
|
|
encodeAndValidate();
|
|
|
|
EXPECT_FALSE(conn_.writableBytesLimit);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
TEST_F(SourceAddressTokenTest, ThreeSourceTokensMatch) {
|
|
appToken_.sourceAddresses = {folly::IPAddress("1.2.3.5"),
|
|
folly::IPAddress("1.2.3.4"),
|
|
folly::IPAddress("1.2.3.7")};
|
|
encodeAndValidate();
|
|
|
|
EXPECT_FALSE(conn_.writableBytesLimit);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(
|
|
folly::IPAddress("1.2.3.5"),
|
|
folly::IPAddress("1.2.3.7"),
|
|
conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
class SourceAddressTokenRejectNoMatchPolicyTest
|
|
: public SourceAddressTokenTest {
|
|
public:
|
|
void SetUp() override {
|
|
SourceAddressTokenTest::SetUp();
|
|
conn_.transportSettings.zeroRttSourceTokenMatchingPolicy =
|
|
ZeroRttSourceTokenMatchingPolicy::REJECT_IF_NO_EXACT_MATCH;
|
|
}
|
|
};
|
|
|
|
TEST_F(SourceAddressTokenRejectNoMatchPolicyTest, EmptySourceToken) {
|
|
encodeAndValidate(false);
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(conn_.peerAddress.getIPAddress()));
|
|
}
|
|
|
|
TEST_F(SourceAddressTokenRejectNoMatchPolicyTest, OneSourceTokensNoMatch) {
|
|
appToken_.sourceAddresses = {folly::IPAddress("1.2.3.5")};
|
|
encodeAndValidate(false);
|
|
|
|
ASSERT_THAT(
|
|
conn_.tokenSourceAddresses,
|
|
ElementsAre(
|
|
folly::IPAddress("1.2.3.5"), conn_.peerAddress.getIPAddress()));
|
|
}
|
|
} // namespace test
|
|
} // namespace quic
|