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

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: Fixes after review comments 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') | no next file » | 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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 312
313 // This is the index used with SSL_get_ex_data to retrieve the owner 313 // This is the index used with SSL_get_ex_data to retrieve the owner
314 // SSLClientSocketOpenSSL object from an SSL instance. 314 // SSLClientSocketOpenSSL object from an SSL instance.
315 int ssl_socket_data_index_; 315 int ssl_socket_data_index_;
316 316
317 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; 317 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
318 // |session_cache_| must be destroyed before |ssl_ctx_|. 318 // |session_cache_| must be destroyed before |ssl_ctx_|.
319 SSLSessionCacheOpenSSL session_cache_; 319 SSLSessionCacheOpenSSL session_cache_;
320 }; 320 };
321 321
322 // PeerCertificateChain is a helper object which extracts the certificate
323 // chain, as given by the server, from an OpenSSL socket and performs the needed
324 // resource management. The first element of the chain is the leaf certificate
325 // and the other elements are in the order given by the server.
326 class SSLClientSocketOpenSSL::PeerCertificateChain {
327 public:
328 virtual ~PeerCertificateChain() {};
329
330 // Resets the current chain, freeing any resources, and updates the current
331 // chain to be a referenced copy of the chain stored in |ssl|.
332 // If |ssl| is NULL, then the current certificate chain will be freed.
333 void Reset(SSL* ssl) {
334 x509_certs_.clear();
335 der_certs_chain_.clear();
336 der_certs_mem_handler_.clear();
337
338 if (ssl == NULL)
339 return;
340
341 STACK_OF(X509)* intermediates = SSL_get_peer_cert_chain(ssl);
342 if (intermediates) {
343 for (int i = 0; i < sk_X509_num(intermediates); ++i) {
344 if (!AddCert(sk_X509_value(intermediates, i))) {
345 Reset(NULL);
346 return;
347 }
348 }
349 }
350 }
351
352 // Returns the current certificate chain as a vector of DER-encoded
353 // base::StringPieces. The returned vector remains valid until Reset is
354 // called.
355 std::vector<base::StringPiece> AsStringPieceVector() const {
356 return der_certs_chain_;
357 }
358
359 bool empty() const { return x509_certs_.empty(); }
360 size_t size() const { return x509_certs_.size(); }
361
362 X509* operator[](size_t index) const {
363 DCHECK_LT(index, x509_certs_.size());
364 return x509_certs_[index].get();
365 }
366
367 private:
368 struct OpenSSLFreeDeleter {
369 inline void operator()(void* ptr) const { OPENSSL_free(ptr); }
370 };
371
372 struct X509Deleter {
373 inline void operator()(X509* ptr) const { X509_free(ptr); }
374 };
375
376 typedef scoped_ptr<unsigned char, OpenSSLFreeDeleter> ScopedOpenSSLArray;
377 typedef scoped_ptr<X509, X509Deleter> ScopedX509;
378
379 bool AddCert(X509* cert) {
380 unsigned char* cert_data = NULL;
381 int cert_data_length = i2d_X509(cert, &cert_data);
382 if (cert_data_length <= 0 || !cert_data)
383 return false;
384
385 der_certs_mem_handler_.push_back(ScopedOpenSSLArray(cert_data));
386 der_certs_chain_.push_back(base::StringPiece(
387 reinterpret_cast<char*>(cert_data), cert_data_length));
388
389 x509_certs_.push_back(ScopedX509(cert));
390 // Increase reference count for cert
391 CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
392
393 return true;
394 }
395
396 std::vector<base::StringPiece> der_certs_chain_;
397
398 // Make sure the DER data strings are free'd with OPENSSL_free
399 std::vector<PeerCertificateChain::ScopedOpenSSLArray> der_certs_mem_handler_;
400
401 std::vector<ScopedX509> x509_certs_;
Ryan Sleevi 2014/02/25 20:27:09 Storing a vector of ScopedX509 doesn't work before
haavardm 2014/02/25 20:53:52 Seems good. I guess I got a little too focused on
haavardm 2014/03/11 18:43:20 Done.
402 };
403
322 // static 404 // static
323 SSLSessionCacheOpenSSL::Config 405 SSLSessionCacheOpenSSL::Config
324 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { 406 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = {
325 &GetSessionCacheKey, // key_func 407 &GetSessionCacheKey, // key_func
326 1024, // max_entries 408 1024, // max_entries
327 256, // expiration_check_count 409 256, // expiration_check_count
328 60 * 60, // timeout_seconds 410 60 * 60, // timeout_seconds
329 }; 411 };
330 412
331 // static 413 // static
332 void SSLClientSocket::ClearSessionCache() { 414 void SSLClientSocket::ClearSessionCache() {
333 SSLClientSocketOpenSSL::SSLContext* context = 415 SSLClientSocketOpenSSL::SSLContext* context =
334 SSLClientSocketOpenSSL::SSLContext::GetInstance(); 416 SSLClientSocketOpenSSL::SSLContext::GetInstance();
335 context->session_cache()->Flush(); 417 context->session_cache()->Flush();
336 OpenSSLClientKeyStore::GetInstance()->Flush(); 418 OpenSSLClientKeyStore::GetInstance()->Flush();
337 } 419 }
338 420
339 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 421 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
340 scoped_ptr<ClientSocketHandle> transport_socket, 422 scoped_ptr<ClientSocketHandle> transport_socket,
341 const HostPortPair& host_and_port, 423 const HostPortPair& host_and_port,
342 const SSLConfig& ssl_config, 424 const SSLConfig& ssl_config,
343 const SSLClientSocketContext& context) 425 const SSLClientSocketContext& context)
344 : transport_send_busy_(false), 426 : transport_send_busy_(false),
345 transport_recv_busy_(false), 427 transport_recv_busy_(false),
346 transport_recv_eof_(false), 428 transport_recv_eof_(false),
347 weak_factory_(this), 429 weak_factory_(this),
348 pending_read_error_(kNoPendingReadResult), 430 pending_read_error_(kNoPendingReadResult),
349 transport_write_error_(OK), 431 transport_write_error_(OK),
432 server_cert_chain_(new PeerCertificateChain()),
433 server_cert_(NULL),
350 completed_handshake_(false), 434 completed_handshake_(false),
351 client_auth_cert_needed_(false), 435 client_auth_cert_needed_(false),
352 cert_verifier_(context.cert_verifier), 436 cert_verifier_(context.cert_verifier),
353 server_bound_cert_service_(context.server_bound_cert_service), 437 server_bound_cert_service_(context.server_bound_cert_service),
354 ssl_(NULL), 438 ssl_(NULL),
355 transport_bio_(NULL), 439 transport_bio_(NULL),
356 transport_(transport_socket.Pass()), 440 transport_(transport_socket.Pass()),
357 host_and_port_(host_and_port), 441 host_and_port_(host_and_port),
358 ssl_config_(ssl_config), 442 ssl_config_(ssl_config),
359 ssl_session_cache_shard_(context.ssl_session_cache_shard), 443 ssl_session_cache_shard_(context.ssl_session_cache_shard),
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 994
911 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { 995 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
912 if (!user_connect_callback_.is_null()) { 996 if (!user_connect_callback_.is_null()) {
913 CompletionCallback c = user_connect_callback_; 997 CompletionCallback c = user_connect_callback_;
914 user_connect_callback_.Reset(); 998 user_connect_callback_.Reset();
915 c.Run(rv > OK ? OK : rv); 999 c.Run(rv > OK ? OK : rv);
916 } 1000 }
917 } 1001 }
918 1002
919 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { 1003 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
920 if (server_cert_.get()) 1004 #ifdef USE_OPENSSL
921 return server_cert_.get();
922
923 crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
haavardm 2014/02/25 19:37:37 I removed this, as it seems that server certificat
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 1005 // 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. 1006 // increment the reference so sk_X509_free does not need to be called.
931 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); 1007 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
932 X509Certificate::OSCertHandles intermediates; 1008 X509Certificate::OSCertHandles intermediates;
933 if (chain) { 1009 if (chain) {
934 for (int i = 0; i < sk_X509_num(chain); ++i) 1010 for (int i = 1; i < sk_X509_num(chain); ++i)
935 intermediates.push_back(sk_X509_value(chain, i)); 1011 intermediates.push_back(sk_X509_value(chain, i));
936 } 1012 }
937 server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates); 1013 server_cert_ =
938 DCHECK(server_cert_.get()); 1014 X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates);
Ryan Sleevi 2014/02/25 20:27:09 if |chain| is false, or sk_X509_num(chain) is 0, t
haavardm 2014/03/11 18:43:20 Done.
1015 #else
1016 server_cert_chain_->Reset(ssl_);
1017 server_cert_ = X509Certificate::CreateFromDERCertChain(
1018 server_cert_chain_->AsStringPieceVector());
1019 #endif
939 1020
940 return server_cert_.get(); 1021 return server_cert_.get();
941 } 1022 }
942 1023
943 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { 1024 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
944 int rv = DoHandshakeLoop(result); 1025 int rv = DoHandshakeLoop(result);
945 if (rv != ERR_IO_PENDING) { 1026 if (rv != ERR_IO_PENDING) {
946 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 1027 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
947 DoConnectCallback(rv); 1028 DoConnectCallback(rv);
948 } 1029 }
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 } 1499 }
1419 1500
1420 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); 1501 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
1421 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); 1502 server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
1422 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1503 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1423 #endif 1504 #endif
1424 return SSL_TLSEXT_ERR_OK; 1505 return SSL_TLSEXT_ERR_OK;
1425 } 1506 }
1426 1507
1427 } // namespace net 1508 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698