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 // 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 #include "net/base/io_buffer.h" | 81 #include "net/base/io_buffer.h" |
82 #include "net/base/net_errors.h" | 82 #include "net/base/net_errors.h" |
83 #include "net/base/net_log.h" | 83 #include "net/base/net_log.h" |
84 #include "net/base/ssl_cert_request_info.h" | 84 #include "net/base/ssl_cert_request_info.h" |
85 #include "net/base/ssl_connection_status_flags.h" | 85 #include "net/base/ssl_connection_status_flags.h" |
86 #include "net/base/ssl_info.h" | 86 #include "net/base/ssl_info.h" |
87 #include "net/base/sys_addrinfo.h" | 87 #include "net/base/sys_addrinfo.h" |
88 #include "net/ocsp/nss_ocsp.h" | 88 #include "net/ocsp/nss_ocsp.h" |
89 #include "net/socket/client_socket_handle.h" | 89 #include "net/socket/client_socket_handle.h" |
90 #include "net/socket/dns_cert_provenance_checker.h" | 90 #include "net/socket/dns_cert_provenance_checker.h" |
91 #include "net/socket/nss_common.h" | |
91 #include "net/socket/ssl_error_params.h" | 92 #include "net/socket/ssl_error_params.h" |
92 #include "net/socket/ssl_host_info.h" | 93 #include "net/socket/ssl_host_info.h" |
93 | 94 |
94 #if defined(USE_SYSTEM_SSL) | 95 #if defined(USE_SYSTEM_SSL) |
95 #include <dlfcn.h> | 96 #include <dlfcn.h> |
96 #endif | 97 #endif |
97 #if defined(OS_WIN) | 98 #if defined(OS_WIN) |
98 #include <windows.h> | 99 #include <windows.h> |
99 #include <wincrypt.h> | 100 #include <wincrypt.h> |
100 #elif defined(OS_MACOSX) | 101 #elif defined(OS_MACOSX) |
101 #include <Security/SecBase.h> | 102 #include <Security/SecBase.h> |
102 #include <Security/SecCertificate.h> | 103 #include <Security/SecCertificate.h> |
103 #include <Security/SecIdentity.h> | 104 #include <Security/SecIdentity.h> |
104 #endif | 105 #endif |
105 | 106 |
106 static const int kRecvBufferSize = 4096; | 107 static const int kRecvBufferSize = 4096; |
107 | 108 |
108 // kCorkTimeoutMs is the number of milliseconds for which we'll wait for a | 109 // kCorkTimeoutMs is the number of milliseconds for which we'll wait for a |
109 // Write to an SSL socket which we're False Starting. Since corking stops the | 110 // Write to an SSL socket which we're False Starting. Since corking stops the |
110 // Finished message from being sent, the server sees an incomplete handshake | 111 // Finished message from being sent, the server sees an incomplete handshake |
111 // and some will time out such sockets quite aggressively. | 112 // and some will time out such sockets quite aggressively. |
112 static const int kCorkTimeoutMs = 200; | 113 static const int kCorkTimeoutMs = 200; |
113 | 114 |
114 namespace net { | 115 namespace net { |
115 | 116 |
116 // State machines are easier to debug if you log state transitions. | 117 // State machines are easier to debug if you log state transitions. |
117 // Enable these if you want to see what's going on. | 118 // Enable these if you want to see what's going on. |
118 #if 1 | 119 #if 0 |
wtc
2010/12/17 00:16:26
IMPORTANT: please undo this change.
Alpha Left Google
2010/12/17 08:30:43
Uhh.... Careless.. This is done.
| |
119 #define EnterFunction(x) | 120 #define EnterFunction(x) |
120 #define LeaveFunction(x) | 121 #define LeaveFunction(x) |
121 #define GotoState(s) next_handshake_state_ = s | 122 #define GotoState(s) next_handshake_state_ = s |
122 #define LogData(s, len) | 123 #define LogData(s, len) |
123 #else | 124 #else |
124 #define EnterFunction(x)\ | 125 #define EnterFunction(x)\ |
125 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\ | 126 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\ |
126 << "; next_handshake_state " << next_handshake_state_ | 127 << "; next_handshake_state " << next_handshake_state_ |
127 #define LeaveFunction(x)\ | 128 #define LeaveFunction(x)\ |
128 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\ | 129 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\ |
129 << "; next_handshake_state " << next_handshake_state_ | 130 << "; next_handshake_state " << next_handshake_state_ |
130 #define GotoState(s)\ | 131 #define GotoState(s)\ |
131 do {\ | 132 do {\ |
132 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\ | 133 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\ |
133 next_handshake_state_ = s;\ | 134 next_handshake_state_ = s;\ |
134 } while (0) | 135 } while (0) |
135 #define LogData(s, len)\ | 136 #define LogData(s, len)\ |
136 VLOG(1) << (void *)this << " " << __FUNCTION__\ | 137 VLOG(1) << (void *)this << " " << __FUNCTION__\ |
137 << " data [" << std::string(s, len) << "]" | 138 << " data [" << std::string(s, len) << "]" |
138 #endif | 139 #endif |
139 | 140 |
140 namespace { | 141 namespace { |
141 | 142 |
142 class NSSSSLInitSingleton { | |
143 public: | |
144 NSSSSLInitSingleton() { | |
145 base::EnsureNSSInit(); | |
146 | |
147 NSS_SetDomesticPolicy(); | |
148 | |
149 #if defined(USE_SYSTEM_SSL) | |
150 // Use late binding to avoid scary but benign warning | |
151 // "Symbol `SSL_ImplementedCiphers' has different size in shared object, | |
152 // consider re-linking" | |
153 // TODO(wtc): Use the new SSL_GetImplementedCiphers and | |
154 // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6. | |
155 // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993. | |
156 const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>( | |
157 dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers")); | |
158 if (pSSL_ImplementedCiphers == NULL) { | |
159 NOTREACHED() << "Can't get list of supported ciphers"; | |
160 return; | |
161 } | |
162 #else | |
163 #define pSSL_ImplementedCiphers SSL_ImplementedCiphers | |
164 #endif | |
165 | |
166 // Explicitly enable exactly those ciphers with keys of at least 80 bits | |
167 for (int i = 0; i < SSL_NumImplementedCiphers; i++) { | |
168 SSLCipherSuiteInfo info; | |
169 if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info, | |
170 sizeof(info)) == SECSuccess) { | |
171 SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i], | |
172 (info.effectiveKeyBits >= 80)); | |
173 } | |
174 } | |
175 | |
176 // Enable SSL. | |
177 SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); | |
178 | |
179 // All other SSL options are set per-session by SSLClientSocket. | |
180 } | |
181 | |
182 ~NSSSSLInitSingleton() { | |
183 // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY. | |
184 SSL_ClearSessionCache(); | |
185 } | |
186 }; | |
187 | |
188 // Initialize the NSS SSL library if it isn't already initialized. This must | |
189 // be called before any other NSS SSL functions. This function is | |
190 // thread-safe, and the NSS SSL library will only ever be initialized once. | |
191 // The NSS SSL library will be properly shut down on program exit. | |
192 void EnsureNSSSSLInit() { | |
193 // Initializing SSL causes us to do blocking IO. | |
194 // Temporarily allow it until we fix | |
195 // http://code.google.com/p/chromium/issues/detail?id=59847 | |
196 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
197 | |
198 Singleton<NSSSSLInitSingleton>::get(); | |
199 } | |
200 | |
201 // The default error mapping function. | |
202 // Maps an NSPR error code to a network error code. | |
203 int MapNSPRError(PRErrorCode err) { | |
204 // TODO(port): fill this out as we learn what's important | |
205 switch (err) { | |
206 case PR_WOULD_BLOCK_ERROR: | |
207 return ERR_IO_PENDING; | |
208 case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect. | |
209 case PR_NO_ACCESS_RIGHTS_ERROR: | |
210 return ERR_ACCESS_DENIED; | |
211 case PR_IO_TIMEOUT_ERROR: | |
212 return ERR_TIMED_OUT; | |
213 case PR_CONNECT_RESET_ERROR: | |
214 return ERR_CONNECTION_RESET; | |
215 case PR_CONNECT_ABORTED_ERROR: | |
216 return ERR_CONNECTION_ABORTED; | |
217 case PR_CONNECT_REFUSED_ERROR: | |
218 return ERR_CONNECTION_REFUSED; | |
219 case PR_HOST_UNREACHABLE_ERROR: | |
220 case PR_NETWORK_UNREACHABLE_ERROR: | |
221 return ERR_ADDRESS_UNREACHABLE; | |
222 case PR_ADDRESS_NOT_AVAILABLE_ERROR: | |
223 return ERR_ADDRESS_INVALID; | |
224 case PR_INVALID_ARGUMENT_ERROR: | |
225 return ERR_INVALID_ARGUMENT; | |
226 case PR_END_OF_FILE_ERROR: | |
227 return ERR_CONNECTION_CLOSED; | |
228 case PR_NOT_IMPLEMENTED_ERROR: | |
229 return ERR_NOT_IMPLEMENTED; | |
230 | |
231 case SEC_ERROR_INVALID_ARGS: | |
232 return ERR_INVALID_ARGUMENT; | |
233 | |
234 case SSL_ERROR_SSL_DISABLED: | |
235 return ERR_NO_SSL_VERSIONS_ENABLED; | |
236 case SSL_ERROR_NO_CYPHER_OVERLAP: | |
237 case SSL_ERROR_UNSUPPORTED_VERSION: | |
238 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; | |
239 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: | |
240 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: | |
241 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: | |
242 return ERR_SSL_PROTOCOL_ERROR; | |
243 case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT: | |
244 return ERR_SSL_DECOMPRESSION_FAILURE_ALERT; | |
245 case SSL_ERROR_BAD_MAC_ALERT: | |
246 return ERR_SSL_BAD_RECORD_MAC_ALERT; | |
247 case SSL_ERROR_UNSAFE_NEGOTIATION: | |
248 return ERR_SSL_UNSAFE_NEGOTIATION; | |
249 case SSL_ERROR_WEAK_SERVER_KEY: | |
250 return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY; | |
251 | |
252 default: { | |
253 if (IS_SSL_ERROR(err)) { | |
254 LOG(WARNING) << "Unknown SSL error " << err << | |
255 " mapped to net::ERR_SSL_PROTOCOL_ERROR"; | |
256 return ERR_SSL_PROTOCOL_ERROR; | |
257 } | |
258 LOG(WARNING) << "Unknown error " << err << | |
259 " mapped to net::ERR_FAILED"; | |
260 return ERR_FAILED; | |
261 } | |
262 } | |
263 } | |
264 | |
265 // Context-sensitive error mapping functions. | |
266 | |
267 int MapHandshakeError(PRErrorCode err) { | |
268 switch (err) { | |
269 // If the server closed on us, it is a protocol error. | |
270 // Some TLS-intolerant servers do this when we request TLS. | |
271 case PR_END_OF_FILE_ERROR: | |
272 // The handshake may fail because some signature (for example, the | |
273 // signature in the ServerKeyExchange message for an ephemeral | |
274 // Diffie-Hellman cipher suite) is invalid. | |
275 case SEC_ERROR_BAD_SIGNATURE: | |
276 return ERR_SSL_PROTOCOL_ERROR; | |
277 default: | |
278 return MapNSPRError(err); | |
279 } | |
280 } | |
281 | |
282 // Extra parameters to attach to the NetLog when we receive an error in response | |
283 // to a call to an NSS function. Used instead of SSLErrorParams with | |
284 // events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error. | |
285 class SSLFailedNSSFunctionParams : public NetLog::EventParameters { | |
286 public: | |
287 // |param| is ignored if it has a length of 0. | |
288 SSLFailedNSSFunctionParams(const std::string& function, | |
289 const std::string& param) | |
290 : function_(function), param_(param), ssl_lib_error_(PR_GetError()) { | |
291 } | |
292 | |
293 virtual Value* ToValue() const { | |
294 DictionaryValue* dict = new DictionaryValue(); | |
295 dict->SetString("function", function_); | |
296 if (!param_.empty()) | |
297 dict->SetString("param", param_); | |
298 dict->SetInteger("ssl_lib_error", ssl_lib_error_); | |
299 return dict; | |
300 } | |
301 | |
302 private: | |
303 const std::string function_; | |
304 const std::string param_; | |
305 const PRErrorCode ssl_lib_error_; | |
306 }; | |
307 | |
308 void LogFailedNSSFunction(const BoundNetLog& net_log, | |
309 const char* function, | |
310 const char* param) { | |
311 net_log.AddEvent( | |
312 NetLog::TYPE_SSL_NSS_ERROR, | |
313 make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param))); | |
314 } | |
315 | |
316 #if defined(OS_WIN) | 143 #if defined(OS_WIN) |
317 | 144 |
318 // This callback is intended to be used with CertFindChainInStore. In addition | 145 // This callback is intended to be used with CertFindChainInStore. In addition |
319 // to filtering by extended/enhanced key usage, we do not show expired | 146 // to filtering by extended/enhanced key usage, we do not show expired |
320 // certificates and require digital signature usage in the key usage | 147 // certificates and require digital signature usage in the key usage |
321 // extension. | 148 // extension. |
322 // | 149 // |
323 // This matches our behavior on Mac OS X and that of NSS. It also matches the | 150 // This matches our behavior on Mac OS X and that of NSS. It also matches the |
324 // default behavior of IE8. See http://support.microsoft.com/kb/890326 and | 151 // default behavior of IE8. See http://support.microsoft.com/kb/890326 and |
325 // http://blogs.msdn.com/b/askie/archive/2009/06/09/my-expired-client-certificat es-no-longer-display-when-connecting-to-my-web-server-using-ie8.aspx | 152 // http://blogs.msdn.com/b/askie/archive/2009/06/09/my-expired-client-certificat es-no-longer-display-when-connecting-to-my-web-server-using-ie8.aspx |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
722 // Support RFC 5077 | 549 // Support RFC 5077 |
723 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); | 550 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); |
724 if (rv != SECSuccess) { | 551 if (rv != SECSuccess) { |
725 LogFailedNSSFunction( | 552 LogFailedNSSFunction( |
726 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); | 553 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); |
727 } | 554 } |
728 #else | 555 #else |
729 #error "You need to install NSS-3.12 or later to build chromium" | 556 #error "You need to install NSS-3.12 or later to build chromium" |
730 #endif | 557 #endif |
731 | 558 |
559 rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE, ssl_config_.no_cache_enabled); | |
560 if (rv != SECSuccess) { | |
561 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE"); | |
562 return ERR_UNEXPECTED; | |
563 } | |
564 | |
732 #ifdef SSL_ENABLE_DEFLATE | 565 #ifdef SSL_ENABLE_DEFLATE |
733 // Some web servers have been found to break if TLS is used *or* if DEFLATE | 566 // Some web servers have been found to break if TLS is used *or* if DEFLATE |
734 // is advertised. Thus, if TLS is disabled (probably because we are doing | 567 // is advertised. Thus, if TLS is disabled (probably because we are doing |
735 // SSLv3 fallback), we disable DEFLATE also. | 568 // SSLv3 fallback), we disable DEFLATE also. |
736 // See http://crbug.com/31628 | 569 // See http://crbug.com/31628 |
737 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled); | 570 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled); |
738 if (rv != SECSuccess) | 571 if (rv != SECSuccess) |
739 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE"); | 572 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE"); |
740 #endif | 573 #endif |
741 | 574 |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1344 LeaveFunction(""); | 1177 LeaveFunction(""); |
1345 return; | 1178 return; |
1346 } | 1179 } |
1347 | 1180 |
1348 int rv = DoReadLoop(result); | 1181 int rv = DoReadLoop(result); |
1349 if (rv != ERR_IO_PENDING) | 1182 if (rv != ERR_IO_PENDING) |
1350 DoReadCallback(rv); | 1183 DoReadCallback(rv); |
1351 LeaveFunction(""); | 1184 LeaveFunction(""); |
1352 } | 1185 } |
1353 | 1186 |
1354 // Map a Chromium net error code to an NSS error code. | |
1355 // See _MD_unix_map_default_error in the NSS source | |
1356 // tree for inspiration. | |
1357 static PRErrorCode MapErrorToNSS(int result) { | |
1358 if (result >=0) | |
1359 return result; | |
1360 | |
1361 switch (result) { | |
1362 case ERR_IO_PENDING: | |
1363 return PR_WOULD_BLOCK_ERROR; | |
1364 case ERR_ACCESS_DENIED: | |
1365 case ERR_NETWORK_ACCESS_DENIED: | |
1366 // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR. | |
1367 return PR_NO_ACCESS_RIGHTS_ERROR; | |
1368 case ERR_NOT_IMPLEMENTED: | |
1369 return PR_NOT_IMPLEMENTED_ERROR; | |
1370 case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN. | |
1371 return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation. | |
1372 case ERR_CONNECTION_TIMED_OUT: | |
1373 case ERR_TIMED_OUT: | |
1374 return PR_IO_TIMEOUT_ERROR; | |
1375 case ERR_CONNECTION_RESET: | |
1376 return PR_CONNECT_RESET_ERROR; | |
1377 case ERR_CONNECTION_ABORTED: | |
1378 return PR_CONNECT_ABORTED_ERROR; | |
1379 case ERR_CONNECTION_REFUSED: | |
1380 return PR_CONNECT_REFUSED_ERROR; | |
1381 case ERR_ADDRESS_UNREACHABLE: | |
1382 return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR. | |
1383 case ERR_ADDRESS_INVALID: | |
1384 return PR_ADDRESS_NOT_AVAILABLE_ERROR; | |
1385 case ERR_NAME_NOT_RESOLVED: | |
1386 return PR_DIRECTORY_LOOKUP_ERROR; | |
1387 default: | |
1388 LOG(WARNING) << "MapErrorToNSS " << result | |
1389 << " mapped to PR_UNKNOWN_ERROR"; | |
1390 return PR_UNKNOWN_ERROR; | |
1391 } | |
1392 } | |
1393 | |
1394 // Do network I/O between the given buffer and the given socket. | 1187 // Do network I/O between the given buffer and the given socket. |
1395 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) | 1188 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) |
1396 bool SSLClientSocketNSS::DoTransportIO() { | 1189 bool SSLClientSocketNSS::DoTransportIO() { |
1397 EnterFunction(""); | 1190 EnterFunction(""); |
1398 bool network_moved = false; | 1191 bool network_moved = false; |
1399 if (nss_bufs_ != NULL) { | 1192 if (nss_bufs_ != NULL) { |
1400 int nsent = BufferSend(); | 1193 int nsent = BufferSend(); |
1401 int nreceived = BufferRecv(); | 1194 int nreceived = BufferRecv(); |
1402 network_moved = (nsent > 0 || nreceived >= 0); | 1195 network_moved = (nsent > 0 || nreceived >= 0); |
1403 } | 1196 } |
(...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2607 case SSL_CONNECTION_VERSION_TLS1_1: | 2400 case SSL_CONNECTION_VERSION_TLS1_1: |
2608 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); | 2401 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); |
2609 break; | 2402 break; |
2610 case SSL_CONNECTION_VERSION_TLS1_2: | 2403 case SSL_CONNECTION_VERSION_TLS1_2: |
2611 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); | 2404 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); |
2612 break; | 2405 break; |
2613 }; | 2406 }; |
2614 } | 2407 } |
2615 | 2408 |
2616 } // namespace net | 2409 } // namespace net |
OLD | NEW |