Copilot commented on code in PR #13202:
URL: https://github.com/apache/trafficserver/pull/13202#discussion_r3352278545


##########
src/iocore/net/SSLNetVConnection.cc:
##########
@@ -123,11 +123,26 @@ SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx)
 
       SSL_set_bio(ssl, bio, bio);
     } else {
-      this->initialize_handshake_buffers();
-      BIO *rbio = BIO_new(BIO_s_mem());
-      BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
-      BIO_set_mem_eof_return(wbio, -1);
-      SSL_set_bio(ssl, rbio, wbio);
+      if (this->transparentPassThrough || this->allowPlain) {
+        // Blind-tunnel possible: keep handshake buffers to capture/replay the 
CLIENT_HELLO.
+        this->initialize_handshake_buffers();
+        BIO *rbio = BIO_new(BIO_s_mem());
+        BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+        BIO_set_mem_eof_return(wbio, -1);
+        SSL_set_bio(ssl, rbio, wbio);
+      } else {
+        // No blind-tunnel: direct socket BIO, skip handshake buffers. On 
OpenSSL a
+        // write-side buffer BIO coalesces TLS records into fewer write() 
syscalls;
+        // BoringSSL has no filter BIOs, so it uses the plain socket BIO.
+        BIO *rbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+        BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+#if !defined(OPENSSL_IS_BORINGSSL)
+        BIO *buf_wbio = BIO_new(BIO_f_buffer());
+        BIO_set_write_buffer_size(buf_wbio, 65536);
+        wbio = BIO_push(buf_wbio, wbio);
+#endif

Review Comment:
   BIO_new(BIO_f_buffer()) / BIO_push() results are not checked for failure. If 
allocation or push fails, buf_wbio may be nullptr (crash on 
BIO_set_write_buffer_size) or BIO_push may return nullptr, leaving wbio invalid.



##########
src/iocore/net/SSLNetVConnection.cc:
##########
@@ -123,11 +123,26 @@ SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx)
 
       SSL_set_bio(ssl, bio, bio);
     } else {
-      this->initialize_handshake_buffers();
-      BIO *rbio = BIO_new(BIO_s_mem());
-      BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
-      BIO_set_mem_eof_return(wbio, -1);
-      SSL_set_bio(ssl, rbio, wbio);
+      if (this->transparentPassThrough || this->allowPlain) {
+        // Blind-tunnel possible: keep handshake buffers to capture/replay the 
CLIENT_HELLO.
+        this->initialize_handshake_buffers();
+        BIO *rbio = BIO_new(BIO_s_mem());
+        BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+        BIO_set_mem_eof_return(wbio, -1);
+        SSL_set_bio(ssl, rbio, wbio);
+      } else {
+        // No blind-tunnel: direct socket BIO, skip handshake buffers. On 
OpenSSL a
+        // write-side buffer BIO coalesces TLS records into fewer write() 
syscalls;
+        // BoringSSL has no filter BIOs, so it uses the plain socket BIO.
+        BIO *rbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+        BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
+#if !defined(OPENSSL_IS_BORINGSSL)
+        BIO *buf_wbio = BIO_new(BIO_f_buffer());
+        BIO_set_write_buffer_size(buf_wbio, 65536);
+        wbio = BIO_push(buf_wbio, wbio);
+#endif
+        SSL_set_bio(ssl, rbio, wbio);
+      }

Review Comment:
   A buffered filter BIO is pushed onto the SSL wbio before the TLS handshake 
runs, but the handshake path (_ssl_accept / _sslStartHandShake) never calls 
BIO_flush. Because BIO_f_buffer can retain handshake records until flush / 
buffer-full, SSL_accept() may return WANT_READ while the ServerHello/etc are 
still stuck in the buffer, potentially stalling the handshake.



##########
src/iocore/net/SSLNetVConnection.cc:
##########
@@ -123,11 +123,26 @@ SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx)
 
       SSL_set_bio(ssl, bio, bio);
     } else {
-      this->initialize_handshake_buffers();
-      BIO *rbio = BIO_new(BIO_s_mem());
-      BIO *wbio = BIO_new_socket(this->get_socket(), BIO_NOCLOSE);
-      BIO_set_mem_eof_return(wbio, -1);
-      SSL_set_bio(ssl, rbio, wbio);
+      if (this->transparentPassThrough || this->allowPlain) {
+        // Blind-tunnel possible: keep handshake buffers to capture/replay the 
CLIENT_HELLO.
+        this->initialize_handshake_buffers();

Review Comment:
   This change skips handshake buffers unless transparent passthrough / 
allow-plain is enabled, but SSLNetVConnection::read_raw_data() (used during 
CLIENT_HELLO buffering) is also where PROXY protocol is parsed and the 
allowlist is enforced. With handshake buffers disabled, the PROXY header will 
be consumed by OpenSSL as TLS bytes and proxy protocol will no longer work on 
normal TLS ports.



##########
src/iocore/net/SSLNetVConnection.cc:
##########
@@ -796,6 +811,14 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, 
MIOBufferAccessor &buf
     Metrics::Counter::increment(net_rsb.calls_to_write);
   } while (num_really_written == try_to_write && total_written < towrite);
 
+  // Flush the buffer BIO once here, not per-record, so a response coalesces 
into
+  // one write(). No-op on a plain socket BIO.
+  if (total_written > 0) {
+    if (BIO *wbio = SSL_get_wbio(ssl); wbio != nullptr) {
+      (void)BIO_flush(wbio);
+    }
+  }

Review Comment:
   BIO_flush() return value is ignored. With a write-side buffer BIO, flush can 
fail / retry (e.g. EAGAIN) leaving encrypted bytes pending in the BIO. If the 
application buffer becomes empty, UnixNetVConnection::write_to_net() will 
disable further write events, so the pending BIO output may never be flushed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to