Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: net/socket/ssl_client_socket_nss.cc

Issue 5746003: Defines SSLServerSocket and implements SSLServerSocketNSS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix style Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698