CharonVpnService provides a function to get trusted certificates via JNI

This commit is contained in:
Tobias Brunner
2012-08-13 11:00:28 +02:00
parent 8c2af60ceb
commit 2bec193a1b
3 changed files with 118 additions and 0 deletions
@@ -142,6 +142,53 @@ failed:
return FALSE;
}
METHOD(charonservice_t, get_trusted_certificates, linked_list_t*,
private_charonservice_t *this)
{
JNIEnv *env;
jmethodID method_id;
jobjectArray jcerts;
linked_list_t *list;
jsize i;
androidjni_attach_thread(&env);
method_id = (*env)->GetMethodID(env,
android_charonvpnservice_class,
"getTrustedCertificates", "(Ljava/lang/String;)[[B");
if (!method_id)
{
goto failed;
}
jcerts = (*env)->CallObjectMethod(env, this->vpn_service, method_id, NULL);
if (!jcerts)
{
goto failed;
}
list = linked_list_create();
for (i = 0; i < (*env)->GetArrayLength(env, jcerts); ++i)
{
chunk_t *ca_cert;
jbyteArray jcert;
ca_cert = malloc_thing(chunk_t);
list->insert_last(list, ca_cert);
jcert = (*env)->GetObjectArrayElement(env, jcerts, i);
*ca_cert = chunk_alloc((*env)->GetArrayLength(env, jcert));
(*env)->GetByteArrayRegion(env, jcert, 0, ca_cert->len, ca_cert->ptr);
(*env)->DeleteLocalRef(env, jcert);
}
(*env)->DeleteLocalRef(env, jcerts);
androidjni_detach_thread();
return list;
failed:
androidjni_exception_occurred(env);
androidjni_detach_thread();
return NULL;
}
/**
* Initialize the charonservice object
*/
@@ -159,6 +206,7 @@ static void charonservice_init(JNIEnv *env, jobject service)
.public = {
.update_status = _update_status,
.bypass_socket = _bypass_socket,
.get_trusted_certificates = _get_trusted_certificates,
},
.vpn_service = (*env)->NewGlobalRef(env, service),
);
@@ -29,6 +29,7 @@
#define CHARONSERVICE_H_
#include <library.h>
#include <utils/linked_list.h>
typedef enum android_vpn_state_t android_vpn_state_t;
typedef struct charonservice_t charonservice_t;
@@ -71,6 +72,14 @@ struct charonservice_t {
*/
bool (*bypass_socket)(charonservice_t *this, int fd, int family);
/**
* Get a list of trusted certificates via JNI
*
* @return list of DER encoded certificates (as chunk_t*),
* NULL on failure
*/
linked_list_t *(*get_trusted_certificates)(charonservice_t *this);
};
/**
@@ -17,6 +17,10 @@
package org.strongswan.android.logic;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import org.strongswan.android.data.VpnProfile;
import org.strongswan.android.data.VpnProfileDataSource;
import org.strongswan.android.logic.VpnStateService.ErrorState;
@@ -328,6 +332,63 @@ public class CharonVpnService extends VpnService implements Runnable
}
}
/**
* Function called via JNI to generate a list of DER encoded CA certificates
* as byte array.
*
* @param hash optional alias (only hash part), if given matching certificates are returned
* @return a list of DER encoded CA certificates
*/
private synchronized byte[][] getTrustedCertificates(String hash)
{
ArrayList<byte[]> certs = new ArrayList<byte[]>();
TrustedCertificateManager certman = TrustedCertificateManager.getInstance();
try
{
if (hash != null)
{
String alias = "user:" + hash + ".0";
X509Certificate cert = certman.getCACertificateFromAlias(alias);
if (cert == null)
{
alias = "system:" + hash + ".0";
cert = certman.getCACertificateFromAlias(alias);
}
if (cert == null)
{
return null;
}
certs.add(cert.getEncoded());
}
else
{
String alias = this.mCurrentProfile.getCertificateAlias();
if (alias != null)
{
X509Certificate cert = certman.getCACertificateFromAlias(alias);
if (cert == null)
{
return null;
}
certs.add(cert.getEncoded());
}
else
{
for (X509Certificate cert : certman.getAllCACertificates().values())
{
certs.add(cert.getEncoded());
}
}
}
}
catch (CertificateEncodingException e)
{
e.printStackTrace();
return null;
}
return certs.toArray(new byte[certs.size()][]);
}
/**
* Initialization of charon, provided by libandroidbridge.so
*/