namespace {
-enum ServerConfigState {
- // WARNING: Do not change the numerical values of any of server config state.
- // Do not remove deprecated server config states - just comment them as
- // deprecated.
- SERVER_CONFIG_EMPTY = 0,
- SERVER_CONFIG_INVALID = 1,
- SERVER_CONFIG_CORRUPTED = 2,
- SERVER_CONFIG_EXPIRED = 3,
- SERVER_CONFIG_INVALID_EXPIRY = 4,
-
- // NOTE: Add new server config states only immediately above this line. Make
- // sure to update the QuicServerConfigState enum in
- // tools/metrics/histograms/histograms.xml accordingly.
- SERVER_CONFIG_COUNT
-};
-
-void RecordServerConfigState(ServerConfigState server_config_state) {
- UMA_HISTOGRAM_ENUMERATION("Net.QuicClientHelloServerConfigState",
- server_config_state, SERVER_CONFIG_COUNT);
+// Tracks the reason (the state of the server config) for sending inchoate
+// ClientHello to the server.
+void RecordInchoateClientHelloReason(
+ QuicCryptoClientConfig::CachedState::ServerConfigState state) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.QuicInchoateClientHelloReason", state,
+ QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT);
+}
+
+// Tracks the state of the QUIC server information loaded from the disk cache.
+void RecordDiskCacheServerConfigState(
+ QuicCryptoClientConfig::CachedState::ServerConfigState state) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.QuicServerInfo.DiskCacheState", state,
+ QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT);
}
} // namespace
QuicCryptoClientConfig::QuicCryptoClientConfig()
- : disable_ecdsa_(false) {}
+ : disable_ecdsa_(false) {
+ SetDefaults();
+}
QuicCryptoClientConfig::~QuicCryptoClientConfig() {
STLDeleteValues(&cached_states_);
bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
if (server_config_.empty()) {
- RecordServerConfigState(SERVER_CONFIG_EMPTY);
+ RecordInchoateClientHelloReason(SERVER_CONFIG_EMPTY);
return false;
}
if (!server_config_valid_) {
- RecordServerConfigState(SERVER_CONFIG_INVALID);
+ RecordInchoateClientHelloReason(SERVER_CONFIG_INVALID);
return false;
}
if (!scfg) {
// Should be impossible short of cache corruption.
DCHECK(false);
- RecordServerConfigState(SERVER_CONFIG_CORRUPTED);
+ RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED);
return false;
}
uint64 expiry_seconds;
if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
- RecordServerConfigState(SERVER_CONFIG_INVALID_EXPIRY);
+ RecordInchoateClientHelloReason(SERVER_CONFIG_INVALID_EXPIRY);
return false;
}
if (now.ToUNIXSeconds() >= expiry_seconds) {
"Net.QuicClientHelloServerConfig.InvalidDuration",
base::TimeDelta::FromSeconds(now.ToUNIXSeconds() - expiry_seconds),
base::TimeDelta::FromMinutes(1), base::TimeDelta::FromDays(20), 50);
- RecordServerConfigState(SERVER_CONFIG_EXPIRED);
+ RecordInchoateClientHelloReason(SERVER_CONFIG_EXPIRED);
return false;
}
const CryptoHandshakeMessage*
QuicCryptoClientConfig::CachedState::GetServerConfig() const {
if (server_config_.empty()) {
- return NULL;
+ return nullptr;
}
if (!scfg_.get()) {
return scfg_.get();
}
-QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig(
+QuicCryptoClientConfig::CachedState::ServerConfigState
+QuicCryptoClientConfig::CachedState::SetServerConfig(
StringPiece server_config, QuicWallTime now, string* error_details) {
const bool matches_existing = server_config == server_config_;
if (!new_scfg) {
*error_details = "SCFG invalid";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ return SERVER_CONFIG_INVALID;
}
uint64 expiry_seconds;
if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
*error_details = "SCFG missing EXPY";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ return SERVER_CONFIG_INVALID_EXPIRY;
}
if (now.ToUNIXSeconds() >= expiry_seconds) {
*error_details = "SCFG has expired";
- return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
+ return SERVER_CONFIG_EXPIRED;
}
if (!matches_existing) {
SetProofInvalid();
scfg_.reset(new_scfg_storage.release());
}
- return QUIC_NO_ERROR;
+ return SERVER_CONFIG_VALID;
}
void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
DCHECK(server_config_.empty());
if (server_config.empty()) {
+ RecordDiskCacheServerConfigState(SERVER_CONFIG_EMPTY);
return false;
}
string error_details;
- QuicErrorCode error = SetServerConfig(server_config, now,
- &error_details);
- if (error != QUIC_NO_ERROR) {
+ ServerConfigState state = SetServerConfig(server_config, now,
+ &error_details);
+ RecordDiskCacheServerConfigState(state);
+ if (state != SERVER_CONFIG_VALID) {
DVLOG(1) << "SetServerConfig failed with " << error_details;
return false;
}
certs_ = other.certs_;
server_config_sig_ = other.server_config_sig_;
server_config_valid_ = other.server_config_valid_;
- if (other.proof_verify_details_.get() != NULL) {
+ if (other.proof_verify_details_.get() != nullptr) {
proof_verify_details_.reset(other.proof_verify_details_->Clone());
}
++generation_counter_;
CachedState* cached = new CachedState;
cached_states_.insert(make_pair(server_id, cached));
- PopulateFromCanonicalConfig(server_id, cached);
+ bool cache_populated = PopulateFromCanonicalConfig(server_id, cached);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Net.QuicCryptoClientConfig.PopulatedFromCanonicalConfig",
+ cache_populated);
return cached;
}
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out,
string* error_details) const {
- DCHECK(error_details != NULL);
+ DCHECK(error_details != nullptr);
FillInchoateClientHello(server_id, preferred_version, cached,
out_params, out);
size_t key_exchange_index;
if (!QuicUtils::FindMutualTag(
aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY,
- &out_params->aead, NULL) ||
+ &out_params->aead, nullptr) ||
!QuicUtils::FindMutualTag(
kexs, their_key_exchanges, num_their_key_exchanges,
QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange,
out_params->aead, out_params->client_nonce,
out_params->server_nonce, hkdf_input,
CryptoUtils::CLIENT, &crypters,
- NULL /* subkey secret */)) {
+ nullptr /* subkey secret */)) {
*error_details = "Symmetric key setup failed";
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
out_params->initial_premaster_secret, out_params->aead,
out_params->client_nonce, out_params->server_nonce, hkdf_input,
CryptoUtils::CLIENT, &out_params->initial_crypters,
- NULL /* subkey secret */)) {
+ nullptr /* subkey secret */)) {
*error_details = "Symmetric key setup failed";
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
const vector<string>& cached_certs,
CachedState* cached,
string* error_details) {
- DCHECK(error_details != NULL);
+ DCHECK(error_details != nullptr);
StringPiece scfg;
if (!message.GetStringPiece(kSCFG, &scfg)) {
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
- QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details);
- if (error != QUIC_NO_ERROR) {
- return error;
+ CachedState::ServerConfigState state = cached->SetServerConfig(
+ scfg, now, error_details);
+ if (state == CachedState::SERVER_CONFIG_EXPIRED) {
+ return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
+ }
+ // TODO(rtenneti): Return more specific error code than returning
+ // QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER.
+ if (state != CachedState::SERVER_CONFIG_VALID) {
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
StringPiece token;
cached->SetProof(certs, proof);
} else {
- if (proof_verifier() != NULL) {
+ if (proof_verifier() != nullptr) {
// Secure QUIC: clear existing proof as we have been sent a new SCFG
// without matching proof/certs.
cached->ClearProof();
bool is_https,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
- DCHECK(error_details != NULL);
+ DCHECK(error_details != nullptr);
if (rej.tag() != kREJ) {
*error_details = "Message is not REJ";
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
- DCHECK(error_details != NULL);
+ DCHECK(error_details != nullptr);
if (server_hello.tag() != kSHLO) {
*error_details = "Bad tag";
CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
- DCHECK(error_details != NULL);
+ DCHECK(error_details != nullptr);
if (server_config_update.tag() != kSCUP) {
*error_details = "ServerConfigUpdate must have kSCUP tag.";
}
void QuicCryptoClientConfig::AddCanonicalSuffix(const string& suffix) {
- canoncial_suffixes_.push_back(suffix);
+ canonical_suffixes_.push_back(suffix);
}
void QuicCryptoClientConfig::PreferAesGcm() {
disable_ecdsa_ = true;
}
-void QuicCryptoClientConfig::PopulateFromCanonicalConfig(
+bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
const QuicServerId& server_id,
CachedState* server_state) {
DCHECK(server_state->IsEmpty());
size_t i = 0;
- for (; i < canoncial_suffixes_.size(); ++i) {
- if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) {
+ for (; i < canonical_suffixes_.size(); ++i) {
+ if (EndsWith(server_id.host(), canonical_suffixes_[i], false)) {
break;
}
}
- if (i == canoncial_suffixes_.size())
- return;
+ if (i == canonical_suffixes_.size())
+ return false;
- QuicServerId suffix_server_id(canoncial_suffixes_[i], server_id.port(),
+ QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(),
server_id.is_https(),
server_id.privacy_mode());
if (!ContainsKey(canonical_server_map_, suffix_server_id)) {
// This is the first host we've seen which matches the suffix, so make it
// canonical.
canonical_server_map_[suffix_server_id] = server_id;
- return;
+ return false;
}
const QuicServerId& canonical_server_id =
canonical_server_map_[suffix_server_id];
CachedState* canonical_state = cached_states_[canonical_server_id];
if (!canonical_state->proof_valid()) {
- return;
+ return false;
}
// Update canonical version to point at the "most recent" entry.
canonical_server_map_[suffix_server_id] = server_id;
server_state->InitializeFrom(*canonical_state);
+ return true;
}
} // namespace net