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 <errno.h> | 10 #include <errno.h> |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 #endif | 50 #endif |
51 | 51 |
52 // This constant can be any non-negative/non-zero value (eg: it does not | 52 // This constant can be any non-negative/non-zero value (eg: it does not |
53 // overlap with any value of the net::Error range, including net::OK). | 53 // overlap with any value of the net::Error range, including net::OK). |
54 const int kNoPendingReadResult = 1; | 54 const int kNoPendingReadResult = 1; |
55 | 55 |
56 // If a client doesn't have a list of protocols that it supports, but | 56 // If a client doesn't have a list of protocols that it supports, but |
57 // the server supports NPN, choosing "http/1.1" is the best answer. | 57 // the server supports NPN, choosing "http/1.1" is the best answer. |
58 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; | 58 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; |
59 | 59 |
60 void FreeX509Stack(STACK_OF(X509)* ptr) { | |
61 sk_X509_pop_free(ptr, X509_free); | |
62 } | |
63 | |
60 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509; | 64 typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509; |
65 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>::Type | |
66 ScopedX509Stack; | |
61 | 67 |
62 #if OPENSSL_VERSION_NUMBER < 0x1000103fL | 68 #if OPENSSL_VERSION_NUMBER < 0x1000103fL |
63 // This method doesn't seem to have made it into the OpenSSL headers. | 69 // This method doesn't seem to have made it into the OpenSSL headers. |
64 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } | 70 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } |
65 #endif | 71 #endif |
66 | 72 |
67 // Used for encoding the |connection_status| field of an SSLInfo object. | 73 // Used for encoding the |connection_status| field of an SSLInfo object. |
68 int EncodeSSLConnectionStatus(int cipher_suite, | 74 int EncodeSSLConnectionStatus(int cipher_suite, |
69 int compression, | 75 int compression, |
70 int version) { | 76 int version) { |
(...skipping 17 matching lines...) Expand all Loading... | |
88 return SSL_CONNECTION_VERSION_TLS1; | 94 return SSL_CONNECTION_VERSION_TLS1; |
89 case 0x0302: | 95 case 0x0302: |
90 return SSL_CONNECTION_VERSION_TLS1_1; | 96 return SSL_CONNECTION_VERSION_TLS1_1; |
91 case 0x0303: | 97 case 0x0303: |
92 return SSL_CONNECTION_VERSION_TLS1_2; | 98 return SSL_CONNECTION_VERSION_TLS1_2; |
93 default: | 99 default: |
94 return SSL_CONNECTION_VERSION_UNKNOWN; | 100 return SSL_CONNECTION_VERSION_UNKNOWN; |
95 } | 101 } |
96 } | 102 } |
97 | 103 |
98 void FreeX509Stack(STACK_OF(X509) * ptr) { | |
99 sk_X509_pop_free(ptr, X509_free); | |
100 } | |
101 | |
102 ScopedX509 OSCertHandleToOpenSSL( | 104 ScopedX509 OSCertHandleToOpenSSL( |
103 X509Certificate::OSCertHandle os_handle) { | 105 X509Certificate::OSCertHandle os_handle) { |
104 #if defined(USE_OPENSSL_CERTS) | 106 #if defined(USE_OPENSSL_CERTS) |
105 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); | 107 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); |
106 #else // !defined(USE_OPENSSL_CERTS) | 108 #else // !defined(USE_OPENSSL_CERTS) |
107 std::string der_encoded; | 109 std::string der_encoded; |
108 if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) | 110 if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) |
109 return ScopedX509(); | 111 return ScopedX509(); |
110 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); | 112 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); |
111 return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); | 113 return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); |
112 #endif // defined(USE_OPENSSL_CERTS) | 114 #endif // defined(USE_OPENSSL_CERTS) |
113 } | 115 } |
114 | 116 |
117 ScopedX509Stack OSCertHandlesToOpenSSL( | |
118 const X509Certificate::OSCertHandles& os_handles) { | |
119 ScopedX509Stack stack(sk_X509_new_null()); | |
120 for (size_t i = 0; i < os_handles.size(); i++) { | |
121 ScopedX509 x509 = OSCertHandleToOpenSSL(os_handles[i]); | |
122 if (!x509) | |
123 return ScopedX509Stack(); | |
124 sk_X509_push(stack.get(), x509.release()); | |
125 } | |
126 return stack.Pass(); | |
127 } | |
128 | |
115 } // namespace | 129 } // namespace |
116 | 130 |
117 class SSLClientSocketOpenSSL::SSLContext { | 131 class SSLClientSocketOpenSSL::SSLContext { |
118 public: | 132 public: |
119 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } | 133 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } |
120 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } | 134 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } |
121 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } | 135 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } |
122 | 136 |
123 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { | 137 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { |
124 DCHECK(ssl); | 138 DCHECK(ssl); |
(...skipping 10 matching lines...) Expand all Loading... | |
135 private: | 149 private: |
136 friend struct DefaultSingletonTraits<SSLContext>; | 150 friend struct DefaultSingletonTraits<SSLContext>; |
137 | 151 |
138 SSLContext() { | 152 SSLContext() { |
139 crypto::EnsureOpenSSLInit(); | 153 crypto::EnsureOpenSSLInit(); |
140 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 154 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
141 DCHECK_NE(ssl_socket_data_index_, -1); | 155 DCHECK_NE(ssl_socket_data_index_, -1); |
142 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 156 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
143 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); | 157 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); |
144 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); | 158 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); |
145 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 159 SSL_CTX_set_cert_cb(ssl_ctx_.get(), ClientCertRequestCallback, NULL); |
146 SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); | 160 SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); |
147 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. | 161 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. |
148 // It would be better if the callback were not a global setting, | 162 // It would be better if the callback were not a global setting, |
149 // but that is an OpenSSL issue. | 163 // but that is an OpenSSL issue. |
150 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, | 164 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, |
151 NULL); | 165 NULL); |
152 ssl_ctx_->tlsext_channel_id_enabled_new = 1; | 166 ssl_ctx_->tlsext_channel_id_enabled_new = 1; |
153 } | 167 } |
154 | 168 |
155 static std::string GetSessionCacheKey(const SSL* ssl) { | 169 static std::string GetSessionCacheKey(const SSL* ssl) { |
156 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 170 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
157 DCHECK(socket); | 171 DCHECK(socket); |
158 return socket->GetSessionCacheKey(); | 172 return socket->GetSessionCacheKey(); |
159 } | 173 } |
160 | 174 |
161 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; | 175 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; |
162 | 176 |
163 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 177 static int ClientCertRequestCallback(SSL* ssl, void* arg) { |
164 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 178 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
165 CHECK(socket); | 179 CHECK(socket); |
agl
2014/08/14 17:06:46
could probably be a DCHECK.
davidben
2014/08/14 17:50:07
Done. (*shrug* I suppose it'd crash immediately af
| |
166 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 180 return socket->ClientCertRequestCallback(ssl); |
167 } | 181 } |
168 | 182 |
169 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { | 183 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { |
170 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( | 184 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( |
171 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); | 185 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); |
172 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 186 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
173 CHECK(socket); | 187 CHECK(socket); |
174 | 188 |
175 return socket->CertVerifyCallback(store_ctx); | 189 return socket->CertVerifyCallback(store_ctx); |
176 } | 190 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 } | 233 } |
220 | 234 |
221 X509* operator[](size_t index) const { | 235 X509* operator[](size_t index) const { |
222 DCHECK_LT(index, size()); | 236 DCHECK_LT(index, size()); |
223 return sk_X509_value(openssl_chain_.get(), index); | 237 return sk_X509_value(openssl_chain_.get(), index); |
224 } | 238 } |
225 | 239 |
226 bool IsValid() { return os_chain_.get() && openssl_chain_.get(); } | 240 bool IsValid() { return os_chain_.get() && openssl_chain_.get(); } |
227 | 241 |
228 private: | 242 private: |
229 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>::Type | |
230 ScopedX509Stack; | |
231 | |
232 ScopedX509Stack openssl_chain_; | 243 ScopedX509Stack openssl_chain_; |
233 | 244 |
234 scoped_refptr<X509Certificate> os_chain_; | 245 scoped_refptr<X509Certificate> os_chain_; |
235 }; | 246 }; |
236 | 247 |
237 SSLClientSocketOpenSSL::PeerCertificateChain& | 248 SSLClientSocketOpenSSL::PeerCertificateChain& |
238 SSLClientSocketOpenSSL::PeerCertificateChain::operator=( | 249 SSLClientSocketOpenSSL::PeerCertificateChain::operator=( |
239 const PeerCertificateChain& other) { | 250 const PeerCertificateChain& other) { |
240 if (this == &other) | 251 if (this == &other) |
241 return *this; | 252 return *this; |
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1388 DCHECK(recv_buffer_.get()); | 1399 DCHECK(recv_buffer_.get()); |
1389 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); | 1400 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); |
1390 // A write into a memory BIO should always succeed. | 1401 // A write into a memory BIO should always succeed. |
1391 DCHECK_EQ(result, ret); | 1402 DCHECK_EQ(result, ret); |
1392 } | 1403 } |
1393 recv_buffer_ = NULL; | 1404 recv_buffer_ = NULL; |
1394 transport_recv_busy_ = false; | 1405 transport_recv_busy_ = false; |
1395 return result; | 1406 return result; |
1396 } | 1407 } |
1397 | 1408 |
1398 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, | 1409 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl) { |
1399 X509** x509, | |
1400 EVP_PKEY** pkey) { | |
1401 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; | 1410 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; |
1402 DCHECK(ssl == ssl_); | 1411 DCHECK(ssl == ssl_); |
1403 DCHECK(*x509 == NULL); | 1412 |
1404 DCHECK(*pkey == NULL); | 1413 // Clear any currently configured certificates. |
1414 SSL_certs_clear(ssl_); | |
1405 | 1415 |
1406 #if defined(OS_IOS) | 1416 #if defined(OS_IOS) |
1407 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954). | 1417 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954). |
1408 LOG(WARNING) << "Client auth is not supported"; | 1418 LOG(WARNING) << "Client auth is not supported"; |
1409 #else // !defined(OS_IOS) | 1419 #else // !defined(OS_IOS) |
1410 if (!ssl_config_.send_client_cert) { | 1420 if (!ssl_config_.send_client_cert) { |
1411 // First pass: we know that a client certificate is needed, but we do not | 1421 // First pass: we know that a client certificate is needed, but we do not |
1412 // have one at hand. | 1422 // have one at hand. |
1413 client_auth_cert_needed_ = true; | 1423 client_auth_cert_needed_ = true; |
1414 STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl); | 1424 STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl); |
(...skipping 13 matching lines...) Expand all Loading... | |
1428 for (size_t i = 0; i < num_client_cert_types; i++) { | 1438 for (size_t i = 0; i < num_client_cert_types; i++) { |
1429 cert_key_types_.push_back( | 1439 cert_key_types_.push_back( |
1430 static_cast<SSLClientCertType>(client_cert_types[i])); | 1440 static_cast<SSLClientCertType>(client_cert_types[i])); |
1431 } | 1441 } |
1432 | 1442 |
1433 return -1; // Suspends handshake. | 1443 return -1; // Suspends handshake. |
1434 } | 1444 } |
1435 | 1445 |
1436 // Second pass: a client certificate should have been selected. | 1446 // Second pass: a client certificate should have been selected. |
1437 if (ssl_config_.client_cert.get()) { | 1447 if (ssl_config_.client_cert.get()) { |
1438 // TODO(davidben): Configure OpenSSL to also send the intermediates. | |
1439 ScopedX509 leaf_x509 = | 1448 ScopedX509 leaf_x509 = |
1440 OSCertHandleToOpenSSL(ssl_config_.client_cert->os_cert_handle()); | 1449 OSCertHandleToOpenSSL(ssl_config_.client_cert->os_cert_handle()); |
1441 if (!leaf_x509) { | 1450 if (!leaf_x509) { |
1442 LOG(WARNING) << "Failed to import certificate"; | 1451 LOG(WARNING) << "Failed to import certificate"; |
1443 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); | 1452 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); |
1444 return -1; | 1453 return -1; |
1445 } | 1454 } |
1446 | 1455 |
1456 ScopedX509Stack chain = OSCertHandlesToOpenSSL( | |
1457 ssl_config_.client_cert->GetIntermediateCertificates()); | |
1458 if (!chain) { | |
1459 LOG(WARNING) << "Failed to import intermediate certificates"; | |
1460 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); | |
1461 return -1; | |
1462 } | |
1463 | |
1447 // TODO(davidben): With Linux client auth support, this should be | 1464 // TODO(davidben): With Linux client auth support, this should be |
1448 // conditioned on OS_ANDROID and then, with https://crbug.com/394131, | 1465 // conditioned on OS_ANDROID and then, with https://crbug.com/394131, |
1449 // removed altogether. OpenSSLClientKeyStore is mostly an artifact of the | 1466 // removed altogether. OpenSSLClientKeyStore is mostly an artifact of the |
1450 // net/ client auth API lacking a private key handle. | 1467 // net/ client auth API lacking a private key handle. |
1451 #if defined(USE_OPENSSL_CERTS) | 1468 #if defined(USE_OPENSSL_CERTS) |
1452 crypto::ScopedEVP_PKEY privkey = | 1469 crypto::ScopedEVP_PKEY privkey = |
1453 OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( | 1470 OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( |
1454 ssl_config_.client_cert.get()); | 1471 ssl_config_.client_cert.get()); |
1455 #else // !defined(USE_OPENSSL_CERTS) | 1472 #else // !defined(USE_OPENSSL_CERTS) |
1456 crypto::ScopedEVP_PKEY privkey = | 1473 crypto::ScopedEVP_PKEY privkey = |
1457 FetchClientCertPrivateKey(ssl_config_.client_cert.get()); | 1474 FetchClientCertPrivateKey(ssl_config_.client_cert.get()); |
1458 #endif // defined(USE_OPENSSL_CERTS) | 1475 #endif // defined(USE_OPENSSL_CERTS) |
1459 if (!privkey) { | 1476 if (!privkey) { |
1460 // Could not find the private key. Fail the handshake and surface an | 1477 // Could not find the private key. Fail the handshake and surface an |
1461 // appropriate error to the caller. | 1478 // appropriate error to the caller. |
1462 LOG(WARNING) << "Client cert found without private key"; | 1479 LOG(WARNING) << "Client cert found without private key"; |
1463 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY); | 1480 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY); |
1464 return -1; | 1481 return -1; |
1465 } | 1482 } |
1466 | 1483 |
1467 // TODO(joth): (copied from NSS) We should wait for server certificate | 1484 if (!SSL_use_certificate(ssl_, leaf_x509.get()) || |
1468 // verification before sending our credentials. See http://crbug.com/13934 | 1485 !SSL_use_PrivateKey(ssl_, privkey.get()) || |
1469 *x509 = leaf_x509.release(); | 1486 !SSL_set1_chain(ssl_, chain.get())) { |
1470 *pkey = privkey.release(); | 1487 LOG(WARNING) << "Failed to set client certificate"; |
1488 return -1; | |
1489 } | |
1471 return 1; | 1490 return 1; |
1472 } | 1491 } |
1473 #endif // defined(OS_IOS) | 1492 #endif // defined(OS_IOS) |
1474 | 1493 |
1475 // Send no client certificate. | 1494 // Send no client certificate. |
1476 return 0; | 1495 return 1; |
1477 } | 1496 } |
1478 | 1497 |
1479 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { | 1498 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { |
1480 if (!completed_handshake_) { | 1499 if (!completed_handshake_) { |
1481 // If the first handshake hasn't completed then we accept any certificates | 1500 // If the first handshake hasn't completed then we accept any certificates |
1482 // because we verify after the handshake. | 1501 // because we verify after the handshake. |
1483 return 1; | 1502 return 1; |
1484 } | 1503 } |
1485 | 1504 |
1486 CHECK(server_cert_.get()); | 1505 CHECK(server_cert_.get()); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1589 return socket->MaybeReplayTransportError( | 1608 return socket->MaybeReplayTransportError( |
1590 bio, cmd, argp, argi, argl, retvalue); | 1609 bio, cmd, argp, argi, argl, retvalue); |
1591 } | 1610 } |
1592 | 1611 |
1593 scoped_refptr<X509Certificate> | 1612 scoped_refptr<X509Certificate> |
1594 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1613 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
1595 return server_cert_; | 1614 return server_cert_; |
1596 } | 1615 } |
1597 | 1616 |
1598 } // namespace net | 1617 } // namespace net |
OLD | NEW |