| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived | 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived |
| 6 // from AuthCertificateCallback() in | 6 // from AuthCertificateCallback() in |
| 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
| 8 | 8 |
| 9 /* ***** BEGIN LICENSE BLOCK ***** | 9 /* ***** BEGIN LICENSE BLOCK ***** |
| 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 } | 272 } |
| 273 | 273 |
| 274 return v; | 274 return v; |
| 275 } | 275 } |
| 276 | 276 |
| 277 private: | 277 private: |
| 278 unsigned num_certs_; | 278 unsigned num_certs_; |
| 279 CERTCertificate** certs_; | 279 CERTCertificate** certs_; |
| 280 }; | 280 }; |
| 281 | 281 |
| 282 void DestroyCertificates(CERTCertificate** certs, unsigned len) { |
| 283 for (unsigned i = 0; i < len; i++) |
| 284 CERT_DestroyCertificate(certs[i]); |
| 285 } |
| 286 |
| 287 // DNSValidationResult enumerates the possible outcomes from processing a |
| 288 // set of DNS records. |
| 289 enum DNSValidationResult { |
| 290 DNSVR_SUCCESS, // the cert is immediately acceptable. |
| 291 DNSVR_FAILURE, // the cert is unconditionally rejected. |
| 292 DNSVR_CONTINUE, // perform CA validation as usual. |
| 293 }; |
| 294 |
| 295 // VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and |
| 296 // checks them against the given certificate. |
| 297 // dnssec: if true then the TXT records are DNSSEC validated. In this case, |
| 298 // DNSVR_SUCCESS may be returned. |
| 299 // server_cert_nss: the certificate to validate |
| 300 // rrdatas: the TXT records for the current domain. |
| 301 DNSValidationResult VerifyTXTRecords( |
| 302 bool dnssec, |
| 303 CERTCertificate* server_cert_nss, |
| 304 const std::vector<base::StringPiece>& rrdatas) { |
| 305 bool found_well_formed_record = false; |
| 306 bool matched_record = false; |
| 307 |
| 308 for (std::vector<base::StringPiece>::const_iterator |
| 309 i = rrdatas.begin(); i != rrdatas.end(); ++i) { |
| 310 std::map<std::string, std::string> m( |
| 311 DNSSECChainVerifier::ParseTLSTXTRecord(*i)); |
| 312 if (m.empty()) |
| 313 continue; |
| 314 |
| 315 std::map<std::string, std::string>::const_iterator j; |
| 316 j = m.find("v"); |
| 317 if (j == m.end() || j->second != "tls1") |
| 318 continue; |
| 319 |
| 320 j = m.find("ha"); |
| 321 |
| 322 HASH_HashType hash_algorithm; |
| 323 unsigned hash_length; |
| 324 if (j == m.end() || j->second == "sha1") { |
| 325 hash_algorithm = HASH_AlgSHA1; |
| 326 hash_length = SHA1_LENGTH; |
| 327 } else if (j->second == "sha256") { |
| 328 hash_algorithm = HASH_AlgSHA256; |
| 329 hash_length = SHA256_LENGTH; |
| 330 } else { |
| 331 continue; |
| 332 } |
| 333 |
| 334 j = m.find("h"); |
| 335 if (j == m.end()) |
| 336 continue; |
| 337 |
| 338 std::vector<uint8> given_hash; |
| 339 if (!base::HexStringToBytes(j->second, &given_hash)) |
| 340 continue; |
| 341 |
| 342 if (given_hash.size() != hash_length) |
| 343 continue; |
| 344 |
| 345 uint8 calculated_hash[SHA256_LENGTH]; // SHA256 is the largest. |
| 346 SECStatus rv; |
| 347 |
| 348 j = m.find("hr"); |
| 349 if (j == m.end() || j->second == "pubkey") { |
| 350 rv = HASH_HashBuf(hash_algorithm, calculated_hash, |
| 351 server_cert_nss->derPublicKey.data, |
| 352 server_cert_nss->derPublicKey.len); |
| 353 } else if (j->second == "cert") { |
| 354 rv = HASH_HashBuf(hash_algorithm, calculated_hash, |
| 355 server_cert_nss->derCert.data, |
| 356 server_cert_nss->derCert.len); |
| 357 } else { |
| 358 continue; |
| 359 } |
| 360 |
| 361 if (rv != SECSuccess) |
| 362 NOTREACHED(); |
| 363 |
| 364 found_well_formed_record = true; |
| 365 |
| 366 if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) { |
| 367 matched_record = true; |
| 368 if (dnssec) |
| 369 return DNSVR_SUCCESS; |
| 370 } |
| 371 } |
| 372 |
| 373 if (found_well_formed_record && !matched_record) |
| 374 return DNSVR_FAILURE; |
| 375 |
| 376 return DNSVR_CONTINUE; |
| 377 } |
| 378 |
| 379 // CheckDNSSECChain tries to validate a DNSSEC chain embedded in |
| 380 // |server_cert_nss_|. It returns true iff a chain is found that proves the |
| 381 // value of a TXT record that contains a valid public key fingerprint. |
| 382 DNSValidationResult CheckDNSSECChain( |
| 383 const std::string& hostname, |
| 384 CERTCertificate* server_cert_nss) { |
| 385 if (!server_cert_nss) |
| 386 return DNSVR_CONTINUE; |
| 387 |
| 388 // CERT_FindCertExtensionByOID isn't exported so we have to install an OID, |
| 389 // get a tag for it and find the extension by using that tag. |
| 390 static SECOidTag dnssec_chain_tag; |
| 391 static bool dnssec_chain_tag_valid; |
| 392 if (!dnssec_chain_tag_valid) { |
| 393 // It's harmless if multiple threads enter this block concurrently. |
| 394 static const uint8 kDNSSECChainOID[] = |
| 395 // 1.3.6.1.4.1.11129.2.1.4 |
| 396 // (iso.org.dod.internet.private.enterprises.google.googleSecurity. |
| 397 // certificateExtensions.dnssecEmbeddedChain) |
| 398 {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04}; |
| 399 SECOidData oid_data; |
| 400 memset(&oid_data, 0, sizeof(oid_data)); |
| 401 oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID); |
| 402 oid_data.oid.len = sizeof(kDNSSECChainOID); |
| 403 oid_data.desc = "DNSSEC chain"; |
| 404 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; |
| 405 dnssec_chain_tag = SECOID_AddEntry(&oid_data); |
| 406 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag); |
| 407 dnssec_chain_tag_valid = true; |
| 408 } |
| 409 |
| 410 SECItem dnssec_embedded_chain; |
| 411 SECStatus rv = CERT_FindCertExtension(server_cert_nss, |
| 412 dnssec_chain_tag, &dnssec_embedded_chain); |
| 413 if (rv != SECSuccess) |
| 414 return DNSVR_CONTINUE; |
| 415 |
| 416 base::StringPiece chain( |
| 417 reinterpret_cast<char*>(dnssec_embedded_chain.data), |
| 418 dnssec_embedded_chain.len); |
| 419 std::string dns_hostname; |
| 420 if (!DNSDomainFromDot(hostname, &dns_hostname)) |
| 421 return DNSVR_CONTINUE; |
| 422 DNSSECChainVerifier verifier(dns_hostname, chain); |
| 423 DNSSECChainVerifier::Error err = verifier.Verify(); |
| 424 if (err != DNSSECChainVerifier::OK) { |
| 425 LOG(ERROR) << "DNSSEC chain verification failed: " << err; |
| 426 return DNSVR_CONTINUE; |
| 427 } |
| 428 |
| 429 if (verifier.rrtype() != kDNS_TXT) |
| 430 return DNSVR_CONTINUE; |
| 431 |
| 432 DNSValidationResult r = VerifyTXTRecords( |
| 433 true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas()); |
| 434 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE); |
| 435 return r; |
| 436 } |
| 437 |
| 282 } // namespace | 438 } // namespace |
| 283 | 439 |
| 284 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, | 440 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, |
| 285 const HostPortPair& host_and_port, | 441 const HostPortPair& host_and_port, |
| 286 const SSLConfig& ssl_config, | 442 const SSLConfig& ssl_config, |
| 287 SSLHostInfo* ssl_host_info, | 443 SSLHostInfo* ssl_host_info, |
| 288 CertVerifier* cert_verifier, | 444 CertVerifier* cert_verifier, |
| 289 DnsCertProvenanceChecker* dns_ctx) | 445 DnsCertProvenanceChecker* dns_ctx) |
| 290 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( | 446 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( |
| 291 this, &SSLClientSocketNSS::BufferSendComplete)), | 447 this, &SSLClientSocketNSS::BufferSendComplete)), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 dns_cert_checker_(dns_ctx) { | 482 dns_cert_checker_(dns_ctx) { |
| 327 EnterFunction(""); | 483 EnterFunction(""); |
| 328 } | 484 } |
| 329 | 485 |
| 330 SSLClientSocketNSS::~SSLClientSocketNSS() { | 486 SSLClientSocketNSS::~SSLClientSocketNSS() { |
| 331 EnterFunction(""); | 487 EnterFunction(""); |
| 332 Disconnect(); | 488 Disconnect(); |
| 333 LeaveFunction(""); | 489 LeaveFunction(""); |
| 334 } | 490 } |
| 335 | 491 |
| 336 int SSLClientSocketNSS::Init() { | 492 // static |
| 337 EnterFunction(""); | 493 void SSLClientSocketNSS::ClearSessionCache() { |
| 338 // Initialize the NSS SSL library in a threadsafe way. This also | 494 SSL_ClearSessionCache(); |
| 339 // initializes the NSS base library. | |
| 340 EnsureNSSSSLInit(); | |
| 341 if (!NSS_IsInitialized()) | |
| 342 return ERR_UNEXPECTED; | |
| 343 #if !defined(OS_MACOSX) && !defined(OS_WIN) | |
| 344 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop | |
| 345 // by MessageLoopForIO::current(). | |
| 346 // X509Certificate::Verify() runs on a worker thread of CertVerifier. | |
| 347 EnsureOCSPInit(); | |
| 348 #endif | |
| 349 | |
| 350 LeaveFunction(""); | |
| 351 return OK; | |
| 352 } | 495 } |
| 353 | 496 |
| 354 // SaveSnapStartInfo extracts the information needed to perform a Snap Start | 497 void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { |
| 355 // with this server in the future (if any) and tells |ssl_host_info_| to | 498 EnterFunction(""); |
| 356 // preserve it. | 499 ssl_info->Reset(); |
| 357 void SSLClientSocketNSS::SaveSnapStartInfo() { | |
| 358 if (!ssl_host_info_.get()) | |
| 359 return; | |
| 360 | 500 |
| 361 // If the SSLHostInfo hasn't managed to load from disk yet then we can't save | 501 if (!server_cert_) { |
| 362 // anything. | 502 LOG(DFATAL) << "!server_cert_"; |
| 363 if (ssl_host_info_->WaitForDataReady(NULL) != OK) | |
| 364 return; | |
| 365 | |
| 366 SECStatus rv; | |
| 367 SSLSnapStartResult snap_start_type; | |
| 368 rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type); | |
| 369 if (rv != SECSuccess) { | |
| 370 NOTREACHED(); | |
| 371 return; | |
| 372 } | |
| 373 net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START, | |
| 374 new NetLogIntegerParameter("type", snap_start_type)); | |
| 375 if (snap_start_type == SSL_SNAP_START_FULL || | |
| 376 snap_start_type == SSL_SNAP_START_RESUME) { | |
| 377 // If we did a successful Snap Start then our information was correct and | |
| 378 // there's no point saving it again. | |
| 379 return; | 503 return; |
| 380 } | 504 } |
| 381 | 505 |
| 382 const unsigned char* hello_data; | 506 ssl_info->cert_status = server_cert_verify_result_->cert_status; |
| 383 unsigned hello_data_len; | 507 DCHECK(server_cert_ != NULL); |
| 384 rv = SSL_GetPredictedServerHelloData(nss_fd_, &hello_data, &hello_data_len); | 508 ssl_info->cert = server_cert_; |
| 385 if (rv != SECSuccess) { | 509 ssl_info->connection_status = ssl_connection_status_; |
| 386 NOTREACHED(); | 510 |
| 387 return; | 511 PRUint16 cipher_suite = |
| 512 SSLConnectionStatusToCipherSuite(ssl_connection_status_); |
| 513 SSLCipherSuiteInfo cipher_info; |
| 514 SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite, |
| 515 &cipher_info, sizeof(cipher_info)); |
| 516 if (ok == SECSuccess) { |
| 517 ssl_info->security_bits = cipher_info.effectiveKeyBits; |
| 518 } else { |
| 519 ssl_info->security_bits = -1; |
| 520 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() |
| 521 << " for cipherSuite " << cipher_suite; |
| 388 } | 522 } |
| 389 if (hello_data_len > std::numeric_limits<uint16>::max()) | 523 LeaveFunction(""); |
| 390 return; | 524 } |
| 391 SSLHostInfo::State* state = ssl_host_info_->mutable_state(); | |
| 392 | 525 |
| 393 if (hello_data_len > 0) { | 526 void SSLClientSocketNSS::GetSSLCertRequestInfo( |
| 394 state->server_hello = | 527 SSLCertRequestInfo* cert_request_info) { |
| 395 std::string(reinterpret_cast<const char *>(hello_data), hello_data_len); | 528 EnterFunction(""); |
| 396 state->npn_valid = true; | 529 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair |
| 397 state->npn_status = GetNextProto(&state->npn_protocol); | 530 cert_request_info->host_and_port = host_and_port_.ToString(); |
| 398 } else { | 531 cert_request_info->client_certs = client_certs_; |
| 399 state->server_hello.clear(); | 532 LeaveFunction(cert_request_info->client_certs.size()); |
| 400 state->npn_valid = false; | 533 } |
| 534 |
| 535 SSLClientSocket::NextProtoStatus |
| 536 SSLClientSocketNSS::GetNextProto(std::string* proto) { |
| 537 #if defined(SSL_NEXT_PROTO_NEGOTIATED) |
| 538 if (!handshake_callback_called_) { |
| 539 DCHECK(pseudo_connected_); |
| 540 predicted_npn_proto_used_ = true; |
| 541 *proto = predicted_npn_proto_; |
| 542 return predicted_npn_status_; |
| 401 } | 543 } |
| 402 | 544 |
| 403 state->certs.clear(); | 545 unsigned char buf[255]; |
| 404 PeerCertificateChain certs(nss_fd_); | 546 int state; |
| 405 for (unsigned i = 0; i < certs.size(); i++) { | 547 unsigned len; |
| 406 if (certs[i]->derCert.len > std::numeric_limits<uint16>::max()) | 548 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf)); |
| 407 return; | 549 if (rv != SECSuccess) { |
| 408 | 550 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv; |
| 409 state->certs.push_back(std::string( | 551 proto->clear(); |
| 410 reinterpret_cast<char*>(certs[i]->derCert.data), | 552 return kNextProtoUnsupported; |
| 411 certs[i]->derCert.len)); | |
| 412 } | 553 } |
| 413 | 554 // We don't check for truncation because sizeof(buf) is large enough to hold |
| 414 ssl_host_info_->Persist(); | 555 // the maximum protocol size. |
| 556 switch (state) { |
| 557 case SSL_NEXT_PROTO_NO_SUPPORT: |
| 558 proto->clear(); |
| 559 return kNextProtoUnsupported; |
| 560 case SSL_NEXT_PROTO_NEGOTIATED: |
| 561 *proto = std::string(reinterpret_cast<char*>(buf), len); |
| 562 return kNextProtoNegotiated; |
| 563 case SSL_NEXT_PROTO_NO_OVERLAP: |
| 564 *proto = std::string(reinterpret_cast<char*>(buf), len); |
| 565 return kNextProtoNoOverlap; |
| 566 default: |
| 567 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state; |
| 568 proto->clear(); |
| 569 return kNextProtoUnsupported; |
| 570 } |
| 571 #else |
| 572 // No NPN support in the libssl that we are building with. |
| 573 proto->clear(); |
| 574 return kNextProtoUnsupported; |
| 575 #endif |
| 415 } | 576 } |
| 416 | 577 |
| 417 static void DestroyCertificates(CERTCertificate** certs, unsigned len) { | 578 void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) { |
| 418 for (unsigned i = 0; i < len; i++) | 579 dnssec_provider_ = provider; |
| 419 CERT_DestroyCertificate(certs[i]); | |
| 420 } | |
| 421 | |
| 422 // LoadSnapStartInfo parses |info|, which contains data previously serialised | |
| 423 // by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello | |
| 424 // data on the NSS socket. Returns true on success. If this function returns | |
| 425 // false, the caller should try a normal TLS handshake. | |
| 426 bool SSLClientSocketNSS::LoadSnapStartInfo() { | |
| 427 const SSLHostInfo::State& state(ssl_host_info_->state()); | |
| 428 | |
| 429 if (state.server_hello.empty() || | |
| 430 state.certs.empty() || | |
| 431 !state.npn_valid) { | |
| 432 return false; | |
| 433 } | |
| 434 | |
| 435 SECStatus rv; | |
| 436 rv = SSL_SetPredictedServerHelloData( | |
| 437 nss_fd_, | |
| 438 reinterpret_cast<const uint8*>(state.server_hello.data()), | |
| 439 state.server_hello.size()); | |
| 440 DCHECK_EQ(SECSuccess, rv); | |
| 441 | |
| 442 const std::vector<std::string>& certs_in = state.certs; | |
| 443 scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]); | |
| 444 for (size_t i = 0; i < certs_in.size(); i++) { | |
| 445 SECItem derCert; | |
| 446 derCert.data = | |
| 447 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data())); | |
| 448 derCert.len = certs_in[i].size(); | |
| 449 certs[i] = CERT_NewTempCertificate( | |
| 450 CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */, | |
| 451 PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */); | |
| 452 if (!certs[i]) { | |
| 453 DestroyCertificates(&certs[0], i); | |
| 454 NOTREACHED(); | |
| 455 return false; | |
| 456 } | |
| 457 } | |
| 458 | |
| 459 rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size()); | |
| 460 DestroyCertificates(&certs[0], certs_in.size()); | |
| 461 DCHECK_EQ(SECSuccess, rv); | |
| 462 | |
| 463 if (state.npn_valid) { | |
| 464 predicted_npn_status_ = state.npn_status; | |
| 465 predicted_npn_proto_ = state.npn_protocol; | |
| 466 } | |
| 467 | |
| 468 return true; | |
| 469 } | |
| 470 | |
| 471 bool SSLClientSocketNSS::IsNPNProtocolMispredicted() { | |
| 472 DCHECK(handshake_callback_called_); | |
| 473 if (!predicted_npn_proto_used_) | |
| 474 return false; | |
| 475 std::string npn_proto; | |
| 476 GetNextProto(&npn_proto); | |
| 477 return predicted_npn_proto_ != npn_proto; | |
| 478 } | |
| 479 | |
| 480 void SSLClientSocketNSS::UncorkAfterTimeout() { | |
| 481 corked_ = false; | |
| 482 int nsent; | |
| 483 do { | |
| 484 nsent = BufferSend(); | |
| 485 } while (nsent > 0); | |
| 486 } | 580 } |
| 487 | 581 |
| 488 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { | 582 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { |
| 489 EnterFunction(""); | 583 EnterFunction(""); |
| 490 DCHECK(transport_.get()); | 584 DCHECK(transport_.get()); |
| 491 DCHECK(next_handshake_state_ == STATE_NONE); | 585 DCHECK(next_handshake_state_ == STATE_NONE); |
| 492 DCHECK(!user_read_callback_); | 586 DCHECK(!user_read_callback_); |
| 493 DCHECK(!user_write_callback_); | 587 DCHECK(!user_write_callback_); |
| 494 DCHECK(!user_connect_callback_); | 588 DCHECK(!user_connect_callback_); |
| 495 DCHECK(!user_read_buf_); | 589 DCHECK(!user_read_buf_); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 user_connect_callback_ = callback; | 629 user_connect_callback_ = callback; |
| 536 } | 630 } |
| 537 } else { | 631 } else { |
| 538 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); | 632 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); |
| 539 } | 633 } |
| 540 | 634 |
| 541 LeaveFunction(""); | 635 LeaveFunction(""); |
| 542 return rv > OK ? OK : rv; | 636 return rv > OK ? OK : rv; |
| 543 } | 637 } |
| 544 | 638 |
| 639 void SSLClientSocketNSS::Disconnect() { |
| 640 EnterFunction(""); |
| 641 |
| 642 // TODO(wtc): Send SSL close_notify alert. |
| 643 if (nss_fd_ != NULL) { |
| 644 PR_Close(nss_fd_); |
| 645 nss_fd_ = NULL; |
| 646 } |
| 647 |
| 648 // Shut down anything that may call us back (through buffer_send_callback_, |
| 649 // buffer_recv_callback, or handshake_io_callback_). |
| 650 verifier_.reset(); |
| 651 transport_->socket()->Disconnect(); |
| 652 |
| 653 // Reset object state |
| 654 transport_send_busy_ = false; |
| 655 transport_recv_busy_ = false; |
| 656 user_connect_callback_ = NULL; |
| 657 user_read_callback_ = NULL; |
| 658 user_write_callback_ = NULL; |
| 659 user_read_buf_ = NULL; |
| 660 user_read_buf_len_ = 0; |
| 661 user_write_buf_ = NULL; |
| 662 user_write_buf_len_ = 0; |
| 663 server_cert_ = NULL; |
| 664 if (server_cert_nss_) { |
| 665 CERT_DestroyCertificate(server_cert_nss_); |
| 666 server_cert_nss_ = NULL; |
| 667 } |
| 668 local_server_cert_verify_result_.Reset(); |
| 669 server_cert_verify_result_ = NULL; |
| 670 ssl_connection_status_ = 0; |
| 671 completed_handshake_ = false; |
| 672 pseudo_connected_ = false; |
| 673 eset_mitm_detected_ = false; |
| 674 start_cert_verification_time_ = base::TimeTicks(); |
| 675 predicted_cert_chain_correct_ = false; |
| 676 peername_initialized_ = false; |
| 677 nss_bufs_ = NULL; |
| 678 client_certs_.clear(); |
| 679 client_auth_cert_needed_ = false; |
| 680 |
| 681 LeaveFunction(""); |
| 682 } |
| 683 |
| 684 bool SSLClientSocketNSS::IsConnected() const { |
| 685 // Ideally, we should also check if we have received the close_notify alert |
| 686 // message from the server, and return false in that case. We're not doing |
| 687 // that, so this function may return a false positive. Since the upper |
| 688 // layer (HttpNetworkTransaction) needs to handle a persistent connection |
| 689 // closed by the server when we send a request anyway, a false positive in |
| 690 // exchange for simpler code is a good trade-off. |
| 691 EnterFunction(""); |
| 692 bool ret = (pseudo_connected_ || completed_handshake_) && |
| 693 transport_->socket()->IsConnected(); |
| 694 LeaveFunction(""); |
| 695 return ret; |
| 696 } |
| 697 |
| 698 bool SSLClientSocketNSS::IsConnectedAndIdle() const { |
| 699 // Unlike IsConnected, this method doesn't return a false positive. |
| 700 // |
| 701 // Strictly speaking, we should check if we have received the close_notify |
| 702 // alert message from the server, and return false in that case. Although |
| 703 // the close_notify alert message means EOF in the SSL layer, it is just |
| 704 // bytes to the transport layer below, so |
| 705 // transport_->socket()->IsConnectedAndIdle() returns the desired false |
| 706 // when we receive close_notify. |
| 707 EnterFunction(""); |
| 708 bool ret = (pseudo_connected_ || completed_handshake_) && |
| 709 transport_->socket()->IsConnectedAndIdle(); |
| 710 LeaveFunction(""); |
| 711 return ret; |
| 712 } |
| 713 |
| 714 int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { |
| 715 return transport_->socket()->GetPeerAddress(address); |
| 716 } |
| 717 |
| 718 const BoundNetLog& SSLClientSocketNSS::NetLog() const { |
| 719 return net_log_; |
| 720 } |
| 721 |
| 722 void SSLClientSocketNSS::SetSubresourceSpeculation() { |
| 723 if (transport_.get() && transport_->socket()) { |
| 724 transport_->socket()->SetSubresourceSpeculation(); |
| 725 } else { |
| 726 NOTREACHED(); |
| 727 } |
| 728 } |
| 729 |
| 730 void SSLClientSocketNSS::SetOmniboxSpeculation() { |
| 731 if (transport_.get() && transport_->socket()) { |
| 732 transport_->socket()->SetOmniboxSpeculation(); |
| 733 } else { |
| 734 NOTREACHED(); |
| 735 } |
| 736 } |
| 737 |
| 738 bool SSLClientSocketNSS::WasEverUsed() const { |
| 739 if (transport_.get() && transport_->socket()) { |
| 740 return transport_->socket()->WasEverUsed(); |
| 741 } |
| 742 NOTREACHED(); |
| 743 return false; |
| 744 } |
| 745 |
| 746 bool SSLClientSocketNSS::UsingTCPFastOpen() const { |
| 747 if (transport_.get() && transport_->socket()) { |
| 748 return transport_->socket()->UsingTCPFastOpen(); |
| 749 } |
| 750 NOTREACHED(); |
| 751 return false; |
| 752 } |
| 753 |
| 754 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, |
| 755 CompletionCallback* callback) { |
| 756 EnterFunction(buf_len); |
| 757 DCHECK(!user_read_callback_); |
| 758 DCHECK(!user_connect_callback_); |
| 759 DCHECK(!user_read_buf_); |
| 760 DCHECK(nss_bufs_); |
| 761 |
| 762 user_read_buf_ = buf; |
| 763 user_read_buf_len_ = buf_len; |
| 764 |
| 765 if (!completed_handshake_) { |
| 766 // In this case we have lied about being connected in order to merge the |
| 767 // first Write into a Snap Start handshake. We'll leave the read hanging |
| 768 // until the handshake has completed. |
| 769 DCHECK(pseudo_connected_); |
| 770 |
| 771 user_read_callback_ = callback; |
| 772 LeaveFunction(ERR_IO_PENDING); |
| 773 return ERR_IO_PENDING; |
| 774 } |
| 775 |
| 776 int rv = DoReadLoop(OK); |
| 777 |
| 778 if (rv == ERR_IO_PENDING) { |
| 779 user_read_callback_ = callback; |
| 780 } else { |
| 781 user_read_buf_ = NULL; |
| 782 user_read_buf_len_ = 0; |
| 783 } |
| 784 LeaveFunction(rv); |
| 785 return rv; |
| 786 } |
| 787 |
| 788 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, |
| 789 CompletionCallback* callback) { |
| 790 EnterFunction(buf_len); |
| 791 if (!pseudo_connected_) { |
| 792 DCHECK(completed_handshake_); |
| 793 DCHECK(next_handshake_state_ == STATE_NONE); |
| 794 DCHECK(!user_connect_callback_); |
| 795 } |
| 796 DCHECK(!user_write_callback_); |
| 797 DCHECK(!user_write_buf_); |
| 798 DCHECK(nss_bufs_); |
| 799 |
| 800 user_write_buf_ = buf; |
| 801 user_write_buf_len_ = buf_len; |
| 802 |
| 803 if (next_handshake_state_ == STATE_SNAP_START_WAIT_FOR_WRITE) { |
| 804 // We lied about being connected and we have been waiting for this write in |
| 805 // order to merge it into the Snap Start handshake. We'll leave the write |
| 806 // pending until the handshake completes. |
| 807 DCHECK(pseudo_connected_); |
| 808 int rv = DoHandshakeLoop(OK); |
| 809 if (rv == ERR_IO_PENDING) { |
| 810 user_write_callback_ = callback; |
| 811 } else { |
| 812 user_write_buf_ = NULL; |
| 813 user_write_buf_len_ = 0; |
| 814 } |
| 815 if (rv != OK) |
| 816 return rv; |
| 817 } |
| 818 |
| 819 if (corked_) { |
| 820 corked_ = false; |
| 821 uncork_timer_.Reset(); |
| 822 } |
| 823 int rv = DoWriteLoop(OK); |
| 824 |
| 825 if (rv == ERR_IO_PENDING) { |
| 826 user_write_callback_ = callback; |
| 827 } else { |
| 828 user_write_buf_ = NULL; |
| 829 user_write_buf_len_ = 0; |
| 830 } |
| 831 LeaveFunction(rv); |
| 832 return rv; |
| 833 } |
| 834 |
| 835 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { |
| 836 return transport_->socket()->SetReceiveBufferSize(size); |
| 837 } |
| 838 |
| 839 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { |
| 840 return transport_->socket()->SetSendBufferSize(size); |
| 841 } |
| 842 |
| 843 int SSLClientSocketNSS::Init() { |
| 844 EnterFunction(""); |
| 845 // Initialize the NSS SSL library in a threadsafe way. This also |
| 846 // initializes the NSS base library. |
| 847 EnsureNSSSSLInit(); |
| 848 if (!NSS_IsInitialized()) |
| 849 return ERR_UNEXPECTED; |
| 850 #if !defined(OS_MACOSX) && !defined(OS_WIN) |
| 851 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop |
| 852 // by MessageLoopForIO::current(). |
| 853 // X509Certificate::Verify() runs on a worker thread of CertVerifier. |
| 854 EnsureOCSPInit(); |
| 855 #endif |
| 856 |
| 857 LeaveFunction(""); |
| 858 return OK; |
| 859 } |
| 860 |
| 545 int SSLClientSocketNSS::InitializeSSLOptions() { | 861 int SSLClientSocketNSS::InitializeSSLOptions() { |
| 546 // Transport connected, now hook it up to nss | 862 // Transport connected, now hook it up to nss |
| 547 // TODO(port): specify rx and tx buffer sizes separately | 863 // TODO(port): specify rx and tx buffer sizes separately |
| 548 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 864 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); |
| 549 if (nss_fd_ == NULL) { | 865 if (nss_fd_ == NULL) { |
| 550 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. | 866 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. |
| 551 } | 867 } |
| 552 | 868 |
| 553 // Grab pointer to buffers | 869 // Grab pointer to buffers |
| 554 nss_bufs_ = memio_GetSecret(nss_fd_); | 870 nss_bufs_ = memio_GetSecret(nss_fd_); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 // rather than the destination server's address in that case. | 1073 // rather than the destination server's address in that case. |
| 758 std::string peer_id = host_and_port_.ToString(); | 1074 std::string peer_id = host_and_port_.ToString(); |
| 759 SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str())); | 1075 SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str())); |
| 760 if (rv != SECSuccess) | 1076 if (rv != SECSuccess) |
| 761 LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str()); | 1077 LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str()); |
| 762 | 1078 |
| 763 peername_initialized_ = true; | 1079 peername_initialized_ = true; |
| 764 return OK; | 1080 return OK; |
| 765 } | 1081 } |
| 766 | 1082 |
| 767 void SSLClientSocketNSS::Disconnect() { | |
| 768 EnterFunction(""); | |
| 769 | |
| 770 // TODO(wtc): Send SSL close_notify alert. | |
| 771 if (nss_fd_ != NULL) { | |
| 772 PR_Close(nss_fd_); | |
| 773 nss_fd_ = NULL; | |
| 774 } | |
| 775 | |
| 776 // Shut down anything that may call us back (through buffer_send_callback_, | |
| 777 // buffer_recv_callback, or handshake_io_callback_). | |
| 778 verifier_.reset(); | |
| 779 transport_->socket()->Disconnect(); | |
| 780 | |
| 781 // Reset object state | |
| 782 transport_send_busy_ = false; | |
| 783 transport_recv_busy_ = false; | |
| 784 user_connect_callback_ = NULL; | |
| 785 user_read_callback_ = NULL; | |
| 786 user_write_callback_ = NULL; | |
| 787 user_read_buf_ = NULL; | |
| 788 user_read_buf_len_ = 0; | |
| 789 user_write_buf_ = NULL; | |
| 790 user_write_buf_len_ = 0; | |
| 791 server_cert_ = NULL; | |
| 792 if (server_cert_nss_) { | |
| 793 CERT_DestroyCertificate(server_cert_nss_); | |
| 794 server_cert_nss_ = NULL; | |
| 795 } | |
| 796 local_server_cert_verify_result_.Reset(); | |
| 797 server_cert_verify_result_ = NULL; | |
| 798 ssl_connection_status_ = 0; | |
| 799 completed_handshake_ = false; | |
| 800 pseudo_connected_ = false; | |
| 801 eset_mitm_detected_ = false; | |
| 802 start_cert_verification_time_ = base::TimeTicks(); | |
| 803 predicted_cert_chain_correct_ = false; | |
| 804 peername_initialized_ = false; | |
| 805 nss_bufs_ = NULL; | |
| 806 client_certs_.clear(); | |
| 807 client_auth_cert_needed_ = false; | |
| 808 | |
| 809 LeaveFunction(""); | |
| 810 } | |
| 811 | |
| 812 bool SSLClientSocketNSS::IsConnected() const { | |
| 813 // Ideally, we should also check if we have received the close_notify alert | |
| 814 // message from the server, and return false in that case. We're not doing | |
| 815 // that, so this function may return a false positive. Since the upper | |
| 816 // layer (HttpNetworkTransaction) needs to handle a persistent connection | |
| 817 // closed by the server when we send a request anyway, a false positive in | |
| 818 // exchange for simpler code is a good trade-off. | |
| 819 EnterFunction(""); | |
| 820 bool ret = (pseudo_connected_ || completed_handshake_) && | |
| 821 transport_->socket()->IsConnected(); | |
| 822 LeaveFunction(""); | |
| 823 return ret; | |
| 824 } | |
| 825 | |
| 826 bool SSLClientSocketNSS::IsConnectedAndIdle() const { | |
| 827 // Unlike IsConnected, this method doesn't return a false positive. | |
| 828 // | |
| 829 // Strictly speaking, we should check if we have received the close_notify | |
| 830 // alert message from the server, and return false in that case. Although | |
| 831 // the close_notify alert message means EOF in the SSL layer, it is just | |
| 832 // bytes to the transport layer below, so | |
| 833 // transport_->socket()->IsConnectedAndIdle() returns the desired false | |
| 834 // when we receive close_notify. | |
| 835 EnterFunction(""); | |
| 836 bool ret = (pseudo_connected_ || completed_handshake_) && | |
| 837 transport_->socket()->IsConnectedAndIdle(); | |
| 838 LeaveFunction(""); | |
| 839 return ret; | |
| 840 } | |
| 841 | |
| 842 int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { | |
| 843 return transport_->socket()->GetPeerAddress(address); | |
| 844 } | |
| 845 | |
| 846 const BoundNetLog& SSLClientSocketNSS::NetLog() const { | |
| 847 return net_log_; | |
| 848 } | |
| 849 | |
| 850 void SSLClientSocketNSS::SetSubresourceSpeculation() { | |
| 851 if (transport_.get() && transport_->socket()) { | |
| 852 transport_->socket()->SetSubresourceSpeculation(); | |
| 853 } else { | |
| 854 NOTREACHED(); | |
| 855 } | |
| 856 } | |
| 857 | |
| 858 void SSLClientSocketNSS::SetOmniboxSpeculation() { | |
| 859 if (transport_.get() && transport_->socket()) { | |
| 860 transport_->socket()->SetOmniboxSpeculation(); | |
| 861 } else { | |
| 862 NOTREACHED(); | |
| 863 } | |
| 864 } | |
| 865 | |
| 866 bool SSLClientSocketNSS::WasEverUsed() const { | |
| 867 if (transport_.get() && transport_->socket()) { | |
| 868 return transport_->socket()->WasEverUsed(); | |
| 869 } | |
| 870 NOTREACHED(); | |
| 871 return false; | |
| 872 } | |
| 873 | |
| 874 bool SSLClientSocketNSS::UsingTCPFastOpen() const { | |
| 875 if (transport_.get() && transport_->socket()) { | |
| 876 return transport_->socket()->UsingTCPFastOpen(); | |
| 877 } | |
| 878 NOTREACHED(); | |
| 879 return false; | |
| 880 } | |
| 881 | |
| 882 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, | |
| 883 CompletionCallback* callback) { | |
| 884 EnterFunction(buf_len); | |
| 885 DCHECK(!user_read_callback_); | |
| 886 DCHECK(!user_connect_callback_); | |
| 887 DCHECK(!user_read_buf_); | |
| 888 DCHECK(nss_bufs_); | |
| 889 | |
| 890 user_read_buf_ = buf; | |
| 891 user_read_buf_len_ = buf_len; | |
| 892 | |
| 893 if (!completed_handshake_) { | |
| 894 // In this case we have lied about being connected in order to merge the | |
| 895 // first Write into a Snap Start handshake. We'll leave the read hanging | |
| 896 // until the handshake has completed. | |
| 897 DCHECK(pseudo_connected_); | |
| 898 | |
| 899 user_read_callback_ = callback; | |
| 900 LeaveFunction(ERR_IO_PENDING); | |
| 901 return ERR_IO_PENDING; | |
| 902 } | |
| 903 | |
| 904 int rv = DoReadLoop(OK); | |
| 905 | |
| 906 if (rv == ERR_IO_PENDING) { | |
| 907 user_read_callback_ = callback; | |
| 908 } else { | |
| 909 user_read_buf_ = NULL; | |
| 910 user_read_buf_len_ = 0; | |
| 911 } | |
| 912 LeaveFunction(rv); | |
| 913 return rv; | |
| 914 } | |
| 915 | |
| 916 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, | |
| 917 CompletionCallback* callback) { | |
| 918 EnterFunction(buf_len); | |
| 919 if (!pseudo_connected_) { | |
| 920 DCHECK(completed_handshake_); | |
| 921 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 922 DCHECK(!user_connect_callback_); | |
| 923 } | |
| 924 DCHECK(!user_write_callback_); | |
| 925 DCHECK(!user_write_buf_); | |
| 926 DCHECK(nss_bufs_); | |
| 927 | |
| 928 user_write_buf_ = buf; | |
| 929 user_write_buf_len_ = buf_len; | |
| 930 | |
| 931 if (next_handshake_state_ == STATE_SNAP_START_WAIT_FOR_WRITE) { | |
| 932 // We lied about being connected and we have been waiting for this write in | |
| 933 // order to merge it into the Snap Start handshake. We'll leave the write | |
| 934 // pending until the handshake completes. | |
| 935 DCHECK(pseudo_connected_); | |
| 936 int rv = DoHandshakeLoop(OK); | |
| 937 if (rv == ERR_IO_PENDING) { | |
| 938 user_write_callback_ = callback; | |
| 939 } else { | |
| 940 user_write_buf_ = NULL; | |
| 941 user_write_buf_len_ = 0; | |
| 942 } | |
| 943 if (rv != OK) | |
| 944 return rv; | |
| 945 } | |
| 946 | |
| 947 if (corked_) { | |
| 948 corked_ = false; | |
| 949 uncork_timer_.Reset(); | |
| 950 } | |
| 951 int rv = DoWriteLoop(OK); | |
| 952 | |
| 953 if (rv == ERR_IO_PENDING) { | |
| 954 user_write_callback_ = callback; | |
| 955 } else { | |
| 956 user_write_buf_ = NULL; | |
| 957 user_write_buf_len_ = 0; | |
| 958 } | |
| 959 LeaveFunction(rv); | |
| 960 return rv; | |
| 961 } | |
| 962 | |
| 963 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | |
| 964 return transport_->socket()->SetReceiveBufferSize(size); | |
| 965 } | |
| 966 | |
| 967 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { | |
| 968 return transport_->socket()->SetSendBufferSize(size); | |
| 969 } | |
| 970 | |
| 971 // static | |
| 972 void SSLClientSocketNSS::ClearSessionCache() { | |
| 973 SSL_ClearSessionCache(); | |
| 974 } | |
| 975 | 1083 |
| 976 // Sets server_cert_ and server_cert_nss_ if not yet set. | 1084 // Sets server_cert_ and server_cert_nss_ if not yet set. |
| 977 // Returns server_cert_. | 1085 // Returns server_cert_. |
| 978 X509Certificate *SSLClientSocketNSS::UpdateServerCert() { | 1086 X509Certificate *SSLClientSocketNSS::UpdateServerCert() { |
| 979 // We set the server_cert_ from HandshakeCallback(). | 1087 // We set the server_cert_ from HandshakeCallback(). |
| 980 if (server_cert_ == NULL) { | 1088 if (server_cert_ == NULL) { |
| 981 server_cert_nss_ = SSL_PeerCertificate(nss_fd_); | 1089 server_cert_nss_ = SSL_PeerCertificate(nss_fd_); |
| 982 if (server_cert_nss_) { | 1090 if (server_cert_nss_) { |
| 983 PeerCertificateChain certs(nss_fd_); | 1091 PeerCertificateChain certs(nss_fd_); |
| 984 server_cert_ = X509Certificate::CreateFromDERCertChain( | 1092 server_cert_ = X509Certificate::CreateFromDERCertChain( |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 } | 1152 } |
| 1045 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", | 1153 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", |
| 1046 peer_supports_renego_ext, 2); | 1154 peer_supports_renego_ext, 2); |
| 1047 } | 1155 } |
| 1048 #endif | 1156 #endif |
| 1049 | 1157 |
| 1050 if (ssl_config_.ssl3_fallback) | 1158 if (ssl_config_.ssl3_fallback) |
| 1051 ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK; | 1159 ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK; |
| 1052 } | 1160 } |
| 1053 | 1161 |
| 1054 void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { | |
| 1055 EnterFunction(""); | |
| 1056 ssl_info->Reset(); | |
| 1057 | |
| 1058 if (!server_cert_) { | |
| 1059 LOG(DFATAL) << "!server_cert_"; | |
| 1060 return; | |
| 1061 } | |
| 1062 | |
| 1063 ssl_info->cert_status = server_cert_verify_result_->cert_status; | |
| 1064 DCHECK(server_cert_ != NULL); | |
| 1065 ssl_info->cert = server_cert_; | |
| 1066 ssl_info->connection_status = ssl_connection_status_; | |
| 1067 | |
| 1068 PRUint16 cipher_suite = | |
| 1069 SSLConnectionStatusToCipherSuite(ssl_connection_status_); | |
| 1070 SSLCipherSuiteInfo cipher_info; | |
| 1071 SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite, | |
| 1072 &cipher_info, sizeof(cipher_info)); | |
| 1073 if (ok == SECSuccess) { | |
| 1074 ssl_info->security_bits = cipher_info.effectiveKeyBits; | |
| 1075 } else { | |
| 1076 ssl_info->security_bits = -1; | |
| 1077 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() | |
| 1078 << " for cipherSuite " << cipher_suite; | |
| 1079 } | |
| 1080 LeaveFunction(""); | |
| 1081 } | |
| 1082 | |
| 1083 void SSLClientSocketNSS::GetSSLCertRequestInfo( | |
| 1084 SSLCertRequestInfo* cert_request_info) { | |
| 1085 EnterFunction(""); | |
| 1086 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair | |
| 1087 cert_request_info->host_and_port = host_and_port_.ToString(); | |
| 1088 cert_request_info->client_certs = client_certs_; | |
| 1089 LeaveFunction(cert_request_info->client_certs.size()); | |
| 1090 } | |
| 1091 | |
| 1092 SSLClientSocket::NextProtoStatus | |
| 1093 SSLClientSocketNSS::GetNextProto(std::string* proto) { | |
| 1094 #if defined(SSL_NEXT_PROTO_NEGOTIATED) | |
| 1095 if (!handshake_callback_called_) { | |
| 1096 DCHECK(pseudo_connected_); | |
| 1097 predicted_npn_proto_used_ = true; | |
| 1098 *proto = predicted_npn_proto_; | |
| 1099 return predicted_npn_status_; | |
| 1100 } | |
| 1101 | |
| 1102 unsigned char buf[255]; | |
| 1103 int state; | |
| 1104 unsigned len; | |
| 1105 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf)); | |
| 1106 if (rv != SECSuccess) { | |
| 1107 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv; | |
| 1108 proto->clear(); | |
| 1109 return kNextProtoUnsupported; | |
| 1110 } | |
| 1111 // We don't check for truncation because sizeof(buf) is large enough to hold | |
| 1112 // the maximum protocol size. | |
| 1113 switch (state) { | |
| 1114 case SSL_NEXT_PROTO_NO_SUPPORT: | |
| 1115 proto->clear(); | |
| 1116 return kNextProtoUnsupported; | |
| 1117 case SSL_NEXT_PROTO_NEGOTIATED: | |
| 1118 *proto = std::string(reinterpret_cast<char*>(buf), len); | |
| 1119 return kNextProtoNegotiated; | |
| 1120 case SSL_NEXT_PROTO_NO_OVERLAP: | |
| 1121 *proto = std::string(reinterpret_cast<char*>(buf), len); | |
| 1122 return kNextProtoNoOverlap; | |
| 1123 default: | |
| 1124 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state; | |
| 1125 proto->clear(); | |
| 1126 return kNextProtoUnsupported; | |
| 1127 } | |
| 1128 #else | |
| 1129 // No NPN support in the libssl that we are building with. | |
| 1130 proto->clear(); | |
| 1131 return kNextProtoUnsupported; | |
| 1132 #endif | |
| 1133 } | |
| 1134 | |
| 1135 void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) { | |
| 1136 dnssec_provider_ = provider; | |
| 1137 } | |
| 1138 | |
| 1139 void SSLClientSocketNSS::DoReadCallback(int rv) { | 1162 void SSLClientSocketNSS::DoReadCallback(int rv) { |
| 1140 EnterFunction(rv); | 1163 EnterFunction(rv); |
| 1141 DCHECK(rv != ERR_IO_PENDING); | 1164 DCHECK(rv != ERR_IO_PENDING); |
| 1142 DCHECK(user_read_callback_); | 1165 DCHECK(user_read_callback_); |
| 1143 | 1166 |
| 1144 // Since Run may result in Read being called, clear |user_read_callback_| | 1167 // Since Run may result in Read being called, clear |user_read_callback_| |
| 1145 // up front. | 1168 // up front. |
| 1146 CompletionCallback* c = user_read_callback_; | 1169 CompletionCallback* c = user_read_callback_; |
| 1147 user_read_callback_ = NULL; | 1170 user_read_callback_ = NULL; |
| 1148 user_read_buf_ = NULL; | 1171 user_read_buf_ = NULL; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 LeaveFunction(""); | 1266 LeaveFunction(""); |
| 1244 return; | 1267 return; |
| 1245 } | 1268 } |
| 1246 | 1269 |
| 1247 int rv = DoReadLoop(result); | 1270 int rv = DoReadLoop(result); |
| 1248 if (rv != ERR_IO_PENDING) | 1271 if (rv != ERR_IO_PENDING) |
| 1249 DoReadCallback(rv); | 1272 DoReadCallback(rv); |
| 1250 LeaveFunction(""); | 1273 LeaveFunction(""); |
| 1251 } | 1274 } |
| 1252 | 1275 |
| 1253 // Do network I/O between the given buffer and the given socket. | |
| 1254 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) | |
| 1255 bool SSLClientSocketNSS::DoTransportIO() { | |
| 1256 EnterFunction(""); | |
| 1257 bool network_moved = false; | |
| 1258 if (nss_bufs_ != NULL) { | |
| 1259 int nsent = BufferSend(); | |
| 1260 int nreceived = BufferRecv(); | |
| 1261 network_moved = (nsent > 0 || nreceived >= 0); | |
| 1262 } | |
| 1263 LeaveFunction(network_moved); | |
| 1264 return network_moved; | |
| 1265 } | |
| 1266 | |
| 1267 // Return 0 for EOF, | |
| 1268 // > 0 for bytes transferred immediately, | |
| 1269 // < 0 for error (or the non-error ERR_IO_PENDING). | |
| 1270 int SSLClientSocketNSS::BufferSend(void) { | |
| 1271 if (transport_send_busy_) | |
| 1272 return ERR_IO_PENDING; | |
| 1273 | |
| 1274 EnterFunction(""); | |
| 1275 const char* buf1; | |
| 1276 const char* buf2; | |
| 1277 unsigned int len1, len2; | |
| 1278 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2); | |
| 1279 const unsigned int len = len1 + len2; | |
| 1280 | |
| 1281 if (corked_ && len < kRecvBufferSize / 2) | |
| 1282 return 0; | |
| 1283 | |
| 1284 int rv = 0; | |
| 1285 if (len) { | |
| 1286 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len)); | |
| 1287 memcpy(send_buffer->data(), buf1, len1); | |
| 1288 memcpy(send_buffer->data() + len1, buf2, len2); | |
| 1289 rv = transport_->socket()->Write(send_buffer, len, | |
| 1290 &buffer_send_callback_); | |
| 1291 if (rv == ERR_IO_PENDING) { | |
| 1292 transport_send_busy_ = true; | |
| 1293 } else { | |
| 1294 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); | |
| 1295 } | |
| 1296 } | |
| 1297 | |
| 1298 LeaveFunction(rv); | |
| 1299 return rv; | |
| 1300 } | |
| 1301 | |
| 1302 void SSLClientSocketNSS::BufferSendComplete(int result) { | |
| 1303 EnterFunction(result); | |
| 1304 | |
| 1305 // In the case of TCP FastOpen, connect is now finished. | |
| 1306 if (!peername_initialized_ && UsingTCPFastOpen()) | |
| 1307 InitializeSSLPeerName(); | |
| 1308 | |
| 1309 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result)); | |
| 1310 transport_send_busy_ = false; | |
| 1311 OnSendComplete(result); | |
| 1312 LeaveFunction(""); | |
| 1313 } | |
| 1314 | |
| 1315 | |
| 1316 int SSLClientSocketNSS::BufferRecv(void) { | |
| 1317 if (transport_recv_busy_) return ERR_IO_PENDING; | |
| 1318 | |
| 1319 char *buf; | |
| 1320 int nb = memio_GetReadParams(nss_bufs_, &buf); | |
| 1321 EnterFunction(nb); | |
| 1322 int rv; | |
| 1323 if (!nb) { | |
| 1324 // buffer too full to read into, so no I/O possible at moment | |
| 1325 rv = ERR_IO_PENDING; | |
| 1326 } else { | |
| 1327 recv_buffer_ = new IOBuffer(nb); | |
| 1328 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_); | |
| 1329 if (rv == ERR_IO_PENDING) { | |
| 1330 transport_recv_busy_ = true; | |
| 1331 } else { | |
| 1332 if (rv > 0) | |
| 1333 memcpy(buf, recv_buffer_->data(), rv); | |
| 1334 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); | |
| 1335 recv_buffer_ = NULL; | |
| 1336 } | |
| 1337 } | |
| 1338 LeaveFunction(rv); | |
| 1339 return rv; | |
| 1340 } | |
| 1341 | |
| 1342 void SSLClientSocketNSS::BufferRecvComplete(int result) { | |
| 1343 EnterFunction(result); | |
| 1344 if (result > 0) { | |
| 1345 char *buf; | |
| 1346 memio_GetReadParams(nss_bufs_, &buf); | |
| 1347 memcpy(buf, recv_buffer_->data(), result); | |
| 1348 } | |
| 1349 recv_buffer_ = NULL; | |
| 1350 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result)); | |
| 1351 transport_recv_busy_ = false; | |
| 1352 OnRecvComplete(result); | |
| 1353 LeaveFunction(""); | |
| 1354 } | |
| 1355 | |
| 1356 int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) { | 1276 int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) { |
| 1357 EnterFunction(last_io_result); | 1277 EnterFunction(last_io_result); |
| 1358 bool network_moved; | 1278 bool network_moved; |
| 1359 int rv = last_io_result; | 1279 int rv = last_io_result; |
| 1360 do { | 1280 do { |
| 1361 // Default to STATE_NONE for next state. | 1281 // Default to STATE_NONE for next state. |
| 1362 // (This is a quirk carried over from the windows | 1282 // (This is a quirk carried over from the windows |
| 1363 // implementation. It makes reading the logs a bit harder.) | 1283 // implementation. It makes reading the logs a bit harder.) |
| 1364 // State handlers can and often do call GotoState just | 1284 // State handlers can and often do call GotoState just |
| 1365 // to stay in the current state. | 1285 // to stay in the current state. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 int rv; | 1372 int rv; |
| 1453 do { | 1373 do { |
| 1454 rv = DoPayloadWrite(); | 1374 rv = DoPayloadWrite(); |
| 1455 network_moved = DoTransportIO(); | 1375 network_moved = DoTransportIO(); |
| 1456 } while (rv == ERR_IO_PENDING && network_moved); | 1376 } while (rv == ERR_IO_PENDING && network_moved); |
| 1457 | 1377 |
| 1458 LeaveFunction(""); | 1378 LeaveFunction(""); |
| 1459 return rv; | 1379 return rv; |
| 1460 } | 1380 } |
| 1461 | 1381 |
| 1382 int SSLClientSocketNSS::DoSnapStartLoadInfo() { |
| 1383 EnterFunction(""); |
| 1384 int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_); |
| 1385 GotoState(STATE_HANDSHAKE); |
| 1386 |
| 1387 if (rv == OK) { |
| 1388 if (ssl_host_info_->WaitForCertVerification(NULL) == OK) { |
| 1389 if (LoadSnapStartInfo()) { |
| 1390 pseudo_connected_ = true; |
| 1391 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE); |
| 1392 if (user_connect_callback_) |
| 1393 DoConnectCallback(OK); |
| 1394 } |
| 1395 } else if (!ssl_host_info_->state().server_hello.empty()) { |
| 1396 // A non-empty ServerHello suggests that we would have tried a Snap Start |
| 1397 // connection. |
| 1398 base::TimeTicks now = base::TimeTicks::Now(); |
| 1399 const base::TimeDelta duration = |
| 1400 now - ssl_host_info_->verification_start_time(); |
| 1401 UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration); |
| 1402 VLOG(1) << "Cannot snap start because verification isn't ready. " |
| 1403 << "Wanted verification after " |
| 1404 << duration.InMilliseconds() << "ms"; |
| 1405 } |
| 1406 } else { |
| 1407 DCHECK_EQ(ERR_IO_PENDING, rv); |
| 1408 GotoState(STATE_SNAP_START_LOAD_INFO); |
| 1409 } |
| 1410 |
| 1411 LeaveFunction(""); |
| 1412 return rv; |
| 1413 } |
| 1414 |
| 1415 int SSLClientSocketNSS::DoSnapStartWaitForWrite() { |
| 1416 EnterFunction(""); |
| 1417 // In this state, we're waiting for the first Write call so that we can merge |
| 1418 // it into the Snap Start handshake. |
| 1419 if (!user_write_buf_) { |
| 1420 // We'll lie and say that we're connected in order that someone will call |
| 1421 // Write. |
| 1422 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE); |
| 1423 DCHECK(!user_connect_callback_); |
| 1424 LeaveFunction(""); |
| 1425 return ERR_IO_PENDING; |
| 1426 } |
| 1427 |
| 1428 // This is the largest Snap Start application data payload that we'll try to |
| 1429 // use. A TCP client can only send three frames of data without an ACK and, |
| 1430 // at 2048 bytes, this leaves some space for the rest of the ClientHello |
| 1431 // (including possible session ticket). |
| 1432 static const int kMaxSnapStartPayloadSize = 2048; |
| 1433 |
| 1434 if (user_write_buf_len_ > kMaxSnapStartPayloadSize) { |
| 1435 user_write_buf_len_ = kMaxSnapStartPayloadSize; |
| 1436 // When we complete the handshake and call user_write_callback_ we'll say |
| 1437 // that we only wrote |kMaxSnapStartPayloadSize| bytes. That way the rest |
| 1438 // of the payload will be presented to |Write| again and transmitted as |
| 1439 // normal application data. |
| 1440 } |
| 1441 |
| 1442 SECStatus rv = SSL_SetSnapStartApplicationData( |
| 1443 nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()), |
| 1444 user_write_buf_len_); |
| 1445 DCHECK_EQ(SECSuccess, rv); |
| 1446 |
| 1447 GotoState(STATE_HANDSHAKE); |
| 1448 LeaveFunction(""); |
| 1449 return OK; |
| 1450 } |
| 1451 |
| 1452 int SSLClientSocketNSS::DoHandshake() { |
| 1453 EnterFunction(""); |
| 1454 int net_error = net::OK; |
| 1455 SECStatus rv = SSL_ForceHandshake(nss_fd_); |
| 1456 |
| 1457 if (client_auth_cert_needed_) { |
| 1458 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 1459 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 1460 make_scoped_refptr(new SSLErrorParams(net_error, 0))); |
| 1461 // If the handshake already succeeded (because the server requests but |
| 1462 // doesn't require a client cert), we need to invalidate the SSL session |
| 1463 // so that we won't try to resume the non-client-authenticated session in |
| 1464 // the next handshake. This will cause the server to ask for a client |
| 1465 // cert again. |
| 1466 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { |
| 1467 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); |
| 1468 } |
| 1469 } else if (rv == SECSuccess) { |
| 1470 if (handshake_callback_called_) { |
| 1471 if (eset_mitm_detected_) { |
| 1472 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; |
| 1473 } else { |
| 1474 // We need to see if the predicted certificate chain (in |
| 1475 // |ssl_host_info_->state().certs) matches the actual certificate chain |
| 1476 // before we call SaveSnapStartInfo, as that will update |
| 1477 // |ssl_host_info_|. |
| 1478 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { |
| 1479 PeerCertificateChain certs(nss_fd_); |
| 1480 const SSLHostInfo::State& state = ssl_host_info_->state(); |
| 1481 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); |
| 1482 if (predicted_cert_chain_correct_) { |
| 1483 for (unsigned i = 0; i < certs.size(); i++) { |
| 1484 if (certs[i]->derCert.len != state.certs[i].size() || |
| 1485 memcmp(certs[i]->derCert.data, state.certs[i].data(), |
| 1486 certs[i]->derCert.len) != 0) { |
| 1487 predicted_cert_chain_correct_ = false; |
| 1488 break; |
| 1489 } |
| 1490 } |
| 1491 } |
| 1492 } |
| 1493 |
| 1494 #if defined(SSL_ENABLE_OCSP_STAPLING) |
| 1495 const CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = |
| 1496 GetCacheOCSPResponseFromSideChannelFunction(); |
| 1497 // TODO: we need to be able to plumb an OCSP response into the system |
| 1498 // libraries. When we do, GetOCSPResponseFromSideChannelFunction |
| 1499 // needs to be updated for those platforms. |
| 1500 if (!predicted_cert_chain_correct_ && cache_ocsp_response) { |
| 1501 unsigned int len = 0; |
| 1502 SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len); |
| 1503 if (len) { |
| 1504 const unsigned int orig_len = len; |
| 1505 scoped_array<uint8> ocsp_response(new uint8[orig_len]); |
| 1506 SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len); |
| 1507 DCHECK_EQ(orig_len, len); |
| 1508 |
| 1509 SECItem ocsp_response_item; |
| 1510 ocsp_response_item.type = siBuffer; |
| 1511 ocsp_response_item.data = ocsp_response.get(); |
| 1512 ocsp_response_item.len = len; |
| 1513 |
| 1514 cache_ocsp_response( |
| 1515 CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(), |
| 1516 &ocsp_response_item, NULL); |
| 1517 } |
| 1518 } |
| 1519 #endif |
| 1520 |
| 1521 SaveSnapStartInfo(); |
| 1522 // SSL handshake is completed. It's possible that we mispredicted the |
| 1523 // NPN agreed protocol. In this case, we've just sent a request in the |
| 1524 // wrong protocol! The higher levels of this network stack aren't |
| 1525 // prepared for switching the protocol like that so we make up an error |
| 1526 // and rely on the fact that the request will be retried. |
| 1527 if (IsNPNProtocolMispredicted()) { |
| 1528 LOG(WARNING) << "Mispredicted NPN protocol for " |
| 1529 << host_and_port_.ToString(); |
| 1530 net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION; |
| 1531 } else { |
| 1532 // Let's verify the certificate. |
| 1533 GotoState(STATE_VERIFY_DNSSEC); |
| 1534 } |
| 1535 } |
| 1536 // Done! |
| 1537 } else { |
| 1538 // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 - |
| 1539 // SSL_ForceHandshake returned SECSuccess prematurely. |
| 1540 rv = SECFailure; |
| 1541 net_error = ERR_SSL_PROTOCOL_ERROR; |
| 1542 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 1543 make_scoped_refptr(new SSLErrorParams(net_error, 0))); |
| 1544 } |
| 1545 } else { |
| 1546 PRErrorCode prerr = PR_GetError(); |
| 1547 net_error = MapNSSHandshakeError(prerr); |
| 1548 |
| 1549 // If not done, stay in this state |
| 1550 if (net_error == ERR_IO_PENDING) { |
| 1551 GotoState(STATE_HANDSHAKE); |
| 1552 } else { |
| 1553 LOG(ERROR) << "handshake failed; NSS error code " << prerr |
| 1554 << ", net_error " << net_error; |
| 1555 net_log_.AddEvent( |
| 1556 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 1557 make_scoped_refptr(new SSLErrorParams(net_error, prerr))); |
| 1558 } |
| 1559 } |
| 1560 |
| 1561 LeaveFunction(""); |
| 1562 return net_error; |
| 1563 } |
| 1564 |
| 1565 int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { |
| 1566 if (ssl_config_.dns_cert_provenance_checking_enabled && |
| 1567 dns_cert_checker_) { |
| 1568 PeerCertificateChain certs(nss_fd_); |
| 1569 dns_cert_checker_->DoAsyncVerification( |
| 1570 host_and_port_.host(), certs.AsStringPieceVector()); |
| 1571 } |
| 1572 |
| 1573 if (ssl_config_.dnssec_enabled) { |
| 1574 DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(), |
| 1575 server_cert_nss_); |
| 1576 if (r == DNSVR_SUCCESS) { |
| 1577 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; |
| 1578 server_cert_verify_result_ = &local_server_cert_verify_result_; |
| 1579 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 1580 return OK; |
| 1581 } |
| 1582 } |
| 1583 |
| 1584 if (dnssec_provider_ == NULL) { |
| 1585 GotoState(STATE_VERIFY_CERT); |
| 1586 return OK; |
| 1587 } |
| 1588 |
| 1589 GotoState(STATE_VERIFY_DNSSEC_COMPLETE); |
| 1590 RRResponse* response; |
| 1591 dnssec_wait_start_time_ = base::Time::Now(); |
| 1592 return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_); |
| 1593 } |
| 1594 |
| 1595 int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) { |
| 1596 RRResponse* response; |
| 1597 int err = dnssec_provider_->GetDNSSECRecords(&response, NULL); |
| 1598 DCHECK_EQ(err, OK); |
| 1599 |
| 1600 const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_; |
| 1601 HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed); |
| 1602 |
| 1603 GotoState(STATE_VERIFY_CERT); |
| 1604 if (!response || response->rrdatas.empty()) |
| 1605 return OK; |
| 1606 |
| 1607 std::vector<base::StringPiece> records; |
| 1608 records.resize(response->rrdatas.size()); |
| 1609 for (unsigned i = 0; i < response->rrdatas.size(); i++) |
| 1610 records[i] = base::StringPiece(response->rrdatas[i]); |
| 1611 DNSValidationResult r = |
| 1612 VerifyTXTRecords(response->dnssec, server_cert_nss_, records); |
| 1613 |
| 1614 if (!ssl_config_.dnssec_enabled) { |
| 1615 // If DNSSEC is not enabled we don't take any action based on the result, |
| 1616 // except to record the latency, above. |
| 1617 return OK; |
| 1618 } |
| 1619 |
| 1620 switch (r) { |
| 1621 case DNSVR_FAILURE: |
| 1622 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 1623 local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS; |
| 1624 server_cert_verify_result_ = &local_server_cert_verify_result_; |
| 1625 return ERR_CERT_NOT_IN_DNS; |
| 1626 case DNSVR_CONTINUE: |
| 1627 GotoState(STATE_VERIFY_CERT); |
| 1628 break; |
| 1629 case DNSVR_SUCCESS: |
| 1630 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; |
| 1631 server_cert_verify_result_ = &local_server_cert_verify_result_; |
| 1632 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 1633 break; |
| 1634 default: |
| 1635 NOTREACHED(); |
| 1636 GotoState(STATE_VERIFY_CERT); |
| 1637 } |
| 1638 |
| 1639 return OK; |
| 1640 } |
| 1641 |
| 1642 int SSLClientSocketNSS::DoVerifyCert(int result) { |
| 1643 DCHECK(server_cert_); |
| 1644 |
| 1645 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 1646 start_cert_verification_time_ = base::TimeTicks::Now(); |
| 1647 |
| 1648 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() && |
| 1649 predicted_cert_chain_correct_) { |
| 1650 // If the SSLHostInfo had a prediction for the certificate chain of this |
| 1651 // server then it will have optimistically started a verification of that |
| 1652 // chain. So, if the prediction was correct, we should wait for that |
| 1653 // verification to finish rather than start our own. |
| 1654 net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL); |
| 1655 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2); |
| 1656 base::TimeTicks end_time = ssl_host_info_->verification_end_time(); |
| 1657 if (end_time.is_null()) |
| 1658 end_time = base::TimeTicks::Now(); |
| 1659 UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved", |
| 1660 end_time - ssl_host_info_->verification_start_time()); |
| 1661 server_cert_verify_result_ = &ssl_host_info_->cert_verify_result(); |
| 1662 return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_); |
| 1663 } else { |
| 1664 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2); |
| 1665 } |
| 1666 |
| 1667 int flags = 0; |
| 1668 if (ssl_config_.rev_checking_enabled) |
| 1669 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
| 1670 if (ssl_config_.verify_ev_cert) |
| 1671 flags |= X509Certificate::VERIFY_EV_CERT; |
| 1672 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); |
| 1673 server_cert_verify_result_ = &local_server_cert_verify_result_; |
| 1674 return verifier_->Verify(server_cert_, host_and_port_.host(), flags, |
| 1675 &local_server_cert_verify_result_, |
| 1676 &handshake_io_callback_); |
| 1677 } |
| 1678 |
| 1679 // Derived from AuthCertificateCallback() in |
| 1680 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. |
| 1681 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { |
| 1682 verifier_.reset(); |
| 1683 |
| 1684 if (!start_cert_verification_time_.is_null()) { |
| 1685 base::TimeDelta verify_time = |
| 1686 base::TimeTicks::Now() - start_cert_verification_time_; |
| 1687 if (result == OK) |
| 1688 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time); |
| 1689 else |
| 1690 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time); |
| 1691 } |
| 1692 |
| 1693 if (ssl_host_info_.get()) |
| 1694 ssl_host_info_->set_cert_verification_finished_time(); |
| 1695 |
| 1696 // We used to remember the intermediate CA certs in the NSS database |
| 1697 // persistently. However, NSS opens a connection to the SQLite database |
| 1698 // during NSS initialization and doesn't close the connection until NSS |
| 1699 // shuts down. If the file system where the database resides is gone, |
| 1700 // the database connection goes bad. What's worse, the connection won't |
| 1701 // recover when the file system comes back. Until this NSS or SQLite bug |
| 1702 // is fixed, we need to avoid using the NSS database for non-essential |
| 1703 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and |
| 1704 // http://crbug.com/15630 for more info. |
| 1705 |
| 1706 // If we have been explicitly told to accept this certificate, override the |
| 1707 // result of verifier_.Verify. |
| 1708 // Eventually, we should cache the cert verification results so that we don't |
| 1709 // need to call verifier_.Verify repeatedly. But for now we need to do this. |
| 1710 // Alternatively, we could use the cert's status that we stored along with |
| 1711 // the cert in the allowed_bad_certs vector. |
| 1712 if (IsCertificateError(result) && |
| 1713 ssl_config_.IsAllowedBadCert(server_cert_)) { |
| 1714 VLOG(1) << "accepting bad SSL certificate, as user told us to"; |
| 1715 result = OK; |
| 1716 } |
| 1717 |
| 1718 if (result == OK) |
| 1719 LogConnectionTypeMetrics(); |
| 1720 |
| 1721 completed_handshake_ = true; |
| 1722 |
| 1723 // If we merged a Write call into the handshake we need to make the |
| 1724 // callback now. |
| 1725 if (user_write_callback_) { |
| 1726 corked_ = false; |
| 1727 if (result != OK) { |
| 1728 DoWriteCallback(result); |
| 1729 } else { |
| 1730 SSLSnapStartResult snap_start_type; |
| 1731 SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type); |
| 1732 DCHECK_EQ(rv, SECSuccess); |
| 1733 DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE); |
| 1734 if (snap_start_type == SSL_SNAP_START_RECOVERY || |
| 1735 snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) { |
| 1736 // If we mispredicted the server's handshake then Snap Start will have |
| 1737 // triggered a recovery mode. The misprediction could have been caused |
| 1738 // by the server having a different certificate so the application data |
| 1739 // wasn't resent. Now that we have verified the certificate, we need to |
| 1740 // resend the application data. |
| 1741 int bytes_written = DoPayloadWrite(); |
| 1742 if (bytes_written != ERR_IO_PENDING) |
| 1743 DoWriteCallback(bytes_written); |
| 1744 } else { |
| 1745 DoWriteCallback(user_write_buf_len_); |
| 1746 } |
| 1747 } |
| 1748 } |
| 1749 |
| 1750 if (user_read_callback_) { |
| 1751 int rv = DoReadLoop(OK); |
| 1752 if (rv != ERR_IO_PENDING) |
| 1753 DoReadCallback(rv); |
| 1754 } |
| 1755 |
| 1756 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
| 1757 DCHECK(next_handshake_state_ == STATE_NONE); |
| 1758 return result; |
| 1759 } |
| 1760 |
| 1761 int SSLClientSocketNSS::DoPayloadRead() { |
| 1762 EnterFunction(user_read_buf_len_); |
| 1763 DCHECK(user_read_buf_); |
| 1764 DCHECK_GT(user_read_buf_len_, 0); |
| 1765 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); |
| 1766 if (client_auth_cert_needed_) { |
| 1767 // We don't need to invalidate the non-client-authenticated SSL session |
| 1768 // because the server will renegotiate anyway. |
| 1769 LeaveFunction(""); |
| 1770 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 1771 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, |
| 1772 make_scoped_refptr(new SSLErrorParams(rv, 0))); |
| 1773 return rv; |
| 1774 } |
| 1775 if (rv >= 0) { |
| 1776 LogData(user_read_buf_->data(), rv); |
| 1777 LeaveFunction(""); |
| 1778 return rv; |
| 1779 } |
| 1780 PRErrorCode prerr = PR_GetError(); |
| 1781 if (prerr == PR_WOULD_BLOCK_ERROR) { |
| 1782 LeaveFunction(""); |
| 1783 return ERR_IO_PENDING; |
| 1784 } |
| 1785 LeaveFunction(""); |
| 1786 rv = MapNSSError(prerr); |
| 1787 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, |
| 1788 make_scoped_refptr(new SSLErrorParams(rv, prerr))); |
| 1789 return rv; |
| 1790 } |
| 1791 |
| 1792 int SSLClientSocketNSS::DoPayloadWrite() { |
| 1793 EnterFunction(user_write_buf_len_); |
| 1794 DCHECK(user_write_buf_); |
| 1795 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); |
| 1796 if (rv >= 0) { |
| 1797 LogData(user_write_buf_->data(), rv); |
| 1798 LeaveFunction(""); |
| 1799 return rv; |
| 1800 } |
| 1801 PRErrorCode prerr = PR_GetError(); |
| 1802 if (prerr == PR_WOULD_BLOCK_ERROR) { |
| 1803 LeaveFunction(""); |
| 1804 return ERR_IO_PENDING; |
| 1805 } |
| 1806 LeaveFunction(""); |
| 1807 rv = MapNSSError(prerr); |
| 1808 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, |
| 1809 make_scoped_refptr(new SSLErrorParams(rv, prerr))); |
| 1810 return rv; |
| 1811 } |
| 1812 |
| 1813 void SSLClientSocketNSS::LogConnectionTypeMetrics() const { |
| 1814 UpdateConnectionTypeHistograms(CONNECTION_SSL); |
| 1815 if (server_cert_verify_result_->has_md5) |
| 1816 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); |
| 1817 if (server_cert_verify_result_->has_md2) |
| 1818 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); |
| 1819 if (server_cert_verify_result_->has_md4) |
| 1820 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); |
| 1821 if (server_cert_verify_result_->has_md5_ca) |
| 1822 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); |
| 1823 if (server_cert_verify_result_->has_md2_ca) |
| 1824 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); |
| 1825 int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_); |
| 1826 switch (ssl_version) { |
| 1827 case SSL_CONNECTION_VERSION_SSL2: |
| 1828 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2); |
| 1829 break; |
| 1830 case SSL_CONNECTION_VERSION_SSL3: |
| 1831 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3); |
| 1832 break; |
| 1833 case SSL_CONNECTION_VERSION_TLS1: |
| 1834 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1); |
| 1835 break; |
| 1836 case SSL_CONNECTION_VERSION_TLS1_1: |
| 1837 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); |
| 1838 break; |
| 1839 case SSL_CONNECTION_VERSION_TLS1_2: |
| 1840 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); |
| 1841 break; |
| 1842 }; |
| 1843 } |
| 1844 |
| 1845 // SaveSnapStartInfo extracts the information needed to perform a Snap Start |
| 1846 // with this server in the future (if any) and tells |ssl_host_info_| to |
| 1847 // preserve it. |
| 1848 void SSLClientSocketNSS::SaveSnapStartInfo() { |
| 1849 if (!ssl_host_info_.get()) |
| 1850 return; |
| 1851 |
| 1852 // If the SSLHostInfo hasn't managed to load from disk yet then we can't save |
| 1853 // anything. |
| 1854 if (ssl_host_info_->WaitForDataReady(NULL) != OK) |
| 1855 return; |
| 1856 |
| 1857 SECStatus rv; |
| 1858 SSLSnapStartResult snap_start_type; |
| 1859 rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type); |
| 1860 if (rv != SECSuccess) { |
| 1861 NOTREACHED(); |
| 1862 return; |
| 1863 } |
| 1864 net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START, |
| 1865 new NetLogIntegerParameter("type", snap_start_type)); |
| 1866 if (snap_start_type == SSL_SNAP_START_FULL || |
| 1867 snap_start_type == SSL_SNAP_START_RESUME) { |
| 1868 // If we did a successful Snap Start then our information was correct and |
| 1869 // there's no point saving it again. |
| 1870 return; |
| 1871 } |
| 1872 |
| 1873 const unsigned char* hello_data; |
| 1874 unsigned hello_data_len; |
| 1875 rv = SSL_GetPredictedServerHelloData(nss_fd_, &hello_data, &hello_data_len); |
| 1876 if (rv != SECSuccess) { |
| 1877 NOTREACHED(); |
| 1878 return; |
| 1879 } |
| 1880 if (hello_data_len > std::numeric_limits<uint16>::max()) |
| 1881 return; |
| 1882 SSLHostInfo::State* state = ssl_host_info_->mutable_state(); |
| 1883 |
| 1884 if (hello_data_len > 0) { |
| 1885 state->server_hello = |
| 1886 std::string(reinterpret_cast<const char *>(hello_data), hello_data_len); |
| 1887 state->npn_valid = true; |
| 1888 state->npn_status = GetNextProto(&state->npn_protocol); |
| 1889 } else { |
| 1890 state->server_hello.clear(); |
| 1891 state->npn_valid = false; |
| 1892 } |
| 1893 |
| 1894 state->certs.clear(); |
| 1895 PeerCertificateChain certs(nss_fd_); |
| 1896 for (unsigned i = 0; i < certs.size(); i++) { |
| 1897 if (certs[i]->derCert.len > std::numeric_limits<uint16>::max()) |
| 1898 return; |
| 1899 |
| 1900 state->certs.push_back(std::string( |
| 1901 reinterpret_cast<char*>(certs[i]->derCert.data), |
| 1902 certs[i]->derCert.len)); |
| 1903 } |
| 1904 |
| 1905 ssl_host_info_->Persist(); |
| 1906 } |
| 1907 |
| 1908 // LoadSnapStartInfo parses |info|, which contains data previously serialised |
| 1909 // by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello |
| 1910 // data on the NSS socket. Returns true on success. If this function returns |
| 1911 // false, the caller should try a normal TLS handshake. |
| 1912 bool SSLClientSocketNSS::LoadSnapStartInfo() { |
| 1913 const SSLHostInfo::State& state(ssl_host_info_->state()); |
| 1914 |
| 1915 if (state.server_hello.empty() || |
| 1916 state.certs.empty() || |
| 1917 !state.npn_valid) { |
| 1918 return false; |
| 1919 } |
| 1920 |
| 1921 SECStatus rv; |
| 1922 rv = SSL_SetPredictedServerHelloData( |
| 1923 nss_fd_, |
| 1924 reinterpret_cast<const uint8*>(state.server_hello.data()), |
| 1925 state.server_hello.size()); |
| 1926 DCHECK_EQ(SECSuccess, rv); |
| 1927 |
| 1928 const std::vector<std::string>& certs_in = state.certs; |
| 1929 scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]); |
| 1930 for (size_t i = 0; i < certs_in.size(); i++) { |
| 1931 SECItem derCert; |
| 1932 derCert.data = |
| 1933 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data())); |
| 1934 derCert.len = certs_in[i].size(); |
| 1935 certs[i] = CERT_NewTempCertificate( |
| 1936 CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */, |
| 1937 PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */); |
| 1938 if (!certs[i]) { |
| 1939 DestroyCertificates(&certs[0], i); |
| 1940 NOTREACHED(); |
| 1941 return false; |
| 1942 } |
| 1943 } |
| 1944 |
| 1945 rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size()); |
| 1946 DestroyCertificates(&certs[0], certs_in.size()); |
| 1947 DCHECK_EQ(SECSuccess, rv); |
| 1948 |
| 1949 if (state.npn_valid) { |
| 1950 predicted_npn_status_ = state.npn_status; |
| 1951 predicted_npn_proto_ = state.npn_protocol; |
| 1952 } |
| 1953 |
| 1954 return true; |
| 1955 } |
| 1956 |
| 1957 bool SSLClientSocketNSS::IsNPNProtocolMispredicted() { |
| 1958 DCHECK(handshake_callback_called_); |
| 1959 if (!predicted_npn_proto_used_) |
| 1960 return false; |
| 1961 std::string npn_proto; |
| 1962 GetNextProto(&npn_proto); |
| 1963 return predicted_npn_proto_ != npn_proto; |
| 1964 } |
| 1965 |
| 1966 void SSLClientSocketNSS::UncorkAfterTimeout() { |
| 1967 corked_ = false; |
| 1968 int nsent; |
| 1969 do { |
| 1970 nsent = BufferSend(); |
| 1971 } while (nsent > 0); |
| 1972 } |
| 1973 |
| 1974 // Do network I/O between the given buffer and the given socket. |
| 1975 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) |
| 1976 bool SSLClientSocketNSS::DoTransportIO() { |
| 1977 EnterFunction(""); |
| 1978 bool network_moved = false; |
| 1979 if (nss_bufs_ != NULL) { |
| 1980 int nsent = BufferSend(); |
| 1981 int nreceived = BufferRecv(); |
| 1982 network_moved = (nsent > 0 || nreceived >= 0); |
| 1983 } |
| 1984 LeaveFunction(network_moved); |
| 1985 return network_moved; |
| 1986 } |
| 1987 |
| 1988 // Return 0 for EOF, |
| 1989 // > 0 for bytes transferred immediately, |
| 1990 // < 0 for error (or the non-error ERR_IO_PENDING). |
| 1991 int SSLClientSocketNSS::BufferSend(void) { |
| 1992 if (transport_send_busy_) |
| 1993 return ERR_IO_PENDING; |
| 1994 |
| 1995 EnterFunction(""); |
| 1996 const char* buf1; |
| 1997 const char* buf2; |
| 1998 unsigned int len1, len2; |
| 1999 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2); |
| 2000 const unsigned int len = len1 + len2; |
| 2001 |
| 2002 if (corked_ && len < kRecvBufferSize / 2) |
| 2003 return 0; |
| 2004 |
| 2005 int rv = 0; |
| 2006 if (len) { |
| 2007 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len)); |
| 2008 memcpy(send_buffer->data(), buf1, len1); |
| 2009 memcpy(send_buffer->data() + len1, buf2, len2); |
| 2010 rv = transport_->socket()->Write(send_buffer, len, |
| 2011 &buffer_send_callback_); |
| 2012 if (rv == ERR_IO_PENDING) { |
| 2013 transport_send_busy_ = true; |
| 2014 } else { |
| 2015 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); |
| 2016 } |
| 2017 } |
| 2018 |
| 2019 LeaveFunction(rv); |
| 2020 return rv; |
| 2021 } |
| 2022 |
| 2023 void SSLClientSocketNSS::BufferSendComplete(int result) { |
| 2024 EnterFunction(result); |
| 2025 |
| 2026 // In the case of TCP FastOpen, connect is now finished. |
| 2027 if (!peername_initialized_ && UsingTCPFastOpen()) |
| 2028 InitializeSSLPeerName(); |
| 2029 |
| 2030 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result)); |
| 2031 transport_send_busy_ = false; |
| 2032 OnSendComplete(result); |
| 2033 LeaveFunction(""); |
| 2034 } |
| 2035 |
| 2036 int SSLClientSocketNSS::BufferRecv(void) { |
| 2037 if (transport_recv_busy_) return ERR_IO_PENDING; |
| 2038 |
| 2039 char *buf; |
| 2040 int nb = memio_GetReadParams(nss_bufs_, &buf); |
| 2041 EnterFunction(nb); |
| 2042 int rv; |
| 2043 if (!nb) { |
| 2044 // buffer too full to read into, so no I/O possible at moment |
| 2045 rv = ERR_IO_PENDING; |
| 2046 } else { |
| 2047 recv_buffer_ = new IOBuffer(nb); |
| 2048 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_); |
| 2049 if (rv == ERR_IO_PENDING) { |
| 2050 transport_recv_busy_ = true; |
| 2051 } else { |
| 2052 if (rv > 0) |
| 2053 memcpy(buf, recv_buffer_->data(), rv); |
| 2054 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); |
| 2055 recv_buffer_ = NULL; |
| 2056 } |
| 2057 } |
| 2058 LeaveFunction(rv); |
| 2059 return rv; |
| 2060 } |
| 2061 |
| 2062 void SSLClientSocketNSS::BufferRecvComplete(int result) { |
| 2063 EnterFunction(result); |
| 2064 if (result > 0) { |
| 2065 char *buf; |
| 2066 memio_GetReadParams(nss_bufs_, &buf); |
| 2067 memcpy(buf, recv_buffer_->data(), result); |
| 2068 } |
| 2069 recv_buffer_ = NULL; |
| 2070 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result)); |
| 2071 transport_recv_busy_ = false; |
| 2072 OnRecvComplete(result); |
| 2073 LeaveFunction(""); |
| 2074 } |
| 2075 |
| 1462 // static | 2076 // static |
| 1463 // NSS calls this if an incoming certificate needs to be verified. | 2077 // NSS calls this if an incoming certificate needs to be verified. |
| 1464 // Do nothing but return SECSuccess. | 2078 // Do nothing but return SECSuccess. |
| 1465 // This is called only in full handshake mode. | 2079 // This is called only in full handshake mode. |
| 1466 // Peer certificate is retrieved in HandshakeCallback() later, which is called | 2080 // Peer certificate is retrieved in HandshakeCallback() later, which is called |
| 1467 // in full handshake mode or in resumption handshake mode. | 2081 // in full handshake mode or in resumption handshake mode. |
| 1468 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, | 2082 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, |
| 1469 PRFileDesc* socket, | 2083 PRFileDesc* socket, |
| 1470 PRBool checksig, | 2084 PRBool checksig, |
| 1471 PRBool is_server) { | 2085 PRBool is_server) { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, | 2507 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, |
| 1894 void* arg) { | 2508 void* arg) { |
| 1895 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 2509 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); |
| 1896 | 2510 |
| 1897 that->handshake_callback_called_ = true; | 2511 that->handshake_callback_called_ = true; |
| 1898 | 2512 |
| 1899 that->UpdateServerCert(); | 2513 that->UpdateServerCert(); |
| 1900 that->UpdateConnectionStatus(); | 2514 that->UpdateConnectionStatus(); |
| 1901 } | 2515 } |
| 1902 | 2516 |
| 1903 int SSLClientSocketNSS::DoSnapStartLoadInfo() { | |
| 1904 EnterFunction(""); | |
| 1905 int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_); | |
| 1906 GotoState(STATE_HANDSHAKE); | |
| 1907 | |
| 1908 if (rv == OK) { | |
| 1909 if (ssl_host_info_->WaitForCertVerification(NULL) == OK) { | |
| 1910 if (LoadSnapStartInfo()) { | |
| 1911 pseudo_connected_ = true; | |
| 1912 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE); | |
| 1913 if (user_connect_callback_) | |
| 1914 DoConnectCallback(OK); | |
| 1915 } | |
| 1916 } else if (!ssl_host_info_->state().server_hello.empty()) { | |
| 1917 // A non-empty ServerHello suggests that we would have tried a Snap Start | |
| 1918 // connection. | |
| 1919 base::TimeTicks now = base::TimeTicks::Now(); | |
| 1920 const base::TimeDelta duration = | |
| 1921 now - ssl_host_info_->verification_start_time(); | |
| 1922 UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration); | |
| 1923 VLOG(1) << "Cannot snap start because verification isn't ready. " | |
| 1924 << "Wanted verification after " | |
| 1925 << duration.InMilliseconds() << "ms"; | |
| 1926 } | |
| 1927 } else { | |
| 1928 DCHECK_EQ(ERR_IO_PENDING, rv); | |
| 1929 GotoState(STATE_SNAP_START_LOAD_INFO); | |
| 1930 } | |
| 1931 | |
| 1932 LeaveFunction(""); | |
| 1933 return rv; | |
| 1934 } | |
| 1935 | |
| 1936 int SSLClientSocketNSS::DoSnapStartWaitForWrite() { | |
| 1937 EnterFunction(""); | |
| 1938 // In this state, we're waiting for the first Write call so that we can merge | |
| 1939 // it into the Snap Start handshake. | |
| 1940 if (!user_write_buf_) { | |
| 1941 // We'll lie and say that we're connected in order that someone will call | |
| 1942 // Write. | |
| 1943 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE); | |
| 1944 DCHECK(!user_connect_callback_); | |
| 1945 LeaveFunction(""); | |
| 1946 return ERR_IO_PENDING; | |
| 1947 } | |
| 1948 | |
| 1949 // This is the largest Snap Start application data payload that we'll try to | |
| 1950 // use. A TCP client can only send three frames of data without an ACK and, | |
| 1951 // at 2048 bytes, this leaves some space for the rest of the ClientHello | |
| 1952 // (including possible session ticket). | |
| 1953 static const int kMaxSnapStartPayloadSize = 2048; | |
| 1954 | |
| 1955 if (user_write_buf_len_ > kMaxSnapStartPayloadSize) { | |
| 1956 user_write_buf_len_ = kMaxSnapStartPayloadSize; | |
| 1957 // When we complete the handshake and call user_write_callback_ we'll say | |
| 1958 // that we only wrote |kMaxSnapStartPayloadSize| bytes. That way the rest | |
| 1959 // of the payload will be presented to |Write| again and transmitted as | |
| 1960 // normal application data. | |
| 1961 } | |
| 1962 | |
| 1963 SECStatus rv = SSL_SetSnapStartApplicationData( | |
| 1964 nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()), | |
| 1965 user_write_buf_len_); | |
| 1966 DCHECK_EQ(SECSuccess, rv); | |
| 1967 | |
| 1968 GotoState(STATE_HANDSHAKE); | |
| 1969 LeaveFunction(""); | |
| 1970 return OK; | |
| 1971 } | |
| 1972 | |
| 1973 int SSLClientSocketNSS::DoHandshake() { | |
| 1974 EnterFunction(""); | |
| 1975 int net_error = net::OK; | |
| 1976 SECStatus rv = SSL_ForceHandshake(nss_fd_); | |
| 1977 | |
| 1978 if (client_auth_cert_needed_) { | |
| 1979 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | |
| 1980 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, | |
| 1981 make_scoped_refptr(new SSLErrorParams(net_error, 0))); | |
| 1982 // If the handshake already succeeded (because the server requests but | |
| 1983 // doesn't require a client cert), we need to invalidate the SSL session | |
| 1984 // so that we won't try to resume the non-client-authenticated session in | |
| 1985 // the next handshake. This will cause the server to ask for a client | |
| 1986 // cert again. | |
| 1987 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { | |
| 1988 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); | |
| 1989 } | |
| 1990 } else if (rv == SECSuccess) { | |
| 1991 if (handshake_callback_called_) { | |
| 1992 if (eset_mitm_detected_) { | |
| 1993 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; | |
| 1994 } else { | |
| 1995 // We need to see if the predicted certificate chain (in | |
| 1996 // |ssl_host_info_->state().certs) matches the actual certificate chain | |
| 1997 // before we call SaveSnapStartInfo, as that will update | |
| 1998 // |ssl_host_info_|. | |
| 1999 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { | |
| 2000 PeerCertificateChain certs(nss_fd_); | |
| 2001 const SSLHostInfo::State& state = ssl_host_info_->state(); | |
| 2002 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); | |
| 2003 if (predicted_cert_chain_correct_) { | |
| 2004 for (unsigned i = 0; i < certs.size(); i++) { | |
| 2005 if (certs[i]->derCert.len != state.certs[i].size() || | |
| 2006 memcmp(certs[i]->derCert.data, state.certs[i].data(), | |
| 2007 certs[i]->derCert.len) != 0) { | |
| 2008 predicted_cert_chain_correct_ = false; | |
| 2009 break; | |
| 2010 } | |
| 2011 } | |
| 2012 } | |
| 2013 } | |
| 2014 | |
| 2015 #if defined(SSL_ENABLE_OCSP_STAPLING) | |
| 2016 const CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = | |
| 2017 GetCacheOCSPResponseFromSideChannelFunction(); | |
| 2018 // TODO: we need to be able to plumb an OCSP response into the system | |
| 2019 // libraries. When we do, GetOCSPResponseFromSideChannelFunction | |
| 2020 // needs to be updated for those platforms. | |
| 2021 if (!predicted_cert_chain_correct_ && cache_ocsp_response) { | |
| 2022 unsigned int len = 0; | |
| 2023 SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len); | |
| 2024 if (len) { | |
| 2025 const unsigned int orig_len = len; | |
| 2026 scoped_array<uint8> ocsp_response(new uint8[orig_len]); | |
| 2027 SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len); | |
| 2028 DCHECK_EQ(orig_len, len); | |
| 2029 | |
| 2030 SECItem ocsp_response_item; | |
| 2031 ocsp_response_item.type = siBuffer; | |
| 2032 ocsp_response_item.data = ocsp_response.get(); | |
| 2033 ocsp_response_item.len = len; | |
| 2034 | |
| 2035 cache_ocsp_response( | |
| 2036 CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(), | |
| 2037 &ocsp_response_item, NULL); | |
| 2038 } | |
| 2039 } | |
| 2040 #endif | |
| 2041 | |
| 2042 SaveSnapStartInfo(); | |
| 2043 // SSL handshake is completed. It's possible that we mispredicted the | |
| 2044 // NPN agreed protocol. In this case, we've just sent a request in the | |
| 2045 // wrong protocol! The higher levels of this network stack aren't | |
| 2046 // prepared for switching the protocol like that so we make up an error | |
| 2047 // and rely on the fact that the request will be retried. | |
| 2048 if (IsNPNProtocolMispredicted()) { | |
| 2049 LOG(WARNING) << "Mispredicted NPN protocol for " | |
| 2050 << host_and_port_.ToString(); | |
| 2051 net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION; | |
| 2052 } else { | |
| 2053 // Let's verify the certificate. | |
| 2054 GotoState(STATE_VERIFY_DNSSEC); | |
| 2055 } | |
| 2056 } | |
| 2057 // Done! | |
| 2058 } else { | |
| 2059 // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 - | |
| 2060 // SSL_ForceHandshake returned SECSuccess prematurely. | |
| 2061 rv = SECFailure; | |
| 2062 net_error = ERR_SSL_PROTOCOL_ERROR; | |
| 2063 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, | |
| 2064 make_scoped_refptr(new SSLErrorParams(net_error, 0))); | |
| 2065 } | |
| 2066 } else { | |
| 2067 PRErrorCode prerr = PR_GetError(); | |
| 2068 net_error = MapNSSHandshakeError(prerr); | |
| 2069 | |
| 2070 // If not done, stay in this state | |
| 2071 if (net_error == ERR_IO_PENDING) { | |
| 2072 GotoState(STATE_HANDSHAKE); | |
| 2073 } else { | |
| 2074 LOG(ERROR) << "handshake failed; NSS error code " << prerr | |
| 2075 << ", net_error " << net_error; | |
| 2076 net_log_.AddEvent( | |
| 2077 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | |
| 2078 make_scoped_refptr(new SSLErrorParams(net_error, prerr))); | |
| 2079 } | |
| 2080 } | |
| 2081 | |
| 2082 LeaveFunction(""); | |
| 2083 return net_error; | |
| 2084 } | |
| 2085 | |
| 2086 // DNSValidationResult enumerates the possible outcomes from processing a | |
| 2087 // set of DNS records. | |
| 2088 enum DNSValidationResult { | |
| 2089 DNSVR_SUCCESS, // the cert is immediately acceptable. | |
| 2090 DNSVR_FAILURE, // the cert is unconditionally rejected. | |
| 2091 DNSVR_CONTINUE, // perform CA validation as usual. | |
| 2092 }; | |
| 2093 | |
| 2094 // VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and | |
| 2095 // checks them against the given certificate. | |
| 2096 // dnssec: if true then the TXT records are DNSSEC validated. In this case, | |
| 2097 // DNSVR_SUCCESS may be returned. | |
| 2098 // server_cert_nss: the certificate to validate | |
| 2099 // rrdatas: the TXT records for the current domain. | |
| 2100 static DNSValidationResult VerifyTXTRecords( | |
| 2101 bool dnssec, | |
| 2102 CERTCertificate* server_cert_nss, | |
| 2103 const std::vector<base::StringPiece>& rrdatas) { | |
| 2104 bool found_well_formed_record = false; | |
| 2105 bool matched_record = false; | |
| 2106 | |
| 2107 for (std::vector<base::StringPiece>::const_iterator | |
| 2108 i = rrdatas.begin(); i != rrdatas.end(); ++i) { | |
| 2109 std::map<std::string, std::string> m( | |
| 2110 DNSSECChainVerifier::ParseTLSTXTRecord(*i)); | |
| 2111 if (m.empty()) | |
| 2112 continue; | |
| 2113 | |
| 2114 std::map<std::string, std::string>::const_iterator j; | |
| 2115 j = m.find("v"); | |
| 2116 if (j == m.end() || j->second != "tls1") | |
| 2117 continue; | |
| 2118 | |
| 2119 j = m.find("ha"); | |
| 2120 | |
| 2121 HASH_HashType hash_algorithm; | |
| 2122 unsigned hash_length; | |
| 2123 if (j == m.end() || j->second == "sha1") { | |
| 2124 hash_algorithm = HASH_AlgSHA1; | |
| 2125 hash_length = SHA1_LENGTH; | |
| 2126 } else if (j->second == "sha256") { | |
| 2127 hash_algorithm = HASH_AlgSHA256; | |
| 2128 hash_length = SHA256_LENGTH; | |
| 2129 } else { | |
| 2130 continue; | |
| 2131 } | |
| 2132 | |
| 2133 j = m.find("h"); | |
| 2134 if (j == m.end()) | |
| 2135 continue; | |
| 2136 | |
| 2137 std::vector<uint8> given_hash; | |
| 2138 if (!base::HexStringToBytes(j->second, &given_hash)) | |
| 2139 continue; | |
| 2140 | |
| 2141 if (given_hash.size() != hash_length) | |
| 2142 continue; | |
| 2143 | |
| 2144 uint8 calculated_hash[SHA256_LENGTH]; // SHA256 is the largest. | |
| 2145 SECStatus rv; | |
| 2146 | |
| 2147 j = m.find("hr"); | |
| 2148 if (j == m.end() || j->second == "pubkey") { | |
| 2149 rv = HASH_HashBuf(hash_algorithm, calculated_hash, | |
| 2150 server_cert_nss->derPublicKey.data, | |
| 2151 server_cert_nss->derPublicKey.len); | |
| 2152 } else if (j->second == "cert") { | |
| 2153 rv = HASH_HashBuf(hash_algorithm, calculated_hash, | |
| 2154 server_cert_nss->derCert.data, | |
| 2155 server_cert_nss->derCert.len); | |
| 2156 } else { | |
| 2157 continue; | |
| 2158 } | |
| 2159 | |
| 2160 if (rv != SECSuccess) | |
| 2161 NOTREACHED(); | |
| 2162 | |
| 2163 found_well_formed_record = true; | |
| 2164 | |
| 2165 if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) { | |
| 2166 matched_record = true; | |
| 2167 if (dnssec) | |
| 2168 return DNSVR_SUCCESS; | |
| 2169 } | |
| 2170 } | |
| 2171 | |
| 2172 if (found_well_formed_record && !matched_record) | |
| 2173 return DNSVR_FAILURE; | |
| 2174 | |
| 2175 return DNSVR_CONTINUE; | |
| 2176 } | |
| 2177 | |
| 2178 | |
| 2179 // CheckDNSSECChain tries to validate a DNSSEC chain embedded in | |
| 2180 // |server_cert_nss_|. It returns true iff a chain is found that proves the | |
| 2181 // value of a TXT record that contains a valid public key fingerprint. | |
| 2182 static DNSValidationResult CheckDNSSECChain( | |
| 2183 const std::string& hostname, | |
| 2184 CERTCertificate* server_cert_nss) { | |
| 2185 if (!server_cert_nss) | |
| 2186 return DNSVR_CONTINUE; | |
| 2187 | |
| 2188 // CERT_FindCertExtensionByOID isn't exported so we have to install an OID, | |
| 2189 // get a tag for it and find the extension by using that tag. | |
| 2190 static SECOidTag dnssec_chain_tag; | |
| 2191 static bool dnssec_chain_tag_valid; | |
| 2192 if (!dnssec_chain_tag_valid) { | |
| 2193 // It's harmless if multiple threads enter this block concurrently. | |
| 2194 static const uint8 kDNSSECChainOID[] = | |
| 2195 // 1.3.6.1.4.1.11129.2.1.4 | |
| 2196 // (iso.org.dod.internet.private.enterprises.google.googleSecurity. | |
| 2197 // certificateExtensions.dnssecEmbeddedChain) | |
| 2198 {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04}; | |
| 2199 SECOidData oid_data; | |
| 2200 memset(&oid_data, 0, sizeof(oid_data)); | |
| 2201 oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID); | |
| 2202 oid_data.oid.len = sizeof(kDNSSECChainOID); | |
| 2203 oid_data.desc = "DNSSEC chain"; | |
| 2204 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; | |
| 2205 dnssec_chain_tag = SECOID_AddEntry(&oid_data); | |
| 2206 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag); | |
| 2207 dnssec_chain_tag_valid = true; | |
| 2208 } | |
| 2209 | |
| 2210 SECItem dnssec_embedded_chain; | |
| 2211 SECStatus rv = CERT_FindCertExtension(server_cert_nss, | |
| 2212 dnssec_chain_tag, &dnssec_embedded_chain); | |
| 2213 if (rv != SECSuccess) | |
| 2214 return DNSVR_CONTINUE; | |
| 2215 | |
| 2216 base::StringPiece chain( | |
| 2217 reinterpret_cast<char*>(dnssec_embedded_chain.data), | |
| 2218 dnssec_embedded_chain.len); | |
| 2219 std::string dns_hostname; | |
| 2220 if (!DNSDomainFromDot(hostname, &dns_hostname)) | |
| 2221 return DNSVR_CONTINUE; | |
| 2222 DNSSECChainVerifier verifier(dns_hostname, chain); | |
| 2223 DNSSECChainVerifier::Error err = verifier.Verify(); | |
| 2224 if (err != DNSSECChainVerifier::OK) { | |
| 2225 LOG(ERROR) << "DNSSEC chain verification failed: " << err; | |
| 2226 return DNSVR_CONTINUE; | |
| 2227 } | |
| 2228 | |
| 2229 if (verifier.rrtype() != kDNS_TXT) | |
| 2230 return DNSVR_CONTINUE; | |
| 2231 | |
| 2232 DNSValidationResult r = VerifyTXTRecords( | |
| 2233 true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas()); | |
| 2234 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE); | |
| 2235 return r; | |
| 2236 } | |
| 2237 | |
| 2238 int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { | |
| 2239 if (ssl_config_.dns_cert_provenance_checking_enabled && | |
| 2240 dns_cert_checker_) { | |
| 2241 PeerCertificateChain certs(nss_fd_); | |
| 2242 dns_cert_checker_->DoAsyncVerification( | |
| 2243 host_and_port_.host(), certs.AsStringPieceVector()); | |
| 2244 } | |
| 2245 | |
| 2246 if (ssl_config_.dnssec_enabled) { | |
| 2247 DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(), | |
| 2248 server_cert_nss_); | |
| 2249 if (r == DNSVR_SUCCESS) { | |
| 2250 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; | |
| 2251 server_cert_verify_result_ = &local_server_cert_verify_result_; | |
| 2252 GotoState(STATE_VERIFY_CERT_COMPLETE); | |
| 2253 return OK; | |
| 2254 } | |
| 2255 } | |
| 2256 | |
| 2257 if (dnssec_provider_ == NULL) { | |
| 2258 GotoState(STATE_VERIFY_CERT); | |
| 2259 return OK; | |
| 2260 } | |
| 2261 | |
| 2262 GotoState(STATE_VERIFY_DNSSEC_COMPLETE); | |
| 2263 RRResponse* response; | |
| 2264 dnssec_wait_start_time_ = base::Time::Now(); | |
| 2265 return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_); | |
| 2266 } | |
| 2267 | |
| 2268 int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) { | |
| 2269 RRResponse* response; | |
| 2270 int err = dnssec_provider_->GetDNSSECRecords(&response, NULL); | |
| 2271 DCHECK_EQ(err, OK); | |
| 2272 | |
| 2273 const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_; | |
| 2274 HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed); | |
| 2275 | |
| 2276 GotoState(STATE_VERIFY_CERT); | |
| 2277 if (!response || response->rrdatas.empty()) | |
| 2278 return OK; | |
| 2279 | |
| 2280 std::vector<base::StringPiece> records; | |
| 2281 records.resize(response->rrdatas.size()); | |
| 2282 for (unsigned i = 0; i < response->rrdatas.size(); i++) | |
| 2283 records[i] = base::StringPiece(response->rrdatas[i]); | |
| 2284 DNSValidationResult r = | |
| 2285 VerifyTXTRecords(response->dnssec, server_cert_nss_, records); | |
| 2286 | |
| 2287 if (!ssl_config_.dnssec_enabled) { | |
| 2288 // If DNSSEC is not enabled we don't take any action based on the result, | |
| 2289 // except to record the latency, above. | |
| 2290 return OK; | |
| 2291 } | |
| 2292 | |
| 2293 switch (r) { | |
| 2294 case DNSVR_FAILURE: | |
| 2295 GotoState(STATE_VERIFY_CERT_COMPLETE); | |
| 2296 local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS; | |
| 2297 server_cert_verify_result_ = &local_server_cert_verify_result_; | |
| 2298 return ERR_CERT_NOT_IN_DNS; | |
| 2299 case DNSVR_CONTINUE: | |
| 2300 GotoState(STATE_VERIFY_CERT); | |
| 2301 break; | |
| 2302 case DNSVR_SUCCESS: | |
| 2303 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; | |
| 2304 server_cert_verify_result_ = &local_server_cert_verify_result_; | |
| 2305 GotoState(STATE_VERIFY_CERT_COMPLETE); | |
| 2306 break; | |
| 2307 default: | |
| 2308 NOTREACHED(); | |
| 2309 GotoState(STATE_VERIFY_CERT); | |
| 2310 } | |
| 2311 | |
| 2312 return OK; | |
| 2313 } | |
| 2314 | |
| 2315 int SSLClientSocketNSS::DoVerifyCert(int result) { | |
| 2316 DCHECK(server_cert_); | |
| 2317 | |
| 2318 GotoState(STATE_VERIFY_CERT_COMPLETE); | |
| 2319 start_cert_verification_time_ = base::TimeTicks::Now(); | |
| 2320 | |
| 2321 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() && | |
| 2322 predicted_cert_chain_correct_) { | |
| 2323 // If the SSLHostInfo had a prediction for the certificate chain of this | |
| 2324 // server then it will have optimistically started a verification of that | |
| 2325 // chain. So, if the prediction was correct, we should wait for that | |
| 2326 // verification to finish rather than start our own. | |
| 2327 net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL); | |
| 2328 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2); | |
| 2329 base::TimeTicks end_time = ssl_host_info_->verification_end_time(); | |
| 2330 if (end_time.is_null()) | |
| 2331 end_time = base::TimeTicks::Now(); | |
| 2332 UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved", | |
| 2333 end_time - ssl_host_info_->verification_start_time()); | |
| 2334 server_cert_verify_result_ = &ssl_host_info_->cert_verify_result(); | |
| 2335 return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_); | |
| 2336 } else { | |
| 2337 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2); | |
| 2338 } | |
| 2339 | |
| 2340 int flags = 0; | |
| 2341 if (ssl_config_.rev_checking_enabled) | |
| 2342 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | |
| 2343 if (ssl_config_.verify_ev_cert) | |
| 2344 flags |= X509Certificate::VERIFY_EV_CERT; | |
| 2345 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); | |
| 2346 server_cert_verify_result_ = &local_server_cert_verify_result_; | |
| 2347 return verifier_->Verify(server_cert_, host_and_port_.host(), flags, | |
| 2348 &local_server_cert_verify_result_, | |
| 2349 &handshake_io_callback_); | |
| 2350 } | |
| 2351 | |
| 2352 // Derived from AuthCertificateCallback() in | |
| 2353 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. | |
| 2354 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { | |
| 2355 verifier_.reset(); | |
| 2356 | |
| 2357 if (!start_cert_verification_time_.is_null()) { | |
| 2358 base::TimeDelta verify_time = | |
| 2359 base::TimeTicks::Now() - start_cert_verification_time_; | |
| 2360 if (result == OK) | |
| 2361 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time); | |
| 2362 else | |
| 2363 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time); | |
| 2364 } | |
| 2365 | |
| 2366 if (ssl_host_info_.get()) | |
| 2367 ssl_host_info_->set_cert_verification_finished_time(); | |
| 2368 | |
| 2369 // We used to remember the intermediate CA certs in the NSS database | |
| 2370 // persistently. However, NSS opens a connection to the SQLite database | |
| 2371 // during NSS initialization and doesn't close the connection until NSS | |
| 2372 // shuts down. If the file system where the database resides is gone, | |
| 2373 // the database connection goes bad. What's worse, the connection won't | |
| 2374 // recover when the file system comes back. Until this NSS or SQLite bug | |
| 2375 // is fixed, we need to avoid using the NSS database for non-essential | |
| 2376 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and | |
| 2377 // http://crbug.com/15630 for more info. | |
| 2378 | |
| 2379 // If we have been explicitly told to accept this certificate, override the | |
| 2380 // result of verifier_.Verify. | |
| 2381 // Eventually, we should cache the cert verification results so that we don't | |
| 2382 // need to call verifier_.Verify repeatedly. But for now we need to do this. | |
| 2383 // Alternatively, we could use the cert's status that we stored along with | |
| 2384 // the cert in the allowed_bad_certs vector. | |
| 2385 if (IsCertificateError(result) && | |
| 2386 ssl_config_.IsAllowedBadCert(server_cert_)) { | |
| 2387 VLOG(1) << "accepting bad SSL certificate, as user told us to"; | |
| 2388 result = OK; | |
| 2389 } | |
| 2390 | |
| 2391 if (result == OK) | |
| 2392 LogConnectionTypeMetrics(); | |
| 2393 | |
| 2394 completed_handshake_ = true; | |
| 2395 | |
| 2396 // If we merged a Write call into the handshake we need to make the | |
| 2397 // callback now. | |
| 2398 if (user_write_callback_) { | |
| 2399 corked_ = false; | |
| 2400 if (result != OK) { | |
| 2401 DoWriteCallback(result); | |
| 2402 } else { | |
| 2403 SSLSnapStartResult snap_start_type; | |
| 2404 SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type); | |
| 2405 DCHECK_EQ(rv, SECSuccess); | |
| 2406 DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE); | |
| 2407 if (snap_start_type == SSL_SNAP_START_RECOVERY || | |
| 2408 snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) { | |
| 2409 // If we mispredicted the server's handshake then Snap Start will have | |
| 2410 // triggered a recovery mode. The misprediction could have been caused | |
| 2411 // by the server having a different certificate so the application data | |
| 2412 // wasn't resent. Now that we have verified the certificate, we need to | |
| 2413 // resend the application data. | |
| 2414 int bytes_written = DoPayloadWrite(); | |
| 2415 if (bytes_written != ERR_IO_PENDING) | |
| 2416 DoWriteCallback(bytes_written); | |
| 2417 } else { | |
| 2418 DoWriteCallback(user_write_buf_len_); | |
| 2419 } | |
| 2420 } | |
| 2421 } | |
| 2422 | |
| 2423 if (user_read_callback_) { | |
| 2424 int rv = DoReadLoop(OK); | |
| 2425 if (rv != ERR_IO_PENDING) | |
| 2426 DoReadCallback(rv); | |
| 2427 } | |
| 2428 | |
| 2429 // Exit DoHandshakeLoop and return the result to the caller to Connect. | |
| 2430 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 2431 return result; | |
| 2432 } | |
| 2433 | |
| 2434 int SSLClientSocketNSS::DoPayloadRead() { | |
| 2435 EnterFunction(user_read_buf_len_); | |
| 2436 DCHECK(user_read_buf_); | |
| 2437 DCHECK_GT(user_read_buf_len_, 0); | |
| 2438 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); | |
| 2439 if (client_auth_cert_needed_) { | |
| 2440 // We don't need to invalidate the non-client-authenticated SSL session | |
| 2441 // because the server will renegotiate anyway. | |
| 2442 LeaveFunction(""); | |
| 2443 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | |
| 2444 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, | |
| 2445 make_scoped_refptr(new SSLErrorParams(rv, 0))); | |
| 2446 return rv; | |
| 2447 } | |
| 2448 if (rv >= 0) { | |
| 2449 LogData(user_read_buf_->data(), rv); | |
| 2450 LeaveFunction(""); | |
| 2451 return rv; | |
| 2452 } | |
| 2453 PRErrorCode prerr = PR_GetError(); | |
| 2454 if (prerr == PR_WOULD_BLOCK_ERROR) { | |
| 2455 LeaveFunction(""); | |
| 2456 return ERR_IO_PENDING; | |
| 2457 } | |
| 2458 LeaveFunction(""); | |
| 2459 rv = MapNSSError(prerr); | |
| 2460 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, | |
| 2461 make_scoped_refptr(new SSLErrorParams(rv, prerr))); | |
| 2462 return rv; | |
| 2463 } | |
| 2464 | |
| 2465 int SSLClientSocketNSS::DoPayloadWrite() { | |
| 2466 EnterFunction(user_write_buf_len_); | |
| 2467 DCHECK(user_write_buf_); | |
| 2468 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); | |
| 2469 if (rv >= 0) { | |
| 2470 LogData(user_write_buf_->data(), rv); | |
| 2471 LeaveFunction(""); | |
| 2472 return rv; | |
| 2473 } | |
| 2474 PRErrorCode prerr = PR_GetError(); | |
| 2475 if (prerr == PR_WOULD_BLOCK_ERROR) { | |
| 2476 LeaveFunction(""); | |
| 2477 return ERR_IO_PENDING; | |
| 2478 } | |
| 2479 LeaveFunction(""); | |
| 2480 rv = MapNSSError(prerr); | |
| 2481 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, | |
| 2482 make_scoped_refptr(new SSLErrorParams(rv, prerr))); | |
| 2483 return rv; | |
| 2484 } | |
| 2485 | |
| 2486 void SSLClientSocketNSS::LogConnectionTypeMetrics() const { | |
| 2487 UpdateConnectionTypeHistograms(CONNECTION_SSL); | |
| 2488 if (server_cert_verify_result_->has_md5) | |
| 2489 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); | |
| 2490 if (server_cert_verify_result_->has_md2) | |
| 2491 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); | |
| 2492 if (server_cert_verify_result_->has_md4) | |
| 2493 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); | |
| 2494 if (server_cert_verify_result_->has_md5_ca) | |
| 2495 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); | |
| 2496 if (server_cert_verify_result_->has_md2_ca) | |
| 2497 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); | |
| 2498 int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_); | |
| 2499 switch (ssl_version) { | |
| 2500 case SSL_CONNECTION_VERSION_SSL2: | |
| 2501 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2); | |
| 2502 break; | |
| 2503 case SSL_CONNECTION_VERSION_SSL3: | |
| 2504 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3); | |
| 2505 break; | |
| 2506 case SSL_CONNECTION_VERSION_TLS1: | |
| 2507 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1); | |
| 2508 break; | |
| 2509 case SSL_CONNECTION_VERSION_TLS1_1: | |
| 2510 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); | |
| 2511 break; | |
| 2512 case SSL_CONNECTION_VERSION_TLS1_2: | |
| 2513 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); | |
| 2514 break; | |
| 2515 }; | |
| 2516 } | |
| 2517 | |
| 2518 } // namespace net | 2517 } // namespace net |
| OLD | NEW |