From df9c090e85c4d052cdd17b5f981819be86a56737 Mon Sep 17 00:00:00 2001 From: Brian Carlstrom Date: Thu, 30 Sep 2010 19:22:21 -0700 Subject: [PATCH] SSL* AppData should not hold onto JNI global references Summary: NativeCrypto.SSL_do_handshake stored JNI global references in its AppData instance for use in upcalls from OpenSSL that invoke Java callbacks. However, one of the references was to the SSLHandshakeCallbacks which in the common case of OpenSSLSocketImpl is the OpenSSLSocketImpl instance itself. This meant that if code dropped the OpenSSLSocketImpl without closing (such as Apache HTTP Client), the instances would never be collected, and perhaps more importantly, file descriptors would not be closed. The fix is to pass in the objects required during a callback in all downcalls to SSL_* methods that could result in a callback and clear them on return. The existing code already did this for the JNIEnv*, so that code was expanded to handle setting the jobjects as well. Details: In the native code used to extract the FileDescriptor object from a Socket on the call to NativeCrypto.SSL_do_handshake. However, since we need this for every read and write operations, we now do this in Java to avoid the repeated overhead. NativeCrypto.SSL_do_handshake now takes a FileDescriptor, which it extracted from the Socket the convenience function using NativeCrypto.getFileDescriptor(Socket) luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java In addition to tracking changes to pass FileDescriptor and SSLHandshakeCallbacks, removed final uses of getFieldId since the code no longer needs to extract FileDescriptors itself luni/src/main/native/NativeCrypto.cpp The Socket field used to be non-null in the wrapper case and null in the non-wrapper case. To simplify things a bit, "socket == this" in the non-wrapper case. The socket field is now also final and joined by a final FileDescriptor field. luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java Updated NativeCryptoTest to track FileDescriptor and SSLHandshakeCallbacks by expanding the Hooks.afterHandshake to provide them. Also changed to add a 5 second timeout to many test cases. luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java Bug: 2989218 Change-Id: Iccef92b59475f3c1929e990893579493ece9d442 --- .../harmony/xnet/provider/jsse/NativeCrypto.java | 54 ++- .../xnet/provider/jsse/OpenSSLSocketImpl.java | 49 ++- luni/src/main/native/NativeCrypto.cpp | 314 +++++++-------- .../xnet/provider/jsse/NativeCryptoTest.java | 431 +++++++++++++++------ 4 files changed, 532 insertions(+), 316 deletions(-) diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java index a9ef11b6..ee2b33a7 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java @@ -16,8 +16,11 @@ package org.apache.harmony.xnet.provider.jsse; +import java.io.FileDescriptor; import java.io.IOException; +import java.lang.reflect.Field; import java.net.Socket; +import java.net.SocketImpl; import java.net.SocketTimeoutException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; @@ -117,6 +120,31 @@ public final class NativeCrypto { // --- SSL handling -------------------------------------------------------- + private static final Field JAVA_NET_SOCKET_IMPL; + private static final Field JAVA_NET_SOCKETIMPL_FD; + static { + try { + JAVA_NET_SOCKET_IMPL = Socket.class.getDeclaredField("impl"); + JAVA_NET_SOCKET_IMPL.setAccessible(true); + JAVA_NET_SOCKETIMPL_FD = SocketImpl.class.getDeclaredField("fd"); + JAVA_NET_SOCKETIMPL_FD.setAccessible(true); + } catch (Exception e) { + throw new AssertionError(e); + } + } + /** + * Return the FileDescriptor associated with the provided socket. + */ + public static FileDescriptor getFileDescriptor(Socket socket) { + try { + SocketImpl socketImpl = (SocketImpl) JAVA_NET_SOCKET_IMPL.get(socket); + FileDescriptor fd = (FileDescriptor) JAVA_NET_SOCKETIMPL_FD.get(socketImpl); + return fd; + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + } + private static final String SUPPORTED_PROTOCOL_SSLV3 = "SSLv3"; private static final String SUPPORTED_PROTOCOL_TLSV1 = "TLSv1"; @@ -490,7 +518,7 @@ public final class NativeCrypto { * Returns the sslSessionNativePointer of the negotiated session */ public static native int SSL_do_handshake(int sslNativePointer, - Socket sock, + FileDescriptor fd, SSLHandshakeCallbacks shc, int timeout, boolean client_mode) @@ -516,19 +544,33 @@ public final class NativeCrypto { * Reads with the native SSL_read function from the encrypted data stream * @return -1 if error or the end of the stream is reached. */ - public static native int SSL_read_byte(int sslNativePointer, int timeout) throws IOException; - public static native int SSL_read(int sslNativePointer, byte[] b, int off, int len, int timeout) + public static native int SSL_read_byte(int sslNativePointer, + FileDescriptor fd, + SSLHandshakeCallbacks shc, + int timeout) throws IOException; + public static native int SSL_read(int sslNativePointer, + FileDescriptor fd, + SSLHandshakeCallbacks shc, + byte[] b, int off, int len, int timeout) throws IOException; /** * Writes with the native SSL_write function to the encrypted data stream. */ - public static native void SSL_write_byte(int sslNativePointer, int b) throws IOException; - public static native void SSL_write(int sslNativePointer, byte[] b, int off, int len) + public static native void SSL_write_byte(int sslNativePointer, + FileDescriptor fd, + SSLHandshakeCallbacks shc, + int b) throws IOException; + public static native void SSL_write(int sslNativePointer, + FileDescriptor fd, + SSLHandshakeCallbacks shc, + byte[] b, int off, int len) throws IOException; public static native void SSL_interrupt(int sslNativePointer) throws IOException; - public static native void SSL_shutdown(int sslNativePointer) throws IOException; + public static native void SSL_shutdown(int sslNativePointer, + FileDescriptor fd, + SSLHandshakeCallbacks shc) throws IOException; public static native void SSL_free(int sslNativePointer); diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java index 0d487caf..86329a92 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java @@ -17,6 +17,7 @@ package org.apache.harmony.xnet.provider.jsse; import dalvik.system.BlockGuard; +import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -56,6 +57,7 @@ import org.apache.harmony.security.provider.cert.X509CertImpl; public class OpenSSLSocketImpl extends javax.net.ssl.SSLSocket implements NativeCrypto.SSLHandshakeCallbacks { + private int sslNativePointer; private InputStream is; private OutputStream os; @@ -69,7 +71,8 @@ public class OpenSSLSocketImpl private boolean useSessionTickets; private String hostname; private OpenSSLSessionImpl sslSession; - private Socket socket; + private final Socket socket; + private final FileDescriptor fd; private boolean autoClose; private boolean handshakeStarted = false; @@ -116,6 +119,8 @@ public class OpenSSLSocketImpl */ protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { super(); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters); } @@ -131,6 +136,8 @@ public class OpenSSLSocketImpl String[] enabledCipherSuites, String[] enabledCompressionMethods) throws IOException { super(); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods); } @@ -141,8 +148,10 @@ public class OpenSSLSocketImpl * @throws java.net.UnknownHostException host not defined */ protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) - throws IOException { + throws IOException { super(host, port); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters); } @@ -153,8 +162,10 @@ public class OpenSSLSocketImpl * @throws java.net.UnknownHostException host not defined */ protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) - throws IOException { + throws IOException { super(address, port); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters); } @@ -168,8 +179,10 @@ public class OpenSSLSocketImpl protected OpenSSLSocketImpl(String host, int port, InetAddress clientAddress, int clientPort, SSLParametersImpl sslParameters) - throws IOException { + throws IOException { super(host, port, clientAddress, clientPort); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters); } @@ -182,8 +195,10 @@ public class OpenSSLSocketImpl protected OpenSSLSocketImpl(InetAddress address, int port, InetAddress clientAddress, int clientPort, SSLParametersImpl sslParameters) - throws IOException { + throws IOException { super(address, port, clientAddress, clientPort); + this.socket = this; + this.fd = NativeCrypto.getFileDescriptor(socket); init(sslParameters); } @@ -197,6 +212,7 @@ public class OpenSSLSocketImpl boolean autoClose, SSLParametersImpl sslParameters) throws IOException { super(); this.socket = socket; + this.fd = NativeCrypto.getFileDescriptor(socket); this.wrappedHost = host; this.wrappedPort = port; this.autoClose = autoClose; @@ -453,11 +469,10 @@ public class OpenSSLSocketImpl // END android-added - Socket socket = this.socket != null ? this.socket : this; int sslSessionNativePointer; try { - sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, socket, - this, getSoTimeout(), client); + sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, fd, this, + getSoTimeout(), client); } catch (CertificateException e) { throw new SSLPeerUnverifiedException(e.getMessage()); } @@ -513,7 +528,7 @@ public class OpenSSLSocketImpl * Return a possibly null array of X509Certificates given the * possibly null array of DER encoded bytes. */ - private static final X509Certificate[] createCertChain(byte[][] certificatesBytes) { + private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { if (certificatesBytes == null) { return null; } @@ -745,7 +760,8 @@ public class OpenSSLSocketImpl checkOpen(); BlockGuard.getThreadPolicy().onNetwork(); synchronized (readLock) { - return NativeCrypto.SSL_read_byte(sslNativePointer, getSoTimeout()); + return NativeCrypto.SSL_read_byte(sslNativePointer, fd, OpenSSLSocketImpl.this, + getSoTimeout()); } } @@ -767,7 +783,8 @@ public class OpenSSLSocketImpl return 0; } synchronized (readLock) { - return NativeCrypto.SSL_read(sslNativePointer, b, off, len, getSoTimeout()); + return NativeCrypto.SSL_read(sslNativePointer, fd, OpenSSLSocketImpl.this, + b, off, len, getSoTimeout()); } } } @@ -795,7 +812,7 @@ public class OpenSSLSocketImpl checkOpen(); BlockGuard.getThreadPolicy().onNetwork(); synchronized (writeLock) { - NativeCrypto.SSL_write_byte(sslNativePointer, b); + NativeCrypto.SSL_write_byte(sslNativePointer, fd, OpenSSLSocketImpl.this, b); } } @@ -817,7 +834,7 @@ public class OpenSSLSocketImpl return; } synchronized (writeLock) { - NativeCrypto.SSL_write(sslNativePointer, b, start, len); + NativeCrypto.SSL_write(sslNativePointer, fd, OpenSSLSocketImpl.this, b, start, len); } } } @@ -1189,7 +1206,7 @@ public class OpenSSLSocketImpl synchronized (this) { free(); - if (socket != null) { + if (socket != this) { if (autoClose && !socket.isClosed()) socket.close(); } else { if (!super.isClosed()) super.close(); @@ -1212,7 +1229,7 @@ public class OpenSSLSocketImpl try { if (handshakeStarted) { BlockGuard.getThreadPolicy().onNetwork(); - NativeCrypto.SSL_shutdown(sslNativePointer); + NativeCrypto.SSL_shutdown(sslNativePointer, fd, this); } } catch (IOException ex) { /* @@ -1229,7 +1246,7 @@ public class OpenSSLSocketImpl */ free(); - if (socket != null) { + if (socket != this) { if (autoClose && !socket.isClosed()) socket.close(); } else { diff --git a/luni/src/main/native/NativeCrypto.cpp b/luni/src/main/native/NativeCrypto.cpp index 01b72741..d380215e 100644 --- a/luni/src/main/native/NativeCrypto.cpp +++ b/luni/src/main/native/NativeCrypto.cpp @@ -1277,66 +1277,20 @@ class AppData { Unique_RSA ephemeralRsa; /** - * Creates our application data and attaches it to a given SSL connection. - * - * @param env The JNIEnv - * @param shc The SSLHandshakeCallbacks - * @param fd The FileDescriptor + * Creates the application data context for the SSL*. */ public: - static AppData* create(JNIEnv* env, - jobject shc, - jobject fd) { - if (shc == NULL) { - return NULL; - } - if (fd == NULL) { - return NULL; - } - AppData* appData = new AppData(env); - if (pipe(appData->fdsEmergency) == -1) { - destroy(env, appData); - return NULL; - } - if (MUTEX_SETUP(appData->mutex) == -1) { - destroy(env, appData); + static AppData* create() { + UniquePtr appData(new AppData()); + if (pipe(appData.get()->fdsEmergency) == -1) { return NULL; } - appData->sslHandshakeCallbacks = env->NewGlobalRef(shc); - if (appData->sslHandshakeCallbacks == NULL) { - destroy(env, appData); + if (MUTEX_SETUP(appData.get()->mutex) == -1) { return NULL; } - appData->fileDescriptor = env->NewGlobalRef(fd); - if (appData->fileDescriptor == NULL) { - destroy(env, appData); - return NULL; - } - return appData; + return appData.release(); } - static void destroy(JNIEnv* env, AppData* appData) { - if (appData == NULL) { - return; - } - appData->cleanupGlobalRef(env); - delete appData; - } - - private: - AppData(JNIEnv* e) : - aliveAndKicking(1), - waitingThreads(0), - env(e), - sslHandshakeCallbacks(NULL), - ephemeralRsa(NULL) { - fdsEmergency[0] = -1; - fdsEmergency[1] = -1; - } - - /** - * Destroys our application data, cleaning up everything in the process. - */ ~AppData() { aliveAndKicking = 0; if (fdsEmergency[0] != -1) { @@ -1348,30 +1302,42 @@ class AppData { MUTEX_CLEANUP(mutex); } - void cleanupGlobalRef(JNIEnv* env) { - if (sslHandshakeCallbacks != NULL) { - env->DeleteGlobalRef(sslHandshakeCallbacks); - sslHandshakeCallbacks = NULL; - } - if (fileDescriptor != NULL) { - env->DeleteGlobalRef(fileDescriptor); - fileDescriptor = NULL; - } - clearEnv(); + private: + AppData() : + aliveAndKicking(1), + waitingThreads(0), + env(NULL), + sslHandshakeCallbacks(NULL), + ephemeralRsa(NULL) { + fdsEmergency[0] = -1; + fdsEmergency[1] = -1; } public: - bool setEnv(JNIEnv* e) { - NetFd fd(e, fileDescriptor); - if (fd.isClosed()) { + /** + * Used to set the SSL-to-Java callback state before each SSL_* + * call that may result in a callback. It should be cleared after + * the operation returns with clearCallbackState. + * + * @param env The JNIEnv + * @param shc The SSLHandshakeCallbacks + * @param fd The FileDescriptor + */ + bool setCallbackState(JNIEnv* e, jobject shc, jobject fd) { + NetFd netFd(e, fd); + if (netFd.isClosed()) { return false; } env = e; + sslHandshakeCallbacks = shc; + fileDescriptor = fd; return true; } - void clearEnv() { + void clearCallbackState() { env = NULL; + sslHandshakeCallbacks = NULL; + fileDescriptor = NULL; } }; @@ -1388,6 +1354,7 @@ class AppData { * * @param env * @param type Either SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE + * @param fdObject The FileDescriptor, since appData->fileDescriptor should be NULL * @param appData The application data structure with mutex info etc. * @param timeout The timeout value for select call, with the special value * 0 meaning no timeout at all (wait indefinitely). Note: This is @@ -1397,7 +1364,7 @@ class AppData { * THROW_SOCKETEXCEPTION if a SocketException was thrown, -1 on * additional errors */ -static int sslSelect(JNIEnv* env, int type, AppData* appData, int timeout) { +static int sslSelect(JNIEnv* env, int type, jobject fdObject, AppData* appData, int timeout) { // This loop is an expanded version of the NET_FAILURE_RETRY // macro. It cannot simply be used in this case because select // cannot be restarted without recreating the fd_sets and timeout @@ -1406,7 +1373,7 @@ static int sslSelect(JNIEnv* env, int type, AppData* appData, int timeout) { fd_set rfds; fd_set wfds; do { - NetFd fd(env, appData->fileDescriptor); + NetFd fd(env, fdObject); if (fd.isClosed()) { result = THROWN_SOCKETEXCEPTION; break; @@ -1876,7 +1843,6 @@ static void NativeCrypto_SSL_CTX_free(JNIEnv* env, if (ssl_ctx == NULL) { return; } - env->DeleteGlobalRef((jobject) ssl_ctx->app_verify_arg); SSL_CTX_free(ssl_ctx); } @@ -2377,27 +2343,19 @@ static jstring NativeCrypto_SSL_get_servername(JNIEnv* env, jclass, jint ssl_add } /** - * Module scope variables initialized during JNI registration. - */ -static jfieldID field_Socket_mImpl; -static jfieldID field_Socket_mFD; - -/** * Perform SSL handshake */ static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, - jint ssl_address, jobject socketObject, jobject shc, jint timeout, jboolean client_mode) + jint ssl_address, jobject fdObject, jobject shc, jint timeout, jboolean client_mode) { SSL* ssl = to_SSL(env, ssl_address, true); - JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake " - "socketObject=%p sslHandshakeCallbacks=%p timeout=%d client_mode=%d", - ssl, socketObject, shc, timeout, client_mode); + JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout=%d client_mode=%d", + ssl, fdObject, shc, timeout, client_mode); if (ssl == NULL) { return 0; } - - if (socketObject == NULL) { - jniThrowNullPointerException(env, "socket == null"); + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl); return 0; } @@ -2407,22 +2365,6 @@ static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, return 0; } - jobject socketImplObject = env->GetObjectField(socketObject, field_Socket_mImpl); - if (socketImplObject == NULL) { - throwSSLExceptionStr(env, - "couldn't get the socket impl from the socket"); - JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl); - return 0; - } - - jobject fdObject = env->GetObjectField(socketImplObject, field_Socket_mFD); - if (fdObject == NULL) { - throwSSLExceptionStr(env, - "couldn't get the file descriptor from the socket impl"); - JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl); - return 0; - } - NetFd fd(env, fdObject); if (fd.isClosed()) { // SocketException thrown by NetFd.isClosed @@ -2456,7 +2398,7 @@ static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, /* * Create our special application data. */ - AppData* appData = AppData::create(env, shc, fdObject); + AppData* appData = AppData::create(); if (appData == NULL) { throwSSLExceptionStr(env, "Unable to create application data"); SSL_clear(ssl); @@ -2475,14 +2417,14 @@ static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, ret = 0; while (appData->aliveAndKicking) { errno = 0; - if (!appData->setEnv(env)) { + if (!appData->setCallbackState(env, shc, fdObject)) { // SocketException thrown by NetFd.isClosed SSL_clear(ssl); JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => 0", ssl); return 0; } ret = SSL_do_handshake(ssl); - appData->clearEnv(); + appData->clearCallbackState(); // cert_verify_callback threw exception if (env->ExceptionCheck()) { SSL_clear(ssl); @@ -2512,7 +2454,7 @@ static jint NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, */ if (sslError == SSL_ERROR_WANT_READ || sslError == SSL_ERROR_WANT_WRITE) { appData->waitingThreads++; - int selectResult = sslSelect(env, sslError, appData, timeout); + int selectResult = sslSelect(env, sslError, fdObject, appData, timeout); if (selectResult == THROWN_SOCKETEXCEPTION) { // SocketException thrown by NetFd.isClosed @@ -2687,8 +2629,8 @@ static jobjectArray NativeCrypto_SSL_get_peer_cert_chain(JNIEnv* env, jclass, ji * @return number of bytes read on success, -1 if the connection was * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown. */ -static int sslRead(JNIEnv* env, SSL* ssl, char* buf, jint len, int* sslReturnCode, - int* sslErrorCode, int timeout) { +static int sslRead(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, char* buf, jint len, + int* sslReturnCode, int* sslErrorCode, int timeout) { // LOGD("Entering sslRead, caller requests to read %d bytes...", len); @@ -2715,12 +2657,12 @@ static int sslRead(JNIEnv* env, SSL* ssl, char* buf, jint len, int* sslReturnCod unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio); // LOGD("Doing SSL_Read()"); - if (!appData->setEnv(env)) { + if (!appData->setCallbackState(env, shc, fdObject)) { MUTEX_UNLOCK(appData->mutex); return THROWN_SOCKETEXCEPTION; } int result = SSL_read(ssl, buf, len); - appData->clearEnv(); + appData->clearCallbackState(); int sslError = SSL_ERROR_NONE; if (result <= 0) { sslError = SSL_get_error(ssl, result); @@ -2759,7 +2701,7 @@ static int sslRead(JNIEnv* env, SSL* ssl, char* buf, jint len, int* sslReturnCod // Need to wait for availability of underlying layer, then retry. case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - int selectResult = sslSelect(env, sslError, appData, timeout); + int selectResult = sslSelect(env, sslError, fdObject, appData, timeout); if (selectResult == THROWN_SOCKETEXCEPTION) { return THROWN_SOCKETEXCEPTION; } @@ -2808,19 +2750,31 @@ static int sslRead(JNIEnv* env, SSL* ssl, char* buf, jint len, int* sslReturnCod /** * OpenSSL read function (1): only one chunk is read (returned as jint). */ -static jint NativeCrypto_SSL_read_byte(JNIEnv* env, jclass, jint ssl_address, jint timeout) +static jint NativeCrypto_SSL_read_byte(JNIEnv* env, jclass, jint ssl_address, + jobject fdObject, jobject shc, jint timeout) { SSL* ssl = to_SSL(env, ssl_address, true); - JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte timeout=%d", ssl, timeout); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte fd=%p shc=%p timeout=%d", + ssl, fdObject, shc, timeout); if (ssl == NULL) { return 0; } + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => 0", ssl); + return 0; + } + if (shc == NULL) { + jniThrowNullPointerException(env, "sslHandshakeCallbacks == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read_byte => 0", ssl); + return 0; + } unsigned char byteRead; int returnCode = 0; int sslErrorCode = SSL_ERROR_NONE; - int ret = sslRead(env, ssl, reinterpret_cast(&byteRead), 1, + int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast(&byteRead), 1, &returnCode, &sslErrorCode, timeout); int result; @@ -2855,15 +2809,25 @@ static jint NativeCrypto_SSL_read_byte(JNIEnv* env, jclass, jint ssl_address, ji * OpenSSL read function (2): read into buffer at offset n chunks. * Returns 1 (success) or value <= 0 (failure). */ -static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint - ssl_address, jbyteArray b, jint offset, jint len, jint timeout) +static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint ssl_address, jobject fdObject, + jobject shc, jbyteArray b, jint offset, jint len, jint timeout) { SSL* ssl = to_SSL(env, ssl_address, true); - JNI_TRACE("ssl=%p NativeCrypto_SSL_read b=%p offset=%d len=%d timeout=%d", - ssl, b, offset, len, timeout); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read fd=%p shc=%p b=%p offset=%d len=%d timeout=%d", + ssl, fdObject, shc, b, offset, len, timeout); if (ssl == NULL) { return 0; } + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read => fd == null", ssl); + return 0; + } + if (shc == NULL) { + jniThrowNullPointerException(env, "sslHandshakeCallbacks == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_read => sslHandshakeCallbacks == null", ssl); + return 0; + } ScopedByteArrayRW bytes(env, b); if (bytes.get() == NULL) { @@ -2873,7 +2837,7 @@ static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint int returnCode = 0; int sslErrorCode = SSL_ERROR_NONE;; - int ret = sslRead(env, ssl, reinterpret_cast(bytes.get() + offset), len, + int ret = sslRead(env, ssl, fdObject, shc, reinterpret_cast(bytes.get() + offset), len, &returnCode, &sslErrorCode, timeout); int result; @@ -2912,8 +2876,8 @@ static jint NativeCrypto_SSL_read(JNIEnv* env, jclass, jint * @return number of bytes read on success, -1 if the connection was * cleanly shut down, or THROW_EXCEPTION if an exception should be thrown. */ -static int sslWrite(JNIEnv* env, SSL* ssl, const char* buf, jint len, int* sslReturnCode, - int* sslErrorCode) { +static int sslWrite(JNIEnv* env, SSL* ssl, jobject fdObject, jobject shc, const char* buf, jint len, + int* sslReturnCode, int* sslErrorCode) { // LOGD("Entering sslWrite(), caller requests to write %d bytes...", len); @@ -2940,12 +2904,12 @@ static int sslWrite(JNIEnv* env, SSL* ssl, const char* buf, jint len, int* sslRe unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio); // LOGD("Doing SSL_write() with %d bytes to go", len); - if (!appData->setEnv(env)) { + if (!appData->setCallbackState(env, shc, fdObject)) { MUTEX_UNLOCK(appData->mutex); return THROWN_SOCKETEXCEPTION; } int result = SSL_write(ssl, buf, len); - appData->clearEnv(); + appData->clearCallbackState(); int sslError = SSL_ERROR_NONE; if (result <= 0) { sslError = SSL_get_error(ssl, result); @@ -2987,7 +2951,7 @@ static int sslWrite(JNIEnv* env, SSL* ssl, const char* buf, jint len, int* sslRe // it's also not standard Java behavior, so we wait forever here. case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - int selectResult = sslSelect(env, sslError, appData, 0); + int selectResult = sslSelect(env, sslError, fdObject, appData, 0); if (selectResult == THROWN_SOCKETEXCEPTION) { return THROWN_SOCKETEXCEPTION; } @@ -3037,18 +3001,29 @@ static int sslWrite(JNIEnv* env, SSL* ssl, const char* buf, jint len, int* sslRe /** * OpenSSL write function (1): only one chunk is written. */ -static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address, jint b) +static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address, + jobject fdObject, jobject shc, jint b) { SSL* ssl = to_SSL(env, ssl_address, true); - JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte b=%d", ssl, b); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte fd=%p shc=%p b=%d", ssl, fdObject, shc, b); if (ssl == NULL) { return; } + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte => fd == null", ssl); + return; + } + if (shc == NULL) { + jniThrowNullPointerException(env, "sslHandshakeCallbacks == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write_byte => sslHandshakeCallbacks == null", ssl); + return; + } int returnCode = 0; int sslErrorCode = SSL_ERROR_NONE; char buf[1] = { (char) b }; - int ret = sslWrite(env, ssl, buf, 1, &returnCode, &sslErrorCode); + int ret = sslWrite(env, ssl, fdObject, shc, buf, 1, &returnCode, &sslErrorCode); switch (ret) { case THROW_EXCEPTION: @@ -3069,14 +3044,25 @@ static void NativeCrypto_SSL_write_byte(JNIEnv* env, jclass, jint ssl_address, j /** * OpenSSL write function (2): write into buffer at offset n chunks. */ -static void NativeCrypto_SSL_write(JNIEnv* env, jclass, - jint ssl_address, jbyteArray b, jint offset, jint len) +static void NativeCrypto_SSL_write(JNIEnv* env, jclass, jint ssl_address, jobject fdObject, + jobject shc, jbyteArray b, jint offset, jint len) { SSL* ssl = to_SSL(env, ssl_address, true); - JNI_TRACE("ssl=%p NativeCrypto_SSL_write b=%p offset=%d len=%d", ssl, b, offset, len); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write fd=%p shc=%p b=%p offset=%d len=%d", + ssl, fdObject, shc, b, offset, len); if (ssl == NULL) { return; } + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write => fd == null", ssl); + return; + } + if (shc == NULL) { + jniThrowNullPointerException(env, "sslHandshakeCallbacks == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_write => sslHandshakeCallbacks == null", ssl); + return; + } ScopedByteArrayRO bytes(env, b); if (bytes.get() == NULL) { @@ -3085,8 +3071,8 @@ static void NativeCrypto_SSL_write(JNIEnv* env, jclass, } int returnCode = 0; int sslErrorCode = SSL_ERROR_NONE; - int ret = sslWrite(env, ssl, reinterpret_cast(bytes.get() + offset), len, - &returnCode, &sslErrorCode); + int ret = sslWrite(env, ssl, fdObject, shc, reinterpret_cast(bytes.get() + offset), + len, &returnCode, &sslErrorCode); switch (ret) { case THROW_EXCEPTION: @@ -3132,15 +3118,27 @@ static void NativeCrypto_SSL_interrupt( /** * OpenSSL close SSL socket function. */ -static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jint ssl_address) { +static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jint ssl_address, + jobject fdObject, jobject shc) { SSL* ssl = to_SSL(env, ssl_address, false); - JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown", ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown fd=%p shc=%p", ssl, fdObject, shc); if (ssl == NULL) { return; } + if (fdObject == NULL) { + jniThrowNullPointerException(env, "fd == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => fd == null", ssl); + return; + } + if (shc == NULL) { + jniThrowNullPointerException(env, "sslHandshakeCallbacks == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_shutdown => sslHandshakeCallbacks == null", ssl); + return; + } + AppData* appData = toAppData(ssl); if (appData != NULL) { - if (!appData->setEnv(env)) { + if (!appData->setCallbackState(env, shc, fdObject)) { // SocketException thrown by NetFd.isClosed SSL_clear(ssl); freeSslErrorState(); @@ -3184,7 +3182,7 @@ static void NativeCrypto_SSL_shutdown(JNIEnv* env, jclass, jint ssl_address) { throwSSLExceptionWithSslErrors(env, ssl, sslError, "SSL shutdown failed"); break; } - appData->clearEnv(); + appData->clearCallbackState(); } SSL_clear(ssl); @@ -3201,10 +3199,10 @@ static void NativeCrypto_SSL_free(JNIEnv* env, jclass, jint ssl_address) if (ssl == NULL) { return; } + AppData* appData = toAppData(ssl); SSL_set_app_data(ssl, NULL); - JNI_TRACE("ssl=%p AppData::destroy(%p)", ssl, appData); - AppData::destroy(env, appData); + delete appData; SSL_free(ssl); } @@ -3388,11 +3386,8 @@ static jint NativeCrypto_d2i_SSL_SESSION(JNIEnv* env, jclass, jbyteArray javaByt return static_cast(reinterpret_cast(ssl_session)); } -/* - * Defines the mapping from Java methods and their signatures - * to native functions. Order is (1) Java name, (2) signature, - * (3) pointer to C function. - */ +#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;" +#define SSL_CALLBACKS "Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$SSLHandshakeCallbacks;" static JNINativeMethod sNativeCryptoMethods[] = { NATIVE_METHOD(NativeCrypto, clinit, "()V"), NATIVE_METHOD(NativeCrypto, EVP_PKEY_new_DSA, "([B[B[B[B[B)I"), @@ -3431,16 +3426,16 @@ static JNINativeMethod sNativeCryptoMethods[] = { NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(IZ)V"), NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(ILjava/lang/String;)V"), NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(I)Ljava/lang/String;"), - NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$SSLHandshakeCallbacks;IZ)I"), + NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "IZ)I"), NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(I)V"), NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(I)[[B"), NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(I)[[B"), - NATIVE_METHOD(NativeCrypto, SSL_read_byte, "(II)I"), - NATIVE_METHOD(NativeCrypto, SSL_read, "(I[BIII)I"), - NATIVE_METHOD(NativeCrypto, SSL_write_byte, "(II)V"), - NATIVE_METHOD(NativeCrypto, SSL_write, "(I[BII)V"), + NATIVE_METHOD(NativeCrypto, SSL_read_byte, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "I)I"), + NATIVE_METHOD(NativeCrypto, SSL_read, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "[BIII)I"), + NATIVE_METHOD(NativeCrypto, SSL_write_byte, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "I)V"), + NATIVE_METHOD(NativeCrypto, SSL_write, "(I" FILE_DESCRIPTOR SSL_CALLBACKS "[BII)V"), NATIVE_METHOD(NativeCrypto, SSL_interrupt, "(I)V"), - NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(I)V"), + NATIVE_METHOD(NativeCrypto, SSL_shutdown, "(I" FILE_DESCRIPTOR SSL_CALLBACKS ")V"), NATIVE_METHOD(NativeCrypto, SSL_free, "(I)V"), NATIVE_METHOD(NativeCrypto, SSL_SESSION_session_id, "(I)[B"), NATIVE_METHOD(NativeCrypto, SSL_SESSION_get_time, "(I)J"), @@ -3455,29 +3450,8 @@ static JNINativeMethod sNativeCryptoMethods[] = { int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) { JNI_TRACE("register_org_apache_harmony_xnet_provider_jsse_NativeCrypto"); // Register org.apache.harmony.xnet.provider.jsse.NativeCrypto methods - int result = jniRegisterNativeMethods(env, - "org/apache/harmony/xnet/provider/jsse/NativeCrypto", - sNativeCryptoMethods, - NELEM(sNativeCryptoMethods)); - if (result == -1) { - return -1; - } - - // java.net.Socket - field_Socket_mImpl = - env->GetFieldID(JniConstants::socketClass, "impl", "Ljava/net/SocketImpl;"); - if (field_Socket_mImpl == NULL) { - LOGE("Can't find field impl in class java.net.Socket"); - return -1; - } - - // java.net.SocketImpl - field_Socket_mFD = - env->GetFieldID(JniConstants::socketImplClass, "fd", "Ljava/io/FileDescriptor;"); - if (field_Socket_mFD == NULL) { - LOGE("Can't find field fd in java.net.SocketImpl"); - return -1; - } - - return 0; + return jniRegisterNativeMethods(env, + "org/apache/harmony/xnet/provider/jsse/NativeCrypto", + sNativeCryptoMethods, + NELEM(sNativeCryptoMethods)); } diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java index 8ceb7dd2..1787fe6e 100644 --- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java +++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java @@ -16,6 +16,7 @@ package org.apache.harmony.xnet.provider.jsse; +import java.io.FileDescriptor; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; @@ -36,6 +37,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; import javax.net.ssl.SSLProtocolException; import javax.security.auth.x500.X500Principal; @@ -45,6 +47,10 @@ import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks; public class NativeCryptoTest extends TestCase { private static final int NULL = 0; + private static final FileDescriptor INVALID_FD = new FileDescriptor(); + private static final SSLHandshakeCallbacks DUMMY_CB = new TestSSLHandshakeCallbacks(-1, null); + + private static final long TIMEOUT_SECONDS = 5; public static void assertEqualSessions(int expected, int actual) { assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected), @@ -436,14 +442,16 @@ public class NativeCryptoTest extends TestCase { return s; } public void clientCertificateRequested(int s) {} - public void afterHandshake(int session, int ssl, int context, Socket socket) + public void afterHandshake(int session, int ssl, int context, + Socket socket, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { if (session != NULL) { NativeCrypto.SSL_SESSION_free(session); } if (ssl != NULL) { try { - NativeCrypto.SSL_shutdown(ssl); + NativeCrypto.SSL_shutdown(ssl, fd, callback); } catch (IOException e) { } NativeCrypto.SSL_free(ssl); @@ -556,6 +564,7 @@ public class NativeCryptoTest extends TestCase { if (timeout == -1) { return null; } + FileDescriptor fd = NativeCrypto.getFileDescriptor(socket); int c = hooks.getContext(); int s = hooks.beforeHandshake(c); TestSSLHandshakeCallbacks callback = new TestSSLHandshakeCallbacks(s, hooks); @@ -564,11 +573,12 @@ public class NativeCryptoTest extends TestCase { + " handshake" + " context=0x" + Integer.toString(c, 16) + " socket=" + socket + + " fd=" + fd + " timeout=" + timeout + " client=" + client); } int session = NativeCrypto.SSL_do_handshake(s, - socket, + fd, callback, timeout, client); @@ -577,7 +587,7 @@ public class NativeCryptoTest extends TestCase { + " handshake" + " session=0x" + Integer.toString(session, 16)); } - hooks.afterHandshake(session, s, c, socket); + hooks.afterHandshake(session, s, c, socket, fd, callback); return callback; } }); @@ -604,7 +614,7 @@ public class NativeCryptoTest extends TestCase { } try { - NativeCrypto.SSL_do_handshake(s, new Socket(), null, 0, true); + NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true); fail(); } catch (NullPointerException e) { } @@ -627,8 +637,8 @@ public class NativeCryptoTest extends TestCase { Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - TestSSLHandshakeCallbacks clientCallback = client.get(); - TestSSLHandshakeCallbacks serverCallback = server.get(); + TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); assertTrue(clientCallback.verifyCertificateChainCalled); assertEqualCertificateChains(SERVER_CERTIFICATES, clientCallback.asn1DerEncodedCertificateChain); @@ -669,8 +679,8 @@ public class NativeCryptoTest extends TestCase { }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - TestSSLHandshakeCallbacks clientCallback = client.get(); - TestSSLHandshakeCallbacks serverCallback = server.get(); + TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); assertTrue(clientCallback.verifyCertificateChainCalled); assertEqualCertificateChains(SERVER_CERTIFICATES, clientCallback.asn1DerEncodedCertificateChain); @@ -714,7 +724,7 @@ public class NativeCryptoTest extends TestCase { }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - server.get(); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); @@ -729,7 +739,7 @@ public class NativeCryptoTest extends TestCase { Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 1, true, cHooks); Future server = handshake(listener, -1, false, sHooks); - client.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); @@ -744,7 +754,7 @@ public class NativeCryptoTest extends TestCase { Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, -1, true, cHooks); Future server = handshake(listener, 1, false, sHooks); - server.get(); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); @@ -779,9 +789,11 @@ public class NativeCryptoTest extends TestCase { return clientContext; } @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - super.afterHandshake(NULL, s, NULL, sock); + super.afterHandshake(NULL, s, NULL, sock, fd, callback); clientSession[0] = session; } }; @@ -791,16 +803,18 @@ public class NativeCryptoTest extends TestCase { return serverContext; } @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - super.afterHandshake(NULL, s, NULL, sock); + super.afterHandshake(NULL, s, NULL, sock, fd, callback); serverSession[0] = session; } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } assertEqualSessions(clientSession[0], serverSession[0]); { @@ -816,10 +830,12 @@ public class NativeCryptoTest extends TestCase { return s; } @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEqualSessions(clientSession[0], session); - super.afterHandshake(NULL, s, NULL, sock); + super.afterHandshake(NULL, s, NULL, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @@ -828,16 +844,18 @@ public class NativeCryptoTest extends TestCase { return serverContext; } @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEqualSessions(serverSession[0], session); - super.afterHandshake(NULL, s, NULL, sock); + super.afterHandshake(NULL, s, NULL, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } NativeCrypto.SSL_SESSION_free(clientSession[0]); NativeCrypto.SSL_SESSION_free(serverSession[0]); @@ -877,7 +895,7 @@ public class NativeCryptoTest extends TestCase { Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); @@ -896,7 +914,7 @@ public class NativeCryptoTest extends TestCase { }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); @@ -954,16 +972,18 @@ public class NativeCryptoTest extends TestCase { }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEquals(hostname, NativeCrypto.SSL_get_servername(s)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_get_servername_null() throws Exception { @@ -993,25 +1013,29 @@ public class NativeCryptoTest extends TestCase { final ServerSocket listener = new ServerSocket(0); Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - assertEquals(42, NativeCrypto.SSL_read_byte(s, 0)); - super.afterHandshake(session, s, c, sock); + assertEquals(42, NativeCrypto.SSL_read_byte(s, fd, callback, 0)); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { NativeCrypto.SSL_renegotiate(s); - NativeCrypto.SSL_write_byte(s, 42); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_write_byte(s, fd, callback, 42); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_get_certificate() throws Exception { @@ -1024,26 +1048,30 @@ public class NativeCryptoTest extends TestCase { final ServerSocket listener = new ServerSocket(0); Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertNull(NativeCrypto.SSL_get_certificate(s)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEqualCertificateChains( SERVER_CERTIFICATES, NativeCrypto.SSL_get_certificate(s)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_get_peer_cert_chain() throws Exception { @@ -1057,33 +1085,61 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { byte[][] cc = NativeCrypto.SSL_get_peer_cert_chain(s); assertEqualCertificateChains(SERVER_CERTIFICATES, cc); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_read_byte() throws Exception { try { - NativeCrypto.SSL_read_byte(NULL, 0); + NativeCrypto.SSL_read_byte(NULL, null, null, 0); fail(); } catch (NullPointerException expected) { } + // null FileDescriptor + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_read_byte(s, null, DUMMY_CB, 0); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + + // null SSLHandshakeCallbacks + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_read_byte(s, INVALID_FD, null, 0); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + // handshaking not yet performed { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_read_byte(s, 0); + NativeCrypto.SSL_read_byte(s, INVALID_FD, DUMMY_CB, 0); fail(); } catch (SSLException expected) { } @@ -1097,47 +1153,55 @@ public class NativeCryptoTest extends TestCase { { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - assertEquals(37, NativeCrypto.SSL_read_byte(s, 0)); - super.afterHandshake(session, s, c, sock); + assertEquals(37, NativeCrypto.SSL_read_byte(s, fd, callback, 0)); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_write_byte(s, 37); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_write_byte(s, fd, callback, 37); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } // timeout case try { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_read_byte(s, 1); + NativeCrypto.SSL_read_byte(s, fd, callback, 1); fail(); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_read_byte(s, 0); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_read_byte(s, fd, callback, 0); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); @@ -1147,22 +1211,49 @@ public class NativeCryptoTest extends TestCase { final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 }; public void test_SSL_read() throws Exception { + + // NULL ssl try { - NativeCrypto.SSL_read(NULL, null, 0, 0, 0); + NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0); fail(); } catch (NullPointerException expected) { } - // null byte array + // null FileDescriptor { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_read(s, null, 0, 0, 0); + NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0); fail(); } catch (NullPointerException expected) { } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + // null SSLHandshakeCallbacks + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + + // null byte array + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0); + fail(); + } catch (NullPointerException expected) { + } NativeCrypto.SSL_free(s); NativeCrypto.SSL_CTX_free(c); } @@ -1172,7 +1263,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_read(s, new byte[1], 0, 1, 0); + NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0); fail(); } catch (SSLException expected) { } @@ -1186,11 +1277,15 @@ public class NativeCryptoTest extends TestCase { { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { byte[] in = new byte[256]; assertEquals(BYTES.length, NativeCrypto.SSL_read(s, + fd, + callback, in, 0, BYTES.length, @@ -1198,44 +1293,50 @@ public class NativeCryptoTest extends TestCase { for (int i = 0; i < BYTES.length; i++) { assertEquals(BYTES[i], in[i]); } - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_write(s, BYTES, 0, BYTES.length); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } // timeout case try { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_read(s, new byte[1], 0, 1, 1); + NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1); fail(); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { - NativeCrypto.SSL_read_byte(s, 0); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_read_byte(s, fd, callback, 0); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); @@ -1244,17 +1345,43 @@ public class NativeCryptoTest extends TestCase { public void test_SSL_write_byte() throws Exception { try { - NativeCrypto.SSL_write_byte(NULL, 0); + NativeCrypto.SSL_write_byte(NULL, null, null, 0); fail(); } catch (NullPointerException expected) { } + // null FileDescriptor + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_write_byte(s, null, DUMMY_CB, 0); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + + // null SSLHandshakeCallbacks + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_write_byte(s, INVALID_FD, null, 0); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + // handshaking not yet performed { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write_byte(s, 0); + NativeCrypto.SSL_write_byte(s, INVALID_FD, DUMMY_CB, 0); fail(); } catch (SSLException expected) { } @@ -1267,17 +1394,43 @@ public class NativeCryptoTest extends TestCase { public void test_SSL_write() throws Exception { try { - NativeCrypto.SSL_write(NULL, null, 0, 0); + NativeCrypto.SSL_write(NULL, null, null, null, 0, 0); fail(); } catch (NullPointerException expected) { } + // null FileDescriptor + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + + // null SSLHandshakeCallbacks + { + int c = NativeCrypto.SSL_CTX_new(); + int s = NativeCrypto.SSL_new(c); + try { + NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1); + fail(); + } catch (NullPointerException expected) { + } + NativeCrypto.SSL_free(s); + NativeCrypto.SSL_CTX_free(c); + } + // null byte array { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, null, 0, 1); + NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1); fail(); } catch (NullPointerException expected) { } @@ -1290,7 +1443,7 @@ public class NativeCryptoTest extends TestCase { int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_write(s, new byte[1], 0, 1); + NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1); fail(); } catch (SSLException expected) { } @@ -1318,16 +1471,20 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { byte[] in = new byte[256]; - NativeCrypto.SSL_read_byte(s, 0); - super.afterHandshake(session, s, c, sock); + NativeCrypto.SSL_read_byte(s, fd, callback, 0); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override - public void afterHandshake(int session, final int s, int c, Socket sock) + public void afterHandshake(int session, final int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { new Thread() { public void run() { @@ -1338,26 +1495,38 @@ public class NativeCryptoTest extends TestCase { } } }.start(); - assertEquals(-1, NativeCrypto.SSL_read_byte(s, 0)); - super.afterHandshake(session, s, c, sock); + assertEquals(-1, NativeCrypto.SSL_read_byte(s, fd, callback, 0)); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_shutdown() throws Exception { + // null FileDescriptor + try { + NativeCrypto.SSL_shutdown(NULL, null, DUMMY_CB); + } catch (NullPointerException expected) { + } + + // null SSLHandshakeCallbacks + try { + NativeCrypto.SSL_shutdown(NULL, INVALID_FD, null); + } catch (NullPointerException expected) { + } + // SSL_shutdown is a rare case that tolerates a null SSL argument - NativeCrypto.SSL_shutdown(NULL); + NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB); // handshaking not yet performed int c = NativeCrypto.SSL_CTX_new(); int s = NativeCrypto.SSL_new(c); try { - NativeCrypto.SSL_shutdown(s); + NativeCrypto.SSL_shutdown(s, INVALID_FD, DUMMY_CB); } catch (SSLProtocolException expected) { } NativeCrypto.SSL_free(s); @@ -1393,19 +1562,21 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { byte[] id = NativeCrypto.SSL_SESSION_session_id(session); assertNotNull(id); assertEquals(32, id.length); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_SESSION_get_time() throws Exception { @@ -1420,19 +1591,21 @@ public class NativeCryptoTest extends TestCase { { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { long time = NativeCrypto.SSL_SESSION_get_time(session); assertTrue(time != 0); assertTrue(time < System.currentTimeMillis()); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } } @@ -1447,18 +1620,20 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { String v = NativeCrypto.SSL_SESSION_get_version(session); assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_SESSION_cipher() throws Exception { @@ -1472,18 +1647,20 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { String a = NativeCrypto.SSL_SESSION_cipher(session); assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_SESSION_compress_meth_null() throws Exception { @@ -1508,17 +1685,19 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEquals("NULL", NativeCrypto.SSL_SESSION_compress_meth(c, session)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_SESSION_compress_meth_ZLIB() throws Exception { @@ -1532,10 +1711,12 @@ public class NativeCryptoTest extends TestCase { return s; } @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { assertEquals("ZLIB", NativeCrypto.SSL_SESSION_compress_meth(c, session)); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @@ -1548,8 +1729,8 @@ public class NativeCryptoTest extends TestCase { }; Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_SSL_SESSION_free() throws Exception { @@ -1574,21 +1755,23 @@ public class NativeCryptoTest extends TestCase { Hooks cHooks = new Hooks() { @Override - public void afterHandshake(int session, int s, int c, Socket sock) + public void afterHandshake(int session, int s, int c, + Socket sock, FileDescriptor fd, + SSLHandshakeCallbacks callback) throws Exception { byte[] b = NativeCrypto.i2d_SSL_SESSION(session); assertNotNull(b); int session2 = NativeCrypto.d2i_SSL_SESSION(b); assertTrue(session2 != NULL); NativeCrypto.SSL_SESSION_free(session2); - super.afterHandshake(session, s, c, sock); + super.afterHandshake(session, s, c, sock, fd, callback); } }; Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES); Future client = handshake(listener, 0, true, cHooks); Future server = handshake(listener, 0, false, sHooks); - client.get(); - server.get(); + client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); + server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); } public void test_d2i_SSL_SESSION() throws Exception { -- 2.11.0