This is an automated email from the ASF dual-hosted git repository.

gavinchou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new c757cb88053 [fix](mysql) Fix SSL unwrap infinite loop on handshake 
failure (#57364)
c757cb88053 is described below

commit c757cb88053b6c6e56b9dcfb9b9a55d8ccf32e8b
Author: abmdocrt <[email protected]>
AuthorDate: Sat Nov 1 21:41:55 2025 +0800

    [fix](mysql) Fix SSL unwrap infinite loop on handshake failure (#57364)
---
 .../java/org/apache/doris/mysql/MysqlChannel.java  |  6 +-
 .../org/apache/doris/mysql/MysqlSslContext.java    |  7 +-
 .../org/apache/doris/mysql/SslEngineHelper.java    | 75 ++++++++++++++++++++++
 3 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlChannel.java 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlChannel.java
index 9edcd1c82ee..da3d251ceb5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlChannel.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlChannel.java
@@ -597,7 +597,7 @@ public class MysqlChannel implements BytesChannel {
             case OK:
                 return true;
             case CLOSED:
-                sslEngine.closeOutbound();
+                SslEngineHelper.checkClosedProgress("wrap", sslEngineResult, 
sslEngine, false);
                 return true;
             case BUFFER_OVERFLOW:
                 // Could attempt to drain the serverNetData buffer of any 
already obtained
@@ -615,13 +615,13 @@ public class MysqlChannel implements BytesChannel {
         }
     }
 
-    private boolean handleUnwrapResult(SSLEngineResult sslEngineResult) {
+    private boolean handleUnwrapResult(SSLEngineResult sslEngineResult) throws 
SSLException {
         switch (sslEngineResult.getStatus()) {
             // normal status.
             case OK:
                 return true;
             case CLOSED:
-                sslEngine.closeOutbound();
+                SslEngineHelper.checkClosedProgress("unwrap", sslEngineResult, 
sslEngine, true);
                 return true;
             case BUFFER_OVERFLOW:
                 // Could attempt to drain the clientAppData buffer of any 
already obtained
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSslContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSslContext.java
index b59b493ceaf..6283e795cfe 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSslContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlSslContext.java
@@ -227,14 +227,13 @@ public class MysqlSslContext {
         }
     }
 
-
     private boolean handleWrapResult(SSLEngineResult sslEngineResult) throws 
SSLException {
         switch (sslEngineResult.getStatus()) {
             // normal status.
             case OK:
                 return true;
             case CLOSED:
-                sslEngine.closeOutbound();
+                SslEngineHelper.checkClosedProgress("wrap", sslEngineResult, 
sslEngine, false);
                 return true;
             case BUFFER_OVERFLOW:
                 // Could attempt to drain the serverNetData buffer of any 
already obtained
@@ -252,13 +251,13 @@ public class MysqlSslContext {
         }
     }
 
-    private boolean handleUnwrapResult(SSLEngineResult sslEngineResult) {
+    private boolean handleUnwrapResult(SSLEngineResult sslEngineResult) throws 
SSLException {
         switch (sslEngineResult.getStatus()) {
             // normal status.
             case OK:
                 return true;
             case CLOSED:
-                sslEngine.closeOutbound();
+                SslEngineHelper.checkClosedProgress("unwrap", sslEngineResult, 
sslEngine, true);
                 return true;
             case BUFFER_OVERFLOW:
                 // Could attempt to drain the clientAppData buffer of any 
already obtained
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/SslEngineHelper.java 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/SslEngineHelper.java
new file mode 100644
index 00000000000..816088d1f2a
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/SslEngineHelper.java
@@ -0,0 +1,75 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.mysql;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+
+/**
+ * Helper class for SSL engine operations.
+ */
+public class SslEngineHelper {
+    private static final Logger LOG = 
LogManager.getLogger(SslEngineHelper.class);
+
+    /**
+     * Check if SSL engine operation has made progress when closed.
+     * @param operation operation name for logging ("wrap" or "unwrap")
+     * @param sslEngineResult the SSL engine result to check
+     * @param sslEngine the SSL engine instance
+     * @param closeInbound whether to close inbound (true for unwrap, false 
for wrap)
+     * @throws SSLException if no progress was made
+     */
+    public static void checkClosedProgress(String operation, SSLEngineResult 
sslEngineResult,
+                                           SSLEngine sslEngine, boolean 
closeInbound) throws SSLException {
+        int consumed = sslEngineResult.bytesConsumed();
+        int produced = sslEngineResult.bytesProduced();
+        if (consumed == 0 && produced == 0) {
+            LOG.warn("SSLEngine {} closed with no progress. status={}, 
handshake={}, "
+                    + "bytesConsumed={}, bytesProduced={}", operation,
+                    sslEngineResult.getStatus(), 
sslEngineResult.getHandshakeStatus(),
+                    consumed, produced);
+            if (closeInbound) {
+                try {
+                    sslEngine.closeInbound();
+                } catch (SSLException e) {
+                    LOG.warn("Error when closing SSL inbound during " + 
operation, e);
+                }
+            }
+            sslEngine.closeOutbound();
+            throw new SSLException("SSL " + operation + " closed with no 
progress (handshakeStatus="
+                    + sslEngineResult.getHandshakeStatus() + ", bytesConsumed="
+                    + consumed + ", bytesProduced=" + produced + ")");
+        }
+        if (closeInbound) {
+            try {
+                sslEngine.closeInbound();
+            } catch (SSLException e) {
+                LOG.debug("closeInbound on normal " + operation + " close 
failed", e);
+            }
+        }
+        LOG.debug("SSLEngine {} closed normally. status={}, handshake={}, "
+                + "bytesConsumed={}, bytesProduced={}", operation,
+                sslEngineResult.getStatus(), 
sslEngineResult.getHandshakeStatus(),
+                consumed, produced);
+        sslEngine.closeOutbound();
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to