Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
41152 views
1
/*
2
* Copyright (c) 2011, 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
// SunJSSE does not support dynamic system properties, no way to re-use
26
// system properties in samevm/agentvm mode.
27
//
28
29
/*
30
* @test
31
* @bug 7031830
32
* @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine
33
* @library /test/lib
34
* @run main/othervm SSLEngineBadBufferArrayAccess
35
*/
36
37
/**
38
* A SSLSocket/SSLEngine interop test case. This is not the way to
39
* code SSLEngine-based servers, but works for what we need to do here,
40
* which is to make sure that SSLEngine/SSLSockets can talk to each other.
41
* SSLEngines can use direct or indirect buffers, and different code
42
* is used to get at the buffer contents internally, so we test that here.
43
*
44
* The test creates one SSLSocket (client) and one SSLEngine (server).
45
* The SSLSocket talks to a raw ServerSocket, and the server code
46
* does the translation between byte [] and ByteBuffers that the SSLEngine
47
* can use. The "transport" layer consists of a Socket Input/OutputStream
48
* and two byte buffers for the SSLEngines: think of them
49
* as directly connected pipes.
50
*
51
* Again, this is a *very* simple example: real code will be much more
52
* involved. For example, different threading and I/O models could be
53
* used, transport mechanisms could close unexpectedly, and so on.
54
*
55
* When this application runs, notice that several messages
56
* (wrap/unwrap) pass before any application data is consumed or
57
* produced. (For more information, please see the SSL/TLS
58
* specifications.) There may several steps for a successful handshake,
59
* so it's typical to see the following series of operations:
60
*
61
* client server message
62
* ====== ====== =======
63
* write() ... ClientHello
64
* ... unwrap() ClientHello
65
* ... wrap() ServerHello/Certificate
66
* read() ... ServerHello/Certificate
67
* write() ... ClientKeyExchange
68
* write() ... ChangeCipherSpec
69
* write() ... Finished
70
* ... unwrap() ClientKeyExchange
71
* ... unwrap() ChangeCipherSpec
72
* ... unwrap() Finished
73
* ... wrap() ChangeCipherSpec
74
* ... wrap() Finished
75
* read() ... ChangeCipherSpec
76
* read() ... Finished
77
*
78
* This particular bug had a problem where byte buffers backed by an
79
* array didn't offset correctly, and we got bad MAC errors.
80
*/
81
import javax.net.ssl.*;
82
import javax.net.ssl.SSLEngineResult.*;
83
import java.io.*;
84
import java.net.*;
85
import java.security.*;
86
import java.nio.*;
87
import java.util.concurrent.CountDownLatch;
88
import java.util.concurrent.TimeUnit;
89
90
import jdk.test.lib.security.SecurityUtils;
91
92
public class SSLEngineBadBufferArrayAccess {
93
94
/*
95
* Enables logging of the SSL/TLS operations.
96
*/
97
private static boolean logging = true;
98
99
/*
100
* Enables the JSSE system debugging system property:
101
*
102
* -Djavax.net.debug=all
103
*
104
* This gives a lot of low-level information about operations underway,
105
* including specific handshake messages, and might be best examined
106
* after gaining some familiarity with this application.
107
*/
108
private static boolean debug = false;
109
private SSLContext sslc;
110
private SSLEngine serverEngine; // server-side SSLEngine
111
112
private final byte[] serverMsg = "Hi there Client, I'm a Server".getBytes();
113
private final byte[] clientMsg = "Hello Server, I'm a Client".getBytes();
114
115
private ByteBuffer serverOut; // write side of serverEngine
116
private ByteBuffer serverIn; // read side of serverEngine
117
118
private volatile Exception clientException;
119
private volatile Exception serverException;
120
121
/*
122
* For data transport, this example uses local ByteBuffers.
123
*/
124
private ByteBuffer cTOs; // "reliable" transport client->server
125
private ByteBuffer sTOc; // "reliable" transport server->client
126
127
/*
128
* The following is to set up the keystores/trust material.
129
*/
130
private static final String pathToStores = "../../../../javax/net/ssl/etc";
131
private static final String keyStoreFile = "keystore";
132
private static final String trustStoreFile = "truststore";
133
private static final String passwd = "passphrase";
134
private static String keyFilename =
135
System.getProperty("test.src", ".") + "/" + pathToStores
136
+ "/" + keyStoreFile;
137
private static String trustFilename =
138
System.getProperty("test.src", ".") + "/" + pathToStores
139
+ "/" + trustStoreFile;
140
141
/*
142
* Is the server ready to serve?
143
*/
144
private static final CountDownLatch serverCondition = new CountDownLatch(1);
145
146
/*
147
* Is the client ready to handshake?
148
*/
149
private static final CountDownLatch clientCondition = new CountDownLatch(1);
150
151
/*
152
* What's the server port? Use any free port by default
153
*/
154
private volatile int serverPort = 0;
155
156
/*
157
* Main entry point for this test.
158
*/
159
public static void main(String args[]) throws Exception {
160
if (debug) {
161
System.setProperty("javax.net.debug", "all");
162
}
163
164
// Re-enable TLSv1 and TLSv1.1 since test depends on them.
165
SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1");
166
167
String [] protocols = new String [] {
168
"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" };
169
170
for (String protocol : protocols) {
171
/*
172
* Run the tests with direct and indirect buffers.
173
*/
174
log("Testing " + protocol + ":true");
175
new SSLEngineBadBufferArrayAccess(protocol).runTest(true);
176
177
log("Testing " + protocol + ":false");
178
new SSLEngineBadBufferArrayAccess(protocol).runTest(false);
179
}
180
181
System.out.println("Test Passed.");
182
}
183
184
/*
185
* Create an initialized SSLContext to use for these tests.
186
*/
187
public SSLEngineBadBufferArrayAccess(String protocol) throws Exception {
188
189
KeyStore ks = KeyStore.getInstance("JKS");
190
KeyStore ts = KeyStore.getInstance("JKS");
191
192
char[] passphrase = "passphrase".toCharArray();
193
194
try (FileInputStream fis = new FileInputStream(keyFilename)) {
195
ks.load(fis, passphrase);
196
}
197
198
try (FileInputStream fis = new FileInputStream(trustFilename)) {
199
ts.load(fis, passphrase);
200
}
201
202
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
203
kmf.init(ks, passphrase);
204
205
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
206
tmf.init(ts);
207
208
SSLContext sslCtx = SSLContext.getInstance(protocol);
209
210
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
211
212
sslc = sslCtx;
213
}
214
215
/*
216
* Run the test.
217
*
218
* Sit in a tight loop, with the server engine calling wrap/unwrap
219
* regardless of whether data is available or not. We do this until
220
* we get the application data. Then we shutdown and go to the next one.
221
*
222
* The main loop handles all of the I/O phases of the SSLEngine's
223
* lifetime:
224
*
225
* initial handshaking
226
* application data transfer
227
* engine closing
228
*
229
* One could easily separate these phases into separate
230
* sections of code.
231
*/
232
private void runTest(boolean direct) throws Exception {
233
boolean serverClose = direct;
234
235
ServerSocket serverSocket = new ServerSocket(0);
236
serverPort = serverSocket.getLocalPort();
237
238
// Signal the client, the server is ready to accept connection.
239
serverCondition.countDown();
240
241
Thread clientThread = runClient(serverClose);
242
243
// Try to accept a connection in 30 seconds.
244
Socket socket;
245
try {
246
serverSocket.setSoTimeout(30000);
247
socket = (Socket) serverSocket.accept();
248
} catch (SocketTimeoutException ste) {
249
serverSocket.close();
250
251
// Ignore the test case if no connection within 30 seconds.
252
System.out.println(
253
"No incoming client connection in 30 seconds. " +
254
"Ignore in server side.");
255
return;
256
}
257
258
// handle the connection
259
try {
260
// Is it the expected client connection?
261
//
262
// Naughty test cases or third party routines may try to
263
// connection to this server port unintentionally. In
264
// order to mitigate the impact of unexpected client
265
// connections and avoid intermittent failure, it should
266
// be checked that the accepted connection is really linked
267
// to the expected client.
268
boolean clientIsReady =
269
clientCondition.await(30L, TimeUnit.SECONDS);
270
271
if (clientIsReady) {
272
// Run the application in server side.
273
runServerApplication(socket, direct, serverClose);
274
} else { // Otherwise, ignore
275
// We don't actually care about plain socket connections
276
// for TLS communication testing generally. Just ignore
277
// the test if the accepted connection is not linked to
278
// the expected client or the client connection timeout
279
// in 30 seconds.
280
System.out.println(
281
"The client is not the expected one or timeout. " +
282
"Ignore in server side.");
283
}
284
} catch (Exception e) {
285
System.out.println("Server died ...");
286
e.printStackTrace(System.out);
287
serverException = e;
288
} finally {
289
socket.close();
290
serverSocket.close();
291
}
292
293
clientThread.join();
294
295
if (clientException != null || serverException != null) {
296
throw new RuntimeException("Test failed");
297
}
298
}
299
300
/*
301
* Define the server side application of the test for the specified socket.
302
*/
303
void runServerApplication(Socket socket, boolean direct,
304
boolean serverClose) throws Exception {
305
306
socket.setSoTimeout(500);
307
308
createSSLEngine();
309
createBuffers(direct);
310
311
boolean closed = false;
312
313
InputStream is = socket.getInputStream();
314
OutputStream os = socket.getOutputStream();
315
316
SSLEngineResult serverResult; // results from last operation
317
318
/*
319
* Examining the SSLEngineResults could be much more involved,
320
* and may alter the overall flow of the application.
321
*
322
* For example, if we received a BUFFER_OVERFLOW when trying
323
* to write to the output pipe, we could reallocate a larger
324
* pipe, but instead we wait for the peer to drain it.
325
*/
326
byte[] inbound = new byte[8192];
327
byte[] outbound = new byte[8192];
328
329
while (!isEngineClosed(serverEngine)) {
330
int len = 0;
331
332
// Inbound data
333
log("================");
334
335
// Read from the Client side.
336
try {
337
len = is.read(inbound);
338
if (len == -1) {
339
throw new Exception("Unexpected EOF");
340
}
341
cTOs.put(inbound, 0, len);
342
} catch (SocketTimeoutException ste) {
343
// swallow. Nothing yet, probably waiting on us.
344
System.out.println("Warning: " + ste);
345
}
346
347
cTOs.flip();
348
349
serverResult = serverEngine.unwrap(cTOs, serverIn);
350
log("server unwrap: ", serverResult);
351
runDelegatedTasks(serverResult, serverEngine);
352
cTOs.compact();
353
354
// Outbound data
355
log("----");
356
357
serverResult = serverEngine.wrap(serverOut, sTOc);
358
log("server wrap: ", serverResult);
359
runDelegatedTasks(serverResult, serverEngine);
360
361
sTOc.flip();
362
363
if ((len = sTOc.remaining()) != 0) {
364
sTOc.get(outbound, 0, len);
365
os.write(outbound, 0, len);
366
// Give the other side a chance to process
367
}
368
369
sTOc.compact();
370
371
if (!closed && (serverOut.remaining() == 0)) {
372
closed = true;
373
374
/*
375
* We'll alternate initiatating the shutdown.
376
* When the server initiates, it will take one more
377
* loop, but tests the orderly shutdown.
378
*/
379
if (serverClose) {
380
serverEngine.closeOutbound();
381
}
382
}
383
384
if (closed && isEngineClosed(serverEngine)) {
385
serverIn.flip();
386
387
/*
388
* A sanity check to ensure we got what was sent.
389
*/
390
if (serverIn.remaining() != clientMsg.length) {
391
throw new Exception("Client: Data length error -" +
392
" IF THIS FAILS, PLEASE REPORT THIS TO THE" +
393
" SECURITY TEAM. WE HAVE BEEN UNABLE TO" +
394
" RELIABLY DUPLICATE.");
395
}
396
397
for (int i = 0; i < clientMsg.length; i++) {
398
if (clientMsg[i] != serverIn.get()) {
399
throw new Exception("Client: Data content error -" +
400
" IF THIS FAILS, PLEASE REPORT THIS TO THE" +
401
" SECURITY TEAM. WE HAVE BEEN UNABLE TO" +
402
" RELIABLY DUPLICATE.");
403
}
404
}
405
serverIn.compact();
406
}
407
}
408
}
409
410
/*
411
* Create a client thread which does simple SSLSocket operations.
412
* We'll write and read one data packet.
413
*/
414
private Thread runClient(final boolean serverClose)
415
throws Exception {
416
417
Thread t = new Thread("ClientThread") {
418
419
@Override
420
public void run() {
421
try {
422
doClientSide(serverClose);
423
} catch (Exception e) {
424
System.out.println("Client died ...");
425
e.printStackTrace(System.out);
426
clientException = e;
427
}
428
}
429
};
430
431
t.start();
432
return t;
433
}
434
435
/*
436
* Define the client side of the test.
437
*/
438
void doClientSide(boolean serverClose) throws Exception {
439
// Wait for server to get started.
440
//
441
// The server side takes care of the issue if the server cannot
442
// get started in 90 seconds. The client side would just ignore
443
// the test case if the serer is not ready.
444
boolean serverIsReady =
445
serverCondition.await(90L, TimeUnit.SECONDS);
446
if (!serverIsReady) {
447
System.out.println(
448
"The server is not ready yet in 90 seconds. " +
449
"Ignore in client side.");
450
return;
451
}
452
453
SSLSocketFactory sslsf = sslc.getSocketFactory();
454
try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
455
try {
456
sslSocket.connect(
457
new InetSocketAddress("localhost", serverPort), 15000);
458
} catch (IOException ioe) {
459
// The server side may be impacted by naughty test cases or
460
// third party routines, and cannot accept connections.
461
//
462
// Just ignore the test if the connection cannot be
463
// established.
464
System.out.println(
465
"Cannot make a connection in 15 seconds. " +
466
"Ignore in client side.");
467
return;
468
}
469
470
// OK, here the client and server get connected.
471
472
// Signal the server, the client is ready to communicate.
473
clientCondition.countDown();
474
475
// There is still a chance in theory that the server thread may
476
// wait client-ready timeout and then quit. The chance should
477
// be really rare so we don't consider it until it becomes a
478
// real problem.
479
480
// Run the application in client side.
481
runClientApplication(sslSocket, serverClose);
482
}
483
}
484
485
/*
486
* Define the server side application of the test for the specified socket.
487
*/
488
void runClientApplication(SSLSocket sslSocket, boolean serverClose)
489
throws Exception {
490
491
OutputStream os = sslSocket.getOutputStream();
492
InputStream is = sslSocket.getInputStream();
493
494
// write(byte[]) goes in one shot.
495
os.write(clientMsg);
496
497
byte[] inbound = new byte[2048];
498
int pos = 0;
499
500
int len;
501
while ((len = is.read(inbound, pos, 2048 - pos)) != -1) {
502
pos += len;
503
// Let the client do the closing.
504
if ((pos == serverMsg.length) && !serverClose) {
505
sslSocket.close();
506
break;
507
}
508
}
509
510
if (pos != serverMsg.length) {
511
throw new Exception("Client: Data length error");
512
}
513
514
for (int i = 0; i < serverMsg.length; i++) {
515
if (inbound[i] != serverMsg[i]) {
516
throw new Exception("Client: Data content error");
517
}
518
}
519
}
520
521
/*
522
* Using the SSLContext created during object creation,
523
* create/configure the SSLEngines we'll use for this test.
524
*/
525
private void createSSLEngine() throws Exception {
526
/*
527
* Configure the serverEngine to act as a server in the SSL/TLS
528
* handshake.
529
*/
530
serverEngine = sslc.createSSLEngine();
531
serverEngine.setUseClientMode(false);
532
serverEngine.getNeedClientAuth();
533
}
534
535
/*
536
* Create and size the buffers appropriately.
537
*/
538
private void createBuffers(boolean direct) {
539
540
SSLSession session = serverEngine.getSession();
541
int appBufferMax = session.getApplicationBufferSize();
542
int netBufferMax = session.getPacketBufferSize();
543
544
/*
545
* We'll make the input buffers a bit bigger than the max needed
546
* size, so that unwrap()s following a successful data transfer
547
* won't generate BUFFER_OVERFLOWS.
548
*
549
* We'll use a mix of direct and indirect ByteBuffers for
550
* tutorial purposes only. In reality, only use direct
551
* ByteBuffers when they give a clear performance enhancement.
552
*/
553
if (direct) {
554
serverIn = ByteBuffer.allocateDirect(appBufferMax + 50);
555
cTOs = ByteBuffer.allocateDirect(netBufferMax);
556
sTOc = ByteBuffer.allocateDirect(netBufferMax);
557
} else {
558
serverIn = ByteBuffer.allocate(appBufferMax + 50);
559
cTOs = ByteBuffer.allocate(netBufferMax);
560
sTOc = ByteBuffer.allocate(netBufferMax);
561
}
562
563
serverOut = ByteBuffer.wrap(serverMsg);
564
}
565
566
/*
567
* If the result indicates that we have outstanding tasks to do,
568
* go ahead and run them in this thread.
569
*/
570
private static void runDelegatedTasks(SSLEngineResult result,
571
SSLEngine engine) throws Exception {
572
573
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
574
Runnable runnable;
575
while ((runnable = engine.getDelegatedTask()) != null) {
576
log("\trunning delegated task...");
577
runnable.run();
578
}
579
HandshakeStatus hsStatus = engine.getHandshakeStatus();
580
if (hsStatus == HandshakeStatus.NEED_TASK) {
581
throw new Exception(
582
"handshake shouldn't need additional tasks");
583
}
584
log("\tnew HandshakeStatus: " + hsStatus);
585
}
586
}
587
588
private static boolean isEngineClosed(SSLEngine engine) {
589
return (engine.isOutboundDone() && engine.isInboundDone());
590
}
591
592
/*
593
* Logging code
594
*/
595
private static boolean resultOnce = true;
596
597
private static void log(String str, SSLEngineResult result) {
598
if (!logging) {
599
return;
600
}
601
if (resultOnce) {
602
resultOnce = false;
603
System.out.println("The format of the SSLEngineResult is: \n"
604
+ "\t\"getStatus() / getHandshakeStatus()\" +\n"
605
+ "\t\"bytesConsumed() / bytesProduced()\"\n");
606
}
607
HandshakeStatus hsStatus = result.getHandshakeStatus();
608
log(str
609
+ result.getStatus() + "/" + hsStatus + ", "
610
+ result.bytesConsumed() + "/" + result.bytesProduced()
611
+ " bytes");
612
if (hsStatus == HandshakeStatus.FINISHED) {
613
log("\t...ready for application data");
614
}
615
}
616
617
private static void log(String str) {
618
if (logging) {
619
System.out.println(str);
620
}
621
}
622
}
623
624