| 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 #include "net/socket/ssl_client_socket.h" | 5 #include "net/socket/ssl_client_socket.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <openssl/bio.h> | 10 #include <openssl/bio.h> |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 namespace net { | 48 namespace net { |
| 49 | 49 |
| 50 namespace { | 50 namespace { |
| 51 | 51 |
| 52 // These client auth tests are currently dependent on OpenSSL's struct X509. | 52 // These client auth tests are currently dependent on OpenSSL's struct X509. |
| 53 #if defined(USE_OPENSSL_CERTS) | 53 #if defined(USE_OPENSSL_CERTS) |
| 54 typedef OpenSSLClientKeyStore::ScopedEVP_PKEY ScopedEVP_PKEY; | 54 typedef OpenSSLClientKeyStore::ScopedEVP_PKEY ScopedEVP_PKEY; |
| 55 | 55 |
| 56 // BIO_free is a macro, it can't be used as a template parameter. | 56 // BIO_free is a macro, it can't be used as a template parameter. |
| 57 void BIO_free_func(BIO* bio) { | 57 void BIO_free_func(BIO* bio) { |
| 58 BIO_free(bio); | 58 BIO_free(bio); |
| 59 } | 59 } |
| 60 | 60 |
| 61 typedef crypto::ScopedOpenSSL<BIO, BIO_free_func> ScopedBIO; | 61 typedef crypto::ScopedOpenSSL<BIO, BIO_free_func> ScopedBIO; |
| 62 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA; | 62 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA; |
| 63 typedef crypto::ScopedOpenSSL<BIGNUM, BN_free> ScopedBIGNUM; | 63 typedef crypto::ScopedOpenSSL<BIGNUM, BN_free> ScopedBIGNUM; |
| 64 | 64 |
| 65 const SSLConfig kDefaultSSLConfig; | 65 const SSLConfig kDefaultSSLConfig; |
| 66 | 66 |
| 67 // A ServerBoundCertStore that always returns an error when asked for a | 67 // A ServerBoundCertStore that always returns an error when asked for a |
| 68 // certificate. | 68 // certificate. |
| 69 class FailingServerBoundCertStore : public ServerBoundCertStore { | 69 class FailingServerBoundCertStore : public ServerBoundCertStore { |
| 70 virtual int GetServerBoundCert(const std::string& server_identifier, | 70 virtual int GetServerBoundCert(const std::string& server_identifier, |
| 71 base::Time* expiration_time, | 71 base::Time* expiration_time, |
| 72 std::string* private_key_result, | 72 std::string* private_key_result, |
| 73 std::string* cert_result, | 73 std::string* cert_result, |
| 74 const GetCertCallback& callback) OVERRIDE { | 74 const GetCertCallback& callback) OVERRIDE { |
| 75 return ERR_UNEXPECTED; | 75 return ERR_UNEXPECTED; |
| 76 } | 76 } |
| 77 virtual void SetServerBoundCert(const std::string& server_identifier, | 77 virtual void SetServerBoundCert(const std::string& server_identifier, |
| 78 base::Time creation_time, | 78 base::Time creation_time, |
| 79 base::Time expiration_time, | 79 base::Time expiration_time, |
| 80 const std::string& private_key, | 80 const std::string& private_key, |
| 81 const std::string& cert) OVERRIDE {} | 81 const std::string& cert) OVERRIDE {} |
| 82 virtual void DeleteServerBoundCert(const std::string& server_identifier, | 82 virtual void DeleteServerBoundCert( |
| 83 const base::Closure& completion_callback) | 83 const std::string& server_identifier, |
| 84 OVERRIDE {} | 84 const base::Closure& completion_callback) OVERRIDE {} |
| 85 virtual void DeleteAllCreatedBetween(base::Time delete_begin, | 85 virtual void DeleteAllCreatedBetween( |
| 86 base::Time delete_end, | 86 base::Time delete_begin, |
| 87 const base::Closure& completion_callback) | 87 base::Time delete_end, |
| 88 OVERRIDE {} | 88 const base::Closure& completion_callback) OVERRIDE {} |
| 89 virtual void DeleteAll(const base::Closure& completion_callback) OVERRIDE {} | 89 virtual void DeleteAll(const base::Closure& completion_callback) OVERRIDE {} |
| 90 virtual void GetAllServerBoundCerts(const GetCertListCallback& callback) | 90 virtual void GetAllServerBoundCerts( |
| 91 OVERRIDE {} | 91 const GetCertListCallback& callback) OVERRIDE {} |
| 92 virtual int GetCertCount() OVERRIDE { return 0; } | 92 virtual int GetCertCount() OVERRIDE { return 0; } |
| 93 virtual void SetForceKeepSessionState() OVERRIDE {} | 93 virtual void SetForceKeepSessionState() OVERRIDE {} |
| 94 }; | 94 }; |
| 95 | 95 |
| 96 // Loads a PEM-encoded private key file into a scoped EVP_PKEY object. | 96 // Loads a PEM-encoded private key file into a scoped EVP_PKEY object. |
| 97 // |filepath| is the private key file path. | 97 // |filepath| is the private key file path. |
| 98 // |*pkey| is reset to the new EVP_PKEY on success, untouched otherwise. | 98 // |*pkey| is reset to the new EVP_PKEY on success, untouched otherwise. |
| 99 // Returns true on success, false on failure. | 99 // Returns true on success, false on failure. |
| 100 bool LoadPrivateKeyOpenSSL( | 100 bool LoadPrivateKeyOpenSSL(const base::FilePath& filepath, |
| 101 const base::FilePath& filepath, | 101 OpenSSLClientKeyStore::ScopedEVP_PKEY* pkey) { |
| 102 OpenSSLClientKeyStore::ScopedEVP_PKEY* pkey) { | |
| 103 std::string data; | 102 std::string data; |
| 104 if (!base::ReadFileToString(filepath, &data)) { | 103 if (!base::ReadFileToString(filepath, &data)) { |
| 105 LOG(ERROR) << "Could not read private key file: " | 104 LOG(ERROR) << "Could not read private key file: " << filepath.value() |
| 106 << filepath.value() << ": " << strerror(errno); | 105 << ": " << strerror(errno); |
| 107 return false; | 106 return false; |
| 108 } | 107 } |
| 109 ScopedBIO bio( | 108 ScopedBIO bio(BIO_new_mem_buf( |
| 110 BIO_new_mem_buf( | 109 const_cast<char*>(reinterpret_cast<const char*>(data.data())), |
| 111 const_cast<char*>(reinterpret_cast<const char*>(data.data())), | 110 static_cast<int>(data.size()))); |
| 112 static_cast<int>(data.size()))); | |
| 113 if (!bio.get()) { | 111 if (!bio.get()) { |
| 114 LOG(ERROR) << "Could not allocate BIO for buffer?"; | 112 LOG(ERROR) << "Could not allocate BIO for buffer?"; |
| 115 return false; | 113 return false; |
| 116 } | 114 } |
| 117 EVP_PKEY* result = PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL); | 115 EVP_PKEY* result = PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL); |
| 118 if (result == NULL) { | 116 if (result == NULL) { |
| 119 LOG(ERROR) << "Could not decode private key file: " | 117 LOG(ERROR) << "Could not decode private key file: " << filepath.value(); |
| 120 << filepath.value(); | |
| 121 return false; | 118 return false; |
| 122 } | 119 } |
| 123 pkey->reset(result); | 120 pkey->reset(result); |
| 124 return true; | 121 return true; |
| 125 } | 122 } |
| 126 | 123 |
| 127 class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest { | 124 class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest { |
| 128 public: | 125 public: |
| 129 SSLClientSocketOpenSSLClientAuthTest() | 126 SSLClientSocketOpenSSLClientAuthTest() |
| 130 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()), | 127 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()), |
| 131 cert_verifier_(new net::MockCertVerifier), | 128 cert_verifier_(new net::MockCertVerifier), |
| 132 transport_security_state_(new net::TransportSecurityState) { | 129 transport_security_state_(new net::TransportSecurityState) { |
| 133 cert_verifier_->set_default_result(net::OK); | 130 cert_verifier_->set_default_result(net::OK); |
| 134 context_.cert_verifier = cert_verifier_.get(); | 131 context_.cert_verifier = cert_verifier_.get(); |
| 135 context_.transport_security_state = transport_security_state_.get(); | 132 context_.transport_security_state = transport_security_state_.get(); |
| 136 key_store_ = net::OpenSSLClientKeyStore::GetInstance(); | 133 key_store_ = net::OpenSSLClientKeyStore::GetInstance(); |
| 137 } | 134 } |
| 138 | 135 |
| 139 virtual ~SSLClientSocketOpenSSLClientAuthTest() { | 136 virtual ~SSLClientSocketOpenSSLClientAuthTest() { key_store_->Flush(); } |
| 140 key_store_->Flush(); | |
| 141 } | |
| 142 | 137 |
| 143 protected: | 138 protected: |
| 144 void EnabledChannelID() { | 139 void EnabledChannelID() { |
| 145 cert_service_.reset( | 140 cert_service_.reset( |
| 146 new ServerBoundCertService(new DefaultServerBoundCertStore(NULL), | 141 new ServerBoundCertService(new DefaultServerBoundCertStore(NULL), |
| 147 base::MessageLoopProxy::current())); | 142 base::MessageLoopProxy::current())); |
| 148 context_.server_bound_cert_service = cert_service_.get(); | 143 context_.server_bound_cert_service = cert_service_.get(); |
| 149 } | 144 } |
| 150 | 145 |
| 151 void EnabledFailingChannelID() { | 146 void EnabledFailingChannelID() { |
| 152 cert_service_.reset( | 147 cert_service_.reset(new ServerBoundCertService( |
| 153 new ServerBoundCertService(new FailingServerBoundCertStore(), | 148 new FailingServerBoundCertStore(), base::MessageLoopProxy::current())); |
| 154 base::MessageLoopProxy::current())); | |
| 155 context_.server_bound_cert_service = cert_service_.get(); | 149 context_.server_bound_cert_service = cert_service_.get(); |
| 156 } | 150 } |
| 157 | 151 |
| 158 scoped_ptr<SSLClientSocket> CreateSSLClientSocket( | 152 scoped_ptr<SSLClientSocket> CreateSSLClientSocket( |
| 159 scoped_ptr<StreamSocket> transport_socket, | 153 scoped_ptr<StreamSocket> transport_socket, |
| 160 const HostPortPair& host_and_port, | 154 const HostPortPair& host_and_port, |
| 161 const SSLConfig& ssl_config) { | 155 const SSLConfig& ssl_config) { |
| 162 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); | 156 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); |
| 163 connection->SetSocket(transport_socket.Pass()); | 157 connection->SetSocket(transport_socket.Pass()); |
| 164 return socket_factory_->CreateSSLClientSocket(connection.Pass(), | 158 return socket_factory_->CreateSSLClientSocket( |
| 165 host_and_port, | 159 connection.Pass(), host_and_port, ssl_config, context_); |
| 166 ssl_config, | |
| 167 context_); | |
| 168 } | 160 } |
| 169 | 161 |
| 170 // Connect to a HTTPS test server. | 162 // Connect to a HTTPS test server. |
| 171 bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) { | 163 bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) { |
| 172 test_server_.reset(new SpawnedTestServer(SpawnedTestServer::TYPE_HTTPS, | 164 test_server_.reset(new SpawnedTestServer( |
| 173 ssl_options, | 165 SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath())); |
| 174 base::FilePath())); | |
| 175 if (!test_server_->Start()) { | 166 if (!test_server_->Start()) { |
| 176 LOG(ERROR) << "Could not start SpawnedTestServer"; | 167 LOG(ERROR) << "Could not start SpawnedTestServer"; |
| 177 return false; | 168 return false; |
| 178 } | 169 } |
| 179 | 170 |
| 180 if (!test_server_->GetAddressList(&addr_)) { | 171 if (!test_server_->GetAddressList(&addr_)) { |
| 181 LOG(ERROR) << "Could not get SpawnedTestServer address list"; | 172 LOG(ERROR) << "Could not get SpawnedTestServer address list"; |
| 182 return false; | 173 return false; |
| 183 } | 174 } |
| 184 | 175 |
| 185 transport_.reset(new TCPClientSocket( | 176 transport_.reset(new TCPClientSocket(addr_, &log_, NetLog::Source())); |
| 186 addr_, &log_, NetLog::Source())); | 177 int rv = callback_.GetResult(transport_->Connect(callback_.callback())); |
| 187 int rv = callback_.GetResult( | |
| 188 transport_->Connect(callback_.callback())); | |
| 189 if (rv != OK) { | 178 if (rv != OK) { |
| 190 LOG(ERROR) << "Could not connect to SpawnedTestServer"; | 179 LOG(ERROR) << "Could not connect to SpawnedTestServer"; |
| 191 return false; | 180 return false; |
| 192 } | 181 } |
| 193 return true; | 182 return true; |
| 194 } | 183 } |
| 195 | 184 |
| 196 // Record a certificate's private key to ensure it can be used | 185 // Record a certificate's private key to ensure it can be used |
| 197 // by the OpenSSL-based SSLClientSocket implementation. | 186 // by the OpenSSL-based SSLClientSocket implementation. |
| 198 // |ssl_config| provides a client certificate. | 187 // |ssl_config| provides a client certificate. |
| 199 // |private_key| must be an EVP_PKEY for the corresponding private key. | 188 // |private_key| must be an EVP_PKEY for the corresponding private key. |
| 200 // Returns true on success, false on failure. | 189 // Returns true on success, false on failure. |
| 201 bool RecordPrivateKey(SSLConfig& ssl_config, | 190 bool RecordPrivateKey(SSLConfig& ssl_config, EVP_PKEY* private_key) { |
| 202 EVP_PKEY* private_key) { | 191 return key_store_->RecordClientCertPrivateKey(ssl_config.client_cert.get(), |
| 203 return key_store_->RecordClientCertPrivateKey( | 192 private_key); |
| 204 ssl_config.client_cert.get(), private_key); | |
| 205 } | 193 } |
| 206 | 194 |
| 207 // Create an SSLClientSocket object and use it to connect to a test | 195 // Create an SSLClientSocket object and use it to connect to a test |
| 208 // server, then wait for connection results. This must be called after | 196 // server, then wait for connection results. This must be called after |
| 209 // a succesful ConnectToTestServer() call. | 197 // a succesful ConnectToTestServer() call. |
| 210 // |ssl_config| the SSL configuration to use. | 198 // |ssl_config| the SSL configuration to use. |
| 211 // |result| will retrieve the ::Connect() result value. | 199 // |result| will retrieve the ::Connect() result value. |
| 212 // Returns true on succes, false otherwise. Success means that the socket | 200 // Returns true on succes, false otherwise. Success means that the socket |
| 213 // could be created and its Connect() was called, not that the connection | 201 // could be created and its Connect() was called, not that the connection |
| 214 // itself was a success. | 202 // itself was a success. |
| 215 bool CreateAndConnectSSLClientSocket(SSLConfig& ssl_config, | 203 bool CreateAndConnectSSLClientSocket(SSLConfig& ssl_config, int* result) { |
| 216 int* result) { | 204 sock_ = CreateSSLClientSocket( |
| 217 sock_ = CreateSSLClientSocket(transport_.Pass(), | 205 transport_.Pass(), test_server_->host_port_pair(), ssl_config); |
| 218 test_server_->host_port_pair(), | |
| 219 ssl_config); | |
| 220 | 206 |
| 221 if (sock_->IsConnected()) { | 207 if (sock_->IsConnected()) { |
| 222 LOG(ERROR) << "SSL Socket prematurely connected"; | 208 LOG(ERROR) << "SSL Socket prematurely connected"; |
| 223 return false; | 209 return false; |
| 224 } | 210 } |
| 225 | 211 |
| 226 *result = callback_.GetResult(sock_->Connect(callback_.callback())); | 212 *result = callback_.GetResult(sock_->Connect(callback_.callback())); |
| 227 return true; | 213 return true; |
| 228 } | 214 } |
| 229 | 215 |
| 230 | |
| 231 // Check that the client certificate was sent. | 216 // Check that the client certificate was sent. |
| 232 // Returns true on success. | 217 // Returns true on success. |
| 233 bool CheckSSLClientSocketSentCert() { | 218 bool CheckSSLClientSocketSentCert() { |
| 234 SSLInfo ssl_info; | 219 SSLInfo ssl_info; |
| 235 sock_->GetSSLInfo(&ssl_info); | 220 sock_->GetSSLInfo(&ssl_info); |
| 236 return ssl_info.client_cert_sent; | 221 return ssl_info.client_cert_sent; |
| 237 } | 222 } |
| 238 | 223 |
| 239 scoped_ptr<ServerBoundCertService> cert_service_; | 224 scoped_ptr<ServerBoundCertService> cert_service_; |
| 240 ClientSocketFactory* socket_factory_; | 225 ClientSocketFactory* socket_factory_; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 int rv; | 344 int rv; |
| 360 ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); | 345 ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); |
| 361 | 346 |
| 362 EXPECT_EQ(ERR_UNEXPECTED, rv); | 347 EXPECT_EQ(ERR_UNEXPECTED, rv); |
| 363 EXPECT_FALSE(sock_->IsConnected()); | 348 EXPECT_FALSE(sock_->IsConnected()); |
| 364 } | 349 } |
| 365 #endif // defined(USE_OPENSSL_CERTS) | 350 #endif // defined(USE_OPENSSL_CERTS) |
| 366 | 351 |
| 367 } // namespace | 352 } // namespace |
| 368 } // namespace net | 353 } // namespace net |
| OLD | NEW |