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

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

Issue 5746003: Defines SSLServerSocket and implements SSLServerSocketNSS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/socket/nss_ssl_util.h"
6
7 #include <nss.h>
8 #include <secerr.h>
9 #include <ssl.h>
10 #include <sslerr.h>
11
12 #include "base/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/nss_util.h"
15 #include "base/singleton.h"
16 #include "base/thread_restrictions.h"
17 #include "base/values.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/net_log.h"
20
21 namespace net {
22
23 class NSSSSLInitSingleton {
24 public:
25 NSSSSLInitSingleton() {
26 base::EnsureNSSInit();
27
28 NSS_SetDomesticPolicy();
29
30 #if defined(USE_SYSTEM_SSL)
31 // Use late binding to avoid scary but benign warning
32 // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
33 // consider re-linking"
34 // TODO(wtc): Use the new SSL_GetImplementedCiphers and
35 // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6.
36 // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993.
37 const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
38 dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
39 if (pSSL_ImplementedCiphers == NULL) {
40 NOTREACHED() << "Can't get list of supported ciphers";
41 return;
42 }
43 #else
44 #define pSSL_ImplementedCiphers SSL_ImplementedCiphers
45 #endif
46
47 // Explicitly enable exactly those ciphers with keys of at least 80 bits
48 for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
49 SSLCipherSuiteInfo info;
50 if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
51 sizeof(info)) == SECSuccess) {
52 SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
53 (info.effectiveKeyBits >= 80));
54 }
55 }
56
57 // Enable SSL.
58 SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
59
60 // All other SSL options are set per-session by SSLClientSocket and
61 // SSLServerSocket.
62 }
63
64 ~NSSSSLInitSingleton() {
65 // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
66 SSL_ClearSessionCache();
67 }
68 };
69
70 static base::LazyInstance<NSSSSLInitSingleton> g_nss_ssl_init_singleton(
71 base::LINKER_INITIALIZED);
72
73 // Initialize the NSS SSL library if it isn't already initialized. This must
74 // be called before any other NSS SSL functions. This function is
75 // thread-safe, and the NSS SSL library will only ever be initialized once.
76 // The NSS SSL library will be properly shut down on program exit.
77 void EnsureNSSSSLInit() {
78 // Initializing SSL causes us to do blocking IO.
79 // Temporarily allow it until we fix
80 // http://code.google.com/p/chromium/issues/detail?id=59847
81 base::ThreadRestrictions::ScopedAllowIO allow_io;
82
83 g_nss_ssl_init_singleton.Get();
84 }
85
86 // Map a Chromium net error code to an NSS error code.
87 // See _MD_unix_map_default_error in the NSS source
88 // tree for inspiration.
89 PRErrorCode MapErrorToNSS(int result) {
90 if (result >=0)
91 return result;
92
93 switch (result) {
94 case ERR_IO_PENDING:
95 return PR_WOULD_BLOCK_ERROR;
96 case ERR_ACCESS_DENIED:
97 case ERR_NETWORK_ACCESS_DENIED:
98 // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
99 return PR_NO_ACCESS_RIGHTS_ERROR;
100 case ERR_NOT_IMPLEMENTED:
101 return PR_NOT_IMPLEMENTED_ERROR;
102 case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN.
103 return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation.
104 case ERR_CONNECTION_TIMED_OUT:
105 case ERR_TIMED_OUT:
106 return PR_IO_TIMEOUT_ERROR;
107 case ERR_CONNECTION_RESET:
108 return PR_CONNECT_RESET_ERROR;
109 case ERR_CONNECTION_ABORTED:
110 return PR_CONNECT_ABORTED_ERROR;
111 case ERR_CONNECTION_REFUSED:
112 return PR_CONNECT_REFUSED_ERROR;
113 case ERR_ADDRESS_UNREACHABLE:
114 return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
115 case ERR_ADDRESS_INVALID:
116 return PR_ADDRESS_NOT_AVAILABLE_ERROR;
117 case ERR_NAME_NOT_RESOLVED:
118 return PR_DIRECTORY_LOOKUP_ERROR;
119 default:
120 LOG(WARNING) << "MapErrorToNSS " << result
121 << " mapped to PR_UNKNOWN_ERROR";
122 return PR_UNKNOWN_ERROR;
123 }
124 }
125
126 // The default error mapping function.
127 // Maps an NSS error code to a network error code.
128 int MapNSSError(PRErrorCode err) {
129 // TODO(port): fill this out as we learn what's important
130 switch (err) {
131 case PR_WOULD_BLOCK_ERROR:
132 return ERR_IO_PENDING;
133 case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
134 case PR_NO_ACCESS_RIGHTS_ERROR:
135 return ERR_ACCESS_DENIED;
136 case PR_IO_TIMEOUT_ERROR:
137 return ERR_TIMED_OUT;
138 case PR_CONNECT_RESET_ERROR:
139 return ERR_CONNECTION_RESET;
140 case PR_CONNECT_ABORTED_ERROR:
141 return ERR_CONNECTION_ABORTED;
142 case PR_CONNECT_REFUSED_ERROR:
143 return ERR_CONNECTION_REFUSED;
144 case PR_HOST_UNREACHABLE_ERROR:
145 case PR_NETWORK_UNREACHABLE_ERROR:
146 return ERR_ADDRESS_UNREACHABLE;
147 case PR_ADDRESS_NOT_AVAILABLE_ERROR:
148 return ERR_ADDRESS_INVALID;
149 case PR_INVALID_ARGUMENT_ERROR:
150 return ERR_INVALID_ARGUMENT;
151 case PR_END_OF_FILE_ERROR:
152 return ERR_CONNECTION_CLOSED;
153 case PR_NOT_IMPLEMENTED_ERROR:
154 return ERR_NOT_IMPLEMENTED;
155
156 case SEC_ERROR_INVALID_ARGS:
157 return ERR_INVALID_ARGUMENT;
158
159 case SSL_ERROR_SSL_DISABLED:
160 return ERR_NO_SSL_VERSIONS_ENABLED;
161 case SSL_ERROR_NO_CYPHER_OVERLAP:
162 case SSL_ERROR_UNSUPPORTED_VERSION:
163 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
164 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
165 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
166 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
167 return ERR_SSL_PROTOCOL_ERROR;
168 case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
169 return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
170 case SSL_ERROR_BAD_MAC_ALERT:
171 return ERR_SSL_BAD_RECORD_MAC_ALERT;
172 case SSL_ERROR_UNSAFE_NEGOTIATION:
173 return ERR_SSL_UNSAFE_NEGOTIATION;
174 case SSL_ERROR_WEAK_SERVER_KEY:
175 return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
176
177 default: {
178 if (IS_SSL_ERROR(err)) {
179 LOG(WARNING) << "Unknown SSL error " << err <<
180 " mapped to net::ERR_SSL_PROTOCOL_ERROR";
181 return ERR_SSL_PROTOCOL_ERROR;
182 }
183 LOG(WARNING) << "Unknown error " << err <<
184 " mapped to net::ERR_FAILED";
185 return ERR_FAILED;
186 }
187 }
188 }
189
190 // Context-sensitive error mapping functions.
191 int MapHandshakeError(PRErrorCode err) {
192 switch (err) {
193 // If the server closed on us, it is a protocol error.
194 // Some TLS-intolerant servers do this when we request TLS.
195 case PR_END_OF_FILE_ERROR:
196 // The handshake may fail because some signature (for example, the
197 // signature in the ServerKeyExchange message for an ephemeral
198 // Diffie-Hellman cipher suite) is invalid.
199 case SEC_ERROR_BAD_SIGNATURE:
200 return ERR_SSL_PROTOCOL_ERROR;
201 default:
202 return MapNSSError(err);
203 }
204 }
205
206 // Extra parameters to attach to the NetLog when we receive an error in response
207 // to a call to an NSS function. Used instead of SSLErrorParams with
208 // events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error.
209 class SSLFailedNSSFunctionParams : public NetLog::EventParameters {
210 public:
211 // |param| is ignored if it has a length of 0.
212 SSLFailedNSSFunctionParams(const std::string& function,
213 const std::string& param)
214 : function_(function), param_(param), ssl_lib_error_(PR_GetError()) {
215 }
216
217 virtual Value* ToValue() const {
218 DictionaryValue* dict = new DictionaryValue();
219 dict->SetString("function", function_);
220 if (!param_.empty())
221 dict->SetString("param", param_);
222 dict->SetInteger("ssl_lib_error", ssl_lib_error_);
223 return dict;
224 }
225
226 private:
227 const std::string function_;
228 const std::string param_;
229 const PRErrorCode ssl_lib_error_;
230 };
231
232 void LogFailedNSSFunction(const BoundNetLog& net_log,
233 const char* function,
234 const char* param) {
235 net_log.AddEvent(
236 NetLog::TYPE_SSL_NSS_ERROR,
237 make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param)));
238 }
239
240 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698