From 7b4177578b53f85c11aee2e929beb10883841c42 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 12 Jun 2017 15:46:41 +0200 Subject: [PATCH] android: Add a simple HTTP(S) fetcher for CRLs --- .../strongswan/android/logic/SimpleFetcher.java | 65 ++++++++++ .../app/src/main/jni/libandroidbridge/Android.mk | 1 + .../src/main/jni/libandroidbridge/android_jni.c | 4 + .../src/main/jni/libandroidbridge/android_jni.h | 1 + .../jni/libandroidbridge/backend/android_fetcher.c | 131 +++++++++++++++++++++ .../jni/libandroidbridge/backend/android_fetcher.h | 33 ++++++ .../src/main/jni/libandroidbridge/charonservice.c | 8 +- 7 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 src/frontends/android/app/src/main/java/org/strongswan/android/logic/SimpleFetcher.java create mode 100644 src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.c create mode 100644 src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.h diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/SimpleFetcher.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/SimpleFetcher.java new file mode 100644 index 0000000..e7f029b --- /dev/null +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/SimpleFetcher.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +package org.strongswan.android.logic; + +import android.support.annotation.Keep; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +@Keep +public class SimpleFetcher +{ + public static byte[] fetch(String uri) throws IOException + { + URL url = new URL(uri); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setConnectTimeout(10000); + conn.setReadTimeout(10000); + try + { + return streamToArray(conn.getInputStream()); + } + finally + { + conn.disconnect(); + } + } + + private static byte[] streamToArray(InputStream in) + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int len; + + try + { + while ((len = in.read(buf)) != -1) + { + out.write(buf, 0, len); + } + return out.toByteArray(); + } + catch (IOException e) + { + e.printStackTrace(); + } + return null; + } +} diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/Android.mk b/src/frontends/android/app/src/main/jni/libandroidbridge/Android.mk index c37210d..49e313a 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/Android.mk +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/Android.mk @@ -6,6 +6,7 @@ LOCAL_SRC_FILES := \ android_jni.c \ backend/android_attr.c \ backend/android_creds.c \ +backend/android_fetcher.c \ backend/android_dns_proxy.c \ backend/android_private_key.c \ backend/android_service.c \ diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.c b/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.c index fb973a8..c16da86 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.c @@ -44,6 +44,7 @@ static struct { jclass *android_charonvpnservice_class; jclass *android_charonvpnservice_builder_class; +jclass *android_simple_fetcher_class; android_sdk_version_t android_sdk_version; /** @@ -122,6 +123,9 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) android_charonvpnservice_builder_class = (*env)->NewGlobalRef(env, (*env)->FindClass(env, JNI_PACKAGE_STRING "/CharonVpnService$BuilderAdapter")); + android_simple_fetcher_class = + (*env)->NewGlobalRef(env, (*env)->FindClass(env, + JNI_PACKAGE_STRING "/SimpleFetcher")); jversion = (*env)->FindClass(env, "android/os/Build$VERSION"); jsdk_int = (*env)->GetStaticFieldID(env, jversion, "SDK_INT", "I"); diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.h b/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.h index b08670f..e4c1372 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.h +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/android_jni.h @@ -44,6 +44,7 @@ */ extern jclass *android_charonvpnservice_class; extern jclass *android_charonvpnservice_builder_class; +extern jclass *android_simple_fetcher_class; /** * Currently known (supported) SDK versions diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.c b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.c new file mode 100644 index 0000000..ce71410 --- /dev/null +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "android_fetcher.h" + +#include "../android_jni.h" +#include "../charonservice.h" +#include + +typedef struct android_fetcher_t android_fetcher_t; + +struct android_fetcher_t { + + /** + * Public interface + */ + fetcher_t public; + + /** + * Callback function + */ + fetcher_callback_t cb; +}; + +METHOD(fetcher_t, fetch, status_t, + android_fetcher_t *this, char *uri, void *userdata) +{ + JNIEnv *env; + jmethodID method_id; + jobjectArray jdata; + jstring juri; + chunk_t data; + status_t status = FAILED; + + if (this->cb == fetcher_default_callback) + { + *(chunk_t*)userdata = chunk_empty; + } + + androidjni_attach_thread(&env); + /* can't use FindClass here as this is not called by the main thread */ + method_id = (*env)->GetStaticMethodID(env, android_simple_fetcher_class, + "fetch", "(Ljava/lang/String;)[B"); + if (!method_id) + { + goto failed; + } + juri = (*env)->NewStringUTF(env, uri); + if (!juri) + { + goto failed; + } + jdata = (*env)->CallStaticObjectMethod(env, android_simple_fetcher_class, + method_id, juri); + if (!jdata || androidjni_exception_occurred(env)) + { + goto failed; + } + data = chunk_from_byte_array(env, jdata); + if (this->cb(userdata, data)) + { + status = SUCCESS; + } + chunk_free(&data); + androidjni_detach_thread(); + return status; + +failed: + DBG1(DBG_LIB, "failed to fetch from '%s'", uri); + androidjni_exception_occurred(env); + androidjni_detach_thread(); + return FAILED; +} + +METHOD(fetcher_t, set_option, bool, + android_fetcher_t *this, fetcher_option_t option, ...) +{ + bool supported = TRUE; + va_list args; + + va_start(args, option); + switch (option) + { + case FETCH_CALLBACK: + { + this->cb = va_arg(args, fetcher_callback_t); + break; + } + default: + supported = FALSE; + break; + } + va_end(args); + return supported; +} + +METHOD(fetcher_t, destroy, void, + android_fetcher_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +fetcher_t *android_fetcher_create() +{ + android_fetcher_t *this; + + INIT(this, + .public = { + .fetch = _fetch, + .set_option = _set_option, + .destroy = _destroy, + }, + .cb = fetcher_default_callback, + ); + + return &this->public; +} diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.h b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.h new file mode 100644 index 0000000..a20cdfd --- /dev/null +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_fetcher.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup android_fetcher android_fetcher + * @{ @ingroup android_backend + */ + +#ifndef ANDROID_FETCHER_H_ +#define ANDROID_FETCHER_H_ + +#include + +/** + * Create an Android-specific fetcher instance based on SimpleFetcher + * + * @return fetcher_t instance + */ +fetcher_t *android_fetcher_create(); + +#endif /** ANDROID_FETCHER_H_ @}*/ diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c index c41ee94..4bcd72b 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2012-2015 Tobias Brunner + * Copyright (C) 2012-2017 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -25,6 +25,7 @@ #include "android_jni.h" #include "backend/android_attr.h" #include "backend/android_creds.h" +#include "backend/android_fetcher.h" #include "backend/android_private_key.h" #include "backend/android_service.h" #include "kernel/android_ipsec.h" @@ -523,6 +524,9 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder, PLUGIN_CALLBACK(charonservice_register, NULL), PLUGIN_PROVIDE(CUSTOM, "android-backend"), PLUGIN_DEPENDS(CUSTOM, "libcharon"), + PLUGIN_REGISTER(FETCHER, android_fetcher_create), + PLUGIN_PROVIDE(FETCHER, "http://"), + PLUGIN_PROVIDE(FETCHER, "https://"), }; INIT(this, -- 2.7.4