1 Star 0 Fork 81

zhaosai/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
8273553-sun.security.ssl.SSLEngineImpl.closeInbound-.patch 22.57 KB
一键复制 编辑 原始数据 按行查看 历史
kuen 提交于 2024-01-18 15:17 . I8X6CH: upgrade to 8u402
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
From 4e32bc622c1f73c2ab6a4ef4b4bbd92e381a3439 Mon Sep 17 00:00:00 2001
From: zhangyipeng <zhangyipeng7@huawei.com>
Date: Mon, 15 Jan 2024 11:11:41 +0800
Subject: [PATCH] [Backport]8273553: sun.security.ssl.SSLEngineImpl.closeInbound also has
similar error of JDK-8253368
---
.../classes/sun/security/ssl/SSLEngineImpl.java | 24 +-
.../classes/sun/security/ssl/SSLSocketImpl.java | 7 +-
.../SSLSocketSSLEngineCloseInbound.java | 491 +++++++++++++++++++++
3 files changed, 508 insertions(+), 14 deletions(-)
create mode 100644 jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java
diff --git a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java
index 05ffb8a00..a9cc989f2 100644
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java
@@ -47,7 +47,7 @@ import javax.net.ssl.SSLProtocolException;
import javax.net.ssl.SSLSession;
/**
- * Implementation of an non-blocking SSLEngine.
+ * Implementation of a non-blocking SSLEngine.
*
* @author Brad Wetmore
*/
@@ -230,7 +230,7 @@ final class SSLEngineImpl extends SSLEngine implements SSLTransport {
if (ciphertext == null && !conContext.isNegotiated &&
conContext.isInboundClosed() &&
hsStatus == HandshakeStatus.NEED_WRAP) {
- // Even the outboud is open, no futher data could be wrapped as:
+ // Even the outbound is open, no further data could be wrapped as:
// 1. the outbound is empty
// 2. no negotiated connection
// 3. the inbound has closed, cannot complete the handshake
@@ -631,17 +631,19 @@ final class SSLEngineImpl extends SSLEngine implements SSLTransport {
SSLLogger.finest("Closing inbound of SSLEngine");
}
- // Is it ready to close inbound?
- //
- // No need to throw exception if the initial handshake is not started.
- if (!conContext.isInputCloseNotified &&
- (conContext.isNegotiated || conContext.handshakeContext != null)) {
- throw conContext.fatal(Alert.INTERNAL_ERROR,
- "closing inbound before receiving peer's close_notify");
+ try {
+ // Is it ready to close inbound?
+ //
+ // No need to throw exception if the initial handshake is not started.
+ if (!conContext.isInputCloseNotified &&
+ (conContext.isNegotiated || conContext.handshakeContext != null)) {
+ throw new SSLException(
+ "closing inbound before receiving peer's close_notify");
+ }
+ } finally {
+ conContext.closeInbound();
}
-
- conContext.closeInbound();
}
@Override
diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
index 69c96f226..7e8b131bb 100644
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
@@ -742,9 +742,10 @@ public final class SSLSocketImpl
// No need to throw exception if the initial handshake is not started.
try {
if (checkCloseNotify && !conContext.isInputCloseNotified &&
- (conContext.isNegotiated || conContext.handshakeContext != null)) {
- throw new SSLException(
- "closing inbound before receiving peer's close_notify");
+ (conContext.isNegotiated ||
+ conContext.handshakeContext != null)) {
+ throw new SSLException(
+ "closing inbound before receiving peer's close_notify");
}
} finally {
conContext.closeInbound();
diff --git a/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java
new file mode 100644
index 000000000..abf1571ca
--- /dev/null
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8273553 8253368
+ * @summary sun.security.ssl.SSLEngineImpl.closeInbound also has similar error
+ * of JDK-8253368
+ * @run main/othervm SSLSocketSSLEngineCloseInbound TLSv1.3
+ * @run main/othervm SSLSocketSSLEngineCloseInbound TLSv1.2
+ * @run main/othervm SSLSocketSSLEngineCloseInbound TLSv1.1
+ * @run main/othervm SSLSocketSSLEngineCloseInbound TLSv1
+ * @run main/othervm SSLSocketSSLEngineCloseInbound TLS
+ */
+
+/**
+ * A SSLSocket/SSLEngine interop test case. This is not the way to
+ * code SSLEngine-based servers, but works for what we need to do here,
+ * which is to make sure that SSLEngine/SSLSockets can talk to each other.
+ * SSLEngines can use direct or indirect buffers, and different code
+ * is used to get at the buffer contents internally, so we test that here.
+ *
+ * The test creates one SSLSocket (client) and one SSLEngine (server).
+ * The SSLSocket talks to a raw ServerSocket, and the server code
+ * does the translation between byte [] and ByteBuffers that the SSLEngine
+ * can use. The "transport" layer consists of a Socket Input/OutputStream
+ * and two byte buffers for the SSLEngines: think of them
+ * as directly connected pipes.
+ *
+ * Again, this is a *very* simple example: real code will be much more
+ * involved. For example, different threading and I/O models could be
+ * used, transport mechanisms could close unexpectedly, and so on.
+ *
+ * When this application runs, notice that several messages
+ * (wrap/unwrap) pass before any application data is consumed or
+ * produced. (For more information, please see the SSL/TLS
+ * specifications.) There may several steps for a successful handshake,
+ * so it's typical to see the following series of operations:
+ *
+ * client server message
+ * ====== ====== =======
+ * write() ... ClientHello
+ * ... unwrap() ClientHello
+ * ... wrap() ServerHello/Certificate
+ * read() ... ServerHello/Certificate
+ * write() ... ClientKeyExchange
+ * write() ... ChangeCipherSpec
+ * write() ... Finished
+ * ... unwrap() ClientKeyExchange
+ * ... unwrap() ChangeCipherSpec
+ * ... unwrap() Finished
+ * ... wrap() ChangeCipherSpec
+ * ... wrap() Finished
+ * read() ... ChangeCipherSpec
+ * read() ... Finished
+ */
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.nio.*;
+
+public class SSLSocketSSLEngineCloseInbound {
+
+ /*
+ * Enables logging of the SSL/TLS operations.
+ */
+ private static final boolean logging = true;
+
+ /*
+ * Enables the JSSE system debugging system property:
+ *
+ * -Djavax.net.debug=all
+ *
+ * This gives a lot of low-level information about operations underway,
+ * including specific handshake messages, and might be best examined
+ * after gaining some familiarity with this application.
+ */
+ private static final boolean debug = false;
+ private final SSLContext sslc;
+ private SSLEngine serverEngine; // server-side SSLEngine
+ private SSLSocket clientSocket;
+
+ private final byte[] serverMsg =
+ "Hi there Client, I'm a Server.".getBytes();
+ private final byte[] clientMsg =
+ "Hello Server, I'm a Client! Pleased to meet you!".getBytes();
+
+ private ByteBuffer serverOut; // write side of serverEngine
+ private ByteBuffer serverIn; // read side of serverEngine
+
+ private volatile Exception clientException;
+ private volatile Exception serverException;
+
+ /*
+ * For data transport, this example uses local ByteBuffers.
+ */
+ private ByteBuffer cTOs; // "reliable" transport client->server
+ private ByteBuffer sTOc; // "reliable" transport server->client
+
+ /*
+ * The following is to set up the keystores/trust material.
+ */
+ private static final String pathToStores = "../../../../javax/net/ssl/etc";
+ private static final String keyStoreFile = "keystore";
+ private static final String trustStoreFile = "truststore";
+ private static final String keyFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores
+ + "/" + keyStoreFile;
+ private static final String trustFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores
+ + "/" + trustStoreFile;
+
+ /*
+ * Main entry point for this test.
+ */
+ public static void main(String[] args) throws Exception {
+ String protocol = args[0];
+
+ // reset security properties to make sure that the algorithms
+ // and keys used in this test are not disabled.
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+ Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+
+ if (debug) {
+ System.setProperty("javax.net.debug", "all");
+ }
+
+ /*
+ * Run the tests with direct and indirect buffers.
+ */
+ SSLSocketSSLEngineCloseInbound test =
+ new SSLSocketSSLEngineCloseInbound(protocol);
+ log("-------------------------------------");
+ log("Testing " + protocol + " for direct buffers ...");
+ test.runTest(true);
+
+ log("---------------------------------------");
+ log("Testing " + protocol + " for indirect buffers ...");
+ test.runTest(false);
+
+ log("Test Passed.");
+ }
+
+ /*
+ * Create an initialized SSLContext to use for these tests.
+ */
+ public SSLSocketSSLEngineCloseInbound(String protocol) throws Exception {
+
+ KeyStore ks = KeyStore.getInstance("JKS");
+ KeyStore ts = KeyStore.getInstance("JKS");
+
+ char[] passphrase = "passphrase".toCharArray();
+
+ try (FileInputStream keyFile = new FileInputStream(keyFilename);
+ FileInputStream trustFile = new FileInputStream(trustFilename)) {
+ ks.load(keyFile, passphrase);
+ ts.load(trustFile, passphrase);
+ }
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ts);
+
+ SSLContext sslCtx = SSLContext.getInstance(protocol);
+
+ sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+ sslc = sslCtx;
+ }
+
+ /*
+ * Run the test.
+ *
+ * Sit in a tight loop, with the server engine calling wrap/unwrap
+ * regardless of whether data is available or not. We do this until
+ * we get the application data. Then we shutdown and go to the next one.
+ *
+ * The main loop handles all the I/O phases of the SSLEngine's
+ * lifetime:
+ *
+ * initial handshaking
+ * application data transfer
+ * engine closing
+ *
+ * One could easily separate these phases into separate
+ * sections of code.
+ */
+ private void runTest(boolean direct) throws Exception {
+ clientSocket = null;
+
+ // generates the server-side Socket
+ try (ServerSocket serverSocket = new ServerSocket()) {
+ serverSocket.setReuseAddress(false);
+ serverSocket.bind(null);
+ int port = serverSocket.getLocalPort();
+ log("Port: " + port);
+ Thread thread = createClientThread(port);
+
+ createSSLEngine();
+ createBuffers(direct);
+
+ // server-side socket that will read
+ try (Socket socket = serverSocket.accept()) {
+ socket.setSoTimeout(500);
+
+ InputStream is = socket.getInputStream();
+ OutputStream os = socket.getOutputStream();
+
+ SSLEngineResult serverResult; // results from last operation
+
+ /*
+ * Examining the SSLEngineResults could be much more involved,
+ * and may alter the overall flow of the application.
+ *
+ * For example, if we received a BUFFER_OVERFLOW when trying
+ * to write to the output pipe, we could reallocate a larger
+ * pipe, but instead we wait for the peer to drain it.
+ */
+ byte[] inbound = new byte[8192];
+ byte[] outbound = new byte[8192];
+
+ while (!isEngineClosed(serverEngine)) {
+ int len;
+
+ // Inbound data
+ log("================");
+
+ // Try reading Client side, even if it's already closed.
+ try {
+ len = is.read(inbound);
+ if (len > 0) {
+ cTOs.put(inbound, 0, len);
+ }
+ } catch (IOException e) {
+ /*
+ * swallow IO/SocketTimeoutExceptions. We'll do
+ * the testing/exit after the unwraps.
+ */
+ }
+
+ cTOs.flip();
+
+ serverResult = serverEngine.unwrap(cTOs, serverIn);
+ log("server unwrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+ cTOs.compact();
+
+ // Outbound data
+ log("----");
+
+ // After we've received our app bytes, close input side
+ // and see what happens. Exit the test at the end.
+ if (serverIn.position() != 0) {
+ try {
+ serverEngine.closeInbound();
+ throw new Exception(
+ "No error shutting down client's input");
+ } catch (SSLException e) {
+ System.out.println(
+ "Server caught the right Exception");
+ }
+
+ if (serverEngine.getSession().isValid()) {
+ System.out.println("Server session is still valid");
+ } else {
+ throw new Exception("Server session is not valid");
+ }
+
+ return;
+ }
+
+ serverResult = serverEngine.wrap(serverOut, sTOc);
+ log("server wrap: ", serverResult);
+ runDelegatedTasks(serverResult, serverEngine);
+
+ sTOc.flip();
+
+ if ((len = sTOc.remaining()) != 0) {
+ sTOc.get(outbound, 0, len);
+ os.write(outbound, 0, len);
+ // Give the other side a chance to process
+ }
+
+ sTOc.compact();
+ }
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ // Wait for the client to join up with us.
+ if (thread != null) {
+ thread.join();
+ }
+ }
+ } finally {
+ if (serverException != null) {
+ if (clientException != null) {
+ serverException.initCause(clientException);
+ }
+ throw serverException;
+ }
+ if (clientException != null) {
+ if (serverException != null) {
+ clientException.initCause(serverException);
+ }
+ throw clientException;
+ }
+ }
+ }
+
+ /*
+ * Create a client thread which does simple SSLSocket operations.
+ * We'll write and read one data packet.
+ */
+ private Thread createClientThread(final int port) {
+
+ Thread t = new Thread("ClientThread") {
+
+ @Override
+ public void run() {
+ // client-side socket
+ try (SSLSocket sslSocket = (SSLSocket)sslc.getSocketFactory().
+ createSocket("localhost", port)) {
+ clientSocket = sslSocket;
+
+ OutputStream os = sslSocket.getOutputStream();
+
+ // write(byte[]) goes in one shot.
+ os.write(clientMsg);
+ os.flush();
+
+ try {
+ sslSocket.shutdownInput();
+ throw new Exception(
+ "No error shutting down client's input");
+ } catch (SSLException e) {
+ System.out.println("Client caught the right Exception");
+ }
+
+ if (sslSocket.getSession().isValid()) {
+ System.out.println("Client session is still valid");
+ } else {
+ throw new Exception("Client's session is not valid");
+ }
+
+ // Give server a chance to read before we shutdown via
+ // the try-with-resources block.
+ Thread.sleep(2000);
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ };
+ t.start();
+ return t;
+ }
+
+ /*
+ * Using the SSLContext created during object creation,
+ * create/configure the SSLEngines we'll use for this test.
+ */
+ private void createSSLEngine() {
+ /*
+ * Configure the serverEngine to act as a server in the SSL/TLS
+ * handshake.
+ */
+ serverEngine = sslc.createSSLEngine();
+ serverEngine.setUseClientMode(false);
+ serverEngine.getNeedClientAuth();
+ }
+
+ /*
+ * Create and size the buffers appropriately.
+ */
+ private void createBuffers(boolean direct) {
+
+ SSLSession session = serverEngine.getSession();
+ int appBufferMax = session.getApplicationBufferSize();
+ int netBufferMax = session.getPacketBufferSize();
+
+ /*
+ * We'll make the input buffers a bit bigger than the max needed
+ * size, so that unwrap()s following a successful data transfer
+ * won't generate BUFFER_OVERFLOWS.
+ *
+ * We'll use a mix of direct and indirect ByteBuffers for
+ * tutorial purposes only. In reality, only use direct
+ * ByteBuffers when they give a clear performance enhancement.
+ */
+ if (direct) {
+ serverIn = ByteBuffer.allocateDirect(appBufferMax + 50);
+ cTOs = ByteBuffer.allocateDirect(netBufferMax);
+ sTOc = ByteBuffer.allocateDirect(netBufferMax);
+ } else {
+ serverIn = ByteBuffer.allocate(appBufferMax + 50);
+ cTOs = ByteBuffer.allocate(netBufferMax);
+ sTOc = ByteBuffer.allocate(netBufferMax);
+ }
+
+ serverOut = ByteBuffer.wrap(serverMsg);
+ }
+
+ /*
+ * If the result indicates that we have outstanding tasks to do,
+ * go ahead and run them in this thread.
+ */
+ private static void runDelegatedTasks(SSLEngineResult result,
+ SSLEngine engine) throws Exception {
+
+ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable runnable;
+ while ((runnable = engine.getDelegatedTask()) != null) {
+ log("\trunning delegated task...");
+ runnable.run();
+ }
+ HandshakeStatus hsStatus = engine.getHandshakeStatus();
+ if (hsStatus == HandshakeStatus.NEED_TASK) {
+ throw new Exception(
+ "handshake shouldn't need additional tasks");
+ }
+ log("\tnew HandshakeStatus: " + hsStatus);
+ }
+ }
+
+ private static boolean isEngineClosed(SSLEngine engine) {
+ return (engine.isOutboundDone() && engine.isInboundDone());
+ }
+
+ /*
+ * Logging code
+ */
+ private static boolean resultOnce = true;
+
+ private static void log(String str, SSLEngineResult result) {
+ if (!logging) {
+ return;
+ }
+ if (resultOnce) {
+ resultOnce = false;
+ log("The format of the SSLEngineResult is: \n"
+ + "\t\"getStatus() / getHandshakeStatus()\" +\n"
+ + "\t\"bytesConsumed() / bytesProduced()\"\n");
+ }
+ HandshakeStatus hsStatus = result.getHandshakeStatus();
+ log(str
+ + result.getStatus() + "/" + hsStatus + ", "
+ + result.bytesConsumed() + "/" + result.bytesProduced()
+ + " bytes");
+ if (hsStatus == HandshakeStatus.FINISHED) {
+ log("\t...ready for application data");
+ }
+ }
+
+ private static void log(String str) {
+ if (logging) {
+ if (debug) {
+ System.err.println(str);
+ } else {
+ System.out.println(str);
+ }
+ }
+ }
+}
--
2.12.3
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhaosai-Simon/openjdk-1.8.0.git
git@gitee.com:zhaosai-Simon/openjdk-1.8.0.git
zhaosai-Simon
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助