Index: net/quic/crypto/quic_crypto_server_config.cc |
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc |
index c8114ff110b27e094027b079890fe27b542056db..f20441f402fc3c3e5a84176ae13869685e6343eb 100644 |
--- a/net/quic/crypto/quic_crypto_server_config.cc |
+++ b/net/quic/crypto/quic_crypto_server_config.cc |
@@ -33,6 +33,7 @@ |
#include "net/quic/crypto/strike_register.h" |
#include "net/quic/crypto/strike_register_client.h" |
#include "net/quic/quic_clock.h" |
+#include "net/quic/quic_flags.h" |
#include "net/quic/quic_protocol.h" |
#include "net/quic/quic_socket_address_coder.h" |
#include "net/quic/quic_utils.h" |
@@ -81,6 +82,9 @@ struct ClientHelloInfo { |
StringPiece client_nonce; |
StringPiece server_nonce; |
StringPiece user_agent_id; |
+ |
+ // Errors from EvaluateClientHello. |
+ vector<HandshakeFailureReason> reject_reasons; |
wtc
2014/06/19 00:13:24
Since reject_reasons is passed to SetVector(), we
ramant (doing other things)
2014/06/19 01:57:35
Done.
avd
2014/06/19 02:27:54
QuicTag has a very specific meaning, and this is n
ramant (doing other things)
2014/06/19 17:25:48
Changed it vector<uint32> and added static_cast<ui
|
}; |
struct ValidateClientHelloResultCallback::Result { |
@@ -146,6 +150,11 @@ class VerifyNonceIsValidAndUniqueCallback |
virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE { |
DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique; |
result_->info.unique = nonce_is_valid_and_unique; |
+ // TODO(rtenneti): Implement capturing of error from strike register. |
+ // Temporarily treat them as CLIENT_NONCE_UNKNOWN_FAILURE. |
+ if (!nonce_is_valid_and_unique) { |
+ result_->info.reject_reasons.push_back(CLIENT_NONCE_UNKNOWN_FAILURE); |
+ } |
done_cb_->Run(result_); |
} |
@@ -888,28 +897,57 @@ void QuicCryptoServerConfig::EvaluateClientHello( |
client_hello.GetStringPiece(kUAID, &info->user_agent_id); |
- StringPiece srct; |
- if (requested_config.get() != NULL && |
- client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) && |
- ValidateSourceAddressToken(*requested_config, |
- srct, |
- info->client_ip, |
- info->now)) { |
- info->valid_source_address_token = true; |
- } else { |
- // No server config with the requested ID, or no valid source address token. |
+ if (!requested_config.get()) { |
+ StringPiece requested_scid; |
+ client_hello.GetStringPiece(kSCID, &requested_scid); |
+ if (requested_scid.empty()) { |
+ info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE); |
+ } else { |
+ info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); |
+ } |
wtc
2014/06/19 00:13:24
Nit: require lines 902-907 as follows:
if (clie
ramant (doing other things)
2014/06/19 01:57:34
Done.
|
+ // No server config with the requested ID. |
wtc
2014/06/19 00:13:24
It is possible to keep going in this case, althoug
ramant (doing other things)
2014/06/19 01:57:34
avd suggested we do an early return. Will submit a
|
helper.ValidationComplete(QUIC_NO_ERROR, ""); |
return; |
} |
+ HandshakeFailureReason source_address_token_error; |
+ StringPiece srct; |
+ DCHECK(requested_config.get()); |
wtc
2014/06/19 00:13:24
This DCHECK's condition is ensured by the test on
ramant (doing other things)
2014/06/19 01:57:35
Done.
|
+ if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { |
+ source_address_token_error = |
+ ValidateSourceAddressToken(*requested_config, |
+ srct, |
+ info->client_ip, |
+ info->now); |
+ info->valid_source_address_token = |
+ (source_address_token_error == HANDSHAKE_OK); |
+ } else { |
+ source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; |
+ } |
+ |
+ bool found_error = false; |
+ if (source_address_token_error != HANDSHAKE_OK) { |
+ info->reject_reasons.push_back(source_address_token_error); |
+ // No valid source address token. |
+ if (FLAGS_use_early_return_when_verifying_chlo) { |
+ helper.ValidationComplete(QUIC_NO_ERROR, ""); |
+ return; |
+ } |
+ found_error = true; |
+ } |
+ |
if (client_hello.GetStringPiece(kNONC, &info->client_nonce) && |
info->client_nonce.size() == kNonceSize) { |
info->client_nonce_well_formed = true; |
} else { |
+ info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); |
// Invalid client nonce. |
DVLOG(1) << "Invalid client nonce."; |
- helper.ValidationComplete(QUIC_NO_ERROR, ""); |
- return; |
+ if (FLAGS_use_early_return_when_verifying_chlo) { |
+ helper.ValidationComplete(QUIC_NO_ERROR, ""); |
+ return; |
+ } |
+ found_error = true; |
} |
if (!replay_protection_) { |
@@ -922,8 +960,23 @@ void QuicCryptoServerConfig::EvaluateClientHello( |
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); |
if (!info->server_nonce.empty()) { |
// If the server nonce is present, use it to establish uniqueness. |
- info->unique = ValidateServerNonce(info->server_nonce, info->now); |
+ HandshakeFailureReason server_nonce_error = |
+ ValidateServerNonce(info->server_nonce, info->now); |
+ if (server_nonce_error == HANDSHAKE_OK) { |
+ info->unique = true; |
+ } else { |
+ info->reject_reasons.push_back(server_nonce_error); |
+ info->unique = false; |
+ } |
DVLOG(1) << "Using server nonce, unique: " << info->unique; |
+ if (FLAGS_use_early_return_when_verifying_chlo) { |
+ helper.ValidationComplete(QUIC_NO_ERROR, ""); |
+ return; |
+ } |
+ found_error = true; |
wtc
2014/06/19 00:13:24
IMPORTANT: replace lines 972-976 with:
helper
ramant (doing other things)
2014/06/19 01:57:34
Done.
|
+ } |
+ |
+ if (found_error) { |
wtc
2014/06/19 00:13:24
Please add a comment to explain why you do not kee
ramant (doing other things)
2014/06/19 01:57:34
Done.
|
helper.ValidationComplete(QUIC_NO_ERROR, ""); |
return; |
} |
@@ -971,6 +1024,12 @@ void QuicCryptoServerConfig::BuildRejection( |
out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now)); |
} |
+ if (FLAGS_send_quic_crypto_reject_reason) { |
+ // Send client the reject reason for debugging purposes. |
+ DCHECK_LT(0u, info.reject_reasons.size()); |
+ out->SetVector(kRejectReason, info.reject_reasons); |
+ } |
+ |
// The client may have requested a certificate chain. |
const QuicTag* their_proof_demands; |
size_t num_their_proof_demands; |
@@ -1288,7 +1347,7 @@ string QuicCryptoServerConfig::NewSourceAddressToken(const Config& config, |
rand, source_address_token.SerializeAsString()); |
} |
-bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
+HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressToken( |
const Config& config, |
StringPiece token, |
const IPEndPoint& ip, |
@@ -1296,13 +1355,13 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
string storage; |
StringPiece plaintext; |
if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) { |
- return false; |
+ return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE; |
} |
SourceAddressToken source_address_token; |
if (!source_address_token.ParseFromArray(plaintext.data(), |
plaintext.size())) { |
- return false; |
+ return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE; |
} |
IPAddressNumber ip_address = ip.address(); |
@@ -1311,7 +1370,7 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
} |
if (source_address_token.ip() != IPAddressToPackedString(ip_address)) { |
// It's for a different IP address. |
- return false; |
+ return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE; |
} |
const QuicWallTime timestamp( |
@@ -1320,15 +1379,15 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
if (now.IsBefore(timestamp) && |
delta.ToSeconds() > source_address_token_future_secs_) { |
- return false; |
+ return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE; |
} |
if (now.IsAfter(timestamp) && |
delta.ToSeconds() > source_address_token_lifetime_secs_) { |
- return false; |
+ return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE; |
} |
- return true; |
+ return HANDSHAKE_OK; |
} |
// kServerNoncePlaintextSize is the number of bytes in an unencrypted server |
@@ -1354,12 +1413,13 @@ string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand, |
StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce))); |
} |
-bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token, |
- QuicWallTime now) const { |
+HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce( |
+ StringPiece token, |
+ QuicWallTime now) const { |
string storage; |
StringPiece plaintext; |
if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) { |
- return false; |
+ return SERVER_NONCE_DECRYPTION_FAILURE; |
} |
// plaintext contains: |
@@ -1369,7 +1429,7 @@ bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token, |
if (plaintext.size() != kServerNoncePlaintextSize) { |
// This should never happen because the value decrypted correctly. |
LOG(DFATAL) << "Seemingly valid server nonce had incorrect length."; |
- return false; |
+ return SERVER_NONCE_INVALID_FAILURE; |
} |
uint8 server_nonce[32]; |
@@ -1394,7 +1454,7 @@ bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token, |
server_nonce, static_cast<uint32>(now.ToUNIXSeconds())); |
} |
- return is_unique; |
+ return is_unique ? HANDSHAKE_OK : SERVER_NONCE_NOT_UNIQUE_FAILURE; |
} |
QuicCryptoServerConfig::Config::Config() |