OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 // negotiated protocol stored in |next_proto|. | 422 // negotiated protocol stored in |next_proto|. |
423 SSLClientSocket::NextProtoStatus next_proto_status; | 423 SSLClientSocket::NextProtoStatus next_proto_status; |
424 std::string next_proto; | 424 std::string next_proto; |
425 // If the server supports NPN, the protocols supported by the server. | 425 // If the server supports NPN, the protocols supported by the server. |
426 std::string server_protos; | 426 std::string server_protos; |
427 | 427 |
428 // True if a channel ID was sent. | 428 // True if a channel ID was sent. |
429 bool channel_id_sent; | 429 bool channel_id_sent; |
430 | 430 |
431 // If the peer requests client certificate authentication, the set of | 431 // If the peer requests client certificate authentication, the set of |
432 // certificates that matched the peer's criteria. | 432 // certificates that matched the peer's criteria. This should be soon removed |
| 433 // as being tracked in http://crbug.com/166642. |
433 CertificateList client_certs; | 434 CertificateList client_certs; |
434 | 435 |
| 436 // List of DER-encoded X.509 DistinguishedName of certificate authorities |
| 437 // allowed by the server. |
| 438 std::vector<std::string> cert_authorities; |
| 439 |
435 // Set when the handshake fully completes. | 440 // Set when the handshake fully completes. |
436 // | 441 // |
437 // The server certificate is first received from NSS as an NSS certificate | 442 // The server certificate is first received from NSS as an NSS certificate |
438 // chain (|server_cert_chain|) and then converted into a platform-specific | 443 // chain (|server_cert_chain|) and then converted into a platform-specific |
439 // X509Certificate object (|server_cert|). It's possible for some | 444 // X509Certificate object (|server_cert|). It's possible for some |
440 // certificates to be successfully parsed by NSS, and not by the platform | 445 // certificates to be successfully parsed by NSS, and not by the platform |
441 // libraries (i.e.: when running within a sandbox, different parsing | 446 // libraries (i.e.: when running within a sandbox, different parsing |
442 // algorithms, etc), so it's not safe to assume that |server_cert| will | 447 // algorithms, etc), so it's not safe to assume that |server_cert| will |
443 // always be non-NULL. | 448 // always be non-NULL. |
444 PeerCertificateChain server_cert_chain; | 449 PeerCertificateChain server_cert_chain; |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 } | 1299 } |
1295 LOG(WARNING) << "Client cert found without private key"; | 1300 LOG(WARNING) << "Client cert found without private key"; |
1296 } | 1301 } |
1297 | 1302 |
1298 // Send no client certificate. | 1303 // Send no client certificate. |
1299 core->AddCertProvidedEvent(0); | 1304 core->AddCertProvidedEvent(0); |
1300 return SECFailure; | 1305 return SECFailure; |
1301 } | 1306 } |
1302 | 1307 |
1303 core->nss_handshake_state_.client_certs.clear(); | 1308 core->nss_handshake_state_.client_certs.clear(); |
| 1309 core->nss_handshake_state_.cert_authorities.clear(); |
1304 | 1310 |
1305 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames); | 1311 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames); |
1306 for (int i = 0; i < ca_names->nnames; ++i) { | 1312 for (int i = 0; i < ca_names->nnames; ++i) { |
1307 issuer_list[i].cbData = ca_names->names[i].len; | 1313 issuer_list[i].cbData = ca_names->names[i].len; |
1308 issuer_list[i].pbData = ca_names->names[i].data; | 1314 issuer_list[i].pbData = ca_names->names[i].data; |
| 1315 core->nss_handshake_state_.cert_authorities.push_back(std::string( |
| 1316 reinterpret_cast<const char*>(ca_names->names[i].data), |
| 1317 static_cast<size_t>(ca_names->names[i].len))); |
1309 } | 1318 } |
1310 | 1319 |
| 1320 // Retrieve the list of matching client certificates. This is to be moved out |
| 1321 // of here as a part of refactoring effort being tracked in |
| 1322 // http://crbug.com/166642. |
| 1323 |
1311 // Client certificates of the user are in the "MY" system certificate store. | 1324 // Client certificates of the user are in the "MY" system certificate store. |
1312 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY"); | 1325 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY"); |
1313 if (!my_cert_store) { | 1326 if (!my_cert_store) { |
1314 PLOG(ERROR) << "Could not open the \"MY\" system certificate store"; | 1327 PLOG(ERROR) << "Could not open the \"MY\" system certificate store"; |
1315 | 1328 |
1316 core->AddCertProvidedEvent(0); | 1329 core->AddCertProvidedEvent(0); |
1317 return SECFailure; | 1330 return SECFailure; |
1318 } | 1331 } |
1319 | 1332 |
1320 // Enumerate the client certificates. | 1333 // Enumerate the client certificates. |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 if (chain) | 1486 if (chain) |
1474 CFRelease(chain); | 1487 CFRelease(chain); |
1475 } | 1488 } |
1476 | 1489 |
1477 // Send no client certificate. | 1490 // Send no client certificate. |
1478 core->AddCertProvidedEvent(0); | 1491 core->AddCertProvidedEvent(0); |
1479 return SECFailure; | 1492 return SECFailure; |
1480 } | 1493 } |
1481 | 1494 |
1482 core->nss_handshake_state_.client_certs.clear(); | 1495 core->nss_handshake_state_.client_certs.clear(); |
| 1496 core->nss_handshake_state_.cert_authorities.clear(); |
1483 | 1497 |
1484 // First, get the cert issuer names allowed by the server. | 1498 // Retrieve the cert issuers accepted by the server. This information is |
| 1499 // currently (temporarily) being saved both in |valid_issuers| and |
| 1500 // |cert_authorities|, the latter being the target solution. The refactoring |
| 1501 // effort is being tracked in http://crbug.com/166642. |
1485 std::vector<CertPrincipal> valid_issuers; | 1502 std::vector<CertPrincipal> valid_issuers; |
1486 int n = ca_names->nnames; | 1503 int n = ca_names->nnames; |
1487 for (int i = 0; i < n; i++) { | 1504 for (int i = 0; i < n; i++) { |
1488 // Parse each name into a CertPrincipal object. | 1505 // Add the DER-encoded issuer DistinguishedName to |cert_authorities|. |
| 1506 core->nss_handshake_state_.cert_authorities.push_back(std::string( |
| 1507 reinterpret_cast<const char*>(ca_names->names[i].data), |
| 1508 static_cast<size_t>(ca_names->names[i].len))); |
| 1509 // Add the CertPrincipal object representing the issuer to |
| 1510 // |valid_issuers|. |
1489 CertPrincipal p; | 1511 CertPrincipal p; |
1490 if (p.ParseDistinguishedName(ca_names->names[i].data, | 1512 if (p.ParseDistinguishedName(ca_names->names[i].data, |
1491 ca_names->names[i].len)) { | 1513 ca_names->names[i].len)) { |
1492 valid_issuers.push_back(p); | 1514 valid_issuers.push_back(p); |
1493 } | 1515 } |
1494 } | 1516 } |
1495 | 1517 |
1496 // Now get the available client certs whose issuers are allowed by the server. | 1518 // Now get the available client certs whose issuers are allowed by the server. |
1497 X509Certificate::GetSSLClientCertificates( | 1519 X509Certificate::GetSSLClientCertificates( |
1498 core->host_and_port_.host(), valid_issuers, | 1520 core->host_and_port_.host(), valid_issuers, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1555 | 1577 |
1556 core->PostOrRunCallback( | 1578 core->PostOrRunCallback( |
1557 FROM_HERE, | 1579 FROM_HERE, |
1558 base::Bind(&AddLogEvent, core->weak_net_log_, | 1580 base::Bind(&AddLogEvent, core->weak_net_log_, |
1559 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED)); | 1581 NetLog::TYPE_SSL_CLIENT_CERT_REQUESTED)); |
1560 | 1582 |
1561 // Regular client certificate requested. | 1583 // Regular client certificate requested. |
1562 core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert; | 1584 core->client_auth_cert_needed_ = !core->ssl_config_.send_client_cert; |
1563 void* wincx = SSL_RevealPinArg(socket); | 1585 void* wincx = SSL_RevealPinArg(socket); |
1564 | 1586 |
1565 // Second pass: a client certificate should have been selected. | |
1566 if (core->ssl_config_.send_client_cert) { | 1587 if (core->ssl_config_.send_client_cert) { |
| 1588 // Second pass: a client certificate should have been selected. |
1567 if (core->ssl_config_.client_cert) { | 1589 if (core->ssl_config_.client_cert) { |
1568 CERTCertificate* cert = CERT_DupCertificate( | 1590 CERTCertificate* cert = CERT_DupCertificate( |
1569 core->ssl_config_.client_cert->os_cert_handle()); | 1591 core->ssl_config_.client_cert->os_cert_handle()); |
1570 SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx); | 1592 SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx); |
1571 if (privkey) { | 1593 if (privkey) { |
1572 // TODO(jsorianopastor): We should wait for server certificate | 1594 // TODO(jsorianopastor): We should wait for server certificate |
1573 // verification before sending our credentials. See | 1595 // verification before sending our credentials. See |
1574 // http://crbug.com/13934. | 1596 // http://crbug.com/13934. |
1575 *result_certificate = cert; | 1597 *result_certificate = cert; |
1576 *result_private_key = privkey; | 1598 *result_private_key = privkey; |
1577 // A cert_count of -1 means the number of certificates is unknown. | 1599 // A cert_count of -1 means the number of certificates is unknown. |
1578 // NSS will construct the certificate chain. | 1600 // NSS will construct the certificate chain. |
1579 core->AddCertProvidedEvent(-1); | 1601 core->AddCertProvidedEvent(-1); |
1580 | 1602 |
1581 return SECSuccess; | 1603 return SECSuccess; |
1582 } | 1604 } |
1583 LOG(WARNING) << "Client cert found without private key"; | 1605 LOG(WARNING) << "Client cert found without private key"; |
1584 } | 1606 } |
1585 // Send no client certificate. | 1607 // Send no client certificate. |
1586 core->AddCertProvidedEvent(0); | 1608 core->AddCertProvidedEvent(0); |
1587 return SECFailure; | 1609 return SECFailure; |
1588 } | 1610 } |
1589 | 1611 |
| 1612 // First pass: client certificate is needed. |
1590 core->nss_handshake_state_.client_certs.clear(); | 1613 core->nss_handshake_state_.client_certs.clear(); |
| 1614 core->nss_handshake_state_.cert_authorities.clear(); |
1591 | 1615 |
1592 // Iterate over all client certificates. | 1616 // Retrieve the DER-encoded DistinguishedName of the cert issuers accepted by |
| 1617 // the server and save them in |cert_authorities|. |
| 1618 for (int i = 0; i < ca_names->nnames; i++) { |
| 1619 core->nss_handshake_state_.cert_authorities.push_back(std::string( |
| 1620 reinterpret_cast<const char*>(ca_names->names[i].data), |
| 1621 static_cast<size_t>(ca_names->names[i].len))); |
| 1622 } |
| 1623 |
| 1624 // Iterate over all client certificates and put the ones matching the server |
| 1625 // criteria in |nss_handshake_state_.client_certs|. This is to be moved out of |
| 1626 // here as a part of refactoring effort being tracked in |
| 1627 // http://crbug.com/166642. |
1593 CERTCertList* client_certs = CERT_FindUserCertsByUsage( | 1628 CERTCertList* client_certs = CERT_FindUserCertsByUsage( |
1594 CERT_GetDefaultCertDB(), certUsageSSLClient, | 1629 CERT_GetDefaultCertDB(), certUsageSSLClient, |
1595 PR_FALSE, PR_FALSE, wincx); | 1630 PR_FALSE, PR_FALSE, wincx); |
1596 if (client_certs) { | 1631 if (client_certs) { |
1597 for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs); | 1632 for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs); |
1598 !CERT_LIST_END(node, client_certs); | 1633 !CERT_LIST_END(node, client_certs); |
1599 node = CERT_LIST_NEXT(node)) { | 1634 node = CERT_LIST_NEXT(node)) { |
1600 // Only offer unexpired certificates. | 1635 // Only offer unexpired certificates. |
1601 if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) != | 1636 if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) != |
1602 secCertTimeValid) { | 1637 secCertTimeValid) { |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2772 | 2807 |
2773 LeaveFunction(""); | 2808 LeaveFunction(""); |
2774 return true; | 2809 return true; |
2775 } | 2810 } |
2776 | 2811 |
2777 void SSLClientSocketNSS::GetSSLCertRequestInfo( | 2812 void SSLClientSocketNSS::GetSSLCertRequestInfo( |
2778 SSLCertRequestInfo* cert_request_info) { | 2813 SSLCertRequestInfo* cert_request_info) { |
2779 EnterFunction(""); | 2814 EnterFunction(""); |
2780 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair | 2815 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair |
2781 cert_request_info->host_and_port = host_and_port_.ToString(); | 2816 cert_request_info->host_and_port = host_and_port_.ToString(); |
| 2817 cert_request_info->cert_authorities = core_->state().cert_authorities; |
| 2818 // This should be removed as being tracked in http://crbug.com/166642. |
2782 cert_request_info->client_certs = core_->state().client_certs; | 2819 cert_request_info->client_certs = core_->state().client_certs; |
2783 LeaveFunction(cert_request_info->client_certs.size()); | 2820 LeaveFunction(cert_request_info->client_certs.size()); |
2784 } | 2821 } |
2785 | 2822 |
2786 int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, | 2823 int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, |
2787 bool has_context, | 2824 bool has_context, |
2788 const base::StringPiece& context, | 2825 const base::StringPiece& context, |
2789 unsigned char* out, | 2826 unsigned char* out, |
2790 unsigned int outlen) { | 2827 unsigned int outlen) { |
2791 if (!IsConnected()) | 2828 if (!IsConnected()) |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3460 EnsureThreadIdAssigned(); | 3497 EnsureThreadIdAssigned(); |
3461 base::AutoLock auto_lock(lock_); | 3498 base::AutoLock auto_lock(lock_); |
3462 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 3499 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
3463 } | 3500 } |
3464 | 3501 |
3465 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { | 3502 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { |
3466 return server_bound_cert_service_; | 3503 return server_bound_cert_service_; |
3467 } | 3504 } |
3468 | 3505 |
3469 } // namespace net | 3506 } // namespace net |
OLD | NEW |