Chromium Code Reviews| Index: net/quic/crypto/proof_verifier_chromium.cc |
| diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc |
| index 096374a747255b451000cf3afccf034083a13368..fdcd2161ab302b19b3e0e802453175c57ca150da 100644 |
| --- a/net/quic/crypto/proof_verifier_chromium.cc |
| +++ b/net/quic/crypto/proof_verifier_chromium.cc |
| @@ -78,6 +78,17 @@ class ProofVerifierChromium::Job { |
| std::unique_ptr<ProofVerifyDetails>* verify_details, |
| ProofVerifierCallback* callback); |
| + // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is |
| + // returned, then |callback| will be invoked asynchronously when the |
| + // verification completes. |
| + QuicAsyncStatus VerifyCertChain( |
| + const std::string& hostname, |
| + const uint16_t port, |
| + const std::vector<std::string>& certs, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details, |
| + ProofVerifierCallback* callback); |
| + |
| private: |
| enum State { |
| STATE_NONE, |
| @@ -85,6 +96,19 @@ class ProofVerifierChromium::Job { |
| STATE_VERIFY_CERT_COMPLETE, |
| }; |
| + // Convert |certs| to |cert_|(X509Certificate). Returns true if successful. |
| + bool GetX509Certificate(const vector<string>& certs, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details); |
| + |
| + // Start the cert verification. |
| + QuicAsyncStatus VerifyCert( |
| + const string& hostname, |
| + const uint16_t port, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details, |
| + ProofVerifierCallback* callback); |
| + |
| int DoLoop(int last_io_result); |
| void OnIOComplete(int result); |
| int DoVerifyCert(int result); |
| @@ -125,6 +149,9 @@ class ProofVerifierChromium::Job { |
| // passed to CertVerifier::Verify. |
| int cert_verify_flags_; |
| + // If set to true, enforces policy checking in DoVerifyCertComplete(). |
| + bool enforce_policy_checking_; |
|
ramant (doing other things)
2016/07/07 19:31:49
Hi Ryan,
As we had discussed offline, added this
|
| + |
| State next_state_; |
| base::TimeTicks start_time_; |
| @@ -148,6 +175,7 @@ ProofVerifierChromium::Job::Job( |
| transport_security_state_(transport_security_state), |
| cert_transparency_verifier_(cert_transparency_verifier), |
| cert_verify_flags_(cert_verify_flags), |
| + enforce_policy_checking_(true), |
| next_state_(STATE_NONE), |
| start_time_(base::TimeTicks::Now()), |
| net_log_(net_log) { |
| @@ -195,25 +223,8 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
| verify_details_.reset(new ProofVerifyDetailsChromium); |
| - if (certs.empty()) { |
| - *error_details = "Failed to create certificate chain. Certs are empty."; |
| - DLOG(WARNING) << *error_details; |
| - verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| - *verify_details = std::move(verify_details_); |
| - return QUIC_FAILURE; |
| - } |
| - |
| - // Convert certs to X509Certificate. |
| - vector<StringPiece> cert_pieces(certs.size()); |
| - for (unsigned i = 0; i < certs.size(); i++) { |
| - cert_pieces[i] = base::StringPiece(certs[i]); |
| - } |
| - cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); |
| - if (!cert_.get()) { |
| - *error_details = "Failed to create certificate chain"; |
| - DLOG(WARNING) << *error_details; |
| - verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| - *verify_details = std::move(verify_details_); |
| + // Converts |certs| to |cert_|. |
| + if (!GetX509Certificate(certs, error_details, verify_details)) { |
| return QUIC_FAILURE; |
| } |
| @@ -237,6 +248,74 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
| return QUIC_FAILURE; |
| } |
| + DCHECK(enforce_policy_checking_); |
| + return VerifyCert(hostname, port, error_details, verify_details, callback); |
| +} |
| + |
| +QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( |
| + const string& hostname, |
| + const uint16_t port, |
| + const vector<string>& certs, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details, |
| + ProofVerifierCallback* callback) { |
| + DCHECK(error_details); |
| + DCHECK(verify_details); |
| + DCHECK(callback); |
| + |
| + error_details->clear(); |
| + |
| + if (STATE_NONE != next_state_) { |
| + *error_details = "Certificate is already set and VerifyCertChain has begun"; |
| + DLOG(DFATAL) << *error_details; |
| + return QUIC_FAILURE; |
| + } |
| + |
| + verify_details_.reset(new ProofVerifyDetailsChromium); |
| + |
| + // Converts |certs| to |cert_|. |
| + if (!GetX509Certificate(certs, error_details, verify_details)) { |
| + return QUIC_FAILURE; |
| + } |
| + |
| + enforce_policy_checking_ = false; |
| + return VerifyCert(hostname, port, error_details, verify_details, callback); |
| +} |
| + |
| +bool ProofVerifierChromium::Job::GetX509Certificate( |
| + const vector<string>& certs, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details) { |
| + if (certs.empty()) { |
| + *error_details = "Failed to create certificate chain. Certs are empty."; |
| + DLOG(WARNING) << *error_details; |
| + verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| + *verify_details = std::move(verify_details_); |
| + return false; |
| + } |
| + |
| + // Convert certs to X509Certificate. |
| + vector<StringPiece> cert_pieces(certs.size()); |
| + for (unsigned i = 0; i < certs.size(); i++) { |
| + cert_pieces[i] = base::StringPiece(certs[i]); |
| + } |
| + cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); |
| + if (!cert_.get()) { |
| + *error_details = "Failed to create certificate chain"; |
| + DLOG(WARNING) << *error_details; |
| + verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| + *verify_details = std::move(verify_details_); |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( |
| + const string& hostname, |
| + const uint16_t port, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details, |
| + ProofVerifierCallback* callback) { |
| hostname_ = hostname; |
| port_ = port; |
| @@ -315,7 +394,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { |
| // If the connection was good, check HPKP and CT status simultaneously, |
| // but prefer to treat the HPKP error as more serious, if there was one. |
| - if ((result == OK || |
| + if (enforce_policy_checking_ && |
| + (result == OK || |
| (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { |
| if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { |
| ct::EVPolicyCompliance ev_policy_compliance = |
| @@ -511,6 +591,32 @@ QuicAsyncStatus ProofVerifierChromium::VerifyProof( |
| return status; |
| } |
| +QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( |
| + const std::string& hostname, |
| + const uint16_t port, |
| + const std::vector<std::string>& certs, |
| + const ProofVerifyContext* verify_context, |
| + std::string* error_details, |
| + std::unique_ptr<ProofVerifyDetails>* verify_details, |
| + ProofVerifierCallback* callback) { |
| + if (!verify_context) { |
| + *error_details = "Missing context"; |
| + return QUIC_FAILURE; |
| + } |
| + const ProofVerifyContextChromium* chromium_context = |
| + reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); |
| + std::unique_ptr<Job> job( |
| + new Job(this, cert_verifier_, ct_policy_enforcer_, |
| + transport_security_state_, cert_transparency_verifier_, |
| + chromium_context->cert_verify_flags, chromium_context->net_log)); |
| + QuicAsyncStatus status = job->VerifyCertChain( |
| + hostname, port, certs, error_details, verify_details, callback); |
| + if (status == QUIC_PENDING) { |
| + active_jobs_.insert(job.release()); |
| + } |
|
Ryan Hamilton
2016/07/07 21:36:12
nit: no {}s
ramant (doing other things)
2016/07/07 22:18:27
Done. Used no {}s in chromium specific files. They
|
| + return status; |
| +} |
| + |
| void ProofVerifierChromium::OnJobComplete(Job* job) { |
| active_jobs_.erase(job); |
| delete job; |