| 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 #include "net/socket/ssl_client_socket_win.h" | 5 #include "net/socket/ssl_client_socket_win.h" |
| 6 | 6 |
| 7 #include <schnlsp.h> | 7 #include <schnlsp.h> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 | 323 |
| 324 // Verify the current time is within the certificate's validity period. | 324 // Verify the current time is within the certificate's validity period. |
| 325 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0) | 325 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0) |
| 326 return FALSE; | 326 return FALSE; |
| 327 | 327 |
| 328 return TRUE; | 328 return TRUE; |
| 329 } | 329 } |
| 330 | 330 |
| 331 //----------------------------------------------------------------------------- | 331 //----------------------------------------------------------------------------- |
| 332 | 332 |
| 333 // A memory certificate store for client certificates. This allows us to | |
| 334 // close the "MY" system certificate store when we finish searching for | |
| 335 // client certificates. | |
| 336 class ClientCertStore { | |
| 337 public: | |
| 338 ClientCertStore() { | |
| 339 store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); | |
| 340 } | |
| 341 | |
| 342 ~ClientCertStore() { | |
| 343 if (store_) { | |
| 344 BOOL ok = CertCloseStore(store_, CERT_CLOSE_STORE_CHECK_FLAG); | |
| 345 DCHECK(ok); | |
| 346 } | |
| 347 } | |
| 348 | |
| 349 PCCERT_CONTEXT CopyCertContext(PCCERT_CONTEXT client_cert) { | |
| 350 PCCERT_CONTEXT copy; | |
| 351 BOOL ok = CertAddCertificateContextToStore(store_, client_cert, | |
| 352 CERT_STORE_ADD_USE_EXISTING, | |
| 353 ©); | |
| 354 DCHECK(ok); | |
| 355 return ok ? copy : NULL; | |
| 356 } | |
| 357 | |
| 358 private: | |
| 359 HCERTSTORE store_; | |
| 360 }; | |
| 361 | |
| 362 static base::LazyInstance<ClientCertStore> g_client_cert_store( | |
| 363 base::LINKER_INITIALIZED); | |
| 364 | |
| 365 //----------------------------------------------------------------------------- | |
| 366 | |
| 367 // Size of recv_buffer_ | 333 // Size of recv_buffer_ |
| 368 // | 334 // |
| 369 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to | 335 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to |
| 370 // have room for a full SSL record, with the header and trailer. Here is the | 336 // have room for a full SSL record, with the header and trailer. Here is the |
| 371 // breakdown of the size: | 337 // breakdown of the size: |
| 372 // 5: SSL record header | 338 // 5: SSL record header |
| 373 // 16K: SSL record maximum size | 339 // 16K: SSL record maximum size |
| 374 // 64: >= SSL record trailer (16 or 20 have been observed) | 340 // 64: >= SSL record trailer (16 or 20 have been observed) |
| 375 static const int kRecvBufferSize = (5 + 16*1024 + 64); | 341 static const int kRecvBufferSize = (5 + 16*1024 + 64); |
| 376 | 342 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 if (!chain_context) { | 471 if (!chain_context) { |
| 506 DWORD err = GetLastError(); | 472 DWORD err = GetLastError(); |
| 507 if (err != CRYPT_E_NOT_FOUND) | 473 if (err != CRYPT_E_NOT_FOUND) |
| 508 DLOG(ERROR) << "CertFindChainInStore failed: " << err; | 474 DLOG(ERROR) << "CertFindChainInStore failed: " << err; |
| 509 break; | 475 break; |
| 510 } | 476 } |
| 511 | 477 |
| 512 // Get the leaf certificate. | 478 // Get the leaf certificate. |
| 513 PCCERT_CONTEXT cert_context = | 479 PCCERT_CONTEXT cert_context = |
| 514 chain_context->rgpChain[0]->rgpElement[0]->pCertContext; | 480 chain_context->rgpChain[0]->rgpElement[0]->pCertContext; |
| 515 // Copy it to our own certificate store, so that we can close the "MY" | 481 // Copy the certificate into a NULL store, so that we can close the "MY" |
| 516 // certificate store before returning from this function. | 482 // store before returning from this function. |
| 517 PCCERT_CONTEXT cert_context2 = | 483 PCCERT_CONTEXT cert_context2 = NULL; |
| 518 g_client_cert_store.Get().CopyCertContext(cert_context); | 484 BOOL ok = CertAddCertificateContextToStore(NULL, cert_context, |
| 519 if (!cert_context2) { | 485 CERT_STORE_ADD_USE_EXISTING, |
| 486 &cert_context2); |
| 487 if (!ok) { |
| 520 NOTREACHED(); | 488 NOTREACHED(); |
| 521 continue; | 489 continue; |
| 522 } | 490 } |
| 491 |
| 492 // Grab the intermediates, if any. |
| 493 X509Certificate::OSCertHandles intermediates; |
| 494 for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) { |
| 495 PCCERT_CONTEXT chain_intermediate = |
| 496 chain_context->rgpChain[0]->rgpElement[i]->pCertContext; |
| 497 PCCERT_CONTEXT chain_intermediate2; |
| 498 ok = CertAddCertificateContextToStore(NULL, chain_intermediate, |
| 499 CERT_STORE_ADD_USE_EXISTING, |
| 500 &chain_intermediate2); |
| 501 if (ok) |
| 502 intermediates.push_back(chain_intermediate2); |
| 503 } |
| 523 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | 504 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( |
| 524 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT, | 505 cert_context2, intermediates); |
| 525 X509Certificate::OSCertHandles()); | |
| 526 cert_request_info->client_certs.push_back(cert); | 506 cert_request_info->client_certs.push_back(cert); |
| 527 CertFreeCertificateContext(cert_context2); | 507 CertFreeCertificateContext(cert_context2); |
| 508 for (size_t i = 0; i < intermediates.size(); ++i) |
| 509 CertFreeCertificateContext(intermediates[i]); |
| 528 } | 510 } |
| 529 | 511 |
| 530 FreeContextBuffer(issuer_list.aIssuers); | 512 FreeContextBuffer(issuer_list.aIssuers); |
| 531 | 513 |
| 532 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG); | 514 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG); |
| 533 DCHECK(ok); | 515 DCHECK(ok); |
| 534 } | 516 } |
| 535 | 517 |
| 536 SSLClientSocket::NextProtoStatus | 518 SSLClientSocket::NextProtoStatus |
| 537 SSLClientSocketWin::GetNextProto(std::string* proto) { | 519 SSLClientSocketWin::GetNextProto(std::string* proto) { |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1466 return MapSecurityError(status); | 1448 return MapSecurityError(status); |
| 1467 } | 1449 } |
| 1468 DCHECK(!server_cert_ || renegotiating_); | 1450 DCHECK(!server_cert_ || renegotiating_); |
| 1469 PCCERT_CONTEXT server_cert_handle = NULL; | 1451 PCCERT_CONTEXT server_cert_handle = NULL; |
| 1470 status = QueryContextAttributes( | 1452 status = QueryContextAttributes( |
| 1471 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); | 1453 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); |
| 1472 if (status != SEC_E_OK) { | 1454 if (status != SEC_E_OK) { |
| 1473 LOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status; | 1455 LOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status; |
| 1474 return MapSecurityError(status); | 1456 return MapSecurityError(status); |
| 1475 } | 1457 } |
| 1458 |
| 1459 X509Certificate::OSCertHandles intermediates; |
| 1460 PCCERT_CONTEXT intermediate = |
| 1461 CertEnumCertificatesInStore(server_cert_handle->hCertStore, NULL); |
| 1462 while (intermediate != NULL) { |
| 1463 intermediates.push_back(CertDuplicateCertificateContext(intermediate)); |
| 1464 intermediate = CertEnumCertificatesInStore(server_cert_handle->hCertStore, |
| 1465 intermediate); |
| 1466 } |
| 1467 |
| 1476 if (renegotiating_ && | 1468 if (renegotiating_ && |
| 1477 X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), | 1469 X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), |
| 1478 server_cert_handle)) { | 1470 server_cert_handle) && |
| 1471 server_cert_->HasIntermediateCertificates(intermediates) && |
| 1472 server_cert_->GetIntermediateCertificates().size() == |
| 1473 intermediates.size()) { |
| 1479 // We already verified the server certificate. Either it is good or the | 1474 // We already verified the server certificate. Either it is good or the |
| 1480 // user has accepted the certificate error. | 1475 // user has accepted the certificate error. |
| 1481 DidCompleteRenegotiation(); | 1476 DidCompleteRenegotiation(); |
| 1482 } else { | 1477 } else { |
| 1483 server_cert_ = X509Certificate::CreateFromHandle( | 1478 server_cert_ = X509Certificate::CreateFromHandle( |
| 1484 server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK, | 1479 server_cert_handle, intermediates); |
| 1485 X509Certificate::OSCertHandles()); | |
| 1486 | 1480 |
| 1487 next_state_ = STATE_VERIFY_CERT; | 1481 next_state_ = STATE_VERIFY_CERT; |
| 1488 } | 1482 } |
| 1489 CertFreeCertificateContext(server_cert_handle); | 1483 CertFreeCertificateContext(server_cert_handle); |
| 1484 for (size_t i = 0; i < intermediates.size(); ++i) |
| 1485 CertFreeCertificateContext(intermediates[i]); |
| 1490 return OK; | 1486 return OK; |
| 1491 } | 1487 } |
| 1492 | 1488 |
| 1493 // Called when a renegotiation is completed. |result| is the verification | 1489 // Called when a renegotiation is completed. |result| is the verification |
| 1494 // result of the server certificate received during renegotiation. | 1490 // result of the server certificate received during renegotiation. |
| 1495 void SSLClientSocketWin::DidCompleteRenegotiation() { | 1491 void SSLClientSocketWin::DidCompleteRenegotiation() { |
| 1496 DCHECK(!user_connect_callback_); | 1492 DCHECK(!user_connect_callback_); |
| 1497 DCHECK(user_read_callback_); | 1493 DCHECK(user_read_callback_); |
| 1498 renegotiating_ = false; | 1494 renegotiating_ = false; |
| 1499 next_state_ = STATE_COMPLETED_RENEGOTIATION; | 1495 next_state_ = STATE_COMPLETED_RENEGOTIATION; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1513 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); | 1509 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); |
| 1514 } | 1510 } |
| 1515 | 1511 |
| 1516 void SSLClientSocketWin::FreeSendBuffer() { | 1512 void SSLClientSocketWin::FreeSendBuffer() { |
| 1517 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); | 1513 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); |
| 1518 DCHECK(status == SEC_E_OK); | 1514 DCHECK(status == SEC_E_OK); |
| 1519 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 1515 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 1520 } | 1516 } |
| 1521 | 1517 |
| 1522 } // namespace net | 1518 } // namespace net |
| OLD | NEW |