OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // OpenSSL binding for SSLClientSocket. The class layout and general principle | 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle |
6 // of operation is derived from SSLClientSocketNSS. | 6 // of operation is derived from SSLClientSocketNSS. |
7 | 7 |
8 #include "net/socket/ssl_client_socket_openssl.h" | 8 #include "net/socket/ssl_client_socket_openssl.h" |
9 | 9 |
10 #include <openssl/err.h> | 10 #include <openssl/err.h> |
11 #include <openssl/opensslv.h> | 11 #include <openssl/opensslv.h> |
12 #include <openssl/ssl.h> | 12 #include <openssl/ssl.h> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
16 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
19 #include "crypto/ec_private_key.h" | 19 #include "crypto/ec_private_key.h" |
20 #include "crypto/openssl_util.h" | 20 #include "crypto/openssl_util.h" |
21 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
22 #include "net/cert/cert_verifier.h" | 22 #include "net/cert/cert_verifier.h" |
23 #include "net/cert/single_request_cert_verifier.h" | 23 #include "net/cert/single_request_cert_verifier.h" |
24 #include "net/cert/x509_certificate_net_log_param.h" | 24 #include "net/cert/x509_certificate_net_log_param.h" |
25 #include "net/socket/ssl_error_params.h" | 25 #include "net/socket/ssl_error_params.h" |
| 26 #include "net/socket/ssl_session_cache_openssl.h" |
26 #include "net/ssl/openssl_client_key_store.h" | 27 #include "net/ssl/openssl_client_key_store.h" |
27 #include "net/ssl/ssl_cert_request_info.h" | 28 #include "net/ssl/ssl_cert_request_info.h" |
28 #include "net/ssl/ssl_connection_status_flags.h" | 29 #include "net/ssl/ssl_connection_status_flags.h" |
29 #include "net/ssl/ssl_info.h" | 30 #include "net/ssl/ssl_info.h" |
30 | 31 |
31 namespace net { | 32 namespace net { |
32 | 33 |
33 namespace { | 34 namespace { |
34 | 35 |
35 // Enable this to see logging for state machine state transitions. | 36 // Enable this to see logging for state machine state transitions. |
36 #if 0 | 37 #if 0 |
37 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ | 38 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ |
38 " jump to state " << s; \ | 39 " jump to state " << s; \ |
39 next_handshake_state_ = s; } while (0) | 40 next_handshake_state_ = s; } while (0) |
40 #else | 41 #else |
41 #define GotoState(s) next_handshake_state_ = s | 42 #define GotoState(s) next_handshake_state_ = s |
42 #endif | 43 #endif |
43 | 44 |
44 const int kSessionCacheTimeoutSeconds = 60 * 60; | |
45 const size_t kSessionCacheMaxEntires = 1024; | |
46 | |
47 // This constant can be any non-negative/non-zero value (eg: it does not | 45 // This constant can be any non-negative/non-zero value (eg: it does not |
48 // overlap with any value of the net::Error range, including net::OK). | 46 // overlap with any value of the net::Error range, including net::OK). |
49 const int kNoPendingReadResult = 1; | 47 const int kNoPendingReadResult = 1; |
50 | 48 |
51 // If a client doesn't have a list of protocols that it supports, but | 49 // If a client doesn't have a list of protocols that it supports, but |
52 // the server supports NPN, choosing "http/1.1" is the best answer. | 50 // the server supports NPN, choosing "http/1.1" is the best answer. |
53 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; | 51 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; |
54 | 52 |
55 #if OPENSSL_VERSION_NUMBER < 0x1000103fL | 53 #if OPENSSL_VERSION_NUMBER < 0x1000103fL |
56 // This method doesn't seem to have made it into the OpenSSL headers. | 54 // This method doesn't seem to have made it into the OpenSSL headers. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 } | 206 } |
209 } | 207 } |
210 | 208 |
211 // We do certificate verification after handshake, so we disable the default | 209 // We do certificate verification after handshake, so we disable the default |
212 // by registering a no-op verify function. | 210 // by registering a no-op verify function. |
213 int NoOpVerifyCallback(X509_STORE_CTX*, void *) { | 211 int NoOpVerifyCallback(X509_STORE_CTX*, void *) { |
214 DVLOG(3) << "skipping cert verify"; | 212 DVLOG(3) << "skipping cert verify"; |
215 return 1; | 213 return 1; |
216 } | 214 } |
217 | 215 |
218 // OpenSSL manages a cache of SSL_SESSION, this class provides the application | |
219 // side policy for that cache about session re-use: we retain one session per | |
220 // unique HostPortPair, per shard. | |
221 class SSLSessionCache { | |
222 public: | |
223 SSLSessionCache() {} | |
224 | |
225 void OnSessionAdded(const HostPortPair& host_and_port, | |
226 const std::string& shard, | |
227 SSL_SESSION* session) { | |
228 // Declare the session cleaner-upper before the lock, so any call into | |
229 // OpenSSL to free the session will happen after the lock is released. | |
230 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | |
231 base::AutoLock lock(lock_); | |
232 | |
233 DCHECK_EQ(0U, session_map_.count(session)); | |
234 const std::string cache_key = GetCacheKey(host_and_port, shard); | |
235 | |
236 std::pair<HostPortMap::iterator, bool> res = | |
237 host_port_map_.insert(std::make_pair(cache_key, session)); | |
238 if (!res.second) { // Already exists: replace old entry. | |
239 session_to_free.reset(res.first->second); | |
240 session_map_.erase(session_to_free.get()); | |
241 res.first->second = session; | |
242 } | |
243 DVLOG(2) << "Adding session " << session << " => " | |
244 << cache_key << ", new entry = " << res.second; | |
245 DCHECK(host_port_map_[cache_key] == session); | |
246 session_map_[session] = res.first; | |
247 DCHECK_EQ(host_port_map_.size(), session_map_.size()); | |
248 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); | |
249 } | |
250 | |
251 void OnSessionRemoved(SSL_SESSION* session) { | |
252 // Declare the session cleaner-upper before the lock, so any call into | |
253 // OpenSSL to free the session will happen after the lock is released. | |
254 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | |
255 base::AutoLock lock(lock_); | |
256 | |
257 SessionMap::iterator it = session_map_.find(session); | |
258 if (it == session_map_.end()) | |
259 return; | |
260 DVLOG(2) << "Remove session " << session << " => " << it->second->first; | |
261 DCHECK(it->second->second == session); | |
262 host_port_map_.erase(it->second); | |
263 session_map_.erase(it); | |
264 session_to_free.reset(session); | |
265 DCHECK_EQ(host_port_map_.size(), session_map_.size()); | |
266 } | |
267 | |
268 // Looks up the host:port in the cache, and if a session is found it is added | |
269 // to |ssl|, returning true on success. | |
270 bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port, | |
271 const std::string& shard) { | |
272 base::AutoLock lock(lock_); | |
273 const std::string cache_key = GetCacheKey(host_and_port, shard); | |
274 HostPortMap::iterator it = host_port_map_.find(cache_key); | |
275 if (it == host_port_map_.end()) | |
276 return false; | |
277 DVLOG(2) << "Lookup session: " << it->second << " => " << cache_key; | |
278 SSL_SESSION* session = it->second; | |
279 DCHECK(session); | |
280 DCHECK(session_map_[session] == it); | |
281 // Ideally we'd release |lock_| before calling into OpenSSL here, however | |
282 // that opens a small risk |session| will go out of scope before it is used. | |
283 // Alternatively we would take a temporary local refcount on |session|, | |
284 // except OpenSSL does not provide a public API for adding a ref (c.f. | |
285 // SSL_SESSION_free which decrements the ref). | |
286 return SSL_set_session(ssl, session) == 1; | |
287 } | |
288 | |
289 // Flush removes all entries from the cache. This is called when a client | |
290 // certificate is added. | |
291 void Flush() { | |
292 base::AutoLock lock(lock_); | |
293 for (HostPortMap::iterator i = host_port_map_.begin(); | |
294 i != host_port_map_.end(); i++) { | |
295 SSL_SESSION_free(i->second); | |
296 } | |
297 host_port_map_.clear(); | |
298 session_map_.clear(); | |
299 } | |
300 | |
301 private: | |
302 static std::string GetCacheKey(const HostPortPair& host_and_port, | |
303 const std::string& shard) { | |
304 return host_and_port.ToString() + "/" + shard; | |
305 } | |
306 | |
307 // A pair of maps to allow bi-directional lookups between host:port and an | |
308 // associated session. | |
309 typedef std::map<std::string, SSL_SESSION*> HostPortMap; | |
310 typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap; | |
311 HostPortMap host_port_map_; | |
312 SessionMap session_map_; | |
313 | |
314 // Protects access to both the above maps. | |
315 base::Lock lock_; | |
316 | |
317 DISALLOW_COPY_AND_ASSIGN(SSLSessionCache); | |
318 }; | |
319 | |
320 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 216 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
321 // options and mode configuration functions. (SSL_set_options etc) | 217 // options and mode configuration functions. (SSL_set_options etc) |
322 struct SslSetClearMask { | 218 struct SslSetClearMask { |
323 SslSetClearMask() : set_mask(0), clear_mask(0) {} | 219 SslSetClearMask() : set_mask(0), clear_mask(0) {} |
324 void ConfigureFlag(long flag, bool state) { | 220 void ConfigureFlag(long flag, bool state) { |
325 (state ? set_mask : clear_mask) |= flag; | 221 (state ? set_mask : clear_mask) |= flag; |
326 // Make sure we haven't got any intersection in the set & clear options. | 222 // Make sure we haven't got any intersection in the set & clear options. |
327 DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; | 223 DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; |
328 } | 224 } |
329 long set_mask; | 225 long set_mask; |
330 long clear_mask; | 226 long clear_mask; |
331 }; | 227 }; |
332 | 228 |
| 229 // Compute a unique key string for the SSL session cache. |socket| is an |
| 230 // input socket object. Return a string. |
| 231 std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) { |
| 232 std::string result = socket.host_and_port().ToString(); |
| 233 result.append("/"); |
| 234 result.append(socket.ssl_session_cache_shard()); |
| 235 return result; |
| 236 } |
| 237 |
333 } // namespace | 238 } // namespace |
334 | 239 |
335 class SSLClientSocketOpenSSL::SSLContext { | 240 class SSLClientSocketOpenSSL::SSLContext { |
336 public: | 241 public: |
337 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } | 242 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } |
338 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } | 243 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } |
339 SSLSessionCache* session_cache() { return &session_cache_; } | 244 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } |
340 | 245 |
341 SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) { | 246 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { |
342 DCHECK(ssl); | 247 DCHECK(ssl); |
343 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>( | 248 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>( |
344 SSL_get_ex_data(ssl, ssl_socket_data_index_)); | 249 SSL_get_ex_data(ssl, ssl_socket_data_index_)); |
345 DCHECK(socket); | 250 DCHECK(socket); |
346 return socket; | 251 return socket; |
347 } | 252 } |
348 | 253 |
349 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { | 254 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { |
350 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; | 255 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; |
351 } | 256 } |
352 | 257 |
353 private: | 258 private: |
354 friend struct DefaultSingletonTraits<SSLContext>; | 259 friend struct DefaultSingletonTraits<SSLContext>; |
355 | 260 |
356 SSLContext() { | 261 SSLContext() { |
357 crypto::EnsureOpenSSLInit(); | 262 crypto::EnsureOpenSSLInit(); |
358 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 263 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
359 DCHECK_NE(ssl_socket_data_index_, -1); | 264 DCHECK_NE(ssl_socket_data_index_, -1); |
360 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 265 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
| 266 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); |
361 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 267 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); |
362 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); | |
363 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | |
364 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | |
365 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | |
366 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | |
367 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 268 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
368 SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback); | 269 SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback); |
369 #if defined(OPENSSL_NPN_NEGOTIATED) | 270 #if defined(OPENSSL_NPN_NEGOTIATED) |
370 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. | 271 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. |
371 // It would be better if the callback were not a global setting, | 272 // It would be better if the callback were not a global setting, |
372 // but that is an OpenSSL issue. | 273 // but that is an OpenSSL issue. |
373 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, | 274 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, |
374 NULL); | 275 NULL); |
375 #endif | 276 #endif |
376 } | 277 } |
377 | 278 |
378 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { | 279 static std::string GetSessionCacheKey(const SSL* ssl) { |
379 return GetInstance()->NewSessionCallback(ssl, session); | 280 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
| 281 DCHECK(socket); |
| 282 return GetSocketSessionCacheKey(*socket); |
380 } | 283 } |
381 | 284 |
382 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { | 285 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; |
383 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); | |
384 session_cache_.OnSessionAdded(socket->host_and_port(), | |
385 socket->ssl_session_cache_shard(), | |
386 session); | |
387 return 1; // 1 => We took ownership of |session|. | |
388 } | |
389 | |
390 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { | |
391 return GetInstance()->RemoveSessionCallback(ctx, session); | |
392 } | |
393 | |
394 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { | |
395 DCHECK(ctx == ssl_ctx()); | |
396 session_cache_.OnSessionRemoved(session); | |
397 } | |
398 | 286 |
399 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 287 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
400 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 288 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
401 CHECK(socket); | 289 CHECK(socket); |
402 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 290 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
403 } | 291 } |
404 | 292 |
405 static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) { | 293 static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) { |
406 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 294 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
407 CHECK(socket); | 295 CHECK(socket); |
408 socket->ChannelIDRequestCallback(ssl, pkey); | 296 socket->ChannelIDRequestCallback(ssl, pkey); |
409 } | 297 } |
410 | 298 |
411 static int SelectNextProtoCallback(SSL* ssl, | 299 static int SelectNextProtoCallback(SSL* ssl, |
412 unsigned char** out, unsigned char* outlen, | 300 unsigned char** out, unsigned char* outlen, |
413 const unsigned char* in, | 301 const unsigned char* in, |
414 unsigned int inlen, void* arg) { | 302 unsigned int inlen, void* arg) { |
415 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 303 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
416 return socket->SelectNextProtoCallback(out, outlen, in, inlen); | 304 return socket->SelectNextProtoCallback(out, outlen, in, inlen); |
417 } | 305 } |
418 | 306 |
419 // This is the index used with SSL_get_ex_data to retrieve the owner | 307 // This is the index used with SSL_get_ex_data to retrieve the owner |
420 // SSLClientSocketOpenSSL object from an SSL instance. | 308 // SSLClientSocketOpenSSL object from an SSL instance. |
421 int ssl_socket_data_index_; | 309 int ssl_socket_data_index_; |
422 | 310 |
423 // session_cache_ must appear before |ssl_ctx_| because the destruction of | |
424 // |ssl_ctx_| may trigger callbacks into |session_cache_|. Therefore, | |
425 // |session_cache_| must be destructed after |ssl_ctx_|. | |
426 SSLSessionCache session_cache_; | |
427 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 311 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
| 312 // |session_cache_| must be destroyed before |ssl_ctx_|. |
| 313 SSLSessionCacheOpenSSL session_cache_; |
428 }; | 314 }; |
429 | 315 |
430 // static | 316 // static |
| 317 SSLSessionCacheOpenSSL::Config |
| 318 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { |
| 319 &GetSessionCacheKey, // key_func |
| 320 1024, // max_entries |
| 321 256, // expiration_check_count |
| 322 60 * 60, // timeout_seconds |
| 323 }; |
| 324 |
| 325 // static |
431 void SSLClientSocket::ClearSessionCache() { | 326 void SSLClientSocket::ClearSessionCache() { |
432 SSLClientSocketOpenSSL::SSLContext* context = | 327 SSLClientSocketOpenSSL::SSLContext* context = |
433 SSLClientSocketOpenSSL::SSLContext::GetInstance(); | 328 SSLClientSocketOpenSSL::SSLContext::GetInstance(); |
434 context->session_cache()->Flush(); | 329 context->session_cache()->Flush(); |
435 } | 330 } |
436 | 331 |
437 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( | 332 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( |
438 scoped_ptr<ClientSocketHandle> transport_socket, | 333 scoped_ptr<ClientSocketHandle> transport_socket, |
439 const HostPortPair& host_and_port, | 334 const HostPortPair& host_and_port, |
440 const SSLConfig& ssl_config, | 335 const SSLConfig& ssl_config, |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 SSLContext* context = SSLContext::GetInstance(); | 641 SSLContext* context = SSLContext::GetInstance(); |
747 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 642 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
748 | 643 |
749 ssl_ = SSL_new(context->ssl_ctx()); | 644 ssl_ = SSL_new(context->ssl_ctx()); |
750 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) | 645 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) |
751 return false; | 646 return false; |
752 | 647 |
753 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) | 648 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) |
754 return false; | 649 return false; |
755 | 650 |
756 trying_cached_session_ = | 651 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
757 context->session_cache()->SetSSLSession(ssl_, host_and_port_, | 652 ssl_, GetSocketSessionCacheKey(*this)); |
758 ssl_session_cache_shard_); | |
759 | 653 |
760 BIO* ssl_bio = NULL; | 654 BIO* ssl_bio = NULL; |
761 // 0 => use default buffer sizes. | 655 // 0 => use default buffer sizes. |
762 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 656 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
763 return false; | 657 return false; |
764 DCHECK(ssl_bio); | 658 DCHECK(ssl_bio); |
765 DCHECK(transport_bio_); | 659 DCHECK(transport_bio_); |
766 | 660 |
767 SSL_set_bio(ssl_, ssl_bio, ssl_bio); | 661 SSL_set_bio(ssl_, ssl_bio, ssl_bio); |
768 | 662 |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1492 } | 1386 } |
1493 | 1387 |
1494 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | 1388 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
1495 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); | 1389 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); |
1496 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 1390 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
1497 #endif | 1391 #endif |
1498 return SSL_TLSEXT_ERR_OK; | 1392 return SSL_TLSEXT_ERR_OK; |
1499 } | 1393 } |
1500 | 1394 |
1501 } // namespace net | 1395 } // namespace net |
OLD | NEW |