Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1023)

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

Issue 148213019: Close the correct end of the BIO pair on transport send failures in openssl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 336 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
337 scoped_ptr<ClientSocketHandle> transport_socket, 337 scoped_ptr<ClientSocketHandle> transport_socket,
338 const HostPortPair& host_and_port, 338 const HostPortPair& host_and_port,
339 const SSLConfig& ssl_config, 339 const SSLConfig& ssl_config,
340 const SSLClientSocketContext& context) 340 const SSLClientSocketContext& context)
341 : transport_send_busy_(false), 341 : transport_send_busy_(false),
342 transport_recv_busy_(false), 342 transport_recv_busy_(false),
343 transport_recv_eof_(false), 343 transport_recv_eof_(false),
344 weak_factory_(this), 344 weak_factory_(this),
345 pending_read_error_(kNoPendingReadResult), 345 pending_read_error_(kNoPendingReadResult),
346 transport_write_error_(OK),
346 completed_handshake_(false), 347 completed_handshake_(false),
347 client_auth_cert_needed_(false), 348 client_auth_cert_needed_(false),
348 cert_verifier_(context.cert_verifier), 349 cert_verifier_(context.cert_verifier),
349 server_bound_cert_service_(context.server_bound_cert_service), 350 server_bound_cert_service_(context.server_bound_cert_service),
350 ssl_(NULL), 351 ssl_(NULL),
351 transport_bio_(NULL), 352 transport_bio_(NULL),
352 transport_(transport_socket.Pass()), 353 transport_(transport_socket.Pass()),
353 host_and_port_(host_and_port), 354 host_and_port_(host_and_port),
354 ssl_config_(ssl_config), 355 ssl_config_(ssl_config),
355 ssl_session_cache_shard_(context.ssl_session_cache_shard), 356 ssl_session_cache_shard_(context.ssl_session_cache_shard),
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 // Shut down anything that may call us back. 451 // Shut down anything that may call us back.
451 verifier_.reset(); 452 verifier_.reset();
452 transport_->socket()->Disconnect(); 453 transport_->socket()->Disconnect();
453 454
454 // Null all callbacks, delete all buffers. 455 // Null all callbacks, delete all buffers.
455 transport_send_busy_ = false; 456 transport_send_busy_ = false;
456 send_buffer_ = NULL; 457 send_buffer_ = NULL;
457 transport_recv_busy_ = false; 458 transport_recv_busy_ = false;
458 transport_recv_eof_ = false; 459 transport_recv_eof_ = false;
459 recv_buffer_ = NULL; 460 recv_buffer_ = NULL;
460 461
Ryan Sleevi 2014/02/04 20:45:02 Don't you need to update transport_write_error_ he
davidben 2014/02/04 23:00:11 Done. Also reset pending_read_error_.
461 user_connect_callback_.Reset(); 462 user_connect_callback_.Reset();
462 user_read_callback_.Reset(); 463 user_read_callback_.Reset();
463 user_write_callback_.Reset(); 464 user_write_callback_.Reset();
464 user_read_buf_ = NULL; 465 user_read_buf_ = NULL;
465 user_read_buf_len_ = 0; 466 user_read_buf_len_ = 0;
466 user_write_buf_ = NULL; 467 user_write_buf_ = NULL;
467 user_write_buf_len_ = 0; 468 user_write_buf_len_ = 0;
468 469
469 server_cert_verify_result_.Reset(); 470 server_cert_verify_result_.Reset();
470 completed_handshake_ = false; 471 completed_handshake_ = false;
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 1198
1198 recv_buffer_ = new IOBuffer(max_write); 1199 recv_buffer_ = new IOBuffer(max_write);
1199 int rv = transport_->socket()->Read( 1200 int rv = transport_->socket()->Read(
1200 recv_buffer_.get(), 1201 recv_buffer_.get(),
1201 max_write, 1202 max_write,
1202 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 1203 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1203 base::Unretained(this))); 1204 base::Unretained(this)));
1204 if (rv == ERR_IO_PENDING) { 1205 if (rv == ERR_IO_PENDING) {
1205 transport_recv_busy_ = true; 1206 transport_recv_busy_ = true;
1206 } else { 1207 } else {
1207 TransportReadComplete(rv); 1208 rv = TransportReadComplete(rv);
1208 } 1209 }
1209 return rv; 1210 return rv;
1210 } 1211 }
1211 1212
1212 void SSLClientSocketOpenSSL::BufferSendComplete(int result) { 1213 void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
1213 transport_send_busy_ = false; 1214 transport_send_busy_ = false;
1214 TransportWriteComplete(result); 1215 TransportWriteComplete(result);
1215 OnSendComplete(result); 1216 OnSendComplete(result);
1216 } 1217 }
1217 1218
1218 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { 1219 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
1219 TransportReadComplete(result); 1220 result = TransportReadComplete(result);
1220 OnRecvComplete(result); 1221 OnRecvComplete(result);
1221 } 1222 }
1222 1223
1223 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { 1224 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
1224 DCHECK(ERR_IO_PENDING != result); 1225 DCHECK(ERR_IO_PENDING != result);
1225 if (result < 0) { 1226 if (result < 0) {
1226 // Got a socket write error; close the BIO to indicate this upward. 1227 // Got a socket write error; close the BIO to indicate this upward.
1228 //
1229 // TODO(davidben): The value of |result| gets lost. Feed the error back into
1230 // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
1231 // BIO_set_callback.
1227 DVLOG(1) << "TransportWriteComplete error " << result; 1232 DVLOG(1) << "TransportWriteComplete error " << result;
1233 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
davidben 2014/02/04 19:27:57 Could get away with even avoiding this line for mi
davidben 2014/02/04 19:27:57 It looks like sometimes OpenSSL wraps the wbio in
Ryan Sleevi 2014/02/04 20:45:02 Future work: Should we be using BIO_set_close() in
davidben 2014/02/04 23:00:11 Hrm. That seems to set the shutdown flag on the BI
1234
1235 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
1236 // from the socket after a write error.
1237 //
1238 // TODO(davidben): Avoid having read and write ends interact this way.
1239 transport_write_error_ = result;
1228 (void)BIO_shutdown_wr(transport_bio_); 1240 (void)BIO_shutdown_wr(transport_bio_);
1229 BIO_set_mem_eof_return(transport_bio_, 0);
davidben 2014/02/04 19:27:57 Looks like these calls don't do anything in BIO pa
1230 send_buffer_ = NULL; 1241 send_buffer_ = NULL;
davidben 2014/02/04 19:27:57 This line is sort of funny. The next time we get a
Ryan Sleevi 2014/02/04 20:45:02 I'm not sure I follow why it's funny. We just had
davidben 2014/02/04 23:00:11 Keeping send_buffer_ around avoids the succeeds wi
1231 } else { 1242 } else {
1232 DCHECK(send_buffer_.get()); 1243 DCHECK(send_buffer_.get());
1233 send_buffer_->DidConsume(result); 1244 send_buffer_->DidConsume(result);
1234 DCHECK_GE(send_buffer_->BytesRemaining(), 0); 1245 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1235 if (send_buffer_->BytesRemaining() <= 0) 1246 if (send_buffer_->BytesRemaining() <= 0)
1236 send_buffer_ = NULL; 1247 send_buffer_ = NULL;
1237 } 1248 }
1238 } 1249 }
1239 1250
1240 void SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1251 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1241 DCHECK(ERR_IO_PENDING != result); 1252 DCHECK(ERR_IO_PENDING != result);
1242 if (result <= 0) { 1253 if (result <= 0) {
1243 DVLOG(1) << "TransportReadComplete result " << result; 1254 DVLOG(1) << "TransportReadComplete result " << result;
1244 // Received 0 (end of file) or an error. Either way, bubble it up to the 1255 // Received 0 (end of file) or an error. Either way, bubble it up to the
1245 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to 1256 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
1246 // relay up to the SSL socket client (i.e. via DoReadCallback). 1257 // relay up to the SSL socket client (i.e. via DoReadCallback).
1247 if (result == 0) 1258 if (result == 0)
1248 transport_recv_eof_ = true; 1259 transport_recv_eof_ = true;
1249 BIO_set_mem_eof_return(transport_bio_, 0);
1250 (void)BIO_shutdown_wr(transport_bio_); 1260 (void)BIO_shutdown_wr(transport_bio_);
1261 } else if (transport_write_error_ < 0) {
1262 // Mirror transport write errors as read failures; transport_bio_ has been
1263 // shut down by TransportWriteComplete, so the BIO_write will fail.
1264 result = transport_write_error_;
Ryan Sleevi 2014/02/04 20:45:02 Let's add bug numbers. This is perhaps the most co
davidben 2014/02/04 23:00:11 Agreed. I kept it this way just to minimize behavi
1251 } else { 1265 } else {
1252 DCHECK(recv_buffer_.get()); 1266 DCHECK(recv_buffer_.get());
1253 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); 1267 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1254 // A write into a memory BIO should always succeed. 1268 // A write into a memory BIO should always succeed.
1255 // Force values on the stack for http://crbug.com/335557 1269 // Force values on the stack for http://crbug.com/335557
1256 base::debug::Alias(&result); 1270 base::debug::Alias(&result);
1257 base::debug::Alias(&ret); 1271 base::debug::Alias(&ret);
1258 CHECK_EQ(result, ret); 1272 CHECK_EQ(result, ret);
1259 } 1273 }
1260 recv_buffer_ = NULL; 1274 recv_buffer_ = NULL;
1261 transport_recv_busy_ = false; 1275 transport_recv_busy_ = false;
1276 return result;
1262 } 1277 }
1263 1278
1264 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, 1279 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
1265 X509** x509, 1280 X509** x509,
1266 EVP_PKEY** pkey) { 1281 EVP_PKEY** pkey) {
1267 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; 1282 DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
1268 DCHECK(ssl == ssl_); 1283 DCHECK(ssl == ssl_);
1269 DCHECK(*x509 == NULL); 1284 DCHECK(*x509 == NULL);
1270 DCHECK(*pkey == NULL); 1285 DCHECK(*pkey == NULL);
1271 1286
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 } 1411 }
1397 1412
1398 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); 1413 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
1399 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); 1414 server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
1400 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1415 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1401 #endif 1416 #endif
1402 return SSL_TLSEXT_ERR_OK; 1417 return SSL_TLSEXT_ERR_OK;
1403 } 1418 }
1404 1419
1405 } // namespace net 1420 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698