Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 // Attempt to initialize the peer name. In the case of TCP FastOpen, | 613 // Attempt to initialize the peer name. In the case of TCP FastOpen, |
| 614 // we don't have the peer yet. | 614 // we don't have the peer yet. |
| 615 if (!UsingTCPFastOpen()) { | 615 if (!UsingTCPFastOpen()) { |
| 616 rv = InitializeSSLPeerName(); | 616 rv = InitializeSSLPeerName(); |
| 617 if (rv != OK) { | 617 if (rv != OK) { |
| 618 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 618 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 619 return rv; | 619 return rv; |
| 620 } | 620 } |
| 621 } | 621 } |
| 622 | 622 |
| 623 GotoState(STATE_HANDSHAKE); | 623 if (ssl_host_info_.get()) { |
|
wtc
2011/06/03 22:56:55
This should also check that the cached info extens
rkn
2011/06/04 20:50:19
Done.
| |
| 624 GotoState(STATE_LOAD_SSL_HOST_INFO); | |
| 625 } else { | |
| 626 GotoState(STATE_HANDSHAKE); | |
| 627 } | |
| 624 | 628 |
| 625 rv = DoHandshakeLoop(OK); | 629 rv = DoHandshakeLoop(OK); |
| 626 if (rv == ERR_IO_PENDING) { | 630 if (rv == ERR_IO_PENDING) { |
| 627 user_connect_callback_ = callback; | 631 user_connect_callback_ = callback; |
| 628 } else { | 632 } else { |
| 629 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 633 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 630 } | 634 } |
| 631 | 635 |
| 632 LeaveFunction(""); | 636 LeaveFunction(""); |
| 633 return rv > OK ? OK : rv; | 637 return rv > OK ? OK : rv; |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 #endif | 953 #endif |
| 950 | 954 |
| 951 #ifdef SSL_ENABLE_OCSP_STAPLING | 955 #ifdef SSL_ENABLE_OCSP_STAPLING |
| 952 if (IsOCSPStaplingSupported()) { | 956 if (IsOCSPStaplingSupported()) { |
| 953 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); | 957 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); |
| 954 if (rv != SECSuccess) | 958 if (rv != SECSuccess) |
| 955 LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", ""); | 959 LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", ""); |
| 956 } | 960 } |
| 957 #endif | 961 #endif |
| 958 | 962 |
| 963 #ifdef SSL_ENABLE_CACHED_INFO | |
| 964 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO, | |
| 965 ssl_config_.cached_info_enabled); | |
| 966 if (rv != SECSuccess) | |
| 967 LogFailedNSSFunction(net_log_, "SSL_OptionSet (CachedInfo)", ""); | |
|
wtc
2011/06/03 22:56:55
I think we should imitate lines 940 and 972 instea
rkn
2011/06/04 20:50:19
Done.
| |
| 968 #endif | |
| 969 | |
| 959 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); | 970 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); |
| 960 if (rv != SECSuccess) { | 971 if (rv != SECSuccess) { |
| 961 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); | 972 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); |
| 962 return ERR_UNEXPECTED; | 973 return ERR_UNEXPECTED; |
| 963 } | 974 } |
| 964 | 975 |
| 965 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); | 976 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); |
| 966 if (rv != SECSuccess) { | 977 if (rv != SECSuccess) { |
| 967 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", ""); | 978 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", ""); |
| 968 return ERR_UNEXPECTED; | 979 return ERR_UNEXPECTED; |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1230 // (This is a quirk carried over from the windows | 1241 // (This is a quirk carried over from the windows |
| 1231 // implementation. It makes reading the logs a bit harder.) | 1242 // implementation. It makes reading the logs a bit harder.) |
| 1232 // State handlers can and often do call GotoState just | 1243 // State handlers can and often do call GotoState just |
| 1233 // to stay in the current state. | 1244 // to stay in the current state. |
| 1234 State state = next_handshake_state_; | 1245 State state = next_handshake_state_; |
| 1235 GotoState(STATE_NONE); | 1246 GotoState(STATE_NONE); |
| 1236 switch (state) { | 1247 switch (state) { |
| 1237 case STATE_NONE: | 1248 case STATE_NONE: |
| 1238 // we're just pumping data between the buffer and the network | 1249 // we're just pumping data between the buffer and the network |
| 1239 break; | 1250 break; |
| 1251 case STATE_LOAD_SSL_HOST_INFO: | |
| 1252 rv = DoLoadSSLHostInfo(); | |
| 1253 break; | |
| 1240 case STATE_HANDSHAKE: | 1254 case STATE_HANDSHAKE: |
| 1241 rv = DoHandshake(); | 1255 rv = DoHandshake(); |
| 1242 break; | 1256 break; |
| 1243 case STATE_VERIFY_DNSSEC: | 1257 case STATE_VERIFY_DNSSEC: |
| 1244 rv = DoVerifyDNSSEC(rv); | 1258 rv = DoVerifyDNSSEC(rv); |
| 1245 break; | 1259 break; |
| 1246 case STATE_VERIFY_DNSSEC_COMPLETE: | 1260 case STATE_VERIFY_DNSSEC_COMPLETE: |
| 1247 rv = DoVerifyDNSSECComplete(rv); | 1261 rv = DoVerifyDNSSECComplete(rv); |
| 1248 break; | 1262 break; |
| 1249 case STATE_VERIFY_CERT: | 1263 case STATE_VERIFY_CERT: |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1314 int rv; | 1328 int rv; |
| 1315 do { | 1329 do { |
| 1316 rv = DoPayloadWrite(); | 1330 rv = DoPayloadWrite(); |
| 1317 network_moved = DoTransportIO(); | 1331 network_moved = DoTransportIO(); |
| 1318 } while (rv == ERR_IO_PENDING && network_moved); | 1332 } while (rv == ERR_IO_PENDING && network_moved); |
| 1319 | 1333 |
| 1320 LeaveFunction(""); | 1334 LeaveFunction(""); |
| 1321 return rv; | 1335 return rv; |
| 1322 } | 1336 } |
| 1323 | 1337 |
| 1338 bool SSLClientSocketNSS::LoadSSLHostInfo() { | |
| 1339 const SSLHostInfo::State& state(ssl_host_info_->state()); | |
| 1340 | |
| 1341 if (state.certs.empty()) { | |
| 1342 return false; | |
| 1343 } | |
| 1344 | |
| 1345 SECStatus rv; | |
| 1346 | |
| 1347 const std::vector<std::string>& certs_in = state.certs; | |
| 1348 scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]); | |
| 1349 for (size_t i = 0; i < certs_in.size(); i++) { | |
| 1350 SECItem derCert; | |
| 1351 derCert.data = | |
| 1352 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data())); | |
| 1353 derCert.len = certs_in[i].size(); | |
| 1354 certs[i] = CERT_NewTempCertificate( | |
| 1355 CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */, | |
| 1356 PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */); | |
| 1357 if (!certs[i]) { | |
| 1358 DestroyCertificates(&certs[0], i); | |
| 1359 NOTREACHED(); // I don't understand this line. | |
| 1360 return false; | |
| 1361 } | |
| 1362 } | |
| 1363 | |
| 1364 rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size()); | |
| 1365 DestroyCertificates(&certs[0], certs_in.size()); | |
| 1366 DCHECK_EQ(SECSuccess, rv); | |
| 1367 | |
| 1368 return true; | |
| 1369 } | |
| 1370 | |
| 1371 int SSLClientSocketNSS::DoLoadSSLHostInfo() { | |
| 1372 EnterFunction(""); | |
| 1373 int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_); | |
| 1374 GotoState(STATE_HANDSHAKE); | |
| 1375 | |
| 1376 if (rv == OK) { | |
| 1377 if (!LoadSSLHostInfo()) | |
| 1378 LOG(WARNING) << "LoadSSLHostInfo failed: " << host_and_port_.ToString(); | |
| 1379 } else { | |
| 1380 DCHECK_EQ(ERR_IO_PENDING, rv); | |
| 1381 GotoState(STATE_LOAD_SSL_HOST_INFO); | |
| 1382 } | |
| 1383 | |
| 1384 LeaveFunction(""); | |
| 1385 return rv; | |
| 1386 } | |
| 1387 | |
| 1324 int SSLClientSocketNSS::DoHandshake() { | 1388 int SSLClientSocketNSS::DoHandshake() { |
| 1325 EnterFunction(""); | 1389 EnterFunction(""); |
| 1326 int net_error = net::OK; | 1390 int net_error = net::OK; |
| 1327 SECStatus rv = SSL_ForceHandshake(nss_fd_); | 1391 SECStatus rv = SSL_ForceHandshake(nss_fd_); |
| 1328 | 1392 |
| 1329 if (client_auth_cert_needed_) { | 1393 if (client_auth_cert_needed_) { |
| 1330 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1394 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 1331 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 1395 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 1332 make_scoped_refptr(new SSLErrorParams(net_error, 0))); | 1396 make_scoped_refptr(new SSLErrorParams(net_error, 0))); |
| 1333 // If the handshake already succeeded (because the server requests but | 1397 // If the handshake already succeeded (because the server requests but |
| 1334 // doesn't require a client cert), we need to invalidate the SSL session | 1398 // doesn't require a client cert), we need to invalidate the SSL session |
| 1335 // so that we won't try to resume the non-client-authenticated session in | 1399 // so that we won't try to resume the non-client-authenticated session in |
| 1336 // the next handshake. This will cause the server to ask for a client | 1400 // the next handshake. This will cause the server to ask for a client |
| 1337 // cert again. | 1401 // cert again. |
| 1338 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { | 1402 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { |
| 1339 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); | 1403 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); |
| 1340 } | 1404 } |
| 1341 } else if (rv == SECSuccess) { | 1405 } else if (rv == SECSuccess) { |
| 1342 if (handshake_callback_called_) { | 1406 if (handshake_callback_called_) { |
| 1343 if (eset_mitm_detected_) { | 1407 if (eset_mitm_detected_) { |
| 1344 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; | 1408 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; |
| 1345 } else { | 1409 } else { |
| 1346 // We need to see if the predicted certificate chain (in | 1410 // We need to see if the predicted certificate chain (in |
| 1347 // |ssl_host_info_->state().certs) matches the actual certificate chain | 1411 // |ssl_host_info_->state().certs) matches the actual certificate chain |
| 1348 // before we try to save it before we update |ssl_host_info_|. | 1412 // before we call SaveSSLHostInfo, as that will update |
| 1413 // |ssl_host_info_|. | |
| 1349 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { | 1414 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { |
| 1350 PeerCertificateChain certs(nss_fd_); | 1415 PeerCertificateChain certs(nss_fd_); |
| 1351 const SSLHostInfo::State& state = ssl_host_info_->state(); | 1416 const SSLHostInfo::State& state = ssl_host_info_->state(); |
| 1352 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); | 1417 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); |
| 1353 if (predicted_cert_chain_correct_) { | 1418 if (predicted_cert_chain_correct_) { |
| 1354 for (unsigned i = 0; i < certs.size(); i++) { | 1419 for (unsigned i = 0; i < certs.size(); i++) { |
| 1355 if (certs[i]->derCert.len != state.certs[i].size() || | 1420 if (certs[i]->derCert.len != state.certs[i].size() || |
| 1356 memcmp(certs[i]->derCert.data, state.certs[i].data(), | 1421 memcmp(certs[i]->derCert.data, state.certs[i].data(), |
| 1357 certs[i]->derCert.len) != 0) { | 1422 certs[i]->derCert.len) != 0) { |
| 1358 predicted_cert_chain_correct_ = false; | 1423 predicted_cert_chain_correct_ = false; |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2264 valid_thread_id_ = base::PlatformThread::CurrentId(); | 2329 valid_thread_id_ = base::PlatformThread::CurrentId(); |
| 2265 } | 2330 } |
| 2266 | 2331 |
| 2267 bool SSLClientSocketNSS::CalledOnValidThread() const { | 2332 bool SSLClientSocketNSS::CalledOnValidThread() const { |
| 2268 EnsureThreadIdAssigned(); | 2333 EnsureThreadIdAssigned(); |
| 2269 base::AutoLock auto_lock(lock_); | 2334 base::AutoLock auto_lock(lock_); |
| 2270 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 2335 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
| 2271 } | 2336 } |
| 2272 | 2337 |
| 2273 } // namespace net | 2338 } // namespace net |
| OLD | NEW |