Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: net/socket/ssl_client_socket_win.cc

Issue 2944008: Refactor X509Certificate caching to cache the OS handle, rather than the X509Certificate (Closed)
Patch Set: Rebase to trunk after splitting out 4645001 Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 &copy);
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
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
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
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
OLDNEW
« net/base/x509_certificate.h ('K') | « net/socket/ssl_client_socket_openssl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698