Fix several leaks in OpenSSL JNI cipher suites code.
I first spotted the missing ReleaseStringUTFChars, but then noticed all
the duplication in the cipher suites functions, and noticed that no
copy appeared to be completely correct. The factored-out replacements
shouldn't leak, and should check all error conditions.
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
index 2a55bbc..eec2efe 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
@@ -157,38 +157,13 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getsupportedciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ctx;
- SSL* ssl;
- STACK_OF(SSL_CIPHER) *sk;
- jobjectArray ret;
- int i;
- const char *c;
-
- ctx = SSL_CTX_new(SSLv23_server_method());
- ssl = SSL_new(ctx);
- sk=SSL_get_ciphers(ssl);
-
- ret= (jobjectArray)env->NewObjectArray(5,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
+ SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+ if (ssl_ctx == NULL) {
+ return NULL;
}
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i=0; ; i++) {
- c=SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ jobjectArray result = makeCipherList(env, ssl_ctx);
+ SSL_CTX_free(ssl_ctx);
+ return result;
}
/**
@@ -198,52 +173,20 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getenabledciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- ssl = SSL_new(ctx);
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i = 0; ; i++) {
- c = SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ return makeCipherList(env, ssl_ctx);
}
/**
* Sets the ciphers suites that are enabled in the OpenSSL server.
*/
static void org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_setenabledciphersuites(JNIEnv* env,
- jobject object, jstring controlstring)
+ jobject object, jstring controlString)
{
- SSL_CTX* ctx;
- const char *str;
- int ret;
-
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- str = env->GetStringUTFChars(controlstring, 0);
- ret = SSL_CTX_set_cipher_list(ctx, str);
-
- if(ret == 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "Illegal cipher suite strings.");
- }
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ setEnabledCipherSuites(env, controlString, ssl_ctx);
}
/**
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 8f046ce..88549e1 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -1414,45 +1414,13 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getsupportedciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ssl_ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ssl_ctx = SSL_CTX_new(SSLv23_client_method());
-
+ SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (ssl_ctx == NULL) {
return NULL;
}
-
- ssl = SSL_new(ssl_ctx);
-
- if (ssl == NULL) {
- SSL_CTX_free(ssl_ctx);
- return NULL;
- }
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i=0; ; i++) {
- c=SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- SSL_free(ssl);
+ jobjectArray result = makeCipherList(env, ssl_ctx);
SSL_CTX_free(ssl_ctx);
-
- return ret;
+ return result;
}
/**
@@ -1462,57 +1430,66 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getenabledciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ssl_ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ssl = getSslPointer(env, object, false);
- if (ssl == NULL) {
- ssl_ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- ssl = SSL_new(ssl_ctx);
- env->SetIntField(object, field_ssl, (int)ssl);
- }
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i = 0; ; i++) {
- c = SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ return makeCipherList(env, ssl_ctx);
}
/**
* Sets the ciphers suites that are enabled in the OpenSSL client.
*/
static void org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_setenabledciphersuites(JNIEnv* env, jobject object,
- jstring controlstring)
+ jstring controlString)
{
- SSL_CTX* ctx;
- const char *str;
- int ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ setEnabledCipherSuites(env, controlString, ssl_ctx);
+}
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- str = env->GetStringUTFChars(controlstring, 0);
- ret = SSL_CTX_set_cipher_list(ctx, str);
+static jobjectArray makeCipherList(JNIEnv* env, SSL* ssl) {
+ // Count the ciphers.
+ int cipherCount = 0;
+ while (SSL_get_cipher_list(ssl, cipherCount) != NULL) {
+ ++cipherCount;
+ }
- if (ret == 0) {
+ // Create a String[].
+ jclass stringClass = env->FindClass("java/lang/String");
+ if (stringClass == NULL) {
+ return NULL;
+ }
+ jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
+ if (array == NULL) {
+ return NULL;
+ }
+
+ // Fill in the cipher names.
+ for (int i = 0; i < cipherCount; ++i) {
+ const char* c = SSL_get_cipher_list(ssl, i);
+ env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
+ }
+ return array;
+}
+
+jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl_ctx) {
+ SSL* ssl = SSL_new(ssl_ctx);
+ if (ssl == NULL) {
+ return NULL;
+ }
+ jobjectArray result = makeCipherList(env, ssl);
+ SSL_free(ssl);
+ return result;
+}
+
+void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx) {
+ const char* str = env->GetStringUTFChars(controlString, NULL);
+ int rc = SSL_CTX_set_cipher_list(ssl_ctx, str);
+ env->ReleaseStringUTFChars(controlString, str);
+ if (rc == 0) {
freeSslErrorState();
jniThrowException(env, "java/lang/IllegalArgumentException",
"Illegal cipher suite strings.");
- }
+ }
}
#define SSL_AUTH_MASK 0x00007F00L
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
index 409b4ec..e78cdd8 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
@@ -26,10 +26,10 @@
/**
* Structure to hold together useful JNI variables.
*/
-typedef struct {
+struct mydata_t {
JNIEnv* env;
jobject object;
-} mydata_t;
+};
/**
* Gives an array back containing all the X509 certificate's bytes.
@@ -117,4 +117,7 @@
return 1;
}
+extern jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl);
+extern void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx);
+
#endif