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 |