OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 DCHECK(!user_read_callback_); | 533 DCHECK(!user_read_callback_); |
534 DCHECK(!user_connect_callback_); | 534 DCHECK(!user_connect_callback_); |
535 DCHECK(!user_read_buf_); | 535 DCHECK(!user_read_buf_); |
536 DCHECK(nss_bufs_); | 536 DCHECK(nss_bufs_); |
537 | 537 |
538 user_read_buf_ = buf; | 538 user_read_buf_ = buf; |
539 user_read_buf_len_ = buf_len; | 539 user_read_buf_len_ = buf_len; |
540 | 540 |
541 int rv = DoReadLoop(OK); | 541 int rv = DoReadLoop(OK); |
542 | 542 |
543 if (rv == ERR_IO_PENDING) | 543 if (rv == ERR_IO_PENDING) { |
544 user_read_callback_ = callback; | 544 user_read_callback_ = callback; |
545 else { | 545 } else { |
546 user_read_buf_ = NULL; | 546 user_read_buf_ = NULL; |
547 user_read_buf_len_ = 0; | 547 user_read_buf_len_ = 0; |
548 } | 548 } |
549 LeaveFunction(rv); | 549 LeaveFunction(rv); |
550 return rv; | 550 return rv; |
551 } | 551 } |
552 | 552 |
553 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, | 553 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, |
554 CompletionCallback* callback) { | 554 CompletionCallback* callback) { |
555 EnterFunction(buf_len); | 555 EnterFunction(buf_len); |
556 DCHECK(completed_handshake_); | 556 DCHECK(completed_handshake_); |
557 DCHECK(next_handshake_state_ == STATE_NONE); | 557 DCHECK(next_handshake_state_ == STATE_NONE); |
558 DCHECK(!user_write_callback_); | 558 DCHECK(!user_write_callback_); |
559 DCHECK(!user_connect_callback_); | 559 DCHECK(!user_connect_callback_); |
560 DCHECK(!user_write_buf_); | 560 DCHECK(!user_write_buf_); |
561 DCHECK(nss_bufs_); | 561 DCHECK(nss_bufs_); |
562 | 562 |
563 user_write_buf_ = buf; | 563 user_write_buf_ = buf; |
564 user_write_buf_len_ = buf_len; | 564 user_write_buf_len_ = buf_len; |
565 | 565 |
566 int rv = DoWriteLoop(OK); | 566 int rv = DoWriteLoop(OK); |
567 | 567 |
568 if (rv == ERR_IO_PENDING) | 568 if (rv == ERR_IO_PENDING) { |
569 user_write_callback_ = callback; | 569 user_write_callback_ = callback; |
570 else { | 570 } else { |
571 user_write_buf_ = NULL; | 571 user_write_buf_ = NULL; |
572 user_write_buf_len_ = 0; | 572 user_write_buf_len_ = 0; |
573 } | 573 } |
574 LeaveFunction(rv); | 574 LeaveFunction(rv); |
575 return rv; | 575 return rv; |
576 } | 576 } |
577 | 577 |
578 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | 578 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { |
579 return transport_->SetReceiveBufferSize(size); | 579 return transport_->SetReceiveBufferSize(size); |
580 } | 580 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 ssl_info->cert_status = server_cert_verify_result_.cert_status; | 691 ssl_info->cert_status = server_cert_verify_result_.cert_status; |
692 DCHECK(server_cert_ != NULL); | 692 DCHECK(server_cert_ != NULL); |
693 ssl_info->cert = server_cert_; | 693 ssl_info->cert = server_cert_; |
694 | 694 |
695 LeaveFunction(""); | 695 LeaveFunction(""); |
696 } | 696 } |
697 | 697 |
698 void SSLClientSocketNSS::GetSSLCertRequestInfo( | 698 void SSLClientSocketNSS::GetSSLCertRequestInfo( |
699 SSLCertRequestInfo* cert_request_info) { | 699 SSLCertRequestInfo* cert_request_info) { |
700 EnterFunction(""); | 700 EnterFunction(""); |
701 cert_request_info->host_and_port = hostname_; | 701 cert_request_info->host_and_port = hostname_; // TODO(wtc): no port! |
702 cert_request_info->client_certs = client_certs_; | 702 cert_request_info->client_certs = client_certs_; |
703 LeaveFunction(cert_request_info->client_certs.size()); | 703 LeaveFunction(cert_request_info->client_certs.size()); |
704 } | 704 } |
705 | 705 |
706 SSLClientSocket::NextProtoStatus | 706 SSLClientSocket::NextProtoStatus |
707 SSLClientSocketNSS::GetNextProto(std::string* proto) { | 707 SSLClientSocketNSS::GetNextProto(std::string* proto) { |
708 #if defined(SSL_NEXT_PROTO_NEGOTIATED) | 708 #if defined(SSL_NEXT_PROTO_NEGOTIATED) |
709 unsigned char buf[255]; | 709 unsigned char buf[255]; |
710 int state; | 710 int state; |
711 unsigned len; | 711 unsigned len; |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 | 1087 |
1088 // static | 1088 // static |
1089 // NSS calls this if a client certificate is needed. | 1089 // NSS calls this if a client certificate is needed. |
1090 // Based on Mozilla's NSS_GetClientAuthData. | 1090 // Based on Mozilla's NSS_GetClientAuthData. |
1091 SECStatus SSLClientSocketNSS::ClientAuthHandler( | 1091 SECStatus SSLClientSocketNSS::ClientAuthHandler( |
1092 void* arg, | 1092 void* arg, |
1093 PRFileDesc* socket, | 1093 PRFileDesc* socket, |
1094 CERTDistNames* ca_names, | 1094 CERTDistNames* ca_names, |
1095 CERTCertificate** result_certificate, | 1095 CERTCertificate** result_certificate, |
1096 SECKEYPrivateKey** result_private_key) { | 1096 SECKEYPrivateKey** result_private_key) { |
1097 #if defined(OS_WIN) | |
1098 // Not implemented. Send no client certificate. | |
1099 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
1100 return SECFailure; | |
1101 #else | |
1102 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 1097 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); |
1103 | 1098 |
1104 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; | 1099 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; |
1105 | 1100 |
| 1101 #if defined(OS_WIN) |
| 1102 if (that->ssl_config_.send_client_cert) { |
| 1103 // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using |
| 1104 // CryptoAPI yet (http://crbug.com/37560), so client_cert must be NULL. |
| 1105 DCHECK(!that->ssl_config_.client_cert); |
| 1106 // Send no client certificate. |
| 1107 return SECFailure; |
| 1108 } |
| 1109 |
| 1110 that->client_certs_.clear(); |
| 1111 |
| 1112 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames); |
| 1113 for (int i = 0; i < ca_names->nnames; ++i) { |
| 1114 issuer_list[i].cbData = ca_names->names[i].len; |
| 1115 issuer_list[i].pbData = ca_names->names[i].data; |
| 1116 } |
| 1117 |
| 1118 // Client certificates of the user are in the "MY" system certificate store. |
| 1119 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY"); |
| 1120 if (!my_cert_store) { |
| 1121 LOG(ERROR) << "Could not open the \"MY\" system certificate store: " |
| 1122 << GetLastError(); |
| 1123 return SECFailure; |
| 1124 } |
| 1125 |
| 1126 // Enumerate the client certificates. |
| 1127 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para; |
| 1128 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para)); |
| 1129 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para); |
| 1130 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH; |
| 1131 find_by_issuer_para.cIssuer = ca_names->nnames; |
| 1132 find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL; |
| 1133 |
| 1134 PCCERT_CHAIN_CONTEXT chain_context = NULL; |
| 1135 |
| 1136 for (;;) { |
| 1137 // Find a certificate chain. |
| 1138 chain_context = CertFindChainInStore(my_cert_store, |
| 1139 X509_ASN_ENCODING, |
| 1140 0, |
| 1141 CERT_CHAIN_FIND_BY_ISSUER, |
| 1142 &find_by_issuer_para, |
| 1143 chain_context); |
| 1144 if (!chain_context) { |
| 1145 DWORD err = GetLastError(); |
| 1146 if (err != CRYPT_E_NOT_FOUND) |
| 1147 DLOG(ERROR) << "CertFindChainInStore failed: " << err; |
| 1148 break; |
| 1149 } |
| 1150 |
| 1151 // Get the leaf certificate. |
| 1152 PCCERT_CONTEXT cert_context = |
| 1153 chain_context->rgpChain[0]->rgpElement[0]->pCertContext; |
| 1154 // Copy it to our own certificate store, so that we can close the "MY" |
| 1155 // certificate store before returning from this function. |
| 1156 PCCERT_CONTEXT cert_context2; |
| 1157 BOOL ok = CertAddCertificateContextToStore(cert_store_, cert_context, |
| 1158 CERT_STORE_ADD_USE_EXISTING, |
| 1159 &cert_context2); |
| 1160 if (!ok) { |
| 1161 NOTREACHED(); |
| 1162 continue; |
| 1163 } |
| 1164 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( |
| 1165 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT, |
| 1166 net::X509Certificate::OSCertHandles()); |
| 1167 that->client_certs_.push_back(cert); |
| 1168 } |
| 1169 |
| 1170 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG); |
| 1171 DCHECK(ok); |
| 1172 |
| 1173 // Tell NSS to suspend the client authentication. We will then abort the |
| 1174 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED. |
| 1175 return SECWouldBlock; |
| 1176 #else |
1106 CERTCertificate* cert = NULL; | 1177 CERTCertificate* cert = NULL; |
1107 SECKEYPrivateKey* privkey = NULL; | 1178 SECKEYPrivateKey* privkey = NULL; |
1108 void* wincx = SSL_RevealPinArg(socket); | 1179 void* wincx = SSL_RevealPinArg(socket); |
1109 | 1180 |
1110 // Second pass: a client certificate should have been selected. | 1181 // Second pass: a client certificate should have been selected. |
1111 if (that->ssl_config_.send_client_cert) { | 1182 if (that->ssl_config_.send_client_cert) { |
1112 if (that->ssl_config_.client_cert) { | 1183 if (that->ssl_config_.client_cert) { |
1113 cert = CERT_DupCertificate( | 1184 cert = CERT_DupCertificate( |
1114 that->ssl_config_.client_cert->os_cert_handle()); | 1185 that->ssl_config_.client_cert->os_cert_handle()); |
1115 privkey = PK11_FindKeyByAnyCert(cert, wincx); | 1186 privkey = PK11_FindKeyByAnyCert(cert, wincx); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 // session with a bad cert. | 1368 // session with a bad cert. |
1298 InvalidateSessionIfBadCertificate(); | 1369 InvalidateSessionIfBadCertificate(); |
1299 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 1370 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
1300 DCHECK(next_handshake_state_ == STATE_NONE); | 1371 DCHECK(next_handshake_state_ == STATE_NONE); |
1301 return result; | 1372 return result; |
1302 } | 1373 } |
1303 | 1374 |
1304 int SSLClientSocketNSS::DoPayloadRead() { | 1375 int SSLClientSocketNSS::DoPayloadRead() { |
1305 EnterFunction(user_read_buf_len_); | 1376 EnterFunction(user_read_buf_len_); |
1306 DCHECK(user_read_buf_); | 1377 DCHECK(user_read_buf_); |
1307 DCHECK(user_read_buf_len_ > 0); | 1378 DCHECK_GT(user_read_buf_len_, 0); |
1308 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); | 1379 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); |
1309 if (client_auth_cert_needed_) { | 1380 if (client_auth_cert_needed_) { |
1310 // We don't need to invalidate the non-client-authenticated SSL session | 1381 // We don't need to invalidate the non-client-authenticated SSL session |
1311 // because the server will renegotiate anyway. | 1382 // because the server will renegotiate anyway. |
1312 LeaveFunction(""); | 1383 LeaveFunction(""); |
1313 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1384 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
1314 } | 1385 } |
1315 if (rv >= 0) { | 1386 if (rv >= 0) { |
1316 LogData(user_read_buf_->data(), rv); | 1387 LogData(user_read_buf_->data(), rv); |
1317 LeaveFunction(""); | 1388 LeaveFunction(""); |
(...skipping 19 matching lines...) Expand all Loading... |
1337 } | 1408 } |
1338 PRErrorCode prerr = PR_GetError(); | 1409 PRErrorCode prerr = PR_GetError(); |
1339 if (prerr == PR_WOULD_BLOCK_ERROR) { | 1410 if (prerr == PR_WOULD_BLOCK_ERROR) { |
1340 return ERR_IO_PENDING; | 1411 return ERR_IO_PENDING; |
1341 } | 1412 } |
1342 LeaveFunction(""); | 1413 LeaveFunction(""); |
1343 return MapNSPRError(prerr); | 1414 return MapNSPRError(prerr); |
1344 } | 1415 } |
1345 | 1416 |
1346 } // namespace net | 1417 } // namespace net |
OLD | NEW |