From 9c9a7be6f40e9c1fc24956fc37e6af43f413ff78 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 15 Dec 2009 13:06:11 -0800 Subject: [PATCH] Fix OpenSSLSessionImpl.getCreationTime and getLastAccessedTime. This addresses one part of this abandoned change from ursg: https://android-git.corp.google.com/g/4743 I've also tidied up the native method names to use the harmony "-Impl" convention, removed useless methods that just forward to a native method, and removed dead code. I've canonicalized some of the duplication too, but I want to go through the rest of out OpenSSL code before I really start trying to remove the duplication. When this is submitted, I'll fix the other (unrelated) bug the abandoned change addressed. --- .../xnet/provider/jsse/OpenSSLSessionImpl.java | 106 ++------ ...rmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp | 274 ++++++--------------- .../tests/api/javax/net/ssl/SSLSessionTest.java | 2 - 3 files changed, 93 insertions(+), 289 deletions(-) diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java index b21827147..9aa4b8618 100644 --- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java +++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java @@ -89,47 +89,18 @@ public class OpenSSLSessionImpl implements SSLSession { this.sessionContext = sessionContext; initializeNative(derData); } - - /** - * Returns the identifier of the actual OpenSSL session. - */ - private native byte[] nativegetid(); /** * Gets the identifier of the actual SSL session * @return array of sessions' identifiers. */ - public byte[] getId() { - return nativegetid(); - } - - /** - * Gets the creation time of the OpenSSL session. - * @return the session's creation time in milli seconds since January - * 1st, 1970 - */ - private native long nativegetcreationtime(); - - /** - * Serialize the native state of the session ( ID, cypher, keys - but - * not certs ), using openSSL i2d_SSL_SESSION() - * - * @return the DER encoding of the session. - */ - private native byte[] nativeserialize(); - - /** - * Create a SSL_SESSION object using d2i_SSL_SESSION. - */ - private native int nativedeserialize(byte[] data, int size); + public native byte[] getId(); /** * Get the session object in DER format. This allows saving the session * data or sharing it with other processes. */ - byte[] getEncoded() { - return nativeserialize(); - } + native byte[] getEncoded(); /** * Init the underlying native object from DER data. This @@ -137,35 +108,28 @@ public class OpenSSLSessionImpl implements SSLSession { * @throws IOException */ private void initializeNative(byte[] derData) throws IOException { - this.session = nativedeserialize(derData, derData.length); - if (this.session == 0) { - throw new IOException("Invalid session data"); - } + this.session = initializeNativeImpl(derData, derData.length); + if (this.session == 0) { + throw new IOException("Invalid session data"); + } } - + private native int initializeNativeImpl(byte[] data, int size); /** * Gets the creation time of the SSL session. - * @return the session's creation time in milli seconds since 12.00 PM, - * January 1st, 1970 + * @return the session's creation time in milliseconds since the epoch */ - public long getCreationTime(){ - return nativegetcreationtime(); - } + public native long getCreationTime(); /** * Gives the last time this concrete SSL session was accessed. Accessing * here is to mean that a new connection with the same SSL context data was * established. * - * @return the session's accessing time in milli seconds since 12.00 PM, - * January 1st, 1970 + * @return the session's last access time in milliseconds since the epoch */ public long getLastAccessedTime() { - if (lastAccessedTime == 0) - return nativegetcreationtime(); - else - return lastAccessedTime; + return (lastAccessedTime == 0) ? getCreationTime() : lastAccessedTime; } /** @@ -220,7 +184,7 @@ public class OpenSSLSessionImpl implements SSLSession { /** * Returns the X509 certificates of the peer in the PEM format. */ - private native byte[][] nativegetpeercertificates(); + private native byte[][] getPeerCertificatesImpl(); /** * Gives the certificate(s) of the peer in this SSL session @@ -230,14 +194,14 @@ public class OpenSSLSessionImpl implements SSLSession { * @return an array of X509 certificates (the peer's one first and then * eventually that of the certification authority) or null if no * certificate were used during the SSL connection. - * @throws SSLPeerUnverifiedcertificateException if either a + * @throws SSLPeerUnverifiedCertificateException if either a * not X509 certificate was used (i.e. Kerberos certificates) or the * peer could not be verified. */ public javax.security.cert.X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { if (peerCertificateChain == null) { try { - byte[][] bytes = nativegetpeercertificates(); + byte[][] bytes = getPeerCertificatesImpl(); if (bytes == null) throw new SSLPeerUnverifiedException("No certificate available"); peerCertificateChain = new javax.security.cert.X509Certificate[bytes.length]; @@ -306,11 +270,6 @@ public class OpenSSLSessionImpl implements SSLSession { } /** - * Returns via OpenSSL call the actual peer host name. - */ - private native String nativegetpeerhost(); - - /** * The peer's host name used in this SSL session is returned. It is the host * name of the client for the server; and that of the server for the client. * It is not a reliable way to get a fully qualified host name: it is mainly @@ -322,15 +281,9 @@ public class OpenSSLSessionImpl implements SSLSession { */ public String getPeerHost() { return peerHost; - //return nativegetpeerhost(); } /** - * Returns via OpenSSL call the actual peer port number. - */ - private native String nativegetpeerport(); - - /** * Gives the peer's port number for the actual SSL session. It is the port * number of the client for the server; and that of the server for the * client. It is not a reliable way to get a peer's port number: it is @@ -341,29 +294,16 @@ public class OpenSSLSessionImpl implements SSLSession { */ public int getPeerPort() { return peerPort; - //return Integer.parseInt(nativegetpeerport()); } /** - * Returns via OpenSSL call the actual cipher suite in use. - */ - private native String nativegetciphersuite(); - - /** * Gives back a string identifier of the crypto tools used in the actual SSL * session. For example AES_256_WITH_MD5. * * @return an identifier for all the cryptographic algorithms used in the * actual SSL session. */ - public String getCipherSuite() { - return nativegetciphersuite(); - } - - /** - * Returns via OpenSSL call the actual version of the SSL protocol. - */ - private native String nativegetprotocol(); + public native String getCipherSuite(); /** * Gives back the standard version name of the SSL protocol used in all @@ -373,9 +313,7 @@ public class OpenSSLSessionImpl implements SSLSession { * connections pertaining to this SSL session. * */ - public String getProtocol() { - return nativegetprotocol(); - } + public native String getProtocol(); /** * Gives back the context to which the actual SSL session is bound. A SSL @@ -406,8 +344,7 @@ public class OpenSSLSessionImpl implements SSLSession { if (isValid && context != null && context.getSessionTimeout() != 0 - && lastAccessedTime + context.getSessionTimeout() > System - .currentTimeMillis()) { + && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) { isValid = false; } return isValid; @@ -510,14 +447,11 @@ public class OpenSSLSessionImpl implements SSLSession { values.remove(name, AccessController.getContext()); } - private native void nativefree(int session); - - /** - * Frees the OpenSSL session in the memory. - */ protected void finalize() { synchronized (OpenSSLSocketImpl.class) { - nativefree(session); + freeImpl(session); } } + + private native void freeImpl(int session); } diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp index 324dacf25..e0ea0b8d2 100644 --- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp +++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp @@ -16,8 +16,10 @@ #define LOG_TAG "OpenSSLSessionImpl" +#include "AndroidSystemNatives.h" +#include "JNIHelp.h" + #include -#include #include #include @@ -35,107 +37,78 @@ #include "org_apache_harmony_xnet_provider_jsse_common.h" -/** - * Module scope variables initialized during JNI registration. - */ static jfieldID field_session; -static SSL_SESSION *getSslSessionPointer(JNIEnv* env, jobject object) { - SSL_SESSION* session = (SSL_SESSION *)env->GetIntField(object, field_session); - - return session; +static SSL_SESSION* getSslSessionPointer(JNIEnv* env, jobject object) { + return reinterpret_cast(env->GetIntField(object, field_session)); } -/** - * Gets the peer certificate in the chain and fills a byte array with the - * information therein. - */ -static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeercertificates(JNIEnv* env, +// Fills a byte[][] with the peer certificates in the chain. +static jobjectArray OpenSSLSessionImpl_getPeerCertificatesImpl(JNIEnv* env, jobject object, jint jssl) { - SSL_SESSION *ssl_session; - SSL_CTX* ssl_ctx; - SSL* ssl; - STACK_OF(X509) *chain; - jobjectArray objectArray; - - ssl_session = getSslSessionPointer(env, object); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - ssl = SSL_new(ssl_ctx); + SSL_SESSION* ssl_session = getSslSessionPointer(env, object); + SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + SSL* ssl = SSL_new(ssl_ctx); SSL_set_session(ssl, ssl_session); - chain = SSL_get_peer_cert_chain(ssl); - - objectArray = getcertificatebytes(env, chain); + STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); + jobjectArray objectArray = getcertificatebytes(env, chain); SSL_free(ssl); SSL_CTX_free(ssl_ctx); - return objectArray; } /** - * Serialize the session. - * See apache mod_ssl + * Serializes the native state of the session (ID, cipher, and keys but + * not certificates). Returns a byte[] containing the DER-encoded state. + * See apache mod_ssl. */ -static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_serialize(JNIEnv* env, jobject object) -{ - SSL_SESSION * ssl_session; - jbyteArray bytes = NULL; - jbyte *tmp; - int size; - unsigned char *ucp; - - ssl_session = getSslSessionPointer(env, object); - if (ssl_session == NULL) { - return NULL; - } - - // Compute the size of the DER data - size = i2d_SSL_SESSION(ssl_session, NULL); - if (size == 0) { - return NULL; - } - - bytes = env->NewByteArray(size); - if (bytes != NULL) { - tmp = env->GetByteArrayElements(bytes, NULL); - ucp = (unsigned char *) tmp; +static jbyteArray OpenSSLSessionImpl_getEncoded(JNIEnv* env, jobject object) { + SSL_SESSION* ssl_session = getSslSessionPointer(env, object); + if (ssl_session == NULL) { + return NULL; + } + + // Compute the size of the DER data + int size = i2d_SSL_SESSION(ssl_session, NULL); + if (size == 0) { + return NULL; + } + + jbyteArray bytes = env->NewByteArray(size); + if (bytes != NULL) { + jbyte* tmp = env->GetByteArrayElements(bytes, NULL); + unsigned char* ucp = reinterpret_cast(tmp); i2d_SSL_SESSION(ssl_session, &ucp); env->ReleaseByteArrayElements(bytes, tmp, 0); - } - - return bytes; + } + return bytes; } /** * Deserialize the session. */ -static jint org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_deserialize(JNIEnv* env, jobject object, jbyteArray bytes, jint size) -{ - const unsigned char *ucp; - jbyte *tmp; - SSL_SESSION *ssl_session; - - if (bytes != NULL) { - tmp = env->GetByteArrayElements(bytes, NULL); - ucp = (const unsigned char *) tmp; - ssl_session = d2i_SSL_SESSION(NULL, &ucp, (long) size); - env->ReleaseByteArrayElements(bytes, tmp, 0); +static jint OpenSSLSessionImpl_initializeNativeImpl(JNIEnv* env, jobject object, jbyteArray bytes, jint size) { + if (bytes == NULL) { + return 0; + } + + jbyte* tmp = env->GetByteArrayElements(bytes, NULL); + const unsigned char* ucp = reinterpret_cast(tmp); + SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, size); + env->ReleaseByteArrayElements(bytes, tmp, 0); - return (jint) ssl_session; - } - return 0; + return static_cast(reinterpret_cast(ssl_session)); } /** * Gets and returns in a byte array the ID of the actual SSL session. */ -static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid(JNIEnv* env, jobject object) -{ +static jbyteArray OpenSSLSessionImpl_getId(JNIEnv* env, jobject object) { SSL_SESSION* ssl_session = getSslSessionPointer(env, object); jbyteArray result = env->NewByteArray(ssl_session->session_id_length); @@ -151,76 +124,10 @@ static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid * Gets and returns in a long integer the creation's time of the * actual SSL session. */ -static jlong org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getcreationtime(JNIEnv* env, jobject object) -{ - SSL_SESSION * ssl_session; - - ssl_session = getSslSessionPointer(env, object); - - // convert the creation time from seconds to milliseconds - return (jlong)(1000L * ssl_session->time); -} - -/** - * Gets and returns in a string the peer's host's name. - */ -static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerhost(JNIEnv* env, jobject object) -{ - SSL_CTX *ssl_ctx; - SSL *ssl; - SSL_SESSION *ssl_session; - BIO *bio; - char* hostname; - jstring result; - - ssl_session = getSslSessionPointer(env, object); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - ssl = SSL_new(ssl_ctx); - - SSL_set_session(ssl, ssl_session); - - bio = SSL_get_rbio(ssl); - - hostname = BIO_get_conn_hostname(bio); - - /* Notice: hostname can be NULL */ - result = env->NewStringUTF(hostname); - - SSL_free(ssl); - SSL_CTX_free(ssl_ctx); - - return result; -} - -/** - * Gets and returns in a string the peer's port name (https, ftp, etc.). - */ -static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerport(JNIEnv* env, jobject object) -{ - SSL_CTX *ssl_ctx; - SSL *ssl; - SSL_SESSION *ssl_session; - BIO *bio; - char *port; - jstring result; - - ssl_session = getSslSessionPointer(env, object); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - ssl = SSL_new(ssl_ctx); - - SSL_set_session(ssl, ssl_session); - - bio = SSL_get_rbio(ssl); - port = BIO_get_conn_port(bio); - - /* Notice: port name can be NULL */ - result = env->NewStringUTF(port); - - SSL_free(ssl); - SSL_CTX_free(ssl_ctx); - +static jlong OpenSSLSessionImpl_getCreationTime(JNIEnv* env, jobject object) { + SSL_SESSION* ssl_session = getSslSessionPointer(env, object); + jlong result = SSL_SESSION_get_time(ssl_session); + result *= 1000; // OpenSSL uses seconds, Java uses milliseconds. return result; } @@ -228,48 +135,32 @@ static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerp * Gets and returns in a string the version of the SSL protocol. If it * returns the string "unknown" it means that no connection is established. */ -static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getprotocol(JNIEnv* env, jobject object) -{ - SSL_CTX *ssl_ctx; - SSL *ssl; - SSL_SESSION *ssl_session; - const char* protocol; - jstring result; - - ssl_session = getSslSessionPointer(env, object); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - ssl = SSL_new(ssl_ctx); +static jstring OpenSSLSessionImpl_getProtocol(JNIEnv* env, jobject object) { + SSL_SESSION* ssl_session = getSslSessionPointer(env, object); + SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + SSL* ssl = SSL_new(ssl_ctx); SSL_set_session(ssl, ssl_session); - protocol = SSL_get_version(ssl); - - result = env->NewStringUTF(protocol); + const char* protocol = SSL_get_version(ssl); + jstring result = env->NewStringUTF(protocol); SSL_free(ssl); SSL_CTX_free(ssl_ctx); - return result; } /** * Gets and returns in a string the set of ciphers the actual SSL session uses. */ -static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getciphersuite(JNIEnv* env, jobject object) -{ - SSL_CTX *ssl_ctx; - SSL *ssl; - SSL_SESSION *ssl_session; - - ssl_session = getSslSessionPointer(env, object); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - ssl = SSL_new(ssl_ctx); +static jstring OpenSSLSessionImpl_getCipherSuite(JNIEnv* env, jobject object) { + SSL_SESSION* ssl_session = getSslSessionPointer(env, object); + SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + SSL* ssl = SSL_new(ssl_ctx); SSL_set_session(ssl, ssl_session); - SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + SSL_CIPHER* cipher = SSL_get_current_cipher(ssl); jstring result = env->NewStringUTF(SSL_CIPHER_get_name(cipher)); SSL_free(ssl); @@ -280,50 +171,31 @@ static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getciphe /** * Frees the SSL session. */ -static void org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_free(JNIEnv* env, jobject object, jint session) -{ +static void OpenSSLSessionImpl_freeImpl(JNIEnv* env, jobject object, jint session) { LOGD("Freeing OpenSSL session"); - SSL_SESSION* ssl_session; - ssl_session = (SSL_SESSION*) session; + SSL_SESSION* ssl_session = reinterpret_cast(session); SSL_SESSION_free(ssl_session); } -/** - * The actual JNI methods' mapping table for the class OpenSSLSessionImpl. - */ -static JNINativeMethod sMethods[] = -{ - {"nativegetid", "()[B", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid}, - {"nativegetcreationtime", "()J", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getcreationtime}, - {"nativegetpeerhost", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerhost}, - {"nativegetpeerport", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerport}, - {"nativegetprotocol", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getprotocol}, - {"nativegetciphersuite", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getciphersuite}, - {"nativegetpeercertificates", "()[[B", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeercertificates}, - {"nativefree", "(I)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_free}, - {"nativeserialize", "()[B", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_serialize}, - {"nativedeserialize", "([BI)I", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_deserialize} +static JNINativeMethod sMethods[] = { + { "freeImpl", "(I)V", (void*) OpenSSLSessionImpl_freeImpl }, + { "getCipherSuite", "()Ljava/lang/String;", (void*) OpenSSLSessionImpl_getCipherSuite }, + { "getCreationTime", "()J", (void*) OpenSSLSessionImpl_getCreationTime }, + { "getEncoded", "()[B", (void*) OpenSSLSessionImpl_getEncoded }, + { "getId", "()[B", (void*) OpenSSLSessionImpl_getId }, + { "getPeerCertificatesImpl", "()[[B", (void*) OpenSSLSessionImpl_getPeerCertificatesImpl }, + { "getProtocol", "()Ljava/lang/String;", (void*) OpenSSLSessionImpl_getProtocol }, + { "initializeNativeImpl", "([BI)I", (void*) OpenSSLSessionImpl_initializeNativeImpl } }; -/** - * Register the native methods with JNI for the class OpenSSLSessionImpl. - */ -extern "C" int register_org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl(JNIEnv* env) -{ - int ret; - jclass clazz; - - clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl"); - +int register_org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl(JNIEnv* env) { + jclass clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl"); if (clazz == NULL) { - LOGE("Can't find org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl"); return -1; } field_session = env->GetFieldID(clazz, "session", "I"); - ret = jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl", + return jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl", sMethods, NELEM(sMethods)); - - return ret; } diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java index 6eca114c7..430d11710 100644 --- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java +++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java @@ -193,7 +193,6 @@ public class SSLSessionTest extends TestCase { method = "getCreationTime", args = {} ) - @KnownFailure("Time returned is corrupted") @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI") public void test_getCreationTime() { try { @@ -235,7 +234,6 @@ public class SSLSessionTest extends TestCase { method = "getLastAccessedTime", args = {} ) - @KnownFailure("Time returned is corrupted") @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI") public void test_getLastAccessedTime() { try { -- 2.11.0