Chromium Code Reviews

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 5528003: Add support for OpenSSL Next Protocol Negotiation (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
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>
11 #include <openssl/err.h> 11 #include <openssl/err.h>
12 12
13 #include "base/lock.h" 13 #include "base/lock.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/openssl_util.h" 15 #include "base/openssl_util.h"
16 #include "base/singleton.h" 16 #include "base/singleton.h"
17 #include "net/base/cert_verifier.h" 17 #include "net/base/cert_verifier.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/ssl_cert_request_info.h" 19 #include "net/base/ssl_cert_request_info.h"
20 #include "net/base/ssl_connection_status_flags.h" 20 #include "net/base/ssl_connection_status_flags.h"
21 #include "net/base/ssl_info.h" 21 #include "net/base/ssl_info.h"
22 // TODO(willchan): Fix this dependency. It's ugly for net/socket to depend on
23 // net/http.
joth 2010/12/02 17:46:55 overlength line
Kristian_ 2010/12/03 14:58:56 Done.
24 #include "net/http/http_stream_factory.h"
joth 2010/12/02 17:46:55 Istead of doing this please see if we can use SSLC
willchan no longer on Chromium 2010/12/03 01:35:06 Agreed, this is preferable, primarily in terms of
Kristian_ 2010/12/03 14:58:56 Done
22 25
23 namespace net { 26 namespace net {
24 27
25 namespace { 28 namespace {
26 29
27 // Enable this to see logging for state machine state transitions. 30 // Enable this to see logging for state machine state transitions.
28 #if 0 31 #if 0
29 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ 32 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
30 " jump to state " << s; \ 33 " jump to state " << s; \
31 next_handshake_state_ = s; } while (0) 34 next_handshake_state_ = s; } while (0)
(...skipping 136 matching lines...)
168 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); 171 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
169 DCHECK_NE(ssl_socket_data_index_, -1); 172 DCHECK_NE(ssl_socket_data_index_, -1);
170 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); 173 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
171 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); 174 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); 175 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
173 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); 176 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
174 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); 177 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
175 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); 178 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
176 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); 179 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
177 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); 180 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
181 #ifdef OPENSSL_NPN_NEGOTIATED
willchan no longer on Chromium 2010/12/03 01:35:06 In Chromium code, we usually do #if defined(OPENSS
Kristian_ 2010/12/03 14:58:56 Done.
182 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), &SelectNextProtoCallback,
joth 2010/12/02 17:46:55 nit: other calls don't use & to get function addre
joth 2010/12/02 17:46:55 Problem: a side effect of calling SSL_CTX_set_next
willchan no longer on Chromium 2010/12/03 01:35:06 NPN next protos are decided on Chrome startup and
Kristian_ 2010/12/03 14:58:56 I'm not sure if setting on first run gives us much
183 NULL);
joth 2010/12/02 17:46:55 align NULL with first param
Kristian_ 2010/12/03 14:58:56 Done.
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 #ifdef OPENSSL_NPN_NEGOTIATED
213 static int SelectNextProtoCallback(SSL* ssl,
214 unsigned char** out, unsigned char* outlen,
215 const unsigned char* in,
216 unsigned int inlen, void* arg) {
217 if (!HttpStreamFactory::next_protos() ||
218 HttpStreamFactory::next_protos()->empty())
219 return SSL_TLSEXT_ERR_OK;
joth 2010/12/02 17:46:55 The docs for SSL_CTX_set_next_proto_select_cb stat
willchan no longer on Chromium 2010/12/03 01:35:06 You're right. That'd be better, but if it's too m
Kristian_ 2010/12/03 14:58:56 The problem is that the contents of SSLConfig::nex
220
221 const std::string& next_protos = *HttpStreamFactory::next_protos();
joth 2010/12/02 17:46:55 maybe add a comment: CARE: |*out| maybe set to poi
222 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl);
223
224 int status = SSL_select_next_proto(
225 out, outlen, in, inlen,
226 reinterpret_cast<const unsigned char*>(next_protos.data()),
227 next_protos.size());
228
229 socket->set_npn_proto(reinterpret_cast<const char*>(*out), *outlen);
230 switch (status) {
231 case OPENSSL_NPN_UNSUPPORTED:
232 socket->set_npn_status(SSLClientSocket::kNextProtoUnsupported);
233 break;
234 case OPENSSL_NPN_NEGOTIATED:
235 socket->set_npn_status(SSLClientSocket::kNextProtoNegotiated);
236 break;
237 case OPENSSL_NPN_NO_OVERLAP:
238 socket->set_npn_status(SSLClientSocket::kNextProtoNoOverlap);
239 break;
240 default:
241 NOTREACHED();
joth 2010/12/02 17:46:55 nit: NOTREACHED() << status;
Kristian_ 2010/12/03 14:58:56 Done.
242 break;
243 }
244 return SSL_TLSEXT_ERR_OK;
245 }
246 #endif
247
205 // This is the index used with SSL_get_ex_data to retrieve the owner 248 // This is the index used with SSL_get_ex_data to retrieve the owner
206 // SSLClientSocketOpenSSL object from an SSL instance. 249 // SSLClientSocketOpenSSL object from an SSL instance.
207 int ssl_socket_data_index_; 250 int ssl_socket_data_index_;
208 251
209 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; 252 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
210 SSLSessionCache session_cache_; 253 SSLSessionCache session_cache_;
211 }; 254 };
212 255
213 // Utility to construct the appropriate set & clear masks for use the OpenSSL 256 // Utility to construct the appropriate set & clear masks for use the OpenSSL
214 // options and mode configuration functions. (SSL_set_options etc) 257 // options and mode configuration functions. (SSL_set_options etc)
(...skipping 26 matching lines...)
241 completed_handshake_(false), 284 completed_handshake_(false),
242 client_auth_cert_needed_(false), 285 client_auth_cert_needed_(false),
243 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( 286 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
244 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)), 287 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)),
245 ssl_(NULL), 288 ssl_(NULL),
246 transport_bio_(NULL), 289 transport_bio_(NULL),
247 transport_(transport_socket), 290 transport_(transport_socket),
248 host_and_port_(host_and_port), 291 host_and_port_(host_and_port),
249 ssl_config_(ssl_config), 292 ssl_config_(ssl_config),
250 trying_cached_session_(false), 293 trying_cached_session_(false),
294 npn_status_(kNextProtoUnsupported),
251 net_log_(transport_socket->socket()->NetLog()) { 295 net_log_(transport_socket->socket()->NetLog()) {
252 } 296 }
253 297
254 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { 298 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
255 Disconnect(); 299 Disconnect();
256 } 300 }
257 301
258 bool SSLClientSocketOpenSSL::Init() { 302 bool SSLClientSocketOpenSSL::Init() {
259 DCHECK(!ssl_); 303 DCHECK(!ssl_);
260 DCHECK(!transport_bio_); 304 DCHECK(!transport_bio_);
(...skipping 102 matching lines...)
363 } 407 }
364 408
365 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( 409 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
366 SSLCertRequestInfo* cert_request_info) { 410 SSLCertRequestInfo* cert_request_info) {
367 cert_request_info->host_and_port = host_and_port_.ToString(); 411 cert_request_info->host_and_port = host_and_port_.ToString();
368 cert_request_info->client_certs = client_certs_; 412 cert_request_info->client_certs = client_certs_;
369 } 413 }
370 414
371 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( 415 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
372 std::string* proto) { 416 std::string* proto) {
373 proto->clear(); 417 proto->assign(npn_proto_);
joth 2010/12/02 17:46:55 nit: *proto = npn_proto_; (probably just slightly
Kristian_ 2010/12/03 14:58:56 Done.
374 return kNextProtoUnsupported; 418 return npn_status_;
375 } 419 }
376 420
377 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { 421 void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
378 // Since Run may result in Read being called, clear |user_read_callback_| 422 // Since Run may result in Read being called, clear |user_read_callback_|
379 // up front. 423 // up front.
380 CompletionCallback* c = user_read_callback_; 424 CompletionCallback* c = user_read_callback_;
381 user_read_callback_ = NULL; 425 user_read_callback_ = NULL;
382 user_read_buf_ = NULL; 426 user_read_buf_ = NULL;
383 user_read_buf_len_ = 0; 427 user_read_buf_len_ = 0;
384 c->Run(rv); 428 c->Run(rv);
(...skipping 559 matching lines...)
944 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); 988 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
945 989
946 if (rv >= 0) 990 if (rv >= 0)
947 return rv; 991 return rv;
948 992
949 int err = SSL_get_error(ssl_, rv); 993 int err = SSL_get_error(ssl_, rv);
950 return MapOpenSSLError(err); 994 return MapOpenSSLError(err);
951 } 995 }
952 996
953 } // namespace net 997 } // namespace net
OLDNEW
« net/socket/ssl_client_socket_openssl.h ('K') | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine