OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "net/ssl/openssl_ssl_util.h" | 5 #include "net/ssl/openssl_ssl_util.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include <openssl/err.h> | 9 #include <openssl/err.h> |
10 #include <openssl/ssl.h> | 10 #include <openssl/ssl.h> |
11 | 11 |
12 #include "base/bind.h" | |
12 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
13 #include "base/location.h" | 14 #include "base/location.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/values.h" | |
15 #include "crypto/openssl_util.h" | 17 #include "crypto/openssl_util.h" |
16 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
17 | 19 |
18 namespace net { | 20 namespace net { |
19 | 21 |
20 SslSetClearMask::SslSetClearMask() | 22 SslSetClearMask::SslSetClearMask() |
21 : set_mask(0), | 23 : set_mask(0), |
22 clear_mask(0) { | 24 clear_mask(0) { |
23 } | 25 } |
24 | 26 |
(...skipping 22 matching lines...) Expand all Loading... | |
47 unsigned net_error_lib_; | 49 unsigned net_error_lib_; |
48 }; | 50 }; |
49 | 51 |
50 base::LazyInstance<OpenSSLNetErrorLibSingleton>::Leaky g_openssl_net_error_lib = | 52 base::LazyInstance<OpenSSLNetErrorLibSingleton>::Leaky g_openssl_net_error_lib = |
51 LAZY_INSTANCE_INITIALIZER; | 53 LAZY_INSTANCE_INITIALIZER; |
52 | 54 |
53 unsigned OpenSSLNetErrorLib() { | 55 unsigned OpenSSLNetErrorLib() { |
54 return g_openssl_net_error_lib.Get().net_error_lib(); | 56 return g_openssl_net_error_lib.Get().net_error_lib(); |
55 } | 57 } |
56 | 58 |
57 int MapOpenSSLErrorSSL(unsigned long error_code) { | 59 int MapOpenSSLErrorSSL(uint32_t error_code) { |
58 DCHECK_EQ(ERR_LIB_SSL, ERR_GET_LIB(error_code)); | 60 DCHECK_EQ(ERR_LIB_SSL, ERR_GET_LIB(error_code)); |
59 | 61 |
60 DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code) | 62 DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code) |
61 << ", name: " << ERR_error_string(error_code, NULL); | 63 << ", name: " << ERR_error_string(error_code, NULL); |
62 switch (ERR_GET_REASON(error_code)) { | 64 switch (ERR_GET_REASON(error_code)) { |
63 case SSL_R_READ_TIMEOUT_EXPIRED: | 65 case SSL_R_READ_TIMEOUT_EXPIRED: |
64 return ERR_TIMED_OUT; | 66 return ERR_TIMED_OUT; |
65 case SSL_R_BAD_RESPONSE_ARGUMENT: | 67 case SSL_R_BAD_RESPONSE_ARGUMENT: |
66 return ERR_INVALID_ARGUMENT; | 68 return ERR_INVALID_ARGUMENT; |
67 case SSL_R_UNKNOWN_CERTIFICATE_TYPE: | 69 case SSL_R_UNKNOWN_CERTIFICATE_TYPE: |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 // the leaf certificate changed during a renegotiation. | 151 // the leaf certificate changed during a renegotiation. |
150 return ERR_SSL_SERVER_CERT_CHANGED; | 152 return ERR_SSL_SERVER_CERT_CHANGED; |
151 case SSL_AD_REASON_OFFSET + SSL3_AD_INAPPROPRIATE_FALLBACK: | 153 case SSL_AD_REASON_OFFSET + SSL3_AD_INAPPROPRIATE_FALLBACK: |
152 return ERR_SSL_INAPPROPRIATE_FALLBACK; | 154 return ERR_SSL_INAPPROPRIATE_FALLBACK; |
153 default: | 155 default: |
154 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); | 156 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); |
155 return ERR_FAILED; | 157 return ERR_FAILED; |
156 } | 158 } |
157 } | 159 } |
158 | 160 |
161 base::Value* NetLogOpenSSLErrorCallback(int net_error, | |
162 int ssl_error, | |
163 uint32_t error_code, | |
164 const char* file, | |
165 int line, | |
166 NetLog::LogLevel /* log_level */) { | |
167 base::DictionaryValue* dict = new base::DictionaryValue(); | |
168 dict->SetInteger("net_error", net_error); | |
169 dict->SetInteger("ssl_error", ssl_error); | |
170 if (error_code != 0) { | |
171 dict->SetInteger("error_lib", ERR_GET_LIB(error_code)); | |
172 dict->SetInteger("error_reason", ERR_GET_REASON(error_code)); | |
Ryan Sleevi
2014/08/25 06:24:35
And we're guaranteed these will always be masks an
davidben
2014/08/26 22:13:51
Yeah, that would be a pretty significant departure
| |
173 } | |
174 if (file != NULL) | |
175 dict->SetString("file", file); | |
176 if (line != 0) | |
177 dict->SetInteger("line", line); | |
178 return dict; | |
179 } | |
180 | |
159 } // namespace | 181 } // namespace |
160 | 182 |
161 void OpenSSLPutNetError(const tracked_objects::Location& location, int err) { | 183 void OpenSSLPutNetError(const tracked_objects::Location& location, int err) { |
162 // Net error codes are negative. Encode them as positive numbers. | 184 // Net error codes are negative. Encode them as positive numbers. |
163 err = -err; | 185 err = -err; |
164 if (err < 0 || err > 0xfff) { | 186 if (err < 0 || err > 0xfff) { |
165 // OpenSSL reserves 12 bits for the reason code. | 187 // OpenSSL reserves 12 bits for the reason code. |
166 NOTREACHED(); | 188 NOTREACHED(); |
167 err = ERR_INVALID_ARGUMENT; | 189 err = ERR_INVALID_ARGUMENT; |
168 } | 190 } |
169 ERR_put_error(OpenSSLNetErrorLib(), 0, err, | 191 ERR_put_error(OpenSSLNetErrorLib(), 0, err, |
170 location.file_name(), location.line_number()); | 192 location.file_name(), location.line_number()); |
171 } | 193 } |
172 | 194 |
173 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { | 195 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { |
196 uint32_t error_code; | |
197 const char* file; | |
198 int line; | |
199 return MapOpenSSLErrorWithDetails(err, tracer, &error_code, &file, &line); | |
200 } | |
201 | |
202 int MapOpenSSLErrorWithDetails(int err, | |
203 const crypto::OpenSSLErrStackTracer& tracer, | |
204 uint32_t* out_error_code, | |
205 const char** out_file, | |
206 int* out_line) { | |
207 *out_error_code = 0; | |
208 *out_file = NULL; | |
209 *out_line = 0; | |
210 | |
174 switch (err) { | 211 switch (err) { |
175 case SSL_ERROR_WANT_READ: | 212 case SSL_ERROR_WANT_READ: |
176 case SSL_ERROR_WANT_WRITE: | 213 case SSL_ERROR_WANT_WRITE: |
177 return ERR_IO_PENDING; | 214 return ERR_IO_PENDING; |
178 case SSL_ERROR_SYSCALL: | 215 case SSL_ERROR_SYSCALL: |
179 LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in " | 216 LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in " |
180 "error queue: " << ERR_peek_error() << ", errno: " | 217 "error queue: " << ERR_peek_error() << ", errno: " |
181 << errno; | 218 << errno; |
182 return ERR_SSL_PROTOCOL_ERROR; | 219 return ERR_SSL_PROTOCOL_ERROR; |
183 case SSL_ERROR_SSL: | 220 case SSL_ERROR_SSL: |
184 // Walk down the error stack to find an SSL or net error. | 221 // Walk down the error stack to find an SSL or net error. |
185 unsigned long error_code; | 222 uint32_t error_code; |
223 const char* file; | |
224 int line; | |
186 do { | 225 do { |
187 error_code = ERR_get_error(); | 226 error_code = ERR_get_error_line(&file, &line); |
188 if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) { | 227 if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) { |
228 *out_error_code = error_code; | |
229 *out_file = file; | |
230 *out_line = line; | |
189 return MapOpenSSLErrorSSL(error_code); | 231 return MapOpenSSLErrorSSL(error_code); |
190 } else if (ERR_GET_LIB(error_code) == OpenSSLNetErrorLib()) { | 232 } else if (ERR_GET_LIB(error_code) == OpenSSLNetErrorLib()) { |
233 *out_error_code = error_code; | |
234 *out_file = file; | |
235 *out_line = line; | |
191 // Net error codes are negative but encoded in OpenSSL as positive | 236 // Net error codes are negative but encoded in OpenSSL as positive |
192 // numbers. | 237 // numbers. |
193 return -ERR_GET_REASON(error_code); | 238 return -ERR_GET_REASON(error_code); |
194 } | 239 } |
195 } while (error_code != 0); | 240 } while (error_code != 0); |
196 return ERR_SSL_PROTOCOL_ERROR; | 241 return ERR_SSL_PROTOCOL_ERROR; |
197 default: | 242 default: |
198 // TODO(joth): Implement full mapping. | 243 // TODO(joth): Implement full mapping. |
199 LOG(WARNING) << "Unknown OpenSSL error " << err; | 244 LOG(WARNING) << "Unknown OpenSSL error " << err; |
200 return ERR_SSL_PROTOCOL_ERROR; | 245 return ERR_SSL_PROTOCOL_ERROR; |
201 } | 246 } |
202 } | 247 } |
203 | 248 |
249 NetLog::ParametersCallback CreateNetLogOpenSSLErrorCallback(int net_error, | |
250 int ssl_error, | |
251 uint32_t error_code, | |
252 const char* file, | |
253 int line) { | |
254 return base::Bind(&NetLogOpenSSLErrorCallback, | |
255 net_error, ssl_error, error_code, file, line); | |
256 } | |
257 | |
204 } // namespace net | 258 } // namespace net |
OLD | NEW |