diff options
author | Nick Hudson <nick.hudson@isode.com> | 2015-01-13 16:25:34 (GMT) |
---|---|---|
committer | Nick Hudson <nick.hudson@isode.com> | 2015-01-14 11:50:29 (GMT) |
commit | d5a42a02f33df608576b90f263319cb2d9438f71 (patch) | |
tree | afc2c041eae3cb7c16acb882fd1ed9507910f6bf /src | |
parent | ad96cd3f5f8c07ad6569cbb4863c782ba0920d3d (diff) | |
download | stroke-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>
Diffstat (limited to 'src')
-rw-r--r-- | src/com/isode/stroke/tls/java/JSSEContext.java | 32 |
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) { |