summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Hudson <nick.hudson@isode.com>2015-01-13 16:25:34 (GMT)
committerNick Hudson <nick.hudson@isode.com>2015-01-14 11:50:29 (GMT)
commitd5a42a02f33df608576b90f263319cb2d9438f71 (patch)
treeafc2c041eae3cb7c16acb882fd1ed9507910f6bf
parentad96cd3f5f8c07ad6569cbb4863c782ba0920d3d (diff)
downloadstroke-d5a42a02f33df608576b90f263319cb2d9438f71.zip
stroke-d5a42a02f33df608576b90f263319cb2d9438f71.tar.bz2
Don't use bytesConsumed from SSLEngineResult
Android Lollipop implementation reports this innaccurately during handshaking, which was causing SSL setup to fail. Now derives the information directly from ByteBuffer positions. This change is based on a similar change for Jetty at https://gist.github.com/tavianator/96e9daab0fd1a45f11f2/8cbbfe028c97cac63d3b39f575b2c317d7a174c2 Test-information: Tested Harrier with IMAPS and STARTTLS against MBox on Android 4.4 and 5.0 emulators, all connect and authenticate OK. Tested MLC on Linux, with extra debugging added - everything works, and the values returned for "lastConsumed" are the same as those returned by "bytesConsumed()" so the change appears to make no difference to behaviour for non-Android Ran unit tests - no failures. Change-Id: I54b3850136b35535918b0eb303409232d64a60b5 Reviewer: Nick Hudson <nick.hudson@isode.com>
-rw-r--r--src/com/isode/stroke/tls/java/JSSEContext.java32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/com/isode/stroke/tls/java/JSSEContext.java b/src/com/isode/stroke/tls/java/JSSEContext.java
index 03a6c8f..52edae1 100644
--- a/src/com/isode/stroke/tls/java/JSSEContext.java
+++ b/src/com/isode/stroke/tls/java/JSSEContext.java
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, Isode Limited, London, England.
+/* Copyright (c) 2012-2015, Isode Limited, London, England.
* All rights reserved.
*
* Acquisition and use of this software and related materials for any
@@ -236,6 +236,7 @@ public class JSSEContext extends TLSContext {
int bytesProduced = 0;
int bytesConsumed = 0;
int bytesToUnwrap = 0;
+ int lastConsumed = 0;
HandshakeStatus handshakeStatus = null;
ByteArray byteArray = null;
@@ -245,27 +246,34 @@ public class JSSEContext extends TLSContext {
boolean unwrapDone = false;
do {
+ int positionBeforeUnwrap = encryptedReceived.position();
bytesToUnwrap = encryptedReceived.remaining();
sslEngineResult = sslEngine.unwrap(encryptedReceived, unwrappedReceived);
status = sslEngineResult.getStatus();
handshakeStatus = sslEngineResult.getHandshakeStatus();
+ /*
+ * This should match sslEngineResult.bytesConsumed(), but we can't use this
+ * due to Android Lollipop bug: https://code.google.com/p/android/issues/detail?id=93740
+ */
+ lastConsumed = encryptedReceived.position() - positionBeforeUnwrap;
+
/* A call to unwrap can generate a status of FINISHED, which
* you won't get from SSLEngine.getHandshakeStatus. Such
* a status is an indication that we need to re-check whether
* anything's pending to be written
*/
if (handshakeStatus == HandshakeStatus.FINISHED ||
- (!handshakeCompleted &&
- handshakeStatus == HandshakeStatus.NOT_HANDSHAKING)) {
+ (!handshakeCompleted &&
+ handshakeStatus == HandshakeStatus.NOT_HANDSHAKING)) {
/* Special case will happen when the handshake completes following
* an unwrap. The first time we tried wrapping some plain stuff,
* it triggers the handshake but won't itself have been dealt with.
* So now the handshake has finished, we have to try sending it
* again
- * The second checking clause is necessary for certain
- * SSLEngine implementations (notably Apache Harmony
- * used on Android) which never return FINISHED
- */
+ * The second checking clause is necessary for certain
+ * SSLEngine implementations (notably Apache Harmony
+ * used on Android) which never return FINISHED
+ */
handshakeCompleted = true;
wrapAndSendData();
@@ -308,20 +316,20 @@ public class JSSEContext extends TLSContext {
case OK:
/* Some stuff was unwrapped. */
- bytesConsumed += sslEngineResult.bytesConsumed();
+ bytesConsumed += lastConsumed;
bytesProduced = sslEngineResult.bytesProduced();
/* It may be that the unwrap consumed some, but not all of
* the data. In which case, the loop continues to give it
* another chance to process whatever's remaining
*/
- if (sslEngineResult.bytesConsumed() == 0) {
+ if (lastConsumed == 0) {
/* No point looping around again */
unwrapDone = true;
}
else {
/* It consumed some bytes, but perhaps not everything */
- unwrapDone = (sslEngineResult.bytesConsumed() == bytesToUnwrap);
+ unwrapDone = (lastConsumed == bytesToUnwrap);
}
break;
}
@@ -329,9 +337,7 @@ public class JSSEContext extends TLSContext {
encryptedReceived.compact();
-
-
- bytesConsumed += sslEngineResult.bytesConsumed();
+ bytesConsumed += lastConsumed;
bytesProduced = sslEngineResult.bytesProduced();
}
catch (SSLException e) {