CharonVpnService provides a function to get trusted certificates via JNI
authorTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 10:35:49 +0000 (12:35 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 13 Aug 2012 09:00:28 +0000 (11:00 +0200)
src/frontends/android/jni/libandroidbridge/charonservice.c
src/frontends/android/jni/libandroidbridge/charonservice.h
src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java

index 874258b..ac6df0d 100644 (file)
@@ -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),
        );
index c537165..d0c0b71 100644 (file)
@@ -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);
+
 };
 
 /**
index c3bb1ad..d66a551 100644 (file)
 
 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;
@@ -329,6 +333,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
         */
        public native void initializeCharon();