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 |