Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java
41152 views
1
/*
2
* Copyright (c) 2011, 2019, 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 7105780
32
* @summary Add SSLSocket client/SSLEngine server to templates directory.
33
* @run main/othervm SSLSocketSSLEngineTemplate TLSv1
34
* @run main/othervm SSLSocketSSLEngineTemplate TLSv1.1
35
* @run main/othervm SSLSocketSSLEngineTemplate TLSv1.2
36
* @run main/othervm SSLSocketSSLEngineTemplate TLSv1.3
37
*/
38
39
/**
40
* A SSLSocket/SSLEngine interop test case. This is not the way to
41
* code SSLEngine-based servers, but works for what we need to do here,
42
* which is to make sure that SSLEngine/SSLSockets can talk to each other.
43
* SSLEngines can use direct or indirect buffers, and different code
44
* is used to get at the buffer contents internally, so we test that here.
45
*
46
* The test creates one SSLSocket (client) and one SSLEngine (server).
47
* The SSLSocket talks to a raw ServerSocket, and the server code
48
* does the translation between byte [] and ByteBuffers that the SSLEngine
49
* can use. The "transport" layer consists of a Socket Input/OutputStream
50
* and two byte buffers for the SSLEngines: think of them
51
* as directly connected pipes.
52
*
53
* Again, this is a *very* simple example: real code will be much more
54
* involved. For example, different threading and I/O models could be
55
* used, transport mechanisms could close unexpectedly, and so on.
56
*
57
* When this application runs, notice that several messages
58
* (wrap/unwrap) pass before any application data is consumed or
59
* produced. (For more information, please see the SSL/TLS
60
* specifications.) There may several steps for a successful handshake,
61
* so it's typical to see the following series of operations:
62
*
63
* client server message
64
* ====== ====== =======
65
* write() ... ClientHello
66
* ... unwrap() ClientHello
67
* ... wrap() ServerHello/Certificate
68
* read() ... ServerHello/Certificate
69
* write() ... ClientKeyExchange
70
* write() ... ChangeCipherSpec
71
* write() ... Finished
72
* ... unwrap() ClientKeyExchange
73
* ... unwrap() ChangeCipherSpec
74
* ... unwrap() Finished
75
* ... wrap() ChangeCipherSpec
76
* ... wrap() Finished
77
* read() ... ChangeCipherSpec
78
* read() ... Finished
79
*/
80
import javax.net.ssl.*;
81
import javax.net.ssl.SSLEngineResult.*;
82
import java.io.*;
83
import java.net.*;
84
import java.security.*;
85
import java.nio.*;
86
87
public class SSLSocketSSLEngineTemplate {
88
89
/*
90
* Enables logging of the SSL/TLS operations.
91
*/
92
private static final boolean logging = true;
93
94
/*
95
* Enables the JSSE system debugging system property:
96
*
97
* -Djavax.net.debug=all
98
*
99
* This gives a lot of low-level information about operations underway,
100
* including specific handshake messages, and might be best examined
101
* after gaining some familiarity with this application.
102
*/
103
private static final boolean debug = false;
104
private final SSLContext sslc;
105
private SSLEngine serverEngine; // server-side SSLEngine
106
private SSLSocket clientSocket;
107
108
private final byte[] serverMsg =
109
"Hi there Client, I'm a Server.".getBytes();
110
private final byte[] clientMsg =
111
"Hello Server, I'm a Client! Pleased to meet you!".getBytes();
112
113
private ByteBuffer serverOut; // write side of serverEngine
114
private ByteBuffer serverIn; // read side of serverEngine
115
116
private volatile Exception clientException;
117
private volatile Exception serverException;
118
119
/*
120
* For data transport, this example uses local ByteBuffers.
121
*/
122
private ByteBuffer cTOs; // "reliable" transport client->server
123
private ByteBuffer sTOc; // "reliable" transport server->client
124
125
/*
126
* The following is to set up the keystores/trust material.
127
*/
128
private static final String pathToStores = "../etc";
129
private static final String keyStoreFile = "keystore";
130
private static final String trustStoreFile = "truststore";
131
private static final String keyFilename =
132
System.getProperty("test.src", ".") + "/" + pathToStores
133
+ "/" + keyStoreFile;
134
private static final String trustFilename =
135
System.getProperty("test.src", ".") + "/" + pathToStores
136
+ "/" + trustStoreFile;
137
138
/*
139
* Main entry point for this test.
140
*/
141
public static void main(String args[]) throws Exception {
142
String protocol = args[0];
143
144
// reset security properties to make sure that the algorithms
145
// and keys used in this test are not disabled.
146
Security.setProperty("jdk.tls.disabledAlgorithms", "");
147
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
148
149
if (debug) {
150
System.setProperty("javax.net.debug", "all");
151
}
152
153
/*
154
* Run the tests with direct and indirect buffers.
155
*/
156
SSLSocketSSLEngineTemplate test =
157
new SSLSocketSSLEngineTemplate(protocol);
158
log("-------------------------------------");
159
log("Testing " + protocol + " for direct buffers ...");
160
test.runTest(true);
161
162
log("---------------------------------------");
163
log("Testing " + protocol + " for indirect buffers ...");
164
test.runTest(false);
165
166
log("Test Passed.");
167
}
168
169
/*
170
* Create an initialized SSLContext to use for these tests.
171
*/
172
public SSLSocketSSLEngineTemplate(String protocol) throws Exception {
173
174
KeyStore ks = KeyStore.getInstance("JKS");
175
KeyStore ts = KeyStore.getInstance("JKS");
176
177
char[] passphrase = "passphrase".toCharArray();
178
179
try (FileInputStream keyFile = new FileInputStream(keyFilename);
180
FileInputStream trustFile = new FileInputStream(trustFilename)) {
181
ks.load(keyFile, passphrase);
182
ts.load(trustFile, passphrase);
183
}
184
185
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
186
kmf.init(ks, passphrase);
187
188
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
189
tmf.init(ts);
190
191
SSLContext sslCtx = SSLContext.getInstance(protocol);
192
193
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
194
195
sslc = sslCtx;
196
}
197
198
/*
199
* Run the test.
200
*
201
* Sit in a tight loop, with the server engine calling wrap/unwrap
202
* regardless of whether data is available or not. We do this until
203
* we get the application data. Then we shutdown and go to the next one.
204
*
205
* The main loop handles all of the I/O phases of the SSLEngine's
206
* lifetime:
207
*
208
* initial handshaking
209
* application data transfer
210
* engine closing
211
*
212
* One could easily separate these phases into separate
213
* sections of code.
214
*/
215
private void runTest(boolean direct) throws Exception {
216
clientSocket = null;
217
boolean serverClose = direct;
218
219
// generates the server-side Socket
220
try (ServerSocket serverSocket = new ServerSocket()) {
221
serverSocket.setReuseAddress(false);
222
serverSocket.bind(null);
223
int port = serverSocket.getLocalPort();
224
log("Port: " + port);
225
Thread thread = createClientThread(port, serverClose);
226
227
createSSLEngine();
228
createBuffers(direct);
229
230
// server-side socket that will read
231
try (Socket socket = serverSocket.accept()) {
232
socket.setSoTimeout(500);
233
234
boolean closed = false;
235
// will try to read one more time in case client message
236
// is fragmented to multiple pieces
237
boolean retry = true;
238
239
InputStream is = socket.getInputStream();
240
OutputStream os = socket.getOutputStream();
241
242
SSLEngineResult serverResult; // results from last operation
243
244
/*
245
* Examining the SSLEngineResults could be much more involved,
246
* and may alter the overall flow of the application.
247
*
248
* For example, if we received a BUFFER_OVERFLOW when trying
249
* to write to the output pipe, we could reallocate a larger
250
* pipe, but instead we wait for the peer to drain it.
251
*/
252
byte[] inbound = new byte[8192];
253
byte[] outbound = new byte[8192];
254
255
while (!isEngineClosed(serverEngine)) {
256
int len;
257
258
// Inbound data
259
log("================");
260
261
// Read from the Client side.
262
try {
263
len = is.read(inbound);
264
if (len == -1) {
265
logSocketStatus(clientSocket);
266
if (clientSocket.isClosed()
267
|| clientSocket.isOutputShutdown()) {
268
log("Client socket was closed or shutdown output");
269
break;
270
} else {
271
throw new Exception("Unexpected EOF");
272
}
273
}
274
cTOs.put(inbound, 0, len);
275
} catch (SocketTimeoutException ste) {
276
// swallow. Nothing yet, probably waiting on us.
277
}
278
279
cTOs.flip();
280
281
serverResult = serverEngine.unwrap(cTOs, serverIn);
282
log("server unwrap: ", serverResult);
283
runDelegatedTasks(serverResult, serverEngine);
284
cTOs.compact();
285
286
// Outbound data
287
log("----");
288
289
serverResult = serverEngine.wrap(serverOut, sTOc);
290
log("server wrap: ", serverResult);
291
runDelegatedTasks(serverResult, serverEngine);
292
293
sTOc.flip();
294
295
if ((len = sTOc.remaining()) != 0) {
296
sTOc.get(outbound, 0, len);
297
os.write(outbound, 0, len);
298
// Give the other side a chance to process
299
}
300
301
sTOc.compact();
302
303
if (!closed && (serverOut.remaining() == 0)) {
304
closed = true;
305
306
/*
307
* We'll alternate initiatating the shutdown.
308
* When the server initiates, it will take one more
309
* loop, but tests the orderly shutdown.
310
*/
311
if (serverClose) {
312
serverEngine.closeOutbound();
313
}
314
serverIn.flip();
315
316
/*
317
* A sanity check to ensure we got what was sent.
318
*/
319
if (serverIn.remaining() != clientMsg.length) {
320
if (retry &&
321
serverIn.remaining() < clientMsg.length) {
322
log("Need to read more from client");
323
serverIn.compact();
324
retry = false;
325
continue;
326
} else {
327
throw new Exception(
328
"Client: Data length error");
329
}
330
}
331
332
for (int i = 0; i < clientMsg.length; i++) {
333
if (clientMsg[i] != serverIn.get()) {
334
throw new Exception(
335
"Client: Data content error");
336
}
337
}
338
serverIn.compact();
339
}
340
}
341
} catch (Exception e) {
342
serverException = e;
343
} finally {
344
// Wait for the client to join up with us.
345
if (thread != null) {
346
thread.join();
347
}
348
}
349
} finally {
350
if (serverException != null) {
351
if (clientException != null) {
352
serverException.initCause(clientException);
353
}
354
throw serverException;
355
}
356
if (clientException != null) {
357
if (serverException != null) {
358
clientException.initCause(serverException);
359
}
360
throw clientException;
361
}
362
}
363
}
364
365
/*
366
* Create a client thread which does simple SSLSocket operations.
367
* We'll write and read one data packet.
368
*/
369
private Thread createClientThread(final int port,
370
final boolean serverClose) throws Exception {
371
372
Thread t = new Thread("ClientThread") {
373
374
@Override
375
public void run() {
376
// client-side socket
377
try (SSLSocket sslSocket = (SSLSocket)sslc.getSocketFactory().
378
createSocket("localhost", port)) {
379
clientSocket = sslSocket;
380
381
OutputStream os = sslSocket.getOutputStream();
382
InputStream is = sslSocket.getInputStream();
383
384
// write(byte[]) goes in one shot.
385
os.write(clientMsg);
386
387
byte[] inbound = new byte[2048];
388
int pos = 0;
389
390
int len;
391
while ((len = is.read(inbound, pos, 2048 - pos)) != -1) {
392
pos += len;
393
// Let the client do the closing.
394
if ((pos == serverMsg.length) && !serverClose) {
395
sslSocket.close();
396
break;
397
}
398
}
399
400
if (pos != serverMsg.length) {
401
throw new Exception("Client: Data length error");
402
}
403
404
for (int i = 0; i < serverMsg.length; i++) {
405
if (inbound[i] != serverMsg[i]) {
406
throw new Exception("Client: Data content error");
407
}
408
}
409
} catch (Exception e) {
410
clientException = e;
411
}
412
}
413
};
414
t.start();
415
return t;
416
}
417
418
/*
419
* Using the SSLContext created during object creation,
420
* create/configure the SSLEngines we'll use for this test.
421
*/
422
private void createSSLEngine() throws Exception {
423
/*
424
* Configure the serverEngine to act as a server in the SSL/TLS
425
* handshake.
426
*/
427
serverEngine = sslc.createSSLEngine();
428
serverEngine.setUseClientMode(false);
429
serverEngine.getNeedClientAuth();
430
}
431
432
/*
433
* Create and size the buffers appropriately.
434
*/
435
private void createBuffers(boolean direct) {
436
437
SSLSession session = serverEngine.getSession();
438
int appBufferMax = session.getApplicationBufferSize();
439
int netBufferMax = session.getPacketBufferSize();
440
441
/*
442
* We'll make the input buffers a bit bigger than the max needed
443
* size, so that unwrap()s following a successful data transfer
444
* won't generate BUFFER_OVERFLOWS.
445
*
446
* We'll use a mix of direct and indirect ByteBuffers for
447
* tutorial purposes only. In reality, only use direct
448
* ByteBuffers when they give a clear performance enhancement.
449
*/
450
if (direct) {
451
serverIn = ByteBuffer.allocateDirect(appBufferMax + 50);
452
cTOs = ByteBuffer.allocateDirect(netBufferMax);
453
sTOc = ByteBuffer.allocateDirect(netBufferMax);
454
} else {
455
serverIn = ByteBuffer.allocate(appBufferMax + 50);
456
cTOs = ByteBuffer.allocate(netBufferMax);
457
sTOc = ByteBuffer.allocate(netBufferMax);
458
}
459
460
serverOut = ByteBuffer.wrap(serverMsg);
461
}
462
463
/*
464
* If the result indicates that we have outstanding tasks to do,
465
* go ahead and run them in this thread.
466
*/
467
private static void runDelegatedTasks(SSLEngineResult result,
468
SSLEngine engine) throws Exception {
469
470
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
471
Runnable runnable;
472
while ((runnable = engine.getDelegatedTask()) != null) {
473
log("\trunning delegated task...");
474
runnable.run();
475
}
476
HandshakeStatus hsStatus = engine.getHandshakeStatus();
477
if (hsStatus == HandshakeStatus.NEED_TASK) {
478
throw new Exception(
479
"handshake shouldn't need additional tasks");
480
}
481
log("\tnew HandshakeStatus: " + hsStatus);
482
}
483
}
484
485
private static boolean isEngineClosed(SSLEngine engine) {
486
return (engine.isOutboundDone() && engine.isInboundDone());
487
}
488
489
private static void logSocketStatus(Socket socket) {
490
log("##### " + socket + " #####");
491
log("isBound: " + socket.isBound());
492
log("isConnected: " + socket.isConnected());
493
log("isClosed: " + socket.isClosed());
494
log("isInputShutdown: " + socket.isInputShutdown());
495
log("isOutputShutdown: " + socket.isOutputShutdown());
496
}
497
498
/*
499
* Logging code
500
*/
501
private static boolean resultOnce = true;
502
503
private static void log(String str, SSLEngineResult result) {
504
if (!logging) {
505
return;
506
}
507
if (resultOnce) {
508
resultOnce = false;
509
log("The format of the SSLEngineResult is: \n"
510
+ "\t\"getStatus() / getHandshakeStatus()\" +\n"
511
+ "\t\"bytesConsumed() / bytesProduced()\"\n");
512
}
513
HandshakeStatus hsStatus = result.getHandshakeStatus();
514
log(str
515
+ result.getStatus() + "/" + hsStatus + ", "
516
+ result.bytesConsumed() + "/" + result.bytesProduced()
517
+ " bytes");
518
if (hsStatus == HandshakeStatus.FINISHED) {
519
log("\t...ready for application data");
520
}
521
}
522
523
private static void log(String str) {
524
if (logging) {
525
if (debug) {
526
System.err.println(str);
527
} else {
528
System.out.println(str);
529
}
530
}
531
}
532
}
533
534