/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include namespace quic { DefaultAppTokenValidator::DefaultAppTokenValidator( QuicServerConnectionState* conn) : conn_(conn) {} bool DefaultAppTokenValidator::validate( const fizz::server::ResumptionState& resumptionState) const { conn_->transportParamsMatching = false; conn_->sourceTokenMatching = false; if (!resumptionState.appToken) { VLOG(10) << "App token does not exist"; return false; } auto appToken = decodeAppToken(*resumptionState.appToken); if (!appToken) { VLOG(10) << "Failed to decode app token"; return false; } if (conn_->version != appToken->version) { VLOG(10) << "QuicVersion mismatch"; return false; } auto& params = appToken->transportParams.parameters; // TODO T33454954 Simplify ticket transport params. see comments in D9324131 // Currenly only initialMaxData, initialMaxStreamData, ackDelayExponent, and // maxRecvPacketSize are written into the ticket. In case new parameters // are added for making early data decision (although not likely), this // validator fails the check if number of parameters is not // kExpectedNumOfParamsInTheTicket. if (params.size() != kExpectedNumOfParamsInTheTicket) { VLOG(10) << "Unexpected number of parameters in the ticket"; return false; } auto ticketIdleTimeout = getIntegerParameter(TransportParameterId::idle_timeout, params); if (!ticketIdleTimeout || conn_->transportSettings.idleTimeout != std::chrono::milliseconds(*ticketIdleTimeout)) { VLOG(10) << "Changed idle timeout"; return false; } auto ticketPacketSize = getIntegerParameter(TransportParameterId::max_packet_size, params); if (!ticketPacketSize || conn_->transportSettings.maxRecvPacketSize < *ticketPacketSize) { VLOG(10) << "Decreased max receive packet size"; return false; } // if the current max data is less than the one advertised previously we // reject the early data auto ticketMaxData = getIntegerParameter(TransportParameterId::initial_max_data, params); if (!ticketMaxData || conn_->transportSettings.advertisedInitialConnectionWindowSize < *ticketMaxData) { VLOG(10) << "Decreased max data"; return false; } auto ticketMaxStreamDataBidiLocal = getIntegerParameter( TransportParameterId::initial_max_stream_data_bidi_local, params); auto ticketMaxStreamDataBidiRemote = getIntegerParameter( TransportParameterId::initial_max_stream_data_bidi_remote, params); auto ticketMaxStreamDataUni = getIntegerParameter( TransportParameterId::initial_max_stream_data_uni, params); if (!ticketMaxStreamDataBidiLocal || conn_->transportSettings.advertisedInitialBidiLocalStreamWindowSize < *ticketMaxStreamDataBidiLocal || !ticketMaxStreamDataBidiRemote || conn_->transportSettings.advertisedInitialBidiRemoteStreamWindowSize < *ticketMaxStreamDataBidiRemote || !ticketMaxStreamDataUni || conn_->transportSettings.advertisedInitialUniStreamWindowSize < *ticketMaxStreamDataUni) { VLOG(10) << "Decreased max stream data"; return false; } auto ticketMaxStreamsBidi = getIntegerParameter( TransportParameterId::initial_max_streams_bidi, params); auto ticketMaxStreamsUni = getIntegerParameter( TransportParameterId::initial_max_streams_uni, params); if (!ticketMaxStreamsBidi || conn_->transportSettings.advertisedInitialMaxStreamsBidi < *ticketMaxStreamsBidi || !ticketMaxStreamsUni || conn_->transportSettings.advertisedInitialMaxStreamsUni < *ticketMaxStreamsUni) { VLOG(10) << "Decreased max stream data"; return false; } // TODO max ack delay, is this really necessary? // spec says disable_migration should also be in the ticket. It shouldn't. conn_->transportParamsMatching = true; if (!validateAndUpdateSourceToken( *conn_, std::move(appToken->sourceAddresses))) { VLOG(10) << "No exact match from source address token"; return false; } updateTransportParamsFromTicket( *conn_, *ticketIdleTimeout, *ticketPacketSize, *ticketMaxData, *ticketMaxStreamDataBidiLocal, *ticketMaxStreamDataBidiRemote, *ticketMaxStreamDataUni, *ticketMaxStreamsBidi, *ticketMaxStreamsUni); return true; } } // namespace quic