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

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

Issue 173853014: Make OpenSSL UpdateServerCert() OS independent. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed android compile error Created 6 years, 9 months 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
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 234
235 // Compute a unique key string for the SSL session cache. |socket| is an 235 // Compute a unique key string for the SSL session cache. |socket| is an
236 // input socket object. Return a string. 236 // input socket object. Return a string.
237 std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) { 237 std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) {
238 std::string result = socket.host_and_port().ToString(); 238 std::string result = socket.host_and_port().ToString();
239 result.append("/"); 239 result.append("/");
240 result.append(socket.ssl_session_cache_shard()); 240 result.append(socket.ssl_session_cache_shard());
241 return result; 241 return result;
242 } 242 }
243 243
244 // Needed by crypto::ScopedOpenSSL to properly free the certificate chain.
245 static void FreeX509Stack(STACK_OF(X509)* cert_chain) {
haavardm 2014/03/17 11:20:33 Moved this out of PeerCertificateChain, is it gave
246 sk_X509_pop_free(cert_chain, X509_free);
247 }
248
244 } // namespace 249 } // namespace
245 250
246 class SSLClientSocketOpenSSL::SSLContext { 251 class SSLClientSocketOpenSSL::SSLContext {
247 public: 252 public:
248 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } 253 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
249 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } 254 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
250 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } 255 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; }
251 256
252 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { 257 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) {
253 DCHECK(ssl); 258 DCHECK(ssl);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 317
313 // This is the index used with SSL_get_ex_data to retrieve the owner 318 // This is the index used with SSL_get_ex_data to retrieve the owner
314 // SSLClientSocketOpenSSL object from an SSL instance. 319 // SSLClientSocketOpenSSL object from an SSL instance.
315 int ssl_socket_data_index_; 320 int ssl_socket_data_index_;
316 321
317 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; 322 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
318 // |session_cache_| must be destroyed before |ssl_ctx_|. 323 // |session_cache_| must be destroyed before |ssl_ctx_|.
319 SSLSessionCacheOpenSSL session_cache_; 324 SSLSessionCacheOpenSSL session_cache_;
320 }; 325 };
321 326
327 // PeerCertificateChain is a helper object which extracts the certificate
328 // chain, as given by the server, from an OpenSSL socket and performs the needed
329 // resource management. The first element of the chain is the leaf certificate
330 // and the other elements are in the order given by the server.
331 class SSLClientSocketOpenSSL::PeerCertificateChain {
332 public:
333 explicit PeerCertificateChain(SSL* ssl) { Reset(ssl); }
334 PeerCertificateChain(const PeerCertificateChain& other) { *this = other; }
335 ~PeerCertificateChain() {}
336 PeerCertificateChain& operator=(const PeerCertificateChain& other);
337
338 // Resets the PeerCertificateChain to the set of certificates supplied by the
339 // peer of |ssl|, which may be NULL, indicating to empty the store
340 // certificates. Note: If an error occurs, such as being unable to parse the
341 // certificates, this will behave as if Reset(NULL) was called.
342 void Reset(SSL* ssl);
343 // Note that when USE_OPENSSL is defined, OSCertHandle is X509*
344 const scoped_refptr<X509Certificate>& AsOSChain() const { return os_chain_; }
345
346 size_t size() const {
347 if (!openssl_chain_.get())
348 return 0;
349 return sk_X509_num(openssl_chain_.get());
350 }
351
352 X509* operator[](size_t index) const {
353 DCHECK_LT(index, size());
354 return sk_X509_value(openssl_chain_.get(), index);
355 }
356
357 private:
358 crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> openssl_chain_;
359
360 scoped_refptr<X509Certificate> os_chain_;
361 };
362
363 SSLClientSocketOpenSSL::PeerCertificateChain&
364 SSLClientSocketOpenSSL::PeerCertificateChain::operator=(
365 const PeerCertificateChain& other) {
366 if (this == &other)
367 return *this;
368
369 // os_chain_ is reference counted by scoped_refptr;
370 os_chain_ = other.os_chain_;
371
372 // Must increase the reference count manually for sk_X509_dup
373 openssl_chain_.reset(sk_X509_dup(other.openssl_chain_.get()));
374 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) {
375 X509* x = sk_X509_value(openssl_chain_.get(), i);
376 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
377 }
378 return *this;
379 }
380
381 #if defined(USE_OPENSSL)
382 // When OSCertHandle is typedef'ed to X509, this implementation does a short cut
383 // to avoid converting back and forth between der and X509 struct.
384 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) {
385 openssl_chain_.reset(NULL);
386 os_chain_ = NULL;
387
388 if (ssl == NULL)
389 return;
390
391 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
392 if (!chain)
393 return;
394
395 X509Certificate::OSCertHandles intermediates;
396 for (int i = 1; i < sk_X509_num(chain); ++i)
397 intermediates.push_back(sk_X509_value(chain, i));
398
399 os_chain_ =
400 X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates);
401
402 // sk_X509_dup does not increase reference count on the certs in the stack.
403 openssl_chain_.reset(sk_X509_dup(chain));
404
405 std::vector<base::StringPiece> der_chain;
406 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) {
407 X509* x = sk_X509_value(openssl_chain_.get(), i);
408 // Increase the reference count for the certs in openssl_chain_.
409 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
410 }
411 }
412 #else // !defined(USE_OPENSSL)
413 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) {
414 openssl_chain_.reset(NULL);
415 os_chain_ = NULL;
416
417 if (ssl == NULL)
418 return;
419
420 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
421 if (!chain)
422 return;
423
424 // sk_X509_dup does not increase reference count on the certs in the stack.
425 openssl_chain_.reset(sk_X509_dup(chain));
426
427 std::vector<base::StringPiece> der_chain;
428 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) {
429 X509* x = sk_X509_value(openssl_chain_.get(), i);
430
431 // Increase the reference count for the certs in openssl_chain_.
432 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
433
434 unsigned char* cert_data = NULL;
435 int cert_data_length = i2d_X509(x, &cert_data);
436 if (cert_data_length && cert_data)
437 der_chain.push_back(base::StringPiece(reinterpret_cast<char*>(cert_data),
438 cert_data_length));
439 }
440
441 os_chain_ = X509Certificate::CreateFromDERCertChain(der_chain);
442
443 for (size_t i = 0; i < der_chain.size(); ++i) {
444 OPENSSL_free(const_cast<char*>(der_chain[i].data()));
445 }
446
447 if (der_chain.size() !=
448 static_cast<size_t>(sk_X509_num(openssl_chain_.get()))) {
449 openssl_chain_.reset(NULL);
450 os_chain_ = NULL;
451 }
452 }
453 #endif // USE_OPENSSL
454
322 // static 455 // static
323 SSLSessionCacheOpenSSL::Config 456 SSLSessionCacheOpenSSL::Config
324 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { 457 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = {
325 &GetSessionCacheKey, // key_func 458 &GetSessionCacheKey, // key_func
326 1024, // max_entries 459 1024, // max_entries
327 256, // expiration_check_count 460 256, // expiration_check_count
328 60 * 60, // timeout_seconds 461 60 * 60, // timeout_seconds
329 }; 462 };
330 463
331 // static 464 // static
332 void SSLClientSocket::ClearSessionCache() { 465 void SSLClientSocket::ClearSessionCache() {
333 SSLClientSocketOpenSSL::SSLContext* context = 466 SSLClientSocketOpenSSL::SSLContext* context =
334 SSLClientSocketOpenSSL::SSLContext::GetInstance(); 467 SSLClientSocketOpenSSL::SSLContext::GetInstance();
335 context->session_cache()->Flush(); 468 context->session_cache()->Flush();
336 OpenSSLClientKeyStore::GetInstance()->Flush(); 469 OpenSSLClientKeyStore::GetInstance()->Flush();
337 } 470 }
338 471
339 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 472 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
340 scoped_ptr<ClientSocketHandle> transport_socket, 473 scoped_ptr<ClientSocketHandle> transport_socket,
341 const HostPortPair& host_and_port, 474 const HostPortPair& host_and_port,
342 const SSLConfig& ssl_config, 475 const SSLConfig& ssl_config,
343 const SSLClientSocketContext& context) 476 const SSLClientSocketContext& context)
344 : transport_send_busy_(false), 477 : transport_send_busy_(false),
345 transport_recv_busy_(false), 478 transport_recv_busy_(false),
346 transport_recv_eof_(false), 479 transport_recv_eof_(false),
347 weak_factory_(this), 480 weak_factory_(this),
348 pending_read_error_(kNoPendingReadResult), 481 pending_read_error_(kNoPendingReadResult),
349 transport_write_error_(OK), 482 transport_write_error_(OK),
483 server_cert_chain_(new PeerCertificateChain(NULL)),
350 completed_handshake_(false), 484 completed_handshake_(false),
351 client_auth_cert_needed_(false), 485 client_auth_cert_needed_(false),
352 cert_verifier_(context.cert_verifier), 486 cert_verifier_(context.cert_verifier),
353 server_bound_cert_service_(context.server_bound_cert_service), 487 server_bound_cert_service_(context.server_bound_cert_service),
354 ssl_(NULL), 488 ssl_(NULL),
355 transport_bio_(NULL), 489 transport_bio_(NULL),
356 transport_(transport_socket.Pass()), 490 transport_(transport_socket.Pass()),
357 host_and_port_(host_and_port), 491 host_and_port_(host_and_port),
358 ssl_config_(ssl_config), 492 ssl_config_(ssl_config),
359 ssl_session_cache_shard_(context.ssl_session_cache_shard), 493 ssl_session_cache_shard_(context.ssl_session_cache_shard),
360 trying_cached_session_(false), 494 trying_cached_session_(false),
361 next_handshake_state_(STATE_NONE), 495 next_handshake_state_(STATE_NONE),
362 npn_status_(kNextProtoUnsupported), 496 npn_status_(kNextProtoUnsupported),
363 channel_id_request_return_value_(ERR_UNEXPECTED), 497 channel_id_request_return_value_(ERR_UNEXPECTED),
364 channel_id_xtn_negotiated_(false), 498 channel_id_xtn_negotiated_(false),
365 net_log_(transport_->socket()->NetLog()) { 499 net_log_(transport_->socket()->NetLog()) {}
366 }
367 500
368 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { 501 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
369 Disconnect(); 502 Disconnect();
370 } 503 }
371 504
372 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( 505 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
373 SSLCertRequestInfo* cert_request_info) { 506 SSLCertRequestInfo* cert_request_info) {
374 cert_request_info->host_and_port = host_and_port_; 507 cert_request_info->host_and_port = host_and_port_;
375 cert_request_info->cert_authorities = cert_authorities_; 508 cert_request_info->cert_authorities = cert_authorities_;
376 } 509 }
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 1043
911 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { 1044 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
912 if (!user_connect_callback_.is_null()) { 1045 if (!user_connect_callback_.is_null()) {
913 CompletionCallback c = user_connect_callback_; 1046 CompletionCallback c = user_connect_callback_;
914 user_connect_callback_.Reset(); 1047 user_connect_callback_.Reset();
915 c.Run(rv > OK ? OK : rv); 1048 c.Run(rv > OK ? OK : rv);
916 } 1049 }
917 } 1050 }
918 1051
919 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { 1052 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
920 if (server_cert_.get()) 1053 server_cert_chain_->Reset(ssl_);
921 return server_cert_.get(); 1054 server_cert_ = server_cert_chain_->AsOSChain();
922
923 crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
924 if (!cert.get()) {
925 LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
926 return NULL;
927 }
928
929 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
930 // increment the reference so sk_X509_free does not need to be called.
931 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
932 X509Certificate::OSCertHandles intermediates;
933 if (chain) {
934 for (int i = 0; i < sk_X509_num(chain); ++i)
935 intermediates.push_back(sk_X509_value(chain, i));
936 }
937 server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates);
938 DCHECK(server_cert_.get());
939
940 return server_cert_.get(); 1055 return server_cert_.get();
941 } 1056 }
942 1057
943 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { 1058 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
944 int rv = DoHandshakeLoop(result); 1059 int rv = DoHandshakeLoop(result);
945 if (rv != ERR_IO_PENDING) { 1060 if (rv != ERR_IO_PENDING) {
946 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 1061 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
947 DoConnectCallback(rv); 1062 DoConnectCallback(rv);
948 } 1063 }
949 } 1064 }
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 *outlen = ssl_config_.next_protos[0].size(); 1532 *outlen = ssl_config_.next_protos[0].size();
1418 } 1533 }
1419 1534
1420 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); 1535 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
1421 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); 1536 server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
1422 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1537 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1423 #endif 1538 #endif
1424 return SSL_TLSEXT_ERR_OK; 1539 return SSL_TLSEXT_ERR_OK;
1425 } 1540 }
1426 1541
1542 scoped_refptr<X509Certificate>
1543 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1544 return server_cert_;
1545 }
1546
1427 } // namespace net 1547 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698