Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java
38853 views
1
/*
2
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 7126889
27
* @summary Incorrect SSLEngine debug output
28
* @library /lib /lib/security
29
* @run main DebugReportsOneExtraByte
30
*/
31
/*
32
* Debug output was reporting n+1 bytes of data was written when it was
33
* really was n.
34
*
35
* SunJSSE does not support dynamic system properties, no way to re-use
36
* system properties in samevm/agentvm mode.
37
*/
38
39
/**
40
* A SSLEngine usage example which simplifies the presentation
41
* by removing the I/O and multi-threading concerns.
42
*
43
* The test creates two SSLEngines, simulating a client and server.
44
* The "transport" layer consists two byte buffers: think of them
45
* as directly connected pipes.
46
*
47
* Note, this is a *very* simple example: real code will be much more
48
* involved. For example, different threading and I/O models could be
49
* used, transport mechanisms could close unexpectedly, and so on.
50
*
51
* When this application runs, notice that several messages
52
* (wrap/unwrap) pass before any application data is consumed or
53
* produced. (For more information, please see the SSL/TLS
54
* specifications.) There may several steps for a successful handshake,
55
* so it's typical to see the following series of operations:
56
*
57
* client server message
58
* ====== ====== =======
59
* wrap() ... ClientHello
60
* ... unwrap() ClientHello
61
* ... wrap() ServerHello/Certificate
62
* unwrap() ... ServerHello/Certificate
63
* wrap() ... ClientKeyExchange
64
* wrap() ... ChangeCipherSpec
65
* wrap() ... Finished
66
* ... unwrap() ClientKeyExchange
67
* ... unwrap() ChangeCipherSpec
68
* ... unwrap() Finished
69
* ... wrap() ChangeCipherSpec
70
* ... wrap() Finished
71
* unwrap() ... ChangeCipherSpec
72
* unwrap() ... Finished
73
*/
74
75
import javax.net.ssl.*;
76
import javax.net.ssl.SSLEngineResult.*;
77
import java.io.*;
78
import java.security.*;
79
import java.nio.*;
80
81
import jdk.test.lib.process.OutputAnalyzer;
82
import jdk.test.lib.process.ProcessTools;
83
84
public class DebugReportsOneExtraByte {
85
86
/*
87
* Enables logging of the SSLEngine operations.
88
*/
89
private static boolean logging = true;
90
91
private SSLContext sslc;
92
93
private SSLEngine clientEngine; // client Engine
94
private ByteBuffer clientOut; // write side of clientEngine
95
private ByteBuffer clientIn; // read side of clientEngine
96
97
private SSLEngine serverEngine; // server Engine
98
private ByteBuffer serverOut; // write side of serverEngine
99
private ByteBuffer serverIn; // read side of serverEngine
100
101
/*
102
* For data transport, this example uses local ByteBuffers. This
103
* isn't really useful, but the purpose of this example is to show
104
* SSLEngine concepts, not how to do network transport.
105
*/
106
private ByteBuffer cTOs; // "reliable" transport client->server
107
private ByteBuffer sTOc; // "reliable" transport server->client
108
109
/*
110
* The following is to set up the keystores.
111
*/
112
private static String pathToStores = "../../../../javax/net/ssl/etc";
113
private static String keyStoreFile = "keystore";
114
private static String trustStoreFile = "truststore";
115
private static String passwd = "passphrase";
116
117
private static String keyFilename =
118
System.getProperty("test.src", ".") + "/" + pathToStores +
119
"/" + keyStoreFile;
120
private static String trustFilename =
121
System.getProperty("test.src", ".") + "/" + pathToStores +
122
"/" + trustStoreFile;
123
124
/*
125
* Main entry point for this test.
126
*/
127
public static void main(String args[]) throws Exception {
128
129
if (args.length == 0) {
130
OutputAnalyzer output = ProcessTools.executeTestJvm(
131
"-Dtest.src=" + System.getProperty("test.src"),
132
"-Djavax.net.debug=all", "DebugReportsOneExtraByte", "p");
133
output.shouldContain("WRITE: TLS10 application_data, length = 8");
134
135
System.out.println("Test Passed.");
136
} else {
137
// Re-enable TLSv1 since test depends on it
138
SecurityUtils.removeFromDisabledTlsAlgs("TLSv1");
139
140
DebugReportsOneExtraByte test = new DebugReportsOneExtraByte();
141
test.runTest();
142
}
143
}
144
145
/*
146
* Create an initialized SSLContext to use for these tests.
147
*/
148
public DebugReportsOneExtraByte() throws Exception {
149
150
KeyStore ks = KeyStore.getInstance("JKS");
151
KeyStore ts = KeyStore.getInstance("JKS");
152
153
char[] passphrase = "passphrase".toCharArray();
154
155
ks.load(new FileInputStream(keyFilename), passphrase);
156
ts.load(new FileInputStream(trustFilename), passphrase);
157
158
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
159
kmf.init(ks, passphrase);
160
161
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
162
tmf.init(ts);
163
164
SSLContext sslCtx = SSLContext.getInstance("TLSv1");
165
166
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
167
168
sslc = sslCtx;
169
}
170
171
/*
172
* Run the test.
173
*
174
* Sit in a tight loop, both engines calling wrap/unwrap regardless
175
* of whether data is available or not. We do this until both engines
176
* report back they are closed.
177
*
178
* The main loop handles all of the I/O phases of the SSLEngine's
179
* lifetime:
180
*
181
* initial handshaking
182
* application data transfer
183
* engine closing
184
*
185
* One could easily separate these phases into separate
186
* sections of code.
187
*/
188
private void runTest() throws Exception {
189
boolean dataDone = false;
190
191
createSSLEngines();
192
createBuffers();
193
194
SSLEngineResult clientResult; // results from client's last operation
195
SSLEngineResult serverResult; // results from server's last operation
196
197
/*
198
* Examining the SSLEngineResults could be much more involved,
199
* and may alter the overall flow of the application.
200
*
201
* For example, if we received a BUFFER_OVERFLOW when trying
202
* to write to the output pipe, we could reallocate a larger
203
* pipe, but instead we wait for the peer to drain it.
204
*/
205
206
/*
207
* Write one byte in first application packet, the rest
208
* will come later.
209
*/
210
serverOut.limit(1);
211
212
while (!isEngineClosed(clientEngine) ||
213
!isEngineClosed(serverEngine)) {
214
215
log("================");
216
217
clientResult = clientEngine.wrap(clientOut, cTOs);
218
log("client wrap: ", clientResult);
219
runDelegatedTasks(clientResult, clientEngine);
220
221
serverResult = serverEngine.wrap(serverOut, sTOc);
222
log("server wrap: ", serverResult);
223
runDelegatedTasks(serverResult, serverEngine);
224
225
// Next wrap will split.
226
if (serverOut.position() == 1) {
227
serverOut.limit(serverOut.capacity());
228
}
229
230
cTOs.flip();
231
sTOc.flip();
232
233
log("----");
234
235
clientResult = clientEngine.unwrap(sTOc, clientIn);
236
log("client unwrap: ", clientResult);
237
runDelegatedTasks(clientResult, clientEngine);
238
239
serverResult = serverEngine.unwrap(cTOs, serverIn);
240
log("server unwrap: ", serverResult);
241
runDelegatedTasks(serverResult, serverEngine);
242
243
cTOs.compact();
244
sTOc.compact();
245
246
/*
247
* After we've transfered all application data between the client
248
* and server, we close the clientEngine's outbound stream.
249
* This generates a close_notify handshake message, which the
250
* server engine receives and responds by closing itself.
251
*/
252
if (!dataDone && (clientOut.limit() == serverIn.position()) &&
253
(serverOut.limit() == clientIn.position())) {
254
255
/*
256
* A sanity check to ensure we got what was sent.
257
*/
258
checkTransfer(serverOut, clientIn);
259
checkTransfer(clientOut, serverIn);
260
261
log("\tClosing clientEngine's *OUTBOUND*...");
262
clientEngine.closeOutbound();
263
dataDone = true;
264
}
265
}
266
}
267
268
/*
269
* Using the SSLContext created during object creation,
270
* create/configure the SSLEngines we'll use for this test.
271
*/
272
private void createSSLEngines() throws Exception {
273
/*
274
* Configure the serverEngine to act as a server in the SSL/TLS
275
* handshake. Also, require SSL client authentication.
276
*/
277
serverEngine = sslc.createSSLEngine();
278
serverEngine.setUseClientMode(false);
279
serverEngine.setNeedClientAuth(true);
280
281
// Force a block-oriented ciphersuite.
282
serverEngine.setEnabledCipherSuites(
283
new String [] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
284
285
/*
286
* Similar to above, but using client mode instead.
287
*/
288
clientEngine = sslc.createSSLEngine("client", 80);
289
clientEngine.setUseClientMode(true);
290
}
291
292
/*
293
* Create and size the buffers appropriately.
294
*/
295
private void createBuffers() {
296
297
/*
298
* We'll assume the buffer sizes are the same
299
* between client and server.
300
*/
301
SSLSession session = clientEngine.getSession();
302
int appBufferMax = session.getApplicationBufferSize();
303
int netBufferMax = session.getPacketBufferSize();
304
305
/*
306
* We'll make the input buffers a bit bigger than the max needed
307
* size, so that unwrap()s following a successful data transfer
308
* won't generate BUFFER_OVERFLOWS.
309
*
310
* We'll use a mix of direct and indirect ByteBuffers for
311
* tutorial purposes only. In reality, only use direct
312
* ByteBuffers when they give a clear performance enhancement.
313
*/
314
clientIn = ByteBuffer.allocate(appBufferMax + 50);
315
serverIn = ByteBuffer.allocate(appBufferMax + 50);
316
317
cTOs = ByteBuffer.allocateDirect(netBufferMax);
318
sTOc = ByteBuffer.allocateDirect(netBufferMax);
319
320
// No need to write anything on the client side, it will
321
// just confuse the output.
322
clientOut = ByteBuffer.wrap("".getBytes());
323
// 10 bytes long
324
serverOut = ByteBuffer.wrap("Hi Client!".getBytes());
325
}
326
327
/*
328
* If the result indicates that we have outstanding tasks to do,
329
* go ahead and run them in this thread.
330
*/
331
private static void runDelegatedTasks(SSLEngineResult result,
332
SSLEngine engine) throws Exception {
333
334
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
335
Runnable runnable;
336
while ((runnable = engine.getDelegatedTask()) != null) {
337
log("\trunning delegated task...");
338
runnable.run();
339
}
340
HandshakeStatus hsStatus = engine.getHandshakeStatus();
341
if (hsStatus == HandshakeStatus.NEED_TASK) {
342
throw new Exception(
343
"handshake shouldn't need additional tasks");
344
}
345
log("\tnew HandshakeStatus: " + hsStatus);
346
}
347
}
348
349
private static boolean isEngineClosed(SSLEngine engine) {
350
return (engine.isOutboundDone() && engine.isInboundDone());
351
}
352
353
/*
354
* Simple check to make sure everything came across as expected.
355
*/
356
private static void checkTransfer(ByteBuffer a, ByteBuffer b)
357
throws Exception {
358
a.flip();
359
b.flip();
360
361
if (!a.equals(b)) {
362
throw new Exception("Data didn't transfer cleanly");
363
} else {
364
log("\tData transferred cleanly");
365
}
366
367
a.position(a.limit());
368
b.position(b.limit());
369
a.limit(a.capacity());
370
b.limit(b.capacity());
371
}
372
373
/*
374
* Logging code
375
*/
376
private static boolean resultOnce = true;
377
378
private static void log(String str, SSLEngineResult result) {
379
if (!logging) {
380
return;
381
}
382
if (resultOnce) {
383
resultOnce = false;
384
System.out.println("The format of the SSLEngineResult is: \n" +
385
"\t\"getStatus() / getHandshakeStatus()\" +\n" +
386
"\t\"bytesConsumed() / bytesProduced()\"\n");
387
}
388
HandshakeStatus hsStatus = result.getHandshakeStatus();
389
log(str +
390
result.getStatus() + "/" + hsStatus + ", " +
391
result.bytesConsumed() + "/" + result.bytesProduced() +
392
" bytes");
393
if (hsStatus == HandshakeStatus.FINISHED) {
394
log("\t...ready for application data");
395
}
396
}
397
398
private static void log(String str) {
399
if (logging) {
400
System.out.println(str);
401
}
402
}
403
}
404
405