28
28
import javax .net .ssl .X509TrustManager ;
29
29
30
30
public class AsyncSSLSocketWrapper implements AsyncSocketWrapper , AsyncSSLSocket {
31
+ public interface HandshakeCallback {
32
+ public void onHandshakeCompleted (Exception e , AsyncSSLSocket socket );
33
+ }
34
+
31
35
static SSLContext defaultSSLContext ;
32
36
33
37
AsyncSocket mSocket ;
34
38
BufferedDataEmitter mEmitter ;
35
39
BufferedDataSink mSink ;
36
- boolean mUnwrapping = false ;
40
+ boolean mUnwrapping ;
41
+ SSLEngine engine ;
42
+ boolean finishedHandshake ;
43
+ private int mPort ;
44
+ private String mHost ;
45
+ private boolean mWrapping ;
37
46
HostnameVerifier hostnameVerifier ;
38
-
39
- /*
40
- private static void initTLS_1_2() {
41
- try {
42
- defaultSSLContext = SSLContext.getInstance("TLSv1.2");
43
- }
44
- catch (NoSuchAlgorithmException e) {
45
- }
46
- }
47
-
48
- private static void initTLS_1_1() {
49
- try {
50
- defaultSSLContext = SSLContext.getInstance("TLSv1.1");
51
- }
52
- catch (NoSuchAlgorithmException e) {
53
- }
54
- }
55
-
56
- private static void initTLS() {
57
- try {
58
- defaultSSLContext = SSLContext.getInstance("TLS");
59
- }
60
- catch (NoSuchAlgorithmException e) {
61
- }
62
- }
63
-
64
- static {
65
- try {
66
- initTLS_1_2();
67
- if (defaultSSLContext == null)
68
- initTLS_1_1();
69
- if (defaultSSLContext == null)
70
- initTLS();
71
- if (defaultSSLContext == null)
72
- defaultSSLContext = SSLContext.getInstance("SSL");
73
- // critical extension 2.5.29.15 is implemented improperly prior to 4.0.3.
74
- // https://code.google.com/p/android/issues/detail?id=9307
75
- // https://groups.google.com/forum/?fromgroups=#!topic/netty/UCfqPPk5O4s
76
- // certs that use this extension will throw in Cipher.java.
77
- // fallback is to use a custom SSLContext, and hack around the x509 extension.
78
- TrustManager[] trustManagers = null;
79
- if (Build.VERSION.SDK_INT <= 15) {
80
- trustManagers = new TrustManager[] { new X509TrustManager() {
81
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
82
- return new X509Certificate[0];
83
- }
84
-
85
- public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
86
- }
87
-
88
- public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
89
- for (X509Certificate cert : certs) {
90
- if (cert != null && cert.getCriticalExtensionOIDs() != null)
91
- cert.getCriticalExtensionOIDs().remove("2.5.29.15");
92
- }
93
- }
94
- } };
95
- }
96
- defaultSSLContext.init(null, trustManagers, null);
97
- }
98
- catch (Exception ex) {
99
- ex.printStackTrace();
100
- }
101
- }
102
-
103
- // android SSL cipher suites were downgraded (!!) for some derpy reason.
104
- // Paranoid people would be wise to enable the original/secure suites.
105
- // http://op-co.de/blog/posts/android_ssl_downgrade/
106
- public static final String RECOMMENDED_CIPHERS[] = {
107
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
108
- "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
109
- "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
110
- "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
111
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
112
- "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
113
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
114
- "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
115
- "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
116
- "TLS_RSA_WITH_AES_128_CBC_SHA",
117
- "TLS_RSA_WITH_AES_256_CBC_SHA",
118
- "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
119
- "SSL_RSA_WITH_RC4_128_SHA",
120
- "SSL_RSA_WITH_RC4_128_MD5",
121
- "TLS_RSA_WITH_AES_256_CBC_SHA256",
122
- };
123
-
124
- public static final String RECOMMENDED_PROTOCOLS[] = {
125
- "TLSv1"
126
- };
127
-
128
- public static void setupRecommendedEngineSecurity(SSLEngine engine) {
129
- LinkedHashSet<String> ciphers = new LinkedHashSet<String>(Arrays.asList(engine.getSupportedCipherSuites()));
130
- ciphers.addAll(Arrays.asList(engine.getSupportedCipherSuites()));
131
- LinkedHashSet<String> protocols = new LinkedHashSet<String>();
132
- protocols.addAll(Arrays.asList(engine.getSupportedProtocols()));
133
-
134
- ArrayList<String> enabledCiphers = new ArrayList<String>();
135
- for (String cipher: RECOMMENDED_CIPHERS) {
136
- if (ciphers.contains(cipher))
137
- enabledCiphers.add(cipher);
138
- }
139
-
140
- ArrayList<String> enabledProtocols = new ArrayList<String>();
141
- for (String protocol: RECOMMENDED_PROTOCOLS) {
142
- if (protocols.contains(protocol))
143
- enabledProtocols.add(protocol);
144
- }
145
-
146
- enabledCiphers.addAll(Arrays.asList(engine.getEnabledCipherSuites()));
147
- enabledProtocols.addAll(Arrays.asList(engine.getEnabledProtocols()));
148
- // engine.setEnabledCipherSuites(enabledCiphers.toArray(new String[enabledCiphers.size()]));
149
- // engine.setEnabledProtocols(enabledProtocols.toArray(new String[enabledProtocols.size()]));
150
- // engine.setEnabledCipherSuites(RECOMMENDED_CIPHERS);
151
- engine.setEnabledProtocols(new String[] {"SSL"});
152
- }
153
- */
47
+ HandshakeCallback handshakeCallback ;
48
+ X509Certificate [] peerCertificates ;
49
+ WritableCallback mWriteableCallback ;
50
+ DataCallback mDataCallback ;
51
+ TrustManager [] trustManagers ;
52
+ boolean clientMode ;
154
53
155
54
static {
156
55
// following is the "trust the system" certs setup
@@ -195,19 +94,25 @@ public static SSLEngine createDefaultSSLEngine() {
195
94
return defaultSSLContext .createSSLEngine ();
196
95
}
197
96
198
- @ Override
199
- public void end () {
200
- mSocket .end ();
201
- }
202
-
203
- public AsyncSSLSocketWrapper (AsyncSocket socket , String host , int port ) {
204
- this (socket , host , port , createDefaultSSLEngine (), null , null , true );
97
+ public static void handshake (AsyncSocket socket ,
98
+ String host , int port ,
99
+ SSLEngine sslEngine ,
100
+ TrustManager [] trustManagers , HostnameVerifier verifier , boolean clientMode ,
101
+ HandshakeCallback callback ) {
102
+ AsyncSSLSocketWrapper wrapper = new AsyncSSLSocketWrapper (socket , host , port , sslEngine , trustManagers , verifier , clientMode );
103
+ wrapper .handshakeCallback = callback ;
104
+ try {
105
+ wrapper .engine .beginHandshake ();
106
+ wrapper .handleHandshakeStatus (wrapper .engine .getHandshakeStatus ());
107
+ } catch (SSLException e ) {
108
+ wrapper .report (e );
109
+ }
205
110
}
206
111
207
- TrustManager [] trustManagers ;
208
- boolean clientMode ;
209
-
210
- public AsyncSSLSocketWrapper ( AsyncSocket socket , String host , int port , SSLEngine sslEngine , TrustManager [] trustManagers , HostnameVerifier verifier , boolean clientMode ) {
112
+ private AsyncSSLSocketWrapper ( AsyncSocket socket ,
113
+ String host , int port ,
114
+ SSLEngine sslEngine ,
115
+ TrustManager [] trustManagers , HostnameVerifier verifier , boolean clientMode ) {
211
116
mSocket = socket ;
212
117
hostnameVerifier = verifier ;
213
118
this .clientMode = clientMode ;
@@ -277,7 +182,7 @@ else if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
277
182
bb .addFirst (b );
278
183
b = ByteBufferList .EMPTY_BYTEBUFFER ;
279
184
}
280
- handleResult (res );
185
+ handleHandshakeStatus (res . getHandshakeStatus () );
281
186
if (b .remaining () == remaining && before == transformed .remaining ()) {
282
187
bb .addFirst (b );
283
188
break ;
@@ -308,32 +213,30 @@ void addToPending(ByteBufferList out, ByteBuffer mReadTmp) {
308
213
}
309
214
310
215
311
- SSLEngine engine ;
312
- boolean finishedHandshake = false ;
313
-
314
- private String mHost ;
216
+ @ Override
217
+ public void end () {
218
+ mSocket . end ();
219
+ }
315
220
316
221
public String getHost () {
317
222
return mHost ;
318
223
}
319
224
320
- private int mPort ;
321
-
322
225
public int getPort () {
323
226
return mPort ;
324
227
}
325
228
326
- private void handleResult ( SSLEngineResult res ) {
327
- if (res . getHandshakeStatus () == HandshakeStatus .NEED_TASK ) {
229
+ private void handleHandshakeStatus ( HandshakeStatus status ) {
230
+ if (status == HandshakeStatus .NEED_TASK ) {
328
231
final Runnable task = engine .getDelegatedTask ();
329
232
task .run ();
330
233
}
331
234
332
- if (res . getHandshakeStatus () == HandshakeStatus .NEED_WRAP ) {
235
+ if (status == HandshakeStatus .NEED_WRAP ) {
333
236
write (ByteBufferList .EMPTY_BYTEBUFFER );
334
237
}
335
238
336
- if (res . getHandshakeStatus () == HandshakeStatus .NEED_UNWRAP ) {
239
+ if (status == HandshakeStatus .NEED_UNWRAP ) {
337
240
mEmitter .onDataAvailable ();
338
241
}
339
242
@@ -380,6 +283,11 @@ private void handleResult(SSLEngineResult res) {
380
283
throw e ;
381
284
}
382
285
}
286
+ else {
287
+ finishedHandshake = true ;
288
+ }
289
+ handshakeCallback .onHandshakeCompleted (null , this );
290
+ handshakeCallback = null ;
383
291
if (mWriteableCallback != null )
384
292
mWriteableCallback .onWriteable ();
385
293
mEmitter .onDataAvailable ();
@@ -403,7 +311,6 @@ private void writeTmp(ByteBuffer mWriteTmp) {
403
311
assert !mWriteTmp .hasRemaining ();
404
312
}
405
313
406
- private boolean mWrapping = false ;
407
314
408
315
int calculateAlloc (int remaining ) {
409
316
// alloc 50% more than we need for writing
@@ -445,7 +352,7 @@ public void write(ByteBuffer bb) {
445
352
else {
446
353
mWriteTmp = ByteBufferList .obtain (calculateAlloc (bb .remaining ()));
447
354
}
448
- handleResult (res );
355
+ handleHandshakeStatus (res . getHandshakeStatus () );
449
356
}
450
357
catch (SSLException e ) {
451
358
report (e );
@@ -489,7 +396,7 @@ public void write(ByteBufferList bb) {
489
396
}
490
397
else {
491
398
mWriteTmp = ByteBufferList .obtain (calculateAlloc (bb .remaining ()));
492
- handleResult (res );
399
+ handleHandshakeStatus (res . getHandshakeStatus () );
493
400
}
494
401
}
495
402
catch (SSLException e ) {
@@ -501,8 +408,6 @@ public void write(ByteBufferList bb) {
501
408
mWrapping = false ;
502
409
}
503
410
504
- WritableCallback mWriteableCallback ;
505
-
506
411
@ Override
507
412
public void setWriteableCallback (WritableCallback handler ) {
508
413
mWriteableCallback = handler ;
@@ -514,13 +419,21 @@ public WritableCallback getWriteableCallback() {
514
419
}
515
420
516
421
private void report (Exception e ) {
422
+ final HandshakeCallback hs = handshakeCallback ;
423
+ if (hs != null ) {
424
+ handshakeCallback = null ;
425
+ mSocket .setDataCallback (new NullDataCallback ());
426
+ mSocket .end ();
427
+ mSocket .close ();
428
+ hs .onHandshakeCompleted (e , null );
429
+ return ;
430
+ }
431
+
517
432
CompletedCallback cb = getEndCallback ();
518
433
if (cb != null )
519
434
cb .onCompleted (e );
520
435
}
521
436
522
- DataCallback mDataCallback ;
523
-
524
437
@ Override
525
438
public void setDataCallback (DataCallback callback ) {
526
439
mDataCallback = callback ;
@@ -596,8 +509,6 @@ public DataEmitter getDataEmitter() {
596
509
return mSocket ;
597
510
}
598
511
599
- X509Certificate [] peerCertificates ;
600
-
601
512
@ Override
602
513
public X509Certificate [] getPeerCertificates () {
603
514
return peerCertificates ;
0 commit comments