Chromium Code Reviews| 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 <openssl/err.h> | 10 #include <openssl/err.h> |
| (...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1270 | 1270 |
| 1271 int SSLClientSocketOpenSSL::BufferSend(void) { | 1271 int SSLClientSocketOpenSSL::BufferSend(void) { |
| 1272 if (transport_send_busy_) | 1272 if (transport_send_busy_) |
| 1273 return ERR_IO_PENDING; | 1273 return ERR_IO_PENDING; |
| 1274 | 1274 |
| 1275 if (!send_buffer_.get()) { | 1275 if (!send_buffer_.get()) { |
| 1276 // Get a fresh send buffer out of the send BIO. | 1276 // Get a fresh send buffer out of the send BIO. |
| 1277 size_t max_read = BIO_ctrl_pending(transport_bio_); | 1277 size_t max_read = BIO_ctrl_pending(transport_bio_); |
| 1278 if (!max_read) | 1278 if (!max_read) |
| 1279 return 0; // Nothing pending in the OpenSSL write BIO. | 1279 return 0; // Nothing pending in the OpenSSL write BIO. |
| 1280 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); | 1280 |
| 1281 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); | 1281 char* bio_transport_buf; |
| 1282 DCHECK_GT(read_bytes, 0); | 1282 // Get the internal buffer and number of bytes available for non-copying |
| 1283 CHECK_EQ(static_cast<int>(max_read), read_bytes); | 1283 // read. |
| 1284 // BIO_ctrl_pending() is still called above. Calling BIO_nread0() when | |
| 1285 // there is no data triggers a call to BIO_nread() to read one byte. This | |
| 1286 // has side effect that the retry flag is set. | |
| 1287 int available_read_bytes = BIO_nread0(transport_bio_, &bio_transport_buf); | |
|
Ryan Sleevi
2014/04/29 18:57:02
Note the comments in bss_bio.c
WARNING: The non-c
haavardm
2014/04/29 20:52:56
Yes I saw that too and agree it's a bit risky, esp
| |
| 1288 // BIO_nread0() might report less than BIO_ctrl_pending() due to the buffer | |
| 1289 // offset and no ring buffer wrap-around for non-copying interface. | |
| 1290 CHECK_GE(static_cast<int>(max_read), available_read_bytes); | |
|
Ryan Sleevi
2014/04/29 18:57:02
Two things:
1) I'm a little nervous about this CHE
haavardm
2014/04/29 20:52:56
Normally, if the read/write index is in the middle
| |
| 1291 if (available_read_bytes <= 0) | |
| 1292 return 0; | |
| 1293 | |
| 1294 send_buffer_ = new DrainableIOBuffer(new WrappedIOBuffer(bio_transport_buf), | |
| 1295 available_read_bytes); | |
|
Ryan Sleevi
2014/04/29 18:57:02
BUG: So, the contract of IOBuffer is that, althoug
haavardm
2014/04/29 20:52:56
Ah, right. I knew about the contract for IOBuffer
| |
| 1284 } | 1296 } |
| 1285 | 1297 |
| 1286 int rv = transport_->socket()->Write( | 1298 int rv = transport_->socket()->Write( |
| 1287 send_buffer_.get(), | 1299 send_buffer_.get(), |
| 1288 send_buffer_->BytesRemaining(), | 1300 send_buffer_->BytesRemaining(), |
| 1289 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, | 1301 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, |
| 1290 base::Unretained(this))); | 1302 base::Unretained(this))); |
| 1291 if (rv == ERR_IO_PENDING) { | 1303 if (rv == ERR_IO_PENDING) { |
| 1292 transport_send_busy_ = true; | 1304 transport_send_busy_ = true; |
| 1293 } else { | 1305 } else { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1315 // One read for the SSL record header (~5 bytes) and one read for the SSL | 1327 // One read for the SSL record header (~5 bytes) and one read for the SSL |
| 1316 // record body. Rather than issuing these reads to the underlying socket | 1328 // record body. Rather than issuing these reads to the underlying socket |
| 1317 // (and constantly allocating new IOBuffers), a single Read() request to | 1329 // (and constantly allocating new IOBuffers), a single Read() request to |
| 1318 // fill |transport_bio_| is issued. As long as an SSL client socket cannot | 1330 // fill |transport_bio_| is issued. As long as an SSL client socket cannot |
| 1319 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL | 1331 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL |
| 1320 // traffic, this over-subscribed Read()ing will not cause issues. | 1332 // traffic, this over-subscribed Read()ing will not cause issues. |
| 1321 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); | 1333 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); |
| 1322 if (!max_write) | 1334 if (!max_write) |
| 1323 return ERR_IO_PENDING; | 1335 return ERR_IO_PENDING; |
| 1324 | 1336 |
| 1325 recv_buffer_ = new IOBuffer(max_write); | 1337 char* bio_transport_buf; |
| 1338 // Get the internal buffer and number of bytes available for non-copying | |
| 1339 // write. | |
| 1340 int available_write_bytes = BIO_nwrite0(transport_bio_, &bio_transport_buf); | |
| 1341 // BIO_nwrite0() might report less than BIO_ctrl_get_write_guarantee() due to | |
| 1342 // the buffer offset and no ring buffer wrap-around for non-copying interface. | |
| 1343 DCHECK_GE(static_cast<int>(max_write), available_write_bytes); | |
| 1344 if (available_write_bytes <= 0) | |
| 1345 return ERR_IO_PENDING; | |
| 1346 | |
| 1347 recv_buffer_ = new WrappedIOBuffer(bio_transport_buf); | |
| 1326 int rv = transport_->socket()->Read( | 1348 int rv = transport_->socket()->Read( |
| 1327 recv_buffer_.get(), | 1349 recv_buffer_.get(), |
| 1328 max_write, | 1350 available_write_bytes, |
| 1329 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, | 1351 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, |
| 1330 base::Unretained(this))); | 1352 base::Unretained(this))); |
| 1331 if (rv == ERR_IO_PENDING) { | 1353 if (rv == ERR_IO_PENDING) { |
| 1332 transport_recv_busy_ = true; | 1354 transport_recv_busy_ = true; |
| 1333 } else { | 1355 } else { |
| 1334 rv = TransportReadComplete(rv); | 1356 rv = TransportReadComplete(rv); |
| 1335 } | 1357 } |
| 1336 return rv; | 1358 return rv; |
| 1337 } | 1359 } |
| 1338 | 1360 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1360 | 1382 |
| 1361 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads | 1383 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads |
| 1362 // from the socket after a write error. | 1384 // from the socket after a write error. |
| 1363 // | 1385 // |
| 1364 // TODO(davidben): Avoid having read and write ends interact this way. | 1386 // TODO(davidben): Avoid having read and write ends interact this way. |
| 1365 transport_write_error_ = result; | 1387 transport_write_error_ = result; |
| 1366 (void)BIO_shutdown_wr(transport_bio_); | 1388 (void)BIO_shutdown_wr(transport_bio_); |
| 1367 send_buffer_ = NULL; | 1389 send_buffer_ = NULL; |
| 1368 } else { | 1390 } else { |
| 1369 DCHECK(send_buffer_.get()); | 1391 DCHECK(send_buffer_.get()); |
| 1392 char* bio_transport_buf; | |
| 1393 // Advance the buffer index. | |
| 1394 int ret = BIO_nread(transport_bio_, &bio_transport_buf, result); | |
| 1395 CHECK_EQ(ret, result); | |
| 1396 CHECK_EQ(bio_transport_buf, send_buffer_->data()); | |
| 1370 send_buffer_->DidConsume(result); | 1397 send_buffer_->DidConsume(result); |
| 1371 DCHECK_GE(send_buffer_->BytesRemaining(), 0); | 1398 DCHECK_GE(send_buffer_->BytesRemaining(), 0); |
| 1372 if (send_buffer_->BytesRemaining() <= 0) | 1399 if (send_buffer_->BytesRemaining() <= 0) |
| 1373 send_buffer_ = NULL; | 1400 send_buffer_ = NULL; |
| 1374 } | 1401 } |
| 1375 } | 1402 } |
| 1376 | 1403 |
| 1377 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { | 1404 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { |
| 1378 DCHECK(ERR_IO_PENDING != result); | 1405 DCHECK(ERR_IO_PENDING != result); |
| 1379 if (result <= 0) { | 1406 if (result <= 0) { |
| 1380 DVLOG(1) << "TransportReadComplete result " << result; | 1407 DVLOG(1) << "TransportReadComplete result " << result; |
| 1381 // Received 0 (end of file) or an error. Either way, bubble it up to the | 1408 // Received 0 (end of file) or an error. Either way, bubble it up to the |
| 1382 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to | 1409 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to |
| 1383 // relay up to the SSL socket client (i.e. via DoReadCallback). | 1410 // relay up to the SSL socket client (i.e. via DoReadCallback). |
| 1384 if (result == 0) | 1411 if (result == 0) |
| 1385 transport_recv_eof_ = true; | 1412 transport_recv_eof_ = true; |
| 1386 (void)BIO_shutdown_wr(transport_bio_); | 1413 (void)BIO_shutdown_wr(transport_bio_); |
| 1387 } else if (transport_write_error_ < 0) { | 1414 } else if (transport_write_error_ < 0) { |
| 1388 // Mirror transport write errors as read failures; transport_bio_ has been | 1415 // Mirror transport write errors as read failures; transport_bio_ has been |
| 1389 // shut down by TransportWriteComplete, so the BIO_write will fail, failing | 1416 // shut down by TransportWriteComplete, so the BIO_write will fail, failing |
| 1390 // the CHECK. http://crbug.com/335557. | 1417 // the CHECK. http://crbug.com/335557. |
| 1391 result = transport_write_error_; | 1418 result = transport_write_error_; |
| 1392 } else { | 1419 } else { |
| 1393 DCHECK(recv_buffer_.get()); | 1420 char* bio_transport_buf; |
| 1394 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); | 1421 // Set the amount of data read into buffer. |
| 1422 int ret = BIO_nwrite(transport_bio_, &bio_transport_buf, result); | |
| 1423 CHECK_EQ(ret, result); | |
| 1424 CHECK_EQ(bio_transport_buf, recv_buffer_->data()); | |
| 1395 // A write into a memory BIO should always succeed. | 1425 // A write into a memory BIO should always succeed. |
| 1396 // Force values on the stack for http://crbug.com/335557 | 1426 // Force values on the stack for http://crbug.com/335557 |
| 1397 base::debug::Alias(&result); | 1427 base::debug::Alias(&result); |
| 1398 base::debug::Alias(&ret); | 1428 base::debug::Alias(&ret); |
| 1399 CHECK_EQ(result, ret); | 1429 CHECK_EQ(result, ret); |
| 1400 } | 1430 } |
| 1401 recv_buffer_ = NULL; | 1431 recv_buffer_ = NULL; |
| 1402 transport_recv_busy_ = false; | 1432 transport_recv_busy_ = false; |
| 1403 return result; | 1433 return result; |
| 1404 } | 1434 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1565 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 1595 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
| 1566 return SSL_TLSEXT_ERR_OK; | 1596 return SSL_TLSEXT_ERR_OK; |
| 1567 } | 1597 } |
| 1568 | 1598 |
| 1569 scoped_refptr<X509Certificate> | 1599 scoped_refptr<X509Certificate> |
| 1570 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1600 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
| 1571 return server_cert_; | 1601 return server_cert_; |
| 1572 } | 1602 } |
| 1573 | 1603 |
| 1574 } // namespace net | 1604 } // namespace net |
| OLD | NEW |