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 |