Index: net/quic/quic_crypto_client_stream.cc |
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc |
index 78b39e759e2db3e042261175dc1f0c337c6a2147..69c63a5664e8c5ee185e3747a6c938c4594f040c 100644 |
--- a/net/quic/quic_crypto_client_stream.cc |
+++ b/net/quic/quic_crypto_client_stream.cc |
@@ -10,6 +10,7 @@ |
#include "net/quic/crypto/crypto_utils.h" |
#include "net/quic/crypto/null_encrypter.h" |
#include "net/quic/crypto/proof_verifier.h" |
+#include "net/quic/crypto/proof_verifier_chromium.h" |
#include "net/quic/quic_protocol.h" |
#include "net/quic/quic_session.h" |
#include "net/ssl/ssl_connection_status_flags.h" |
@@ -17,30 +18,63 @@ |
namespace net { |
+QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( |
+ QuicCryptoClientStream* stream) |
+ : stream_(stream) {} |
+ |
+QuicCryptoClientStream::ProofVerifierCallbackImpl:: |
+ ~ProofVerifierCallbackImpl() {} |
+ |
+void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run( |
+ bool ok, |
+ const string& error_details, |
+ scoped_ptr<ProofVerifyDetails>* details) { |
+ if (stream_ == NULL) { |
+ return; |
+ } |
+ |
+ stream_->verify_ok_ = ok; |
+ stream_->verify_error_details_ = error_details; |
+ stream_->verify_details_.reset(details->release()); |
+ stream_->proof_verify_callback_ = NULL; |
+ stream_->DoHandshakeLoop(NULL); |
+ |
+ // The ProofVerifier owns this object and will delete it when this method |
+ // returns. |
+} |
+ |
+void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() { |
+ stream_ = NULL; |
+} |
+ |
+ |
QuicCryptoClientStream::QuicCryptoClientStream( |
const string& server_hostname, |
QuicSession* session, |
QuicCryptoClientConfig* crypto_config) |
: QuicCryptoStream(session), |
- weak_factory_(this), |
next_state_(STATE_IDLE), |
num_client_hellos_(0), |
crypto_config_(crypto_config), |
server_hostname_(server_hostname), |
- generation_counter_(0) { |
+ generation_counter_(0), |
+ proof_verify_callback_(NULL) { |
} |
QuicCryptoClientStream::~QuicCryptoClientStream() { |
+ if (proof_verify_callback_) { |
+ proof_verify_callback_->Cancel(); |
+ } |
} |
void QuicCryptoClientStream::OnHandshakeMessage( |
const CryptoHandshakeMessage& message) { |
- DoHandshakeLoop(&message, OK); |
+ DoHandshakeLoop(&message); |
} |
bool QuicCryptoClientStream::CryptoConnect() { |
next_state_ = STATE_SEND_CHLO; |
- DoHandshakeLoop(NULL, OK); |
+ DoHandshakeLoop(NULL); |
return true; |
} |
@@ -57,7 +91,8 @@ bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { |
return false; |
} |
const CertVerifyResult* cert_verify_result = |
- cached->cert_verify_result(); |
+ &(reinterpret_cast<const ProofVerifyDetailsChromium*>( |
+ cached->proof_verify_details()))->cert_verify_result; |
ssl_info->cert_status = cert_verify_result->cert_status; |
ssl_info->cert = cert_verify_result->verified_cert; |
@@ -95,8 +130,7 @@ bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) { |
static const int kMaxClientHellos = 3; |
void QuicCryptoClientStream::DoHandshakeLoop( |
- const CryptoHandshakeMessage* in, |
- int result) { |
+ const CryptoHandshakeMessage* in) { |
CryptoHandshakeMessage out; |
QuicErrorCode error; |
string error_details; |
@@ -112,7 +146,6 @@ void QuicCryptoClientStream::DoHandshakeLoop( |
next_state_ = STATE_IDLE; |
switch (state) { |
case STATE_SEND_CHLO: { |
- DCHECK_EQ(OK, result); |
// Send the client hello in plaintext. |
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); |
if (num_client_hellos_ > kMaxClientHellos) { |
@@ -171,7 +204,6 @@ void QuicCryptoClientStream::DoHandshakeLoop( |
return; |
} |
case STATE_RECV_REJ: |
- DCHECK_EQ(OK, result); |
// We sent a dummy CHLO because we didn't have enough information to |
// perform a handshake, or we sent a full hello that the server |
// rejected. Here we hope to have a REJ that contains the information |
@@ -205,25 +237,40 @@ void QuicCryptoClientStream::DoHandshakeLoop( |
DCHECK(verifier); |
next_state_ = STATE_VERIFY_PROOF_COMPLETE; |
generation_counter_ = cached->generation_counter(); |
- result = verifier->VerifyProof( |
+ |
+ ProofVerifierCallbackImpl* proof_verify_callback = |
+ new ProofVerifierCallbackImpl(this); |
+ |
+ verify_ok_ = false; |
+ |
+ ProofVerifier::Status status = verifier->VerifyProof( |
server_hostname_, |
cached->server_config(), |
cached->certs(), |
cached->signature(), |
- &error_details_, |
- &cert_verify_result_, |
- base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete, |
- weak_factory_.GetWeakPtr())); |
- if (result == ERR_IO_PENDING) { |
- DVLOG(1) << "Doing VerifyProof"; |
- return; |
+ &error_details, |
+ &verify_details_, |
+ proof_verify_callback); |
+ |
+ switch (status) { |
+ case ProofVerifier::PENDING: |
+ proof_verify_callback_ = proof_verify_callback; |
+ DVLOG(1) << "Doing VerifyProof"; |
+ return; |
+ case ProofVerifier::FAILURE: |
+ CloseConnectionWithDetails( |
+ QUIC_PROOF_INVALID, "Proof invalid: " + error_details); |
+ return; |
+ case ProofVerifier::SUCCESS: |
+ verify_ok_ = true; |
+ break; |
} |
break; |
} |
case STATE_VERIFY_PROOF_COMPLETE: |
- if (result != OK) { |
+ if (!verify_ok_) { |
CloseConnectionWithDetails( |
- QUIC_PROOF_INVALID, "Proof invalid: " + error_details_); |
+ QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); |
return; |
} |
// Check if generation_counter has changed between STATE_VERIFY_PROOF |
@@ -232,7 +279,7 @@ void QuicCryptoClientStream::DoHandshakeLoop( |
next_state_ = STATE_VERIFY_PROOF; |
} else { |
cached->SetProofValid(); |
- cached->SetCertVerifyResult(cert_verify_result_); |
+ cached->SetProofVerifyDetails(verify_details_.release()); |
next_state_ = STATE_SEND_CHLO; |
} |
break; |
@@ -305,10 +352,4 @@ void QuicCryptoClientStream::DoHandshakeLoop( |
} |
} |
-void QuicCryptoClientStream::OnVerifyProofComplete(int result) { |
- DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETE, next_state_); |
- DVLOG(1) << "VerifyProof completed: " << result; |
- DoHandshakeLoop(NULL, result); |
-} |
- |
} // namespace net |