Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/ssl.h> | 10 #include <openssl/ssl.h> |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 168 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
| 169 DCHECK_NE(ssl_socket_data_index_, -1); | 169 DCHECK_NE(ssl_socket_data_index_, -1); |
| 170 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 170 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
| 171 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 171 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); |
| 172 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); | 172 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); |
| 173 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | 173 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); |
| 174 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | 174 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); |
| 175 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | 175 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); |
| 176 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | 176 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); |
| 177 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 177 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
| 178 #if defined(OPENSSL_NPN_NEGOTIATED) | |
| 179 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. | |
| 180 // It would be better if the callback were not a global setting, | |
| 181 // but that is an OpenSSL issue. | |
| 182 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, | |
| 183 NULL); | |
| 184 #endif | |
| 178 } | 185 } |
| 179 | 186 |
| 180 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { | 187 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { |
| 181 return Get()->NewSessionCallback(ssl, session); | 188 return Get()->NewSessionCallback(ssl, session); |
| 182 } | 189 } |
| 183 | 190 |
| 184 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { | 191 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { |
| 185 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); | 192 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); |
| 186 session_cache_.OnSessionAdded(socket->host_and_port(), session); | 193 session_cache_.OnSessionAdded(socket->host_and_port(), session); |
| 187 return 1; // 1 => We took ownership of |session|. | 194 return 1; // 1 => We took ownership of |session|. |
| 188 } | 195 } |
| 189 | 196 |
| 190 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { | 197 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { |
| 191 return Get()->RemoveSessionCallback(ctx, session); | 198 return Get()->RemoveSessionCallback(ctx, session); |
| 192 } | 199 } |
| 193 | 200 |
| 194 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { | 201 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { |
| 195 DCHECK(ctx == ssl_ctx()); | 202 DCHECK(ctx == ssl_ctx()); |
| 196 session_cache_.OnSessionRemoved(session); | 203 session_cache_.OnSessionRemoved(session); |
| 197 } | 204 } |
| 198 | 205 |
| 199 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 206 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
| 200 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); | 207 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
| 201 CHECK(socket); | 208 CHECK(socket); |
| 202 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 209 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
| 203 } | 210 } |
| 204 | 211 |
| 212 static int SelectNextProtoCallback(SSL* ssl, | |
| 213 unsigned char** out, unsigned char* outlen, | |
| 214 const unsigned char* in, | |
| 215 unsigned int inlen, void* arg) { | |
| 216 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); | |
| 217 return socket->SelectNextProtoCallback(out, outlen, in, inlen); | |
| 218 } | |
| 219 | |
| 205 // This is the index used with SSL_get_ex_data to retrieve the owner | 220 // This is the index used with SSL_get_ex_data to retrieve the owner |
| 206 // SSLClientSocketOpenSSL object from an SSL instance. | 221 // SSLClientSocketOpenSSL object from an SSL instance. |
| 207 int ssl_socket_data_index_; | 222 int ssl_socket_data_index_; |
| 208 | 223 |
| 209 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 224 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
| 210 SSLSessionCache session_cache_; | 225 SSLSessionCache session_cache_; |
| 211 }; | 226 }; |
| 212 | 227 |
| 213 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 228 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
| 214 // options and mode configuration functions. (SSL_set_options etc) | 229 // options and mode configuration functions. (SSL_set_options etc) |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 241 completed_handshake_(false), | 256 completed_handshake_(false), |
| 242 client_auth_cert_needed_(false), | 257 client_auth_cert_needed_(false), |
| 243 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( | 258 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( |
| 244 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)), | 259 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)), |
| 245 ssl_(NULL), | 260 ssl_(NULL), |
| 246 transport_bio_(NULL), | 261 transport_bio_(NULL), |
| 247 transport_(transport_socket), | 262 transport_(transport_socket), |
| 248 host_and_port_(host_and_port), | 263 host_and_port_(host_and_port), |
| 249 ssl_config_(ssl_config), | 264 ssl_config_(ssl_config), |
| 250 trying_cached_session_(false), | 265 trying_cached_session_(false), |
| 266 npn_status_(kNextProtoUnsupported), | |
| 251 net_log_(transport_socket->socket()->NetLog()) { | 267 net_log_(transport_socket->socket()->NetLog()) { |
| 252 } | 268 } |
| 253 | 269 |
| 254 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 270 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
| 255 Disconnect(); | 271 Disconnect(); |
| 256 } | 272 } |
| 257 | 273 |
| 258 bool SSLClientSocketOpenSSL::Init() { | 274 bool SSLClientSocketOpenSSL::Init() { |
| 259 DCHECK(!ssl_); | 275 DCHECK(!ssl_); |
| 260 DCHECK(!transport_bio_); | 276 DCHECK(!transport_bio_); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 } | 379 } |
| 364 | 380 |
| 365 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( | 381 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( |
| 366 SSLCertRequestInfo* cert_request_info) { | 382 SSLCertRequestInfo* cert_request_info) { |
| 367 cert_request_info->host_and_port = host_and_port_.ToString(); | 383 cert_request_info->host_and_port = host_and_port_.ToString(); |
| 368 cert_request_info->client_certs = client_certs_; | 384 cert_request_info->client_certs = client_certs_; |
| 369 } | 385 } |
| 370 | 386 |
| 371 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( | 387 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( |
| 372 std::string* proto) { | 388 std::string* proto) { |
| 373 proto->clear(); | 389 *proto = npn_proto_; |
| 374 return kNextProtoUnsupported; | 390 return npn_status_; |
| 375 } | 391 } |
| 376 | 392 |
| 377 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { | 393 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { |
| 378 // Since Run may result in Read being called, clear |user_read_callback_| | 394 // Since Run may result in Read being called, clear |user_read_callback_| |
| 379 // up front. | 395 // up front. |
| 380 CompletionCallback* c = user_read_callback_; | 396 CompletionCallback* c = user_read_callback_; |
| 381 user_read_callback_ = NULL; | 397 user_read_callback_ = NULL; |
| 382 user_read_buf_ = NULL; | 398 user_read_buf_ = NULL; |
| 383 user_read_buf_len_ = 0; | 399 user_read_buf_len_ = 0; |
| 384 c->Run(rv); | 400 c->Run(rv); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 // TODO(joth): We need a way to lookup the private key this | 576 // TODO(joth): We need a way to lookup the private key this |
| 561 // certificate. See http://crbug.com/64951 and example code in | 577 // certificate. See http://crbug.com/64951 and example code in |
| 562 // http://codereview.chromium.org/5195001/diff/6001/net/socket/ssl_client_so cket_openssl.cc | 578 // http://codereview.chromium.org/5195001/diff/6001/net/socket/ssl_client_so cket_openssl.cc |
| 563 NOTIMPLEMENTED(); | 579 NOTIMPLEMENTED(); |
| 564 } | 580 } |
| 565 | 581 |
| 566 // Send no client certificate. | 582 // Send no client certificate. |
| 567 return 0; | 583 return 0; |
| 568 } | 584 } |
| 569 | 585 |
| 586 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, | |
| 587 unsigned char* outlen, | |
| 588 const unsigned char* in, | |
| 589 unsigned int inlen) { | |
| 590 #if defined(OPENSSL_NPN_NEGOTIATED) | |
| 591 if (ssl_config_.next_protos.empty()) { | |
| 592 *outlen = 0; | |
|
agl
2010/12/03 15:17:37
*out = "http/1.1";
*outlen = 8;
Kristian_
2010/12/03 15:30:57
I added this in later patch, should I change to th
| |
| 593 return SSL_TLSEXT_ERR_OK; | |
| 594 } | |
| 595 | |
| 596 int status = SSL_select_next_proto( | |
| 597 out, outlen, in, inlen, | |
| 598 reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()), | |
| 599 ssl_config_.next_protos.size()); | |
| 600 | |
| 601 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | |
| 602 switch (status) { | |
| 603 //case OPENSSL_NPN_UNSUPPORTED: | |
|
agl
2010/12/03 15:17:37
Why commented out?
Kristian_
2010/12/03 15:30:57
Thanks, it was to test compile on ubuntu where the
| |
| 604 npn_status_ = SSLClientSocket::kNextProtoUnsupported; | |
| 605 break; | |
| 606 //case OPENSSL_NPN_NEGOTIATED: | |
| 607 npn_status_ = SSLClientSocket::kNextProtoNegotiated; | |
| 608 break; | |
| 609 //case OPENSSL_NPN_NO_OVERLAP: | |
| 610 npn_status_ = SSLClientSocket::kNextProtoNoOverlap; | |
| 611 break; | |
| 612 default: | |
| 613 NOTREACHED() << status; | |
| 614 break; | |
| 615 } | |
| 616 #endif | |
| 617 return SSL_TLSEXT_ERR_OK; | |
| 618 } | |
| 619 | |
| 570 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { | 620 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { |
| 571 DCHECK(server_cert_); | 621 DCHECK(server_cert_); |
| 572 GotoState(STATE_VERIFY_CERT_COMPLETE); | 622 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 573 int flags = 0; | 623 int flags = 0; |
| 574 | 624 |
| 575 if (ssl_config_.rev_checking_enabled) | 625 if (ssl_config_.rev_checking_enabled) |
| 576 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 626 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
| 577 if (ssl_config_.verify_ev_cert) | 627 if (ssl_config_.verify_ev_cert) |
| 578 flags |= X509Certificate::VERIFY_EV_CERT; | 628 flags |= X509Certificate::VERIFY_EV_CERT; |
| 579 verifier_.reset(new CertVerifier); | 629 verifier_.reset(new CertVerifier); |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 994 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
| 945 | 995 |
| 946 if (rv >= 0) | 996 if (rv >= 0) |
| 947 return rv; | 997 return rv; |
| 948 | 998 |
| 949 int err = SSL_get_error(ssl_, rv); | 999 int err = SSL_get_error(ssl_, rv); |
| 950 return MapOpenSSLError(err); | 1000 return MapOpenSSLError(err); |
| 951 } | 1001 } |
| 952 | 1002 |
| 953 } // namespace net | 1003 } // namespace net |
| OLD | NEW |