From 19737434432db895f5bc8095645959a1ddc1e622 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 09:35:45 +0200 Subject: [PATCH 01/59] libimcv: Android.mk added --- Android.mk | 3 +- src/libimcv/Android.mk | 65 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/libimcv/Android.mk diff --git a/Android.mk b/Android.mk index e762fe955..aa61cc0e7 100644 --- a/Android.mk +++ b/Android.mk @@ -100,7 +100,8 @@ strongswan_BUILD := \ libhydra \ libstrongswan \ libtncif \ - libtnccs + libtnccs \ + libimcv ifneq ($(strongswan_BUILD_STARTER),) strongswan_BUILD += \ diff --git a/src/libimcv/Android.mk b/src/libimcv/Android.mk new file mode 100644 index 000000000..db953d955 --- /dev/null +++ b/src/libimcv/Android.mk @@ -0,0 +1,65 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# copy-n-paste from Makefile.am +libimcv_la_SOURCES := \ + imcv.h imcv.c \ + imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \ + imc/imc_msg.h imc/imc_msg.c \ + imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \ + imv/imv_agent_if.h imv/imv_if.h \ + imv/imv_database.h imv/imv_database.c \ + imv/imv_msg.h imv/imv_msg.c \ + imv/imv_lang_string.h imv/imv_lang_string.c \ + imv/imv_reason_string.h imv/imv_reason_string.c \ + imv/imv_remediation_string.h imv/imv_remediation_string.c \ + imv/imv_session.h imv/imv_session.c \ + imv/imv_workitem.h imv/imv_workitem.c \ + imv/tables.sql imv/data.sql \ + ietf/ietf_attr.h ietf/ietf_attr.c \ + ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \ + ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \ + ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \ + ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \ + ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \ + ietf/ietf_attr_numeric_version.h ietf/ietf_attr_numeric_version.c \ + ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \ + ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \ + ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \ + ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \ + ietf/ietf_attr_remediation_instr.h ietf/ietf_attr_remediation_instr.c \ + ietf/ietf_attr_string_version.h ietf/ietf_attr_string_version.c \ + ita/ita_attr.h ita/ita_attr.c \ + ita/ita_attr_command.h ita/ita_attr_command.c \ + ita/ita_attr_dummy.h ita/ita_attr_dummy.c \ + ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \ + ita/ita_attr_settings.h ita/ita_attr_settings.c \ + ita/ita_attr_angel.h ita/ita_attr_angel.c \ + ita/ita_attr_device_id.h ita/ita_attr_device_id.c \ + os_info/os_info.h os_info/os_info.c \ + pa_tnc/pa_tnc_attr.h \ + pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \ + pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c + +LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES)) + +# build libimcv ---------------------------------------------------------------- + +LOCAL_C_INCLUDES += \ + $(libvstr_PATH) \ + $(strongswan_PATH)/src/libtncif \ + $(strongswan_PATH)/src/libstrongswan + +LOCAL_CFLAGS := $(strongswan_CFLAGS) + +LOCAL_MODULE := libimcv + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_PRELINK_MODULE := false + +LOCAL_SHARED_LIBRARIES += libstrongswan libtncif + +include $(BUILD_SHARED_LIBRARY) From 71b23661d471a6a2137cdaba5fa5d9aed7a1a6dc Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 11:06:35 +0200 Subject: [PATCH 02/59] android: Added function to include source files from plugin subdirectories --- Android.common.mk.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Android.common.mk.in b/Android.common.mk.in index 1bc8a8304..9f8849d7e 100644 --- a/Android.common.mk.in +++ b/Android.common.mk.in @@ -13,6 +13,17 @@ add_plugin = $(if $(call plugin_enabled,$(1)), \ ) \ ) \ ) +add_plugin_subdirs = $(if $(call plugin_enabled,$(1)), \ + $(patsubst $(LOCAL_PATH)/%,%, \ + $(wildcard \ + $(subst %,$(subst -,_,$(strip $(1))), \ + $(addprefix $(LOCAL_PATH)/plugins/%/,$(addsuffix /*.c, \ + $(strip $(2)) \ + )) \ + ) \ + ) \ + ) \ + ) # strongSwan version, replaced by top Makefile strongswan_VERSION := "@PACKAGE_VERSION@" From 467207819096e2f1f4d21acc129e30fb1795a5d1 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 11:10:19 +0200 Subject: [PATCH 03/59] android: Added support to build eap-tnc, tnc-tnccs and tnccs-20 plugins --- src/libcharon/Android.mk | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 66606f937..825a72c8e 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -186,8 +186,11 @@ endif LOCAL_SRC_FILES += $(call add_plugin, eap-peap) -# adding libtls if any of the three plugins above is enabled -ifneq ($(or $(call plugin_enabled, eap-tls), $(call plugin_enabled, eap-ttls), $(call plugin_enabled, eap-peap)),) +LOCAL_SRC_FILES += $(call add_plugin, eap-tnc) + +# adding libtls if any of the four plugins above is enabled +ifneq ($(or $(call plugin_enabled, eap-tls), $(call plugin_enabled, eap-ttls), \ + $(call plugin_enabled, eap-peap), $(call plugin_enabled, eap-tnc)),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/ LOCAL_SRC_FILES += $(addprefix ../libtls/, \ tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \ @@ -207,6 +210,26 @@ ifneq ($(call plugin_enabled, stroke),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../stroke/ endif +LOCAL_SRC_FILES += $(call add_plugin, tnc-tnccs) + +LOCAL_SRC_FILES += $(call add_plugin, tnccs-20) +LOCAL_SRC_FILES += $(call add_plugin_subdirs, tnccs-20, batch messages state_machine) +ifneq ($(call plugin_enabled, tnccs-20),) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/plugins/tnccs_20/ +# for tls.h +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/ +endif + +ifneq ($(or $(call plugin_enabled, eap-tnc), $(call plugin_enabled, tnc-tnccs), \ + $(call plugin_enabled, tnccs-20)),) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtnccs/ +LOCAL_SHARED_LIBRARIES += libtnccs +endif + +ifneq ($(or $(call plugin_enabled, tnc-tnccs), $(call plugin_enabled, tnccs-20)),) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtncif/ +LOCAL_SHARED_LIBRARIES += libtncif +endif # build libcharon -------------------------------------------------------------- From c9df0f989d3d56116684fe7e3e96686a3e667f20 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 11:28:45 +0200 Subject: [PATCH 04/59] android: Added support to build tnc-imc plugin --- src/libcharon/Android.mk | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 825a72c8e..75cf74fa4 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -210,6 +210,11 @@ ifneq ($(call plugin_enabled, stroke),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../stroke/ endif +LOCAL_SRC_FILES += $(call add_plugin, tnc-imc) +ifneq ($(call plugin_enabled, tnc-imc),) +LOCAL_SHARED_LIBRARIES += libdl +endif + LOCAL_SRC_FILES += $(call add_plugin, tnc-tnccs) LOCAL_SRC_FILES += $(call add_plugin, tnccs-20) @@ -220,13 +225,14 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/plugins/tnccs_20/ LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/ endif -ifneq ($(or $(call plugin_enabled, eap-tnc), $(call plugin_enabled, tnc-tnccs), \ - $(call plugin_enabled, tnccs-20)),) +ifneq ($(or $(call plugin_enabled, eap-tnc), $(call plugin_enabled, tnc-imc), \ + $(call plugin_enabled, tnc-tnccs), $(call plugin_enabled, tnccs-20)),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtnccs/ LOCAL_SHARED_LIBRARIES += libtnccs endif -ifneq ($(or $(call plugin_enabled, tnc-tnccs), $(call plugin_enabled, tnccs-20)),) +ifneq ($(or $(call plugin_enabled, tnc-imc), $(call plugin_enabled, tnc-tnccs), \ + $(call plugin_enabled, tnccs-20)),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtncif/ LOCAL_SHARED_LIBRARIES += libtncif endif From 933155fae6bb47d914a1444e77490e3796315930 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 13:50:18 +0200 Subject: [PATCH 05/59] android: Build option added to load BYOD related plugins and libraries in the Android app --- src/frontends/android/jni/Android.mk | 37 +++++++++++++++---- .../android/logic/CharonVpnService.java | 8 ++++ .../strongswan/android/ui/MainActivity.java | 2 + 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index 0ae18fc4b..781d8a1c4 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -1,10 +1,18 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +# use "bring your own device" (BYOD) features (also see USE_BYOD in +# MainActivity.java) +strongswan_USE_BYOD := true + strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ pkcs1 pkcs8 pem xcbc hmac socket-default kernel-netlink \ eap-identity eap-mschapv2 eap-md5 eap-gtc +ifneq ($(strongswan_USE_BYOD),) +strongswan_CHARON_PLUGINS += eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 +endif + strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) include $(LOCAL_PATH)/strongswan/Android.common.mk @@ -52,12 +60,25 @@ strongswan_CFLAGS := \ -DDEV_RANDOM=\"/dev/random\" \ -DDEV_URANDOM=\"/dev/urandom\" +ifneq ($(strongswan_USE_BYOD),) +strongswan_CFLAGS += -DUSE_BYOD +endif + +strongswan_BUILD := \ + vstr \ + openssl \ + libandroidbridge \ + strongswan/src/libipsec \ + strongswan/src/libcharon \ + strongswan/src/libhydra \ + strongswan/src/libstrongswan + +ifneq ($(strongswan_USE_BYOD),) +strongswan_BUILD += \ + strongswan/src/libtnccs \ + strongswan/src/libtncif \ + strongswan/src/libimcv +endif + include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ - vstr \ - openssl \ - libandroidbridge \ - strongswan/src/libipsec \ - strongswan/src/libcharon \ - strongswan/src/libhydra \ - strongswan/src/libstrongswan \ -)) + $(strongswan_BUILD))) diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 02db8c494..5670131ab 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -600,6 +600,14 @@ public class CharonVpnService extends VpnService implements Runnable { System.loadLibrary("crypto"); System.loadLibrary("strongswan"); + + if (MainActivity.USE_BYOD) + { + System.loadLibrary("tncif"); + System.loadLibrary("tnccs"); + System.loadLibrary("imcv"); + } + System.loadLibrary("hydra"); System.loadLibrary("charon"); System.loadLibrary("ipsec"); diff --git a/src/frontends/android/src/org/strongswan/android/ui/MainActivity.java b/src/frontends/android/src/org/strongswan/android/ui/MainActivity.java index d7c1cc4ef..3cf395054 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/MainActivity.java +++ b/src/frontends/android/src/org/strongswan/android/ui/MainActivity.java @@ -58,6 +58,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen public static final String CONTACT_EMAIL = "android@strongswan.org"; public static final String START_PROFILE = "org.strongswan.android.action.START_PROFILE"; public static final String EXTRA_VPN_PROFILE_ID = "org.strongswan.android.VPN_PROFILE_ID"; + /** Use "bring your own device" (BYOD) features */ + public static final boolean USE_BYOD = true; private static final int PREPARE_VPN_SERVICE = 0; private static final String PROFILE_NAME = "org.strongswan.android.MainActivity.PROFILE_NAME"; private static final String PROFILE_REQUIRES_PASSWORD = "org.strongswan.android.MainActivity.REQUIRES_PASSWORD"; From 96658d7264f9c71cf71a980bb7483f94bb0027ad Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 11 Oct 2012 15:26:19 +0200 Subject: [PATCH 06/59] android: Added a sample IMC that sends some dummy OS data --- .../android/jni/libandroidbridge/Android.mk | 18 + .../jni/libandroidbridge/byod/imc_android.c | 389 ++++++++++++++++++ .../jni/libandroidbridge/byod/imc_android.h | 30 ++ .../libandroidbridge/byod/imc_android_state.c | 157 +++++++ .../libandroidbridge/byod/imc_android_state.h | 33 ++ .../jni/libandroidbridge/charonservice.c | 30 +- .../jni/libandroidbridge/charonservice.h | 3 + 7 files changed, 657 insertions(+), 3 deletions(-) create mode 100644 src/frontends/android/jni/libandroidbridge/byod/imc_android.c create mode 100644 src/frontends/android/jni/libandroidbridge/byod/imc_android.h create mode 100644 src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c create mode 100644 src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk index fbb86126e..ca154722b 100644 --- a/src/frontends/android/jni/libandroidbridge/Android.mk +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -14,6 +14,12 @@ kernel/android_net.c \ kernel/network_manager.c \ vpnservice_builder.c +ifneq ($(strongswan_USE_BYOD),) +LOCAL_SRC_FILES += \ +byod/imc_android_state.c \ +byod/imc_android.c +endif + # build libandroidbridge ------------------------------------------------------- LOCAL_C_INCLUDES += \ @@ -23,6 +29,14 @@ LOCAL_C_INCLUDES += \ $(strongswan_PATH)/src/libcharon \ $(strongswan_PATH)/src/libstrongswan +ifneq ($(strongswan_USE_BYOD),) +LOCAL_C_INCLUDES += \ + $(strongswan_PATH)/src/libimcv \ + $(strongswan_PATH)/src/libtncif \ + $(strongswan_PATH)/src/libtnccs \ + $(strongswan_PATH)/src/libtls +endif + LOCAL_CFLAGS := $(strongswan_CFLAGS) \ -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"' @@ -38,6 +52,10 @@ LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libipsec libcharon +ifneq ($(strongswan_USE_BYOD),) +LOCAL_SHARED_LIBRARIES += libimcv libtncif libtnccs +endif + include $(BUILD_SHARED_LIBRARY) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c new file mode 100644 index 000000000..f83b6fdeb --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2012-2013 Tobias Brunner + * Copyright (C) 2011-2012 Andreas Steffen + * 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 "imc_android_state.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +/* IMC definitions */ + +static const char imc_name[] = "Android"; + +static pen_type_t msg_types[] = { + { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM } +}; + +static imc_agent_t *imc_android; + +/** + * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, + TNC_Version min_version, + TNC_Version max_version, + TNC_Version *actual_version) +{ + if (imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name); + return TNC_RESULT_ALREADY_INITIALIZED; + } + imc_android = imc_agent_create(imc_name, msg_types, countof(msg_types), + imc_id, actual_version); + if (!imc_android) + { + return TNC_RESULT_FATAL; + } + + if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) + { + DBG1(DBG_IMC, "no common IF-IMC version"); + return TNC_RESULT_NO_COMMON_VERSION; + } + return TNC_RESULT_SUCCESS; +} + +/** + * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_ConnectionState new_state) +{ + imc_state_t *state; + + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + switch (new_state) + { + case TNC_CONNECTION_STATE_CREATE: + state = imc_android_state_create(connection_id); + return imc_android->create_state(imc_android, state); + case TNC_CONNECTION_STATE_HANDSHAKE: + if (imc_android->change_state(imc_android, connection_id, new_state, + &state) != TNC_RESULT_SUCCESS) + { + return TNC_RESULT_FATAL; + } + state->set_result(state, imc_id, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + return TNC_RESULT_SUCCESS; + case TNC_CONNECTION_STATE_DELETE: + return imc_android->delete_state(imc_android, connection_id); + default: + return imc_android->change_state(imc_android, connection_id, + new_state, NULL); + } +} + +/** + * Add IETF Product Information attribute to the send queue + */ +static void add_product_info(imc_msg_t *msg) +{ + pa_tnc_attr_t *attr; + chunk_t android_os = { "Android", 7 }; + + attr = ietf_attr_product_info_create(PEN_IETF, 0, android_os); + msg->add_attribute(msg, attr); +} + +/** + * Add IETF String Version attribute to the send queue + */ +static void add_string_version(imc_msg_t *msg) +{ + pa_tnc_attr_t *attr; + chunk_t android_version = { "4.x", 3 }; + + attr = ietf_attr_string_version_create(android_version, chunk_empty, + chunk_empty); + msg->add_attribute(msg, attr); +} + +/** + * Add an IETF Installed Packages attribute to the send queue + */ +static void add_installed_packages(imc_msg_t *msg) +{ + pa_tnc_attr_t *attr; + ietf_attr_installed_packages_t *attr_cast; + chunk_t libc_name = { "libc-bin", 8 }; + chunk_t libc_version = { "2.15-0ubuntu10.2", 16 }; + chunk_t selinux_name = { "selinux", 7 }; + chunk_t selinux_version = { "1:0.11", 6 }; + + attr = ietf_attr_installed_packages_create(); + attr_cast = (ietf_attr_installed_packages_t*)attr; + attr_cast->add(attr_cast, libc_name, libc_version); + attr_cast->add(attr_cast, selinux_name, selinux_version); + msg->add_attribute(msg, attr); +} + +/** + * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) +{ + imc_state_t *state; + imc_msg_t *out_msg; + TNC_Result result = TNC_RESULT_SUCCESS; + + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + if (!imc_android->get_state(imc_android, connection_id, &state)) + { + return TNC_RESULT_FATAL; + } + if (lib->settings->get_bool(lib->settings, + "android.imc.send_os_info", TRUE)) + { + out_msg = imc_msg_create(imc_android, state, connection_id, imc_id, + TNC_IMVID_ANY, msg_types[0]); + add_product_info(out_msg); + add_string_version(out_msg); + + /* send PA-TNC message with the excl flag not set */ + result = out_msg->send(out_msg, FALSE); + out_msg->destroy(out_msg); + } + + return result; +} + +static TNC_Result receive_message(imc_msg_t *in_msg) +{ + imc_msg_t *out_msg; + enumerator_t *enumerator; + pa_tnc_attr_t *attr; + pen_type_t attr_type; + TNC_Result result; + bool fatal_error = FALSE; + + /* parse received PA-TNC message and handle local and remote errors */ + result = in_msg->receive(in_msg, &fatal_error); + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + out_msg = imc_msg_create_as_reply(in_msg); + + /* analyze PA-TNC attributes */ + enumerator = in_msg->create_attribute_enumerator(in_msg); + while (enumerator->enumerate(enumerator, &attr)) + { + attr_type = attr->get_type(attr); + + if (attr_type.vendor_id != PEN_IETF) + { + continue; + } + if (attr_type.type == IETF_ATTR_ATTRIBUTE_REQUEST) + { + ietf_attr_attr_request_t *attr_cast; + pen_type_t *entry; + enumerator_t *e; + + attr_cast = (ietf_attr_attr_request_t*)attr; + + e = attr_cast->create_enumerator(attr_cast); + while (e->enumerate(e, &entry)) + { + if (entry->vendor_id != PEN_IETF) + { + continue; + } + switch (entry->type) + { + case IETF_ATTR_PRODUCT_INFORMATION: + add_product_info(out_msg); + break; + case IETF_ATTR_STRING_VERSION: + add_string_version(out_msg); + break; + case IETF_ATTR_INSTALLED_PACKAGES: + add_installed_packages(out_msg); + break; + default: + break; + } + } + e->destroy(e); + } + } + enumerator->destroy(enumerator); + + if (fatal_error) + { + result = TNC_RESULT_FATAL; + } + else + { + result = out_msg->send(out_msg, TRUE); + } + out_msg->destroy(out_msg); + + return result; +} + +/** + * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3 + + */ +TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + imc_state_t *state; + imc_msg_t *in_msg; + TNC_Result result; + + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + if (!imc_android->get_state(imc_android, connection_id, &state)) + { + return TNC_RESULT_FATAL; + } + in_msg = imc_msg_create_from_data(imc_android, state, connection_id, + msg_type, chunk_create(msg, msg_len)); + result = receive_message(in_msg); + in_msg->destroy(in_msg); + + return result; +} + +/** + * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3 + */ +TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imv_id, + TNC_UInt32 dst_imc_id) +{ + imc_state_t *state; + imc_msg_t *in_msg; + TNC_Result result; + + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + if (!imc_android->get_state(imc_android, connection_id, &state)) + { + return TNC_RESULT_FATAL; + } + in_msg = imc_msg_create_from_long_data(imc_android, state, connection_id, + src_imv_id, dst_imc_id,msg_vid, msg_subtype, + chunk_create(msg, msg_len)); + result =receive_message(in_msg); + in_msg->destroy(in_msg); + + return result; +} + +/** + * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) +{ + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + return TNC_RESULT_SUCCESS; +} + +/** + * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) +{ + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + imc_android->destroy(imc_android); + imc_android = NULL; + return TNC_RESULT_SUCCESS; +} + +/** + * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id, + TNC_TNCC_BindFunctionPointer bind_function) +{ + if (!imc_android) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + return imc_android->bind_functions(imc_android, bind_function); +} + +/* + * Described in header + */ +bool imc_android_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data) +{ + if (reg) + { + return tnc->imcs->load_from_functions(tnc->imcs, "android", + TNC_IMC_Initialize, TNC_IMC_NotifyConnectionChange, + TNC_IMC_BeginHandshake, TNC_IMC_ReceiveMessage, + TNC_IMC_ReceiveMessageLong, TNC_IMC_BatchEnding, + TNC_IMC_Terminate, TNC_IMC_ProvideBindFunction); + } + return TRUE; +} diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.h b/src/frontends/android/jni/libandroidbridge/byod/imc_android.h new file mode 100644 index 000000000..3bfc6de40 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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_imc android_imc + * @{ @ingroup android_byod + */ + +#ifndef ANDROID_IMC_H_ +#define ANDROID_IMC_H_ + +/** + * Callback for the Android IMC plugin + */ +bool imc_android_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data); + +#endif /** ANDROID_IMC_H_ @}*/ diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c new file mode 100644 index 000000000..47eda33cd --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012 Andreas Steffen + * 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 "imc_android_state.h" + +#include + +#include + +typedef struct private_imc_state_t private_imc_state_t; + +/** + * Private data of an imc_state_t object. + */ +struct private_imc_state_t { + + /** + * Public interface + */ + imc_state_t public; + + /** + * TNCCS connection ID + */ + TNC_ConnectionID connection_id; + + /** + * TNCCS connection state + */ + TNC_ConnectionState state; + + /** + * Assessment/Evaluation Result + */ + TNC_IMV_Evaluation_Result result; + + /** + * Does the TNCCS connection support long message types? + */ + bool has_long; + + /** + * Does the TNCCS connection support exclusive delivery? + */ + bool has_excl; + + /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; +}; + +METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, + private_imc_state_t *this) +{ + return this->connection_id; +} + +METHOD(imc_state_t, has_long, bool, + private_imc_state_t *this) +{ + return this->has_long; +} + +METHOD(imc_state_t, has_excl, bool, + private_imc_state_t *this) +{ + return this->has_excl; +} + +METHOD(imc_state_t, set_flags, void, + private_imc_state_t *this, bool has_long, bool has_excl) +{ + this->has_long = has_long; + this->has_excl = has_excl; +} + +METHOD(imc_state_t, set_max_msg_len, void, + private_imc_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imc_state_t, get_max_msg_len, u_int32_t, + private_imc_state_t *this) +{ + return this->max_msg_len; +} + +METHOD(imc_state_t, change_state, void, + private_imc_state_t *this, TNC_ConnectionState new_state) +{ + this->state = new_state; +} + +METHOD(imc_state_t, set_result, void, + private_imc_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result result) +{ + this->result = result; +} + +METHOD(imc_state_t, get_result, bool, + private_imc_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result *result) +{ + if (result) + { + *result = this->result; + } + return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW; +} + +METHOD(imc_state_t, destroy, void, + private_imc_state_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +imc_state_t *imc_android_state_create(TNC_ConnectionID connection_id) +{ + private_imc_state_t *this; + + INIT(this, + .public = { + .get_connection_id = _get_connection_id, + .has_long = _has_long, + .has_excl = _has_excl, + .set_flags = _set_flags, + .set_max_msg_len = _set_max_msg_len, + .get_max_msg_len = _get_max_msg_len, + .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, + .destroy = _destroy, + }, + .state = TNC_CONNECTION_STATE_CREATE, + .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, + .connection_id = connection_id, + ); + + return &this->public; +} diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h new file mode 100644 index 000000000..3acdea143 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 imc_android_state imc_android_state + * @{ @ingroup android_byod + */ + +#ifndef IMC_ANDROID_STATE_H_ +#define IMC_ANDROID_STATE_H_ + +#include + +/** + * Create an imc_android_state_t instance + * + * @param id connection ID + */ +imc_state_t* imc_android_state_create(TNC_ConnectionID id); + +#endif /** IMC_ANDROID_STATE_H_ @}*/ diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index 25fbf89c6..b7bfdccc6 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -30,6 +30,10 @@ #include "kernel/android_ipsec.h" #include "kernel/android_net.h" +#ifdef USE_BYOD +#include "byod/imc_android.h" +#endif + #include #include #include @@ -357,7 +361,7 @@ static void initiate(char *type, char *gateway, char *username, char *password) /** * Initialize/deinitialize Android backend */ -static bool charonservice_register(void *plugin, plugin_feature_t *feature, +static bool charonservice_register(plugin_t *plugin, plugin_feature_t *feature, bool reg, void *data) { private_charonservice_t *this = (private_charonservice_t*)charonservice; @@ -434,6 +438,13 @@ static void set_options(char *logfile) lib->settings->set_str(lib->settings, "charon.interfaces_ignore", "lo, tun0, tun1, tun2, tun3, " "tun4"); + +#ifdef USE_BYOD + lib->settings->set_str(lib->settings, + "charon.plugins.eap-tnc.protocol", "tnccs-2.0"); + lib->settings->set_bool(lib->settings, + "android.imc.send_os_info", TRUE); +#endif } /** @@ -445,10 +456,18 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) static plugin_feature_t features[] = { PLUGIN_CALLBACK(kernel_ipsec_register, kernel_android_ipsec_create), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), - PLUGIN_CALLBACK((plugin_feature_callback_t)charonservice_register, NULL), - PLUGIN_PROVIDE(CUSTOM, "Android backend"), + PLUGIN_CALLBACK(charonservice_register, NULL), + PLUGIN_PROVIDE(CUSTOM, "android-backend"), PLUGIN_DEPENDS(CUSTOM, "libcharon"), }; +#ifdef USE_BYOD + static plugin_feature_t byod_features[] = { + PLUGIN_CALLBACK(imc_android_register, NULL), + PLUGIN_PROVIDE(CUSTOM, "android-imc"), + PLUGIN_DEPENDS(CUSTOM, "android-backend"), + PLUGIN_DEPENDS(CUSTOM, "imc-manager"), + }; +#endif INIT(this, .public = { @@ -471,6 +490,11 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) lib->plugins->add_static_features(lib->plugins, "androidbridge", features, countof(features), TRUE); + +#ifdef USE_BYOD + lib->plugins->add_static_features(lib->plugins, "android-byod", + byod_features, countof(byod_features), TRUE); +#endif } /** diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.h b/src/frontends/android/jni/libandroidbridge/charonservice.h index 7391ea61d..f142f78e5 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/jni/libandroidbridge/charonservice.h @@ -21,6 +21,9 @@ * @defgroup android_backend backend * @ingroup libandroidbridge * + * @defgroup android_byod byod + * @ingroup libandroidbridge + * * @defgroup android_kernel kernel * @ingroup libandroidbridge * From f0e0101a1f8d4f8c9f68583db6c5727b69e8d768 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 24 Apr 2013 18:36:23 +0200 Subject: [PATCH 07/59] libpts: Android.mk added --- src/libpts/Android.mk | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/libpts/Android.mk diff --git a/src/libpts/Android.mk b/src/libpts/Android.mk new file mode 100644 index 000000000..7c353c418 --- /dev/null +++ b/src/libpts/Android.mk @@ -0,0 +1,70 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# copy-n-paste from Makefile.am +libpts_la_SOURCES := \ + libpts.h libpts.c \ + pts/pts.h pts/pts.c \ + pts/pts_error.h pts/pts_error.c \ + pts/pts_pcr.h pts/pts_pcr.c \ + pts/pts_proto_caps.h \ + pts/pts_req_func_comp_evid.h \ + pts/pts_simple_evid_final.h \ + pts/pts_creds.h pts/pts_creds.c \ + pts/pts_database.h pts/pts_database.c \ + pts/pts_dh_group.h pts/pts_dh_group.c \ + pts/pts_file_meas.h pts/pts_file_meas.c \ + pts/pts_file_meta.h pts/pts_file_meta.c \ + pts/pts_file_type.h pts/pts_file_type.c \ + pts/pts_meas_algo.h pts/pts_meas_algo.c \ + pts/components/pts_component.h \ + pts/components/pts_component_manager.h pts/components/pts_component_manager.c \ + pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \ + pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \ + pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \ + pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \ + pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \ + pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \ + pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \ + tcg/tcg_attr.h tcg/tcg_attr.c \ + tcg/tcg_pts_attr_proto_caps.h tcg/tcg_pts_attr_proto_caps.c \ + tcg/tcg_pts_attr_dh_nonce_params_req.h tcg/tcg_pts_attr_dh_nonce_params_req.c \ + tcg/tcg_pts_attr_dh_nonce_params_resp.h tcg/tcg_pts_attr_dh_nonce_params_resp.c \ + tcg/tcg_pts_attr_dh_nonce_finish.h tcg/tcg_pts_attr_dh_nonce_finish.c \ + tcg/tcg_pts_attr_meas_algo.h tcg/tcg_pts_attr_meas_algo.c \ + tcg/tcg_pts_attr_get_tpm_version_info.h tcg/tcg_pts_attr_get_tpm_version_info.c \ + tcg/tcg_pts_attr_tpm_version_info.h tcg/tcg_pts_attr_tpm_version_info.c \ + tcg/tcg_pts_attr_get_aik.h tcg/tcg_pts_attr_get_aik.c \ + tcg/tcg_pts_attr_aik.h tcg/tcg_pts_attr_aik.c \ + tcg/tcg_pts_attr_req_func_comp_evid.h tcg/tcg_pts_attr_req_func_comp_evid.c \ + tcg/tcg_pts_attr_gen_attest_evid.h tcg/tcg_pts_attr_gen_attest_evid.c \ + tcg/tcg_pts_attr_simple_comp_evid.h tcg/tcg_pts_attr_simple_comp_evid.c \ + tcg/tcg_pts_attr_simple_evid_final.h tcg/tcg_pts_attr_simple_evid_final.c \ + tcg/tcg_pts_attr_req_file_meas.h tcg/tcg_pts_attr_req_file_meas.c \ + tcg/tcg_pts_attr_file_meas.h tcg/tcg_pts_attr_file_meas.c \ + tcg/tcg_pts_attr_req_file_meta.h tcg/tcg_pts_attr_req_file_meta.c \ + tcg/tcg_pts_attr_unix_file_meta.h tcg/tcg_pts_attr_unix_file_meta.c + +LOCAL_SRC_FILES := $(filter %.c,$(libpts_la_SOURCES)) + +# build libpts ----------------------------------------------------------------- + +LOCAL_C_INCLUDES += \ + $(libvstr_PATH) \ + $(strongswan_PATH)/src/libtncif \ + $(strongswan_PATH)/src/libimcv \ + $(strongswan_PATH)/src/libstrongswan + +LOCAL_CFLAGS := $(strongswan_CFLAGS) + +LOCAL_MODULE := libpts + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_PRELINK_MODULE := false + +LOCAL_SHARED_LIBRARIES += libstrongswan libimcv + +include $(BUILD_SHARED_LIBRARY) From a6507df2ecaf957233d77899db4bf7229fc2f226 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 24 Apr 2013 18:36:59 +0200 Subject: [PATCH 08/59] android: Build libpts and init/deinit libpts in BYOD IMC --- src/frontends/android/jni/Android.mk | 3 ++- src/frontends/android/jni/libandroidbridge/Android.mk | 3 ++- .../android/jni/libandroidbridge/byod/imc_android.c | 5 +++++ .../src/org/strongswan/android/logic/CharonVpnService.java | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index 781d8a1c4..0163e308d 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -77,7 +77,8 @@ ifneq ($(strongswan_USE_BYOD),) strongswan_BUILD += \ strongswan/src/libtnccs \ strongswan/src/libtncif \ - strongswan/src/libimcv + strongswan/src/libimcv \ + strongswan/src/libpts endif include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk index ca154722b..29f95e58b 100644 --- a/src/frontends/android/jni/libandroidbridge/Android.mk +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -34,6 +34,7 @@ LOCAL_C_INCLUDES += \ $(strongswan_PATH)/src/libimcv \ $(strongswan_PATH)/src/libtncif \ $(strongswan_PATH)/src/libtnccs \ + $(strongswan_PATH)/src/libpts \ $(strongswan_PATH)/src/libtls endif @@ -53,7 +54,7 @@ LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libipsec libcharon ifneq ($(strongswan_USE_BYOD),) -LOCAL_SHARED_LIBRARIES += libimcv libtncif libtnccs +LOCAL_SHARED_LIBRARIES += libimcv libtncif libtnccs libpts endif include $(BUILD_SHARED_LIBRARY) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index f83b6fdeb..06edf359a 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -17,6 +17,7 @@ #include "imc_android_state.h" #include +#include #include #include #include @@ -64,6 +65,8 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } + libpts_init(); + if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) { DBG1(DBG_IMC, "no common IF-IMC version"); @@ -352,6 +355,8 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); return TNC_RESULT_NOT_INITIALIZED; } + /* has to be done before destroying the agent / deinitializing libimcv */ + libpts_deinit(); imc_android->destroy(imc_android); imc_android = NULL; return TNC_RESULT_SUCCESS; diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 5670131ab..f08a48135 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -606,6 +606,7 @@ public class CharonVpnService extends VpnService implements Runnable System.loadLibrary("tncif"); System.loadLibrary("tnccs"); System.loadLibrary("imcv"); + System.loadLibrary("pts"); } System.loadLibrary("hydra"); From ad39ce314b009486c2cddab4807e07ba5754370d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 23 Apr 2013 18:19:34 +0200 Subject: [PATCH 09/59] Ignore Eclipse project/workspace files Students seem to like Eclipse to work on strongSwan. --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3deb9fdb5..0135d6a94 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,8 @@ apidoc/ coverage/ *.gcno *.gcda -*.gcov \ No newline at end of file +*.gcov +.cproject +.project +.metadata/ +.settings/ \ No newline at end of file From 82aceeb151eb5ff5f37eed08e6d2d4bd106ae388 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 24 Apr 2013 15:27:31 +0200 Subject: [PATCH 10/59] libtnccs: Don't try to load IMCs/IMVs from a file if there is no filename --- src/libtnccs/tnc/tnc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libtnccs/tnc/tnc.c b/src/libtnccs/tnc/tnc.c index 769b9fa54..3a5b84596 100644 --- a/src/libtnccs/tnc/tnc.c +++ b/src/libtnccs/tnc/tnc.c @@ -100,6 +100,11 @@ static bool load_imcvs_from_config(char *filename, bool is_imc) void *addr; char *label; + if (!filename || !*filename) + { + return TRUE; + } + label = is_imc ? "IMC" : "IMV"; DBG1(DBG_TNC, "loading %ss from '%s'", label, filename); From 753035f6d7b556e43ce07f5bf2d5257686dd8505 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 24 Apr 2013 15:28:13 +0200 Subject: [PATCH 11/59] android: Don't attempt loading IMCs from /etc/tnc_config --- src/frontends/android/jni/libandroidbridge/charonservice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index b7bfdccc6..fbbda55a9 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -444,6 +444,8 @@ static void set_options(char *logfile) "charon.plugins.eap-tnc.protocol", "tnccs-2.0"); lib->settings->set_bool(lib->settings, "android.imc.send_os_info", TRUE); + lib->settings->set_str(lib->settings, + "libtnccs.tnc_config", ""); #endif } From aa4ff3b2111d5d24d9356b6590b5cf29ad710feb Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 24 Apr 2013 16:24:14 +0200 Subject: [PATCH 12/59] android: Added a Java part to the Android IMC --- .../jni/libandroidbridge/byod/imc_android.c | 63 ++++++++++++++++++- .../jni/libandroidbridge/charonservice.c | 19 +++--- .../android/logic/imc/AndroidImc.java | 28 +++++++++ 3 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 06edf359a..f648456f7 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -15,6 +15,7 @@ */ #include "imc_android_state.h" +#include "../android_jni.h" #include #include @@ -45,6 +46,16 @@ static pen_type_t msg_types[] = { static imc_agent_t *imc_android; +/** + * AndroidImc object accessed via JNI + */ +static jobject android_imc; + +/** + * AndroidImc class object + */ +static jclass android_imc_cls; + /** * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 */ @@ -382,13 +393,59 @@ TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id, bool imc_android_register(plugin_t *plugin, plugin_feature_t *feature, bool reg, void *data) { + JNIEnv *env; + jmethodID method_id; + jobject obj, context = (jobject)data; + jclass cls; + bool success = TRUE; + + androidjni_attach_thread(&env); if (reg) { - return tnc->imcs->load_from_functions(tnc->imcs, "android", + cls = (*env)->FindClass(env, JNI_PACKAGE_STRING "/imc/AndroidImc"); + if (!cls) + { + goto failed; + } + android_imc_cls = (*env)->NewGlobalRef(env, cls); + method_id = (*env)->GetMethodID(env, cls, "", + "(Landroid/content/Context;)V"); + if (!method_id) + { + goto failed; + } + obj = (*env)->NewObject(env, cls, method_id, context); + if (!obj) + { + goto failed; + } + android_imc = (*env)->NewGlobalRef(env, obj); + androidjni_detach_thread(); + + if (tnc->imcs->load_from_functions(tnc->imcs, "Android", TNC_IMC_Initialize, TNC_IMC_NotifyConnectionChange, TNC_IMC_BeginHandshake, TNC_IMC_ReceiveMessage, TNC_IMC_ReceiveMessageLong, TNC_IMC_BatchEnding, - TNC_IMC_Terminate, TNC_IMC_ProvideBindFunction); + TNC_IMC_Terminate, TNC_IMC_ProvideBindFunction)) + { + return TRUE; + } +failed: + DBG1(DBG_IMC, "initialization of Android IMC failed"); + androidjni_exception_occurred(env); + success = FALSE; } - return TRUE; + + if (android_imc) + { + (*env)->DeleteGlobalRef(env, android_imc); + android_imc = NULL; + } + if (android_imc_cls) + { + (*env)->DeleteGlobalRef(env, android_imc_cls); + android_imc_cls = NULL; + } + androidjni_detach_thread(); + return success; } diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index fbbda55a9..1c62e282c 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -462,14 +462,6 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) PLUGIN_PROVIDE(CUSTOM, "android-backend"), PLUGIN_DEPENDS(CUSTOM, "libcharon"), }; -#ifdef USE_BYOD - static plugin_feature_t byod_features[] = { - PLUGIN_CALLBACK(imc_android_register, NULL), - PLUGIN_PROVIDE(CUSTOM, "android-imc"), - PLUGIN_DEPENDS(CUSTOM, "android-backend"), - PLUGIN_DEPENDS(CUSTOM, "imc-manager"), - }; -#endif INIT(this, .public = { @@ -494,8 +486,17 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) countof(features), TRUE); #ifdef USE_BYOD - lib->plugins->add_static_features(lib->plugins, "android-byod", + { + plugin_feature_t byod_features[] = { + PLUGIN_CALLBACK(imc_android_register, this->vpn_service), + PLUGIN_PROVIDE(CUSTOM, "android-imc"), + PLUGIN_DEPENDS(CUSTOM, "android-backend"), + PLUGIN_DEPENDS(CUSTOM, "imc-manager"), + }; + + lib->plugins->add_static_features(lib->plugins, "android-byod", byod_features, countof(byod_features), TRUE); + } #endif } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java new file mode 100644 index 000000000..3067707d1 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc; + +import android.content.Context; + +public class AndroidImc +{ + private final Context mContext; + + public AndroidImc(Context context) + { + mContext = context; + } +} From 2c693364a843b5b513db70ff56738b38124174f8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 12:43:23 +0200 Subject: [PATCH 13/59] imv-scanner: Only add a reason string if there is something to report --- src/libimcv/plugins/imv_scanner/imv_scanner_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c index d8bba988e..4c570c46a 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c @@ -282,7 +282,10 @@ METHOD(imv_state_t, get_reason_string, bool, /* Instantiate a TNC Reason String object */ DESTROY_IF(this->reason_string); this->reason_string = imv_reason_string_create(*reason_language); - this->reason_string->add_reason(this->reason_string, reasons); + if (this->rec != TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) + { + this->reason_string->add_reason(this->reason_string, reasons); + } *reason_string = this->reason_string->get_encoding(this->reason_string); return TRUE; From c53210f9b023cefd4b1a703cf1f6f38aa5d2947d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 17:20:15 +0200 Subject: [PATCH 14/59] android: Add a generic handler for PA-TNC attribute requests The idea is that the Android IMC will return attributes in their binary encoding. This keeps the JNI interface to the IMC pretty simple. --- .../jni/libandroidbridge/byod/imc_android.c | 150 +++++++++++------- .../android/logic/imc/AndroidImc.java | 13 ++ 2 files changed, 102 insertions(+), 61 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index f648456f7..ee216cec0 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2012-2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher * Copyright (C) 2011-2012 Andreas Steffen * Hochschule fuer Technik Rapperswil * @@ -19,6 +21,7 @@ #include #include +#include #include #include #include @@ -123,47 +126,99 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, } /** - * Add IETF Product Information attribute to the send queue + * Get a measurement for the given attribute type from the Android IMC. + * NULL is returned if no measurement is available or an error occurred. */ -static void add_product_info(imc_msg_t *msg) +static pa_tnc_attr_t *get_measurement(pen_type_t attr_type) { + JNIEnv *env; pa_tnc_attr_t *attr; - chunk_t android_os = { "Android", 7 }; + jmethodID method_id; + jbyteArray jmeasurement; + chunk_t data; - attr = ietf_attr_product_info_create(PEN_IETF, 0, android_os); - msg->add_attribute(msg, attr); + androidjni_attach_thread(&env); + method_id = (*env)->GetMethodID(env, android_imc_cls, "getMeasurement", + "(II)[B"); + if (!method_id) + { + goto failed; + } + jmeasurement = (*env)->CallObjectMethod(env, android_imc, method_id, + attr_type.vendor_id, attr_type.type); + if (!jmeasurement || androidjni_exception_occurred(env)) + { + goto failed; + } + data = chunk_create((*env)->GetByteArrayElements(env, jmeasurement, NULL), + (*env)->GetArrayLength(env, jmeasurement)); + if (!data.ptr) + { + goto failed; + } + attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes, + attr_type.vendor_id, attr_type.type, + data); + (*env)->ReleaseByteArrayElements(env, jmeasurement, data.ptr, JNI_ABORT); + androidjni_detach_thread(); + return attr; + +failed: + androidjni_exception_occurred(env); + androidjni_detach_thread(); + return NULL; } /** - * Add IETF String Version attribute to the send queue + * Add the measurement for the requested attribute type. */ -static void add_string_version(imc_msg_t *msg) +static void add_measurement(pen_type_t attr_type, imc_msg_t *msg) { pa_tnc_attr_t *attr; - chunk_t android_version = { "4.x", 3 }; + enum_name_t *pa_attr_names; - attr = ietf_attr_string_version_create(android_version, chunk_empty, - chunk_empty); - msg->add_attribute(msg, attr); + attr = get_measurement(attr_type); + if (attr) + { + msg->add_attribute(msg, attr); + return; + } + pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes, + attr_type.vendor_id); + if (pa_attr_names) + { + DBG1(DBG_IMC, "no measurement available for PA-TNC attribute type " + "'%N/%N' 0x%06x/0x%08x", pen_names, attr_type.vendor_id, + pa_attr_names, attr_type.type, attr_type.vendor_id, attr_type.type); + } + else + { + DBG1(DBG_IMC, "no measurement available for PA-TNC attribute type '%N' " + "0x%06x/0x%08x", pen_names, attr_type.vendor_id, + attr_type.vendor_id, attr_type.type); + } } /** - * Add an IETF Installed Packages attribute to the send queue + * Handle an IETF attribute */ -static void add_installed_packages(imc_msg_t *msg) +static void handle_ietf_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, + imc_msg_t *out_msg) { - pa_tnc_attr_t *attr; - ietf_attr_installed_packages_t *attr_cast; - chunk_t libc_name = { "libc-bin", 8 }; - chunk_t libc_version = { "2.15-0ubuntu10.2", 16 }; - chunk_t selinux_name = { "selinux", 7 }; - chunk_t selinux_version = { "1:0.11", 6 }; + if (attr_type.type == IETF_ATTR_ATTRIBUTE_REQUEST) + { + ietf_attr_attr_request_t *attr_cast; + pen_type_t *entry; + enumerator_t *enumerator; - attr = ietf_attr_installed_packages_create(); - attr_cast = (ietf_attr_installed_packages_t*)attr; - attr_cast->add(attr_cast, libc_name, libc_version); - attr_cast->add(attr_cast, selinux_name, selinux_version); - msg->add_attribute(msg, attr); + attr_cast = (ietf_attr_attr_request_t*)attr; + enumerator = attr_cast->create_enumerator(attr_cast); + while (enumerator->enumerate(enumerator, &entry)) + { + add_measurement(*entry, out_msg); + } + enumerator->destroy(enumerator); + } } /** @@ -190,9 +245,10 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, { out_msg = imc_msg_create(imc_android, state, connection_id, imc_id, TNC_IMVID_ANY, msg_types[0]); - add_product_info(out_msg); - add_string_version(out_msg); - + add_measurement((pen_type_t){ PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION }, + out_msg); + add_measurement((pen_type_t){ PEN_IETF, IETF_ATTR_STRING_VERSION }, + out_msg); /* send PA-TNC message with the excl flag not set */ result = out_msg->send(out_msg, FALSE); out_msg->destroy(out_msg); @@ -224,41 +280,13 @@ static TNC_Result receive_message(imc_msg_t *in_msg) { attr_type = attr->get_type(attr); - if (attr_type.vendor_id != PEN_IETF) + switch (attr_type.vendor_id) { - continue; - } - if (attr_type.type == IETF_ATTR_ATTRIBUTE_REQUEST) - { - ietf_attr_attr_request_t *attr_cast; - pen_type_t *entry; - enumerator_t *e; - - attr_cast = (ietf_attr_attr_request_t*)attr; - - e = attr_cast->create_enumerator(attr_cast); - while (e->enumerate(e, &entry)) - { - if (entry->vendor_id != PEN_IETF) - { - continue; - } - switch (entry->type) - { - case IETF_ATTR_PRODUCT_INFORMATION: - add_product_info(out_msg); - break; - case IETF_ATTR_STRING_VERSION: - add_string_version(out_msg); - break; - case IETF_ATTR_INSTALLED_PACKAGES: - add_installed_packages(out_msg); - break; - default: - break; - } - } - e->destroy(e); + case PEN_IETF: + handle_ietf_attribute(attr_type, attr, out_msg); + /* fall-through */ + default: + continue; } } enumerator->destroy(enumerator); diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 3067707d1..9357296be 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -25,4 +25,17 @@ public class AndroidImc { mContext = context; } + + /** + * Get a measurement (the binary encoding of the requested attribute) for + * the given vendor specific attribute type. + * + * @param vendor vendor ID + * @param type vendor specific attribute type + * @return encoded attribute, or null if not available or failed + */ + public byte[] getMeasurement(int vendor, int type) + { + return null; + } } From 28c268d7073d2c5d6ce81dd4bed23d3439aa14fd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 17:31:54 +0200 Subject: [PATCH 15/59] android: Add enum types for PENs and attribute types --- .../logic/imc/attributes/AttributeType.java | 96 +++++++++++++++++++ .../attributes/PrivateEnterpriseNumber.java | 63 ++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java new file mode 100644 index 000000000..8d915142a --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +public enum AttributeType +{ + IETF_TESTING(PrivateEnterpriseNumber.IETF, 0), + IETF_ATTRIBUTE_REQUEST(PrivateEnterpriseNumber.IETF, 1), + IETF_PRODUCT_INFORMATION(PrivateEnterpriseNumber.IETF, 2), + IETF_NUMERIC_VERSION(PrivateEnterpriseNumber.IETF, 3), + IETF_STRING_VERSION(PrivateEnterpriseNumber.IETF, 4), + IETF_OPERATIONAL_STATUS(PrivateEnterpriseNumber.IETF, 5), + IETF_PORT_FILTER(PrivateEnterpriseNumber.IETF, 6), + IETF_INSTALLED_PACKAGES(PrivateEnterpriseNumber.IETF, 7), + IETF_PA_TNC_ERROR(PrivateEnterpriseNumber.IETF, 8), + IETF_ASSESSMENT_RESULT(PrivateEnterpriseNumber.IETF, 9), + IETF_REMEDIATION_INSTRUCTIONS(PrivateEnterpriseNumber.IETF, 10), + IETF_FORWARDING_ENABLED(PrivateEnterpriseNumber.IETF, 11), + IETF_FACTORY_DEFAULT_PWD_ENABLED(PrivateEnterpriseNumber.IETF, 12), + IETF_RESERVED(PrivateEnterpriseNumber.IETF, 0xffffffff); + + private PrivateEnterpriseNumber mVendor; + private int mType; + + /** + * Enum type for vendor specific attributes (defined in their namespace) + * + * @param vendor private enterprise number of vendor + * @param type vendor specific attribute type + */ + private AttributeType(PrivateEnterpriseNumber vendor, int type) + { + mVendor = vendor; + mType = type; + } + + /** + * Get private enterprise number of vendor + * + * @return PEN + */ + public PrivateEnterpriseNumber getVendor() + { + return mVendor; + } + + /** + * Get vendor specific type + * + * @return type + */ + public int getType() + { + return mType; + } + + /** + * Get the enum entry from the given numeric values, if defined + * + * @param vendor vendor id + * @param type vendor specific type + * @return enum entry or null + */ + public static AttributeType fromValues(int vendor, int type) + { + PrivateEnterpriseNumber pen = PrivateEnterpriseNumber.fromValue(vendor); + + if (pen == null) + { + return null; + } + for (AttributeType attr : AttributeType.values()) + { + if (attr.mVendor == pen && attr.mType == type) + { + return attr; + } + } + return null; + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java new file mode 100644 index 000000000..f014d69a7 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.attributes; + +public enum PrivateEnterpriseNumber +{ + IETF(0x000000), + UNASSIGNED(0xfffffe), + RESERVED(0xffffff); + + private int mValue; + + /** + * Enum for private enterprise numbers (PEN) as allocated by IANA + * + * @param value numeric value + */ + private PrivateEnterpriseNumber(int value) + { + mValue = value; + } + + /** + * Get the numeric value of a PEN + * + * @return numeric value + */ + public int getValue() + { + return mValue; + } + + /** + * Get the enum entry from a numeric value, if defined + * + * @param value numeric value + * @return the enum entry or null + */ + public static PrivateEnterpriseNumber fromValue(int value) + { + for (PrivateEnterpriseNumber pen : PrivateEnterpriseNumber.values()) + { + if (pen.mValue == value) + { + return pen; + } + } + return null; + } +} From 2d378d8a74185890cc8613d19b78788b052792bc Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 18:54:40 +0200 Subject: [PATCH 16/59] android: Add a Java utility class similar to bio_writer_t --- .../android/utils/BufferedByteWriter.java | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java diff --git a/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java b/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java new file mode 100644 index 000000000..8bb9a827f --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.utils; + +import java.nio.ByteBuffer; + +/** + * Very similar to ByteBuffer (although with a stripped interface) but it + * automatically resizes the underlying buffer. + */ +public class BufferedByteWriter +{ + /** + * The underlying byte buffer + */ + private byte[] mBuffer; + + /** + * ByteBuffer used as wrapper around the buffer to easily convert values + */ + private ByteBuffer mWriter; + + /** + * Create a writer with a default initial capacity + */ + public BufferedByteWriter() + { + this(0); + } + + /** + * Create a writer with the given initial capacity (helps avoid expensive + * resizing if known). + * @param capacity initial capacity + */ + public BufferedByteWriter(int capacity) + { + capacity = capacity > 4 ? capacity : 32; + mBuffer = new byte[capacity]; + mWriter = ByteBuffer.wrap(mBuffer); + } + + /** + * Ensure that there is enough space available to write the requested + * number of bytes. If necessary the internal buffer is resized. + * @param required required number of bytes + */ + private void ensureCapacity(int required) + { + if (mWriter.remaining() >= required) + { + return; + } + byte[] buffer = new byte[(mBuffer.length + required) * 2]; + System.arraycopy(mBuffer, 0, buffer, 0, mWriter.position()); + mBuffer = buffer; + ByteBuffer writer = ByteBuffer.wrap(buffer); + writer.position(mWriter.position()); + mWriter = writer; + } + + /** + * Write the given byte array to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put(byte[] value) + { + ensureCapacity(value.length); + mWriter.put(value); + return this; + } + + /** + * Write the given byte to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put(byte value) + { + ensureCapacity(1); + mWriter.put(value); + return this; + } + + /** + * Write the 8-bit length of the given data followed by the data itself + * @param value + * @return the writer + */ + public BufferedByteWriter putLen8(byte[] value) + { + ensureCapacity(1 + value.length); + mWriter.put((byte)value.length); + mWriter.put(value); + return this; + } + + /** + * Write the 16-bit length of the given data followed by the data itself + * @param value + * @return the writer + */ + public BufferedByteWriter putLen16(byte[] value) + { + ensureCapacity(2 + value.length); + mWriter.putShort((short)value.length); + mWriter.put(value); + return this; + } + + /** + * Write the given short value (16-bit) in big-endian order to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put16(short value) + { + ensureCapacity(2); + mWriter.putShort(value); + return this; + } + + /** + * Write the given int value (32-bit) in big-endian order to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put32(int value) + { + ensureCapacity(4); + mWriter.putInt(value); + return this; + } + + /** + * Write the given long value (64-bit) in big-endian order to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put64(long value) + { + ensureCapacity(8); + mWriter.putLong(value); + return this; + } + + /** + * Convert the internal buffer to a new byte array. + * @return byte array + */ + public byte[] toByteArray() + { + int length = mWriter.position(); + byte[] bytes = new byte[length]; + System.arraycopy(mBuffer, 0, bytes, 0, length); + return bytes; + } +} From 4eec7912a1c973b44b314f0a805cb19a1f63a5a3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 19:07:34 +0200 Subject: [PATCH 17/59] android: Interfaces for measurement collectors and attributes added --- .../logic/imc/attributes/Attribute.java | 28 +++++++++++++++++ .../logic/imc/collectors/Collector.java | 30 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/Attribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Collector.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/Attribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/Attribute.java new file mode 100644 index 000000000..ca759000f --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/Attribute.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.attributes; + +/** + * Interface to be implemented by attribute classes + */ +public interface Attribute +{ + /** + * Returns the binary encoding of the attribute + * @return binary encoding + */ + public byte[] getEncoding(); +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Collector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Collector.java new file mode 100644 index 000000000..a686f13a1 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Collector.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.collectors; + +import org.strongswan.android.logic.imc.attributes.Attribute; + +/** + * Interface for measurement collectors + */ +public interface Collector +{ + /** + * This method shall return the result of a measurement, if available + * @return attribute or null + */ + public abstract Attribute getMeasurement(); +} From 5c9706f30b0663e50a86bc1ad2e6c7ea7d828a8a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 25 Apr 2013 19:43:56 +0200 Subject: [PATCH 18/59] android: Add measurement collector for String Version --- .../android/logic/imc/AndroidImc.java | 24 +++++++ .../attributes/StringVersionAttribute.java | 68 +++++++++++++++++++ .../collectors/StringVersionCollector.java | 33 +++++++++ 3 files changed, 125 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/StringVersionAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/StringVersionCollector.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 9357296be..2aec69013 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -15,6 +15,11 @@ package org.strongswan.android.logic.imc; +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.AttributeType; +import org.strongswan.android.logic.imc.collectors.Collector; +import org.strongswan.android.logic.imc.collectors.StringVersionCollector; + import android.content.Context; public class AndroidImc @@ -36,6 +41,25 @@ public class AndroidImc */ public byte[] getMeasurement(int vendor, int type) { + AttributeType attributeType = AttributeType.fromValues(vendor, type); + Collector collector = null; + + switch (attributeType) + { + case IETF_STRING_VERSION: + collector = new StringVersionCollector(); + break; + default: + break; + } + if (collector != null) + { + Attribute attribute = collector.getMeasurement(); + if (attribute != null) + { + return attribute.getEncoding(); + } + } return null; } } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/StringVersionAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/StringVersionAttribute.java new file mode 100644 index 000000000..4b6f2bc37 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/StringVersionAttribute.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +import org.strongswan.android.utils.BufferedByteWriter; + +/** + * PA-TNC String Version attribute (see section 4.2.4 of RFC 5792) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Version Len | Product Version Number (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Build Num Len | Internal Build Number (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Config. Len | Configuration Version Number (Variable Length)| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +public class StringVersionAttribute implements Attribute +{ + private String mVersionNumber; + private String mBuildNumber; + + /** + * Set the product version number + * @param version version number + */ + public void setProductVersionNumber(String version) + { + this.mVersionNumber = version; + } + + /** + * Set the internal build number + * @param build build number + */ + public void setInternalBuildNumber(String build) + { + this.mBuildNumber = build; + } + + @Override + public byte[] getEncoding() + { + BufferedByteWriter writer = new BufferedByteWriter(); + writer.putLen8(mVersionNumber.getBytes()); + writer.putLen8(mBuildNumber.getBytes()); + /* we don't provide a configuration number */ + writer.put((byte)0); + return writer.toByteArray(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/StringVersionCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/StringVersionCollector.java new file mode 100644 index 000000000..6e0df94a5 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/StringVersionCollector.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.collectors; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.StringVersionAttribute; + +public class StringVersionCollector implements Collector +{ + @Override + public Attribute getMeasurement() + { + StringVersionAttribute attribute = new StringVersionAttribute(); + attribute.setProductVersionNumber(android.os.Build.VERSION.RELEASE); + attribute.setInternalBuildNumber(android.os.Build.DISPLAY); + return attribute; + } +} From 75d710ec637571e2a076430173264b21d539e5cd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 14:27:52 +0200 Subject: [PATCH 19/59] android: Also support writing of 24-bit values --- .../android/utils/BufferedByteWriter.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java b/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java index 8bb9a827f..efc728377 100644 --- a/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java +++ b/src/frontends/android/src/org/strongswan/android/utils/BufferedByteWriter.java @@ -134,6 +134,19 @@ public class BufferedByteWriter return this; } + /** + * Write 24-bit of the given value in big-endian order to the buffer + * @param value + * @return the writer + */ + public BufferedByteWriter put24(int value) + { + ensureCapacity(3); + mWriter.put((byte)(value >> 16)); + mWriter.putShort((short)value); + return this; + } + /** * Write the given int value (32-bit) in big-endian order to the buffer * @param value From 2d61172314b432be1c68d213dc666aacc5b6b386 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 14:29:00 +0200 Subject: [PATCH 20/59] android: Add measurement collector for Product Information --- .../android/logic/imc/AndroidImc.java | 4 ++ .../attributes/PrivateEnterpriseNumber.java | 1 + .../ProductInformationAttribute.java | 47 +++++++++++++++++++ .../ProductInformationCollector.java | 30 ++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/ProductInformationAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/ProductInformationCollector.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 2aec69013..828b99d6e 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -18,6 +18,7 @@ package org.strongswan.android.logic.imc; import org.strongswan.android.logic.imc.attributes.Attribute; import org.strongswan.android.logic.imc.attributes.AttributeType; import org.strongswan.android.logic.imc.collectors.Collector; +import org.strongswan.android.logic.imc.collectors.ProductInformationCollector; import org.strongswan.android.logic.imc.collectors.StringVersionCollector; import android.content.Context; @@ -46,6 +47,9 @@ public class AndroidImc switch (attributeType) { + case IETF_PRODUCT_INFORMATION: + collector = new ProductInformationCollector(); + break; case IETF_STRING_VERSION: collector = new StringVersionCollector(); break; diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java index f014d69a7..5af20a855 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java @@ -18,6 +18,7 @@ package org.strongswan.android.logic.imc.attributes; public enum PrivateEnterpriseNumber { IETF(0x000000), + GOOGLE(0x002B79), UNASSIGNED(0xfffffe), RESERVED(0xffffff); diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/ProductInformationAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/ProductInformationAttribute.java new file mode 100644 index 000000000..cace18d55 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/ProductInformationAttribute.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +import org.strongswan.android.utils.BufferedByteWriter; + +/** + * PA-TNC Product Information attribute (see section 4.2.2 of RFC 5792) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Product Vendor ID | Product ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Product ID | Product Name (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +public class ProductInformationAttribute implements Attribute +{ + private final String PRODUCT_NAME = "Android"; + private final short PRODUCT_ID = 0; + + @Override + public byte[] getEncoding() + { + BufferedByteWriter writer = new BufferedByteWriter(); + writer.put24(PrivateEnterpriseNumber.GOOGLE.getValue()); + writer.put16(PRODUCT_ID); + writer.put(PRODUCT_NAME.getBytes()); + return writer.toByteArray(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/ProductInformationCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/ProductInformationCollector.java new file mode 100644 index 000000000..c377e9041 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/ProductInformationCollector.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.collectors; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.ProductInformationAttribute; + +public class ProductInformationCollector implements Collector +{ + @Override + public Attribute getMeasurement() + { /* this is currently hardcoded in the attribute */ + return new ProductInformationAttribute(); + } +} From 7cb8f570ed7fe386ce143ca4f1db3c870b1f8add Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 15:36:03 +0200 Subject: [PATCH 21/59] android: Add measurement collector for Installed Packages --- .../android/logic/imc/AndroidImc.java | 4 ++ .../InstalledPackagesAttribute.java | 67 +++++++++++++++++++ .../InstalledPackagesCollector.java | 55 +++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/InstalledPackagesAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/InstalledPackagesCollector.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 828b99d6e..27f21cd01 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -18,6 +18,7 @@ package org.strongswan.android.logic.imc; import org.strongswan.android.logic.imc.attributes.Attribute; import org.strongswan.android.logic.imc.attributes.AttributeType; import org.strongswan.android.logic.imc.collectors.Collector; +import org.strongswan.android.logic.imc.collectors.InstalledPackagesCollector; import org.strongswan.android.logic.imc.collectors.ProductInformationCollector; import org.strongswan.android.logic.imc.collectors.StringVersionCollector; @@ -53,6 +54,9 @@ public class AndroidImc case IETF_STRING_VERSION: collector = new StringVersionCollector(); break; + case IETF_INSTALLED_PACKAGES: + collector = new InstalledPackagesCollector(mContext); + break; default: break; } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/InstalledPackagesAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/InstalledPackagesAttribute.java new file mode 100644 index 000000000..dd1ad7292 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/InstalledPackagesAttribute.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +import java.util.LinkedList; + +import org.strongswan.android.utils.BufferedByteWriter; + +import android.util.Pair; + +/** + * PA-TNC Installed Packages attribute (see section 4.2.7 of RFC 5792) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Package Count | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pkg Name Len | Package Name (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Version Len | Package Version Number (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +public class InstalledPackagesAttribute implements Attribute +{ + private final short RESERVED = 0; + private final LinkedList> mPackages = new LinkedList>(); + + /** + * Add an installed package to this attribute. + * @param name name of the package + * @param version version number of the package + */ + public void addPackage(String name, String version) + { + mPackages.add(new Pair(name, version)); + } + + @Override + public byte[] getEncoding() + { + BufferedByteWriter writer = new BufferedByteWriter(); + writer.put16(RESERVED); + writer.put16((short)mPackages.size()); + for (Pair pair : mPackages) + { + writer.putLen8(pair.first.getBytes()); + writer.putLen8(pair.second.getBytes()); + } + return writer.toByteArray(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/InstalledPackagesCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/InstalledPackagesCollector.java new file mode 100644 index 000000000..caa5170ec --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/InstalledPackagesCollector.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.collectors; + +import java.util.List; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.InstalledPackagesAttribute; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +public class InstalledPackagesCollector implements Collector +{ + private final PackageManager mPackageManager; + + public InstalledPackagesCollector(Context context) + { + mPackageManager = context.getPackageManager(); + } + + @Override + public Attribute getMeasurement() + { + InstalledPackagesAttribute attribute = new InstalledPackagesAttribute(); + List packages = mPackageManager.getInstalledPackages(0); + for (PackageInfo info : packages) + { + if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || + info.packageName == null || info.versionName == null) + { /* ignore packages installed in the system image */ + continue; + } + attribute.addPackage(info.packageName, info.versionName); + } + return attribute; + } +} From 6500727d6a0b579126f933aaff6477d005b3f7f0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 17:10:20 +0200 Subject: [PATCH 22/59] android: Enum type for transport protocols added --- .../logic/imc/collectors/Protocol.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Protocol.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Protocol.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Protocol.java new file mode 100644 index 000000000..7320652a1 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/Protocol.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.collectors; + +public enum Protocol +{ + TCP((byte)6, "tcp", "tcp6"), + UDP((byte)17, "udp", "udp6"); + + private final byte mValue; + private String[] mNames; + + private Protocol(byte value, String... names) + { + mValue = value; + mNames = names; + } + + /** + * Get the numeric value of the protocol. + * @return numeric value + */ + public byte getValue() + { + return mValue; + } + + /** + * Get the protocol from the given protocol name, if found. + * @param name protocol name (e.g. "udp" or "tcp") + * @return enum entry or null + */ + public static Protocol fromName(String name) + { + for (Protocol protocol : Protocol.values()) + { + for (String keyword : protocol.mNames) + { + if (keyword.equalsIgnoreCase(name)) + { + return protocol; + } + } + } + return null; + } +} From ba59486fc877d3ca462737351bdb42d482ce0ef7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 17:11:15 +0200 Subject: [PATCH 23/59] android: Add measurement collector for Port Filter This collector reports all listening TCP and UDP sockets/ports. --- .../jni/libandroidbridge/byod/imc_android.c | 3 +- .../android/logic/imc/AndroidImc.java | 4 + .../imc/attributes/PortFilterAttribute.java | 65 +++++++++++++++ .../imc/collectors/PortFilterCollector.java | 79 +++++++++++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PortFilterAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index ee216cec0..be2bc4276 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -44,7 +44,8 @@ static const char imc_name[] = "Android"; static pen_type_t msg_types[] = { - { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM } + { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }, + { PEN_IETF, PA_SUBTYPE_IETF_VPN }, }; static imc_agent_t *imc_android; diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 27f21cd01..ca1f74698 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -19,6 +19,7 @@ import org.strongswan.android.logic.imc.attributes.Attribute; import org.strongswan.android.logic.imc.attributes.AttributeType; import org.strongswan.android.logic.imc.collectors.Collector; import org.strongswan.android.logic.imc.collectors.InstalledPackagesCollector; +import org.strongswan.android.logic.imc.collectors.PortFilterCollector; import org.strongswan.android.logic.imc.collectors.ProductInformationCollector; import org.strongswan.android.logic.imc.collectors.StringVersionCollector; @@ -54,6 +55,9 @@ public class AndroidImc case IETF_STRING_VERSION: collector = new StringVersionCollector(); break; + case IETF_PORT_FILTER: + collector = new PortFilterCollector(); + break; case IETF_INSTALLED_PACKAGES: collector = new InstalledPackagesCollector(mContext); break; diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PortFilterAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PortFilterAttribute.java new file mode 100644 index 000000000..191690b94 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PortFilterAttribute.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +import java.util.LinkedList; + +import org.strongswan.android.logic.imc.collectors.Protocol; +import org.strongswan.android.utils.BufferedByteWriter; + +import android.util.Pair; + +/** + * PA-TNC Port Filter attribute (see section 4.2.6 of RFC 5792) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved |B| Protocol | Port Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved |B| Protocol | Port Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +public class PortFilterAttribute implements Attribute +{ + private final LinkedList> mPorts = new LinkedList>(); + + /** + * Add an open port with the given protocol and port number + * @param protocol transport protocol + * @param port port number + */ + public void addPort(Protocol protocol, short port) + { + mPorts.add(new Pair(protocol, port)); + } + + @Override + public byte[] getEncoding() + { + BufferedByteWriter writer = new BufferedByteWriter(); + for (Pair port : mPorts) + { + /* we report open ports, so the BLOCKED flag is not set */ + writer.put((byte)0); + writer.put(port.first.getValue()); + writer.put16(port.second); + } + return writer.toByteArray(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java new file mode 100644 index 000000000..b6e740cad --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.collectors; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.PortFilterAttribute; + +public class PortFilterCollector implements Collector +{ + private static Pattern LISTEN = Pattern.compile("\\bLISTEN\\b"); + private static Pattern PROTOCOL = Pattern.compile("\\b(tcp|udp)6?\\b"); + private static Pattern PORT = Pattern.compile("[:]{1,3}(\\d{1,5})\\b"); + + @Override + public Attribute getMeasurement() + { + PortFilterAttribute attribute = null; + try + { + Process netstat = Runtime.getRuntime().exec("netstat -n"); + try + { + BufferedReader reader = new BufferedReader(new InputStreamReader(netstat.getInputStream())); + String line; + attribute = new PortFilterAttribute(); + while ((line = reader.readLine()) != null) + { + if (!LISTEN.matcher(line).find()) + { + continue; + } + Matcher protocolMatcher = PROTOCOL.matcher(line); + Matcher portMatcher = PORT.matcher(line); + if (protocolMatcher.find() && portMatcher.find()) + { + Protocol protocol = Protocol.fromName(protocolMatcher.group()); + if (protocol == null) + { + continue; + } + int port = Integer.parseInt(portMatcher.group(1)); + attribute.addPort(protocol, (short)port); + } + } + } + finally + { + netstat.destroy(); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + return attribute; + } + +} From 036fa7a16611cfc62c35cdc6fffbb3c18775f5cd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 18:12:21 +0200 Subject: [PATCH 24/59] android: Overload for getMeasurement() that takes a String array as argument --- .../jni/libandroidbridge/byod/imc_android.c | 80 ++++++++++++++++--- .../android/logic/imc/AndroidImc.java | 14 ++++ 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index be2bc4276..9d30ad9b2 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -126,27 +126,85 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, } } +/** + * Convert the native C strings in the enumerator to a Java String array. + * The given enumerator gets destroyed. + */ +static jobjectArray string_array_create(JNIEnv *env, enumerator_t *enumerator) +{ + linked_list_t *list; + jobjectArray jarray; + jstring jstring; + char *native; + jclass cls; + int i = 0; + + cls = (*env)->FindClass(env, "java/lang/String"); + list = linked_list_create_from_enumerator(enumerator); + jarray = (*env)->NewObjectArray(env, list->get_count(list), cls, NULL); + if (!jarray) + { + goto failed; + } + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, (void**)&native)) + { + jstring = (*env)->NewStringUTF(env, native); + if (!jstring) + { + enumerator->destroy(enumerator); + goto failed; + } + (*env)->SetObjectArrayElement(env, jarray, i++, jstring); + } + enumerator->destroy(enumerator); + list->destroy(list); + return jarray; + +failed: + androidjni_exception_occurred(env); + list->destroy(list); + return NULL; +} + /** * Get a measurement for the given attribute type from the Android IMC. * NULL is returned if no measurement is available or an error occurred. + * + * The optional args is an enumerator over char* (gets destroyed). */ -static pa_tnc_attr_t *get_measurement(pen_type_t attr_type) +static pa_tnc_attr_t *get_measurement(pen_type_t attr_type, enumerator_t *args) { JNIEnv *env; pa_tnc_attr_t *attr; jmethodID method_id; jbyteArray jmeasurement; + jobjectArray jargs = NULL; chunk_t data; androidjni_attach_thread(&env); - method_id = (*env)->GetMethodID(env, android_imc_cls, "getMeasurement", - "(II)[B"); + if (args) + { + jargs = string_array_create(env, args); + if (!jargs) + { + goto failed; + } + method_id = (*env)->GetMethodID(env, android_imc_cls, "getMeasurement", + "(II[Ljava/lang/String;)[B"); + } + else + { + method_id = (*env)->GetMethodID(env, android_imc_cls, "getMeasurement", + "(II)[B"); + } if (!method_id) { goto failed; } jmeasurement = (*env)->CallObjectMethod(env, android_imc, method_id, - attr_type.vendor_id, attr_type.type); + attr_type.vendor_id, attr_type.type, + jargs); if (!jmeasurement || androidjni_exception_occurred(env)) { goto failed; @@ -171,14 +229,16 @@ failed: } /** - * Add the measurement for the requested attribute type. + * Add the measurement for the requested attribute type with optional + * arguments (enumerator over char*, gets destroyed). */ -static void add_measurement(pen_type_t attr_type, imc_msg_t *msg) +static void add_measurement(pen_type_t attr_type, imc_msg_t *msg, + enumerator_t *args) { pa_tnc_attr_t *attr; enum_name_t *pa_attr_names; - attr = get_measurement(attr_type); + attr = get_measurement(attr_type, args); if (attr) { msg->add_attribute(msg, attr); @@ -216,7 +276,7 @@ static void handle_ietf_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, enumerator = attr_cast->create_enumerator(attr_cast); while (enumerator->enumerate(enumerator, &entry)) { - add_measurement(*entry, out_msg); + add_measurement(*entry, out_msg, NULL); } enumerator->destroy(enumerator); } @@ -247,9 +307,9 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, out_msg = imc_msg_create(imc_android, state, connection_id, imc_id, TNC_IMVID_ANY, msg_types[0]); add_measurement((pen_type_t){ PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION }, - out_msg); + out_msg, NULL); add_measurement((pen_type_t){ PEN_IETF, IETF_ATTR_STRING_VERSION }, - out_msg); + out_msg, NULL); /* send PA-TNC message with the excl flag not set */ result = out_msg->send(out_msg, FALSE); out_msg->destroy(out_msg); diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index ca1f74698..2219c517d 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -43,6 +43,20 @@ public class AndroidImc * @return encoded attribute, or null if not available or failed */ public byte[] getMeasurement(int vendor, int type) + { + return getMeasurement(vendor, type, null); + } + + /** + * Get a measurement (the binary encoding of the requested attribute) for + * the given vendor specific attribute type. + * + * @param vendor vendor ID + * @param type vendor specific attribute type + * @param args optional arguments for a measurement + * @return encoded attribute, or null if not available or failed + */ + public byte[] getMeasurement(int vendor, int type, String[] args) { AttributeType attributeType = AttributeType.fromValues(vendor, type); Collector collector = null; From c179a3f6f23096610cd73eb86096028809ffd647 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 18:17:07 +0200 Subject: [PATCH 25/59] android: Handle ITA PA-TNC attributes --- .../jni/libandroidbridge/byod/imc_android.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 9d30ad9b2..4079e4c28 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -282,6 +284,22 @@ static void handle_ietf_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, } } +/** + * Handle an ITA attribute + */ +static void handle_ita_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, + imc_msg_t *out_msg) +{ + if (attr_type.type == ITA_ATTR_GET_SETTINGS) + { + ita_attr_get_settings_t *attr_cast; + + attr_cast = (ita_attr_get_settings_t*)attr; + add_measurement((pen_type_t){ PEN_ITA, ITA_ATTR_SETTINGS }, + out_msg, attr_cast->create_enumerator(attr_cast)); + } +} + /** * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 */ From 44330a171f80ccaed77b68bd1d7fd24cae303efe Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 26 Apr 2013 18:17:32 +0200 Subject: [PATCH 26/59] android: Add measurement collector for ITA Settings --- .../jni/libandroidbridge/byod/imc_android.c | 5 +- .../android/logic/imc/AndroidImc.java | 4 + .../logic/imc/attributes/AttributeType.java | 5 +- .../attributes/PrivateEnterpriseNumber.java | 1 + .../imc/attributes/SettingsAttribute.java | 78 +++++++++++++++++++ .../imc/collectors/SettingsCollector.java | 59 ++++++++++++++ 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/SettingsAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 4079e4c28..70419c913 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -363,7 +363,10 @@ static TNC_Result receive_message(imc_msg_t *in_msg) { case PEN_IETF: handle_ietf_attribute(attr_type, attr, out_msg); - /* fall-through */ + continue; + case PEN_ITA: + handle_ita_attribute(attr_type, attr, out_msg); + continue; default: continue; } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 2219c517d..1c298bef3 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -21,6 +21,7 @@ import org.strongswan.android.logic.imc.collectors.Collector; import org.strongswan.android.logic.imc.collectors.InstalledPackagesCollector; import org.strongswan.android.logic.imc.collectors.PortFilterCollector; import org.strongswan.android.logic.imc.collectors.ProductInformationCollector; +import org.strongswan.android.logic.imc.collectors.SettingsCollector; import org.strongswan.android.logic.imc.collectors.StringVersionCollector; import android.content.Context; @@ -75,6 +76,9 @@ public class AndroidImc case IETF_INSTALLED_PACKAGES: collector = new InstalledPackagesCollector(mContext); break; + case ITA_SETTINGS: + collector = new SettingsCollector(mContext, args); + break; default: break; } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java index 8d915142a..52eef97f8 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java @@ -19,6 +19,7 @@ package org.strongswan.android.logic.imc.attributes; public enum AttributeType { + /* IETF standard PA-TNC attribute types defined by RFC 5792 */ IETF_TESTING(PrivateEnterpriseNumber.IETF, 0), IETF_ATTRIBUTE_REQUEST(PrivateEnterpriseNumber.IETF, 1), IETF_PRODUCT_INFORMATION(PrivateEnterpriseNumber.IETF, 2), @@ -32,7 +33,9 @@ public enum AttributeType IETF_REMEDIATION_INSTRUCTIONS(PrivateEnterpriseNumber.IETF, 10), IETF_FORWARDING_ENABLED(PrivateEnterpriseNumber.IETF, 11), IETF_FACTORY_DEFAULT_PWD_ENABLED(PrivateEnterpriseNumber.IETF, 12), - IETF_RESERVED(PrivateEnterpriseNumber.IETF, 0xffffffff); + IETF_RESERVED(PrivateEnterpriseNumber.IETF, 0xffffffff), + /* ITA attributes */ + ITA_SETTINGS(PrivateEnterpriseNumber.ITA, 4); private PrivateEnterpriseNumber mVendor; private int mType; diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java index 5af20a855..9db702ec0 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/PrivateEnterpriseNumber.java @@ -19,6 +19,7 @@ public enum PrivateEnterpriseNumber { IETF(0x000000), GOOGLE(0x002B79), + ITA(0x00902a), UNASSIGNED(0xfffffe), RESERVED(0xffffff); diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/SettingsAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/SettingsAttribute.java new file mode 100644 index 000000000..37d820168 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/SettingsAttribute.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.attributes; + +import java.util.LinkedList; + +import org.strongswan.android.utils.BufferedByteWriter; + +import android.util.Pair; + +/** + * ITA Settings attribute + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Settings Count | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Name Length | Name (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ Name (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Value Length | Value (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ Value (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Name Length | Name (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ Name (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Value Length | Value (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ Value (Variable Length) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ........................... + */ +public class SettingsAttribute implements Attribute +{ + private final LinkedList> mSettings = new LinkedList>(); + + /** + * Add a setting to this attribute. + * @param name name of the setting + * @param value value of the setting + */ + public void addSetting(String name, String value) + { + mSettings.add(new Pair(name, value)); + } + + @Override + public byte[] getEncoding() + { + BufferedByteWriter writer = new BufferedByteWriter(); + writer.put32(mSettings.size()); + for (Pair pair : mSettings) + { + writer.putLen16(pair.first.getBytes()); + writer.putLen16(pair.second.getBytes()); + } + return writer.toByteArray(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java new file mode 100644 index 000000000..3f6bcff6f --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Christoph Buehler + * Copyright (C) 2012 Patrick Loetscher + * 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.imc.collectors; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.SettingsAttribute; + +import android.content.ContentResolver; +import android.content.Context; + +public class SettingsCollector implements Collector +{ + private final ContentResolver mContentResolver; + private final String[] mSettings; + + public SettingsCollector(Context context, String[] args) + { + mContentResolver = context.getContentResolver(); + mSettings = args; + } + + @Override + public Attribute getMeasurement() + { + if (mSettings == null || mSettings.length == 0) + { + return null; + } + SettingsAttribute attribute = new SettingsAttribute(); + for (String name : mSettings) + { + String value = android.provider.Settings.Secure.getString(mContentResolver, name.toLowerCase()); + if (value == null) + { + value = android.provider.Settings.System.getString(mContentResolver, name.toLowerCase()); + } + if (value != null) + { + attribute.addSetting(name, value); + } + } + return attribute; + } +} From 583fe0ccb62bbba9798fece8b0d077e589a77276 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 24 Jun 2013 15:50:48 +0200 Subject: [PATCH 27/59] android: Add measurement collector for ITA Device ID --- .../android/logic/imc/AndroidImc.java | 4 ++ .../logic/imc/attributes/AttributeType.java | 3 +- .../imc/attributes/DeviceIdAttribute.java | 45 +++++++++++++++++++ .../imc/collectors/DeviceIdCollector.java | 45 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/attributes/DeviceIdAttribute.java create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/collectors/DeviceIdCollector.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java index 1c298bef3..351fab801 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/AndroidImc.java @@ -18,6 +18,7 @@ package org.strongswan.android.logic.imc; import org.strongswan.android.logic.imc.attributes.Attribute; import org.strongswan.android.logic.imc.attributes.AttributeType; import org.strongswan.android.logic.imc.collectors.Collector; +import org.strongswan.android.logic.imc.collectors.DeviceIdCollector; import org.strongswan.android.logic.imc.collectors.InstalledPackagesCollector; import org.strongswan.android.logic.imc.collectors.PortFilterCollector; import org.strongswan.android.logic.imc.collectors.ProductInformationCollector; @@ -79,6 +80,9 @@ public class AndroidImc case ITA_SETTINGS: collector = new SettingsCollector(mContext, args); break; + case ITA_DEVICE_ID: + collector = new DeviceIdCollector(mContext); + break; default: break; } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java index 52eef97f8..11f1c61da 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/AttributeType.java @@ -35,7 +35,8 @@ public enum AttributeType IETF_FACTORY_DEFAULT_PWD_ENABLED(PrivateEnterpriseNumber.IETF, 12), IETF_RESERVED(PrivateEnterpriseNumber.IETF, 0xffffffff), /* ITA attributes */ - ITA_SETTINGS(PrivateEnterpriseNumber.ITA, 4); + ITA_SETTINGS(PrivateEnterpriseNumber.ITA, 4), + ITA_DEVICE_ID(PrivateEnterpriseNumber.ITA, 8); private PrivateEnterpriseNumber mVendor; private int mType; diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/DeviceIdAttribute.java b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/DeviceIdAttribute.java new file mode 100644 index 000000000..ecab7db24 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/attributes/DeviceIdAttribute.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.attributes; + +/** + * ITA Device ID attribute + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Device ID (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +public class DeviceIdAttribute implements Attribute +{ + private String mDeviceId; + + /** + * Set the device ID + * @param version version number + */ + public void setDeviceId(String deviceId) + { + this.mDeviceId = deviceId; + } + + @Override + public byte[] getEncoding() + { + return mDeviceId.getBytes(); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/DeviceIdCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/DeviceIdCollector.java new file mode 100644 index 000000000..ebe9e10b0 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/DeviceIdCollector.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc.collectors; + +import org.strongswan.android.logic.imc.attributes.Attribute; +import org.strongswan.android.logic.imc.attributes.DeviceIdAttribute; + +import android.content.ContentResolver; +import android.content.Context; + +public class DeviceIdCollector implements Collector +{ + private final ContentResolver mContentResolver; + + public DeviceIdCollector(Context context) + { + mContentResolver = context.getContentResolver(); + } + + @Override + public Attribute getMeasurement() + { + String id = android.provider.Settings.Secure.getString(mContentResolver, "android_id"); + if (id != null) + { + DeviceIdAttribute attribute = new DeviceIdAttribute(); + attribute.setDeviceId(id); + return attribute; + } + return null; + } +} From 17044a753ab37a1abae8b4195ec35d4dec1f4b95 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 14:13:40 +0200 Subject: [PATCH 28/59] libpts: Skip unreadable files when measuring directories --- src/libpts/pts/pts_file_meas.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c index e69c32443..f684087d7 100644 --- a/src/libpts/pts/pts_file_meas.c +++ b/src/libpts/pts/pts_file_meas.c @@ -302,20 +302,7 @@ pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id, return NULL; } measurement = chunk_create(hash, hasher->get_hash_size(hasher)); - - INIT(this, - .public = { - .get_request_id = _get_request_id, - .get_file_count = _get_file_count, - .add = _add, - .create_enumerator = _create_enumerator, - .check = _check, - .verify = _verify, - .destroy = _destroy, - }, - .request_id = request_id, - .list = linked_list_create(), - ); + this = (private_pts_file_meas_t*)pts_file_meas_create(request_id); if (is_dir) { @@ -338,8 +325,7 @@ pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id, { if (!hash_file(hasher, abs_name, hash)) { - success = FALSE; - break; + continue; } filename = use_rel_name ? rel_name : abs_name; DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename); From 403165102c82b4cdee20409b0ab75125cc580a75 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 14:41:55 +0200 Subject: [PATCH 29/59] android: Define IMC functions static and with lower-case names --- .../jni/libandroidbridge/byod/imc_android.c | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 70419c913..23902e6f8 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -65,10 +65,10 @@ static jclass android_imc_cls; /** * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, - TNC_Version min_version, - TNC_Version max_version, - TNC_Version *actual_version) +static TNC_Result tnc_imc_initialize(TNC_IMCID imc_id, + TNC_Version min_version, + TNC_Version max_version, + TNC_Version *actual_version) { if (imc_android) { @@ -95,9 +95,9 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, /** * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, - TNC_ConnectionID connection_id, - TNC_ConnectionState new_state) +static TNC_Result tnc_imc_notifyconnectionchange(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_ConnectionState new_state) { imc_state_t *state; @@ -303,8 +303,8 @@ static void handle_ita_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, /** * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, - TNC_ConnectionID connection_id) +static TNC_Result tnc_imc_beginhandshake(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) { imc_state_t *state; imc_msg_t *out_msg; @@ -390,11 +390,11 @@ static TNC_Result receive_message(imc_msg_t *in_msg) * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, - TNC_ConnectionID connection_id, - TNC_BufferReference msg, - TNC_UInt32 msg_len, - TNC_MessageType msg_type) +static TNC_Result tnc_imc_receivemessage(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) { imc_state_t *state; imc_msg_t *in_msg; @@ -420,15 +420,15 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, /** * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3 */ -TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id, - TNC_ConnectionID connection_id, - TNC_UInt32 msg_flags, - TNC_BufferReference msg, - TNC_UInt32 msg_len, - TNC_VendorID msg_vid, - TNC_MessageSubtype msg_subtype, - TNC_UInt32 src_imv_id, - TNC_UInt32 dst_imc_id) +static TNC_Result tnc_imc_receivemessagelong(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imv_id, + TNC_UInt32 dst_imc_id) { imc_state_t *state; imc_msg_t *in_msg; @@ -455,8 +455,8 @@ TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id, /** * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id, - TNC_ConnectionID connection_id) +static TNC_Result tnc_imc_batchending(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) { if (!imc_android) { @@ -469,7 +469,7 @@ TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id, /** * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) +static TNC_Result tnc_imc_terminate(TNC_IMCID imc_id) { if (!imc_android) { @@ -486,8 +486,8 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) /** * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3 */ -TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id, - TNC_TNCC_BindFunctionPointer bind_function) +static TNC_Result tnc_imc_providebindfunction(TNC_IMCID imc_id, + TNC_TNCC_BindFunctionPointer bind_function) { if (!imc_android) { @@ -533,10 +533,10 @@ bool imc_android_register(plugin_t *plugin, plugin_feature_t *feature, androidjni_detach_thread(); if (tnc->imcs->load_from_functions(tnc->imcs, "Android", - TNC_IMC_Initialize, TNC_IMC_NotifyConnectionChange, - TNC_IMC_BeginHandshake, TNC_IMC_ReceiveMessage, - TNC_IMC_ReceiveMessageLong, TNC_IMC_BatchEnding, - TNC_IMC_Terminate, TNC_IMC_ProvideBindFunction)) + tnc_imc_initialize, tnc_imc_notifyconnectionchange, + tnc_imc_beginhandshake, tnc_imc_receivemessage, + tnc_imc_receivemessagelong, tnc_imc_batchending, + tnc_imc_terminate, tnc_imc_providebindfunction)) { return TRUE; } From 6bce8e1cfba8d8a12adb9c1da3464074659dff46 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 14:43:28 +0200 Subject: [PATCH 30/59] libimcv: Properly deinitialize libimcv Other users of imcv_pa_tnc_attributes (libpts) check if it is NULL before removing vendor IDs. --- src/libimcv/imcv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c index b52b81c42..b5862daee 100644 --- a/src/libimcv/imcv.c +++ b/src/libimcv/imcv.c @@ -174,6 +174,7 @@ void libimcv_deinit(void) imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_IETF); imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_ITA); DESTROY_IF(imcv_pa_tnc_attributes); + imcv_pa_tnc_attributes = NULL; DESTROY_IF(imcv_db); DBG1(DBG_LIB, "libimcv terminated"); } From 0e53beda323bcf1583c457fe8cf33a24d257ab9b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 18:47:05 +0200 Subject: [PATCH 31/59] android: Provide a public interface for Android IMC state --- .../libandroidbridge/byod/imc_android_state.c | 52 ++++++++++--------- .../libandroidbridge/byod/imc_android_state.h | 13 +++++ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c index 47eda33cd..2018f9d9b 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c @@ -20,17 +20,17 @@ #include -typedef struct private_imc_state_t private_imc_state_t; +typedef struct private_imc_android_state_t private_imc_android_state_t; /** * Private data of an imc_state_t object. */ -struct private_imc_state_t { +struct private_imc_android_state_t { /** * Public interface */ - imc_state_t public; + imc_android_state_t public; /** * TNCCS connection ID @@ -64,56 +64,56 @@ struct private_imc_state_t { }; METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, - private_imc_state_t *this) + private_imc_android_state_t *this) { return this->connection_id; } METHOD(imc_state_t, has_long, bool, - private_imc_state_t *this) + private_imc_android_state_t *this) { return this->has_long; } METHOD(imc_state_t, has_excl, bool, - private_imc_state_t *this) + private_imc_android_state_t *this) { return this->has_excl; } METHOD(imc_state_t, set_flags, void, - private_imc_state_t *this, bool has_long, bool has_excl) + private_imc_android_state_t *this, bool has_long, bool has_excl) { this->has_long = has_long; this->has_excl = has_excl; } METHOD(imc_state_t, set_max_msg_len, void, - private_imc_state_t *this, u_int32_t max_msg_len) + private_imc_android_state_t *this, u_int32_t max_msg_len) { this->max_msg_len = max_msg_len; } METHOD(imc_state_t, get_max_msg_len, u_int32_t, - private_imc_state_t *this) + private_imc_android_state_t *this) { return this->max_msg_len; } METHOD(imc_state_t, change_state, void, - private_imc_state_t *this, TNC_ConnectionState new_state) + private_imc_android_state_t *this, TNC_ConnectionState new_state) { this->state = new_state; } METHOD(imc_state_t, set_result, void, - private_imc_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result result) + private_imc_android_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result result) { this->result = result; } METHOD(imc_state_t, get_result, bool, - private_imc_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result *result) + private_imc_android_state_t *this, TNC_IMCID id, TNC_IMV_Evaluation_Result *result) { if (result) { @@ -123,7 +123,7 @@ METHOD(imc_state_t, get_result, bool, } METHOD(imc_state_t, destroy, void, - private_imc_state_t *this) + private_imc_android_state_t *this) { free(this); } @@ -133,25 +133,27 @@ METHOD(imc_state_t, destroy, void, */ imc_state_t *imc_android_state_create(TNC_ConnectionID connection_id) { - private_imc_state_t *this; + private_imc_android_state_t *this; INIT(this, .public = { - .get_connection_id = _get_connection_id, - .has_long = _has_long, - .has_excl = _has_excl, - .set_flags = _set_flags, - .set_max_msg_len = _set_max_msg_len, - .get_max_msg_len = _get_max_msg_len, - .change_state = _change_state, - .set_result = _set_result, - .get_result = _get_result, - .destroy = _destroy, + .interface = { + .get_connection_id = _get_connection_id, + .has_long = _has_long, + .has_excl = _has_excl, + .set_flags = _set_flags, + .set_max_msg_len = _set_max_msg_len, + .get_max_msg_len = _get_max_msg_len, + .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, + .destroy = _destroy, + }, }, .state = TNC_CONNECTION_STATE_CREATE, .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .connection_id = connection_id, ); - return &this->public; + return &this->public.interface; } diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h index 3acdea143..51bff32cf 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h @@ -23,6 +23,19 @@ #include +typedef struct imc_android_state_t imc_android_state_t; + +/** + * Internal state of an imc_android_t connection instance + */ +struct imc_android_state_t { + + /** + * imc_state_t interface + */ + imc_state_t interface; +}; + /** * Create an imc_android_state_t instance * From fd3aa004e448a9dd72b765de81fe45317f9039f3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 18:48:05 +0200 Subject: [PATCH 32/59] android: Android IMC state provides a Platform Trust Service (PTS) instance --- .../jni/libandroidbridge/byod/imc_android_state.c | 14 ++++++++++++++ .../jni/libandroidbridge/byod/imc_android_state.h | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c index 2018f9d9b..d429b90b7 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.c @@ -61,6 +61,11 @@ struct private_imc_android_state_t { * Maximum PA-TNC message size for this TNCCS connection */ u_int32_t max_msg_len; + + /** + * TCG Platform Trust Service (PTS) + */ + pts_t *pts; }; METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, @@ -125,9 +130,16 @@ METHOD(imc_state_t, get_result, bool, METHOD(imc_state_t, destroy, void, private_imc_android_state_t *this) { + this->pts->destroy(this->pts); free(this); } +METHOD(imc_android_state_t, get_pts, pts_t*, + private_imc_android_state_t *this) +{ + return this->pts; +} + /** * Described in header. */ @@ -149,10 +161,12 @@ imc_state_t *imc_android_state_create(TNC_ConnectionID connection_id) .get_result = _get_result, .destroy = _destroy, }, + .get_pts = _get_pts, }, .state = TNC_CONNECTION_STATE_CREATE, .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .connection_id = connection_id, + .pts = pts_create(TRUE), ); return &this->public.interface; diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h index 51bff32cf..68197f331 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android_state.h @@ -22,6 +22,7 @@ #define IMC_ANDROID_STATE_H_ #include +#include typedef struct imc_android_state_t imc_android_state_t; @@ -34,6 +35,11 @@ struct imc_android_state_t { * imc_state_t interface */ imc_state_t interface; + + /** + * Get TCG Platform Trust Service (PTS) object + */ + pts_t *(*get_pts)(imc_android_state_t *this); }; /** From d087f080f0f0eae9b965c61c6732d053fca55f72 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 May 2013 18:49:26 +0200 Subject: [PATCH 33/59] android: Handle TCG file measurement related attributes using PTS --- .../jni/libandroidbridge/byod/imc_android.c | 124 +++++++++++++++++- 1 file changed, 119 insertions(+), 5 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 23902e6f8..7dfc3a2fd 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -28,10 +28,15 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include +#include #include #include @@ -48,6 +53,7 @@ static const char imc_name[] = "Android"; static pen_type_t msg_types[] = { { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }, { PEN_IETF, PA_SUBTYPE_IETF_VPN }, + { PEN_TCG, PA_SUBTYPE_TCG_PTS }, }; static imc_agent_t *imc_android; @@ -300,6 +306,112 @@ static void handle_ita_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, } } +/** + * Handle a TCG attribute + */ +static void handle_tcg_attribute(imc_android_state_t *state, + pen_type_t attr_type, pa_tnc_attr_t *attr, + imc_msg_t *out_msg) +{ + pts_t *pts; + + pts = state->get_pts(state); + switch (attr_type.type) + { + case TCG_PTS_REQ_PROTO_CAPS: + { + tcg_pts_attr_proto_caps_t *attr_cast; + pts_proto_caps_flag_t caps; + + attr_cast = (tcg_pts_attr_proto_caps_t*)attr; + caps = attr_cast->get_flags(attr_cast) & pts->get_proto_caps(pts); + pts->set_proto_caps(pts, caps); + attr = tcg_pts_attr_proto_caps_create(caps, FALSE); + out_msg->add_attribute(out_msg, attr); + break; + } + case TCG_PTS_MEAS_ALGO: + { + tcg_pts_attr_meas_algo_t *attr_cast; + pts_meas_algorithms_t supported, algo; + + if (!pts_meas_algo_probe(&supported)) + { + attr = pts_hash_alg_error_create(PTS_MEAS_ALGO_NONE); + out_msg->add_attribute(out_msg, attr); + break; + } + attr_cast = (tcg_pts_attr_meas_algo_t*)attr; + algo = pts_meas_algo_select(supported, + attr_cast->get_algorithms(attr_cast)); + if (algo == PTS_MEAS_ALGO_NONE) + { + attr = pts_hash_alg_error_create(supported); + out_msg->add_attribute(out_msg, attr); + break; + } + pts->set_meas_algorithm(pts, algo); + attr = tcg_pts_attr_meas_algo_create(algo, TRUE); + out_msg->add_attribute(out_msg, attr); + break; + } + case TCG_PTS_REQ_FILE_MEAS: + { + tcg_pts_attr_req_file_meas_t *attr_cast; + pts_file_meas_t *measurements; + pts_error_code_t pts_error; + u_int32_t delim; + u_int16_t req_id; + bool is_dir; + char *path; + + attr_cast = (tcg_pts_attr_req_file_meas_t*)attr; + path = attr_cast->get_pathname(attr_cast); + if (!pts->is_path_valid(pts, path, &pts_error)) + { /* silently ignore internal errors */ + break; + } + else if (pts_error) + { + attr = ietf_attr_pa_tnc_error_create(pen_type_create(PEN_TCG, + pts_error), attr->get_value(attr)); + out_msg->add_attribute(out_msg, attr); + break; + } + delim = attr_cast->get_delimiter(attr_cast); + if (delim != SOLIDUS_UTF && delim != REVERSE_SOLIDUS_UTF) + { + attr = ietf_attr_pa_tnc_error_create(pen_type_create(PEN_TCG, + TCG_PTS_INVALID_DELIMITER), attr->get_value(attr)); + out_msg->add_attribute(out_msg, attr); + break; + } + req_id = attr_cast->get_request_id(attr_cast); + is_dir = attr_cast->get_directory_flag(attr_cast); + + DBG1(DBG_IMC, "measurement request %d for %s '%s'", req_id, + is_dir ? "directory" : "file", path); + measurements = pts_file_meas_create_from_path(req_id, path, is_dir, + TRUE, pts->get_meas_algorithm(pts)); + if (!measurements) + { + attr = ietf_attr_pa_tnc_error_create(pen_type_create(PEN_TCG, + TCG_PTS_FILE_NOT_FOUND), attr->get_value(attr)); + out_msg->add_attribute(out_msg, attr); + break; + } + attr = tcg_pts_attr_file_meas_create(measurements); + attr->set_noskip_flag(attr, TRUE); + out_msg->add_attribute(out_msg, attr); + break; + } + default: + DBG1(DBG_IMC, "received unsupported TCG attribute '%N'", + tcg_attr_names, attr_type.type); + break; + } +} + /** * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 */ @@ -336,7 +448,7 @@ static TNC_Result tnc_imc_beginhandshake(TNC_IMCID imc_id, return result; } -static TNC_Result receive_message(imc_msg_t *in_msg) +static TNC_Result receive_message(imc_android_state_t *state, imc_msg_t *in_msg) { imc_msg_t *out_msg; enumerator_t *enumerator; @@ -367,6 +479,9 @@ static TNC_Result receive_message(imc_msg_t *in_msg) case PEN_ITA: handle_ita_attribute(attr_type, attr, out_msg); continue; + case PEN_TCG: + handle_tcg_attribute(state, attr_type, attr, out_msg); + continue; default: continue; } @@ -411,7 +526,7 @@ static TNC_Result tnc_imc_receivemessage(TNC_IMCID imc_id, } in_msg = imc_msg_create_from_data(imc_android, state, connection_id, msg_type, chunk_create(msg, msg_len)); - result = receive_message(in_msg); + result = receive_message((imc_android_state_t*)state, in_msg); in_msg->destroy(in_msg); return result; @@ -446,7 +561,7 @@ static TNC_Result tnc_imc_receivemessagelong(TNC_IMCID imc_id, in_msg = imc_msg_create_from_long_data(imc_android, state, connection_id, src_imv_id, dst_imc_id,msg_vid, msg_subtype, chunk_create(msg, msg_len)); - result =receive_message(in_msg); + result = receive_message((imc_android_state_t*)state, in_msg); in_msg->destroy(in_msg); return result; @@ -476,10 +591,9 @@ static TNC_Result tnc_imc_terminate(TNC_IMCID imc_id) DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); return TNC_RESULT_NOT_INITIALIZED; } - /* has to be done before destroying the agent / deinitializing libimcv */ - libpts_deinit(); imc_android->destroy(imc_android); imc_android = NULL; + libpts_deinit(); return TNC_RESULT_SUCCESS; } From dc52cfab73298272a68eaef3f85b571536ad8a06 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 15 May 2013 15:52:16 +0200 Subject: [PATCH 34/59] android: Add state of IMC to VpnStateService and update it via JNI --- .../jni/libandroidbridge/byod/imc_android.c | 29 ++++++++++ .../jni/libandroidbridge/charonservice.c | 25 ++++++++ .../jni/libandroidbridge/charonservice.h | 21 ++++++- .../android/logic/CharonVpnService.java | 36 +++++++++++- .../android/logic/VpnStateService.java | 37 +++++++++++- .../android/logic/imc/ImcState.java | 58 +++++++++++++++++++ 6 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/ImcState.java diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 7dfc3a2fd..7067e1f89 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -18,6 +18,7 @@ #include "imc_android_state.h" #include "../android_jni.h" +#include "../charonservice.h" #include #include @@ -98,6 +99,29 @@ static TNC_Result tnc_imc_initialize(TNC_IMCID imc_id, return TNC_RESULT_SUCCESS; } +/** + * Update the state in the GUI. + */ +static void update_imc_state(TNC_ConnectionState state) +{ + android_imc_state_t imc_state = ANDROID_IMC_STATE_UNKNOWN; + + switch (state) + { /* map connection states to the values used by the GUI */ + case TNC_CONNECTION_STATE_ACCESS_ALLOWED: + imc_state = ANDROID_IMC_STATE_ALLOW; + break; + case TNC_CONNECTION_STATE_ACCESS_ISOLATED: + imc_state = ANDROID_IMC_STATE_ISOLATE; + break; + case TNC_CONNECTION_STATE_ACCESS_NONE: + imc_state = ANDROID_IMC_STATE_BLOCK; + break; + } + + charonservice->update_imc_state(charonservice, imc_state); +} + /** * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3 */ @@ -128,6 +152,11 @@ static TNC_Result tnc_imc_notifyconnectionchange(TNC_IMCID imc_id, return TNC_RESULT_SUCCESS; case TNC_CONNECTION_STATE_DELETE: return imc_android->delete_state(imc_android, connection_id); + case TNC_CONNECTION_STATE_ACCESS_ALLOWED: + case TNC_CONNECTION_STATE_ACCESS_ISOLATED: + case TNC_CONNECTION_STATE_ACCESS_NONE: + update_imc_state(new_state); + /* fall-through */ default: return imc_android->change_state(imc_android, connection_id, new_state, NULL); diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index 1c62e282c..115b53232 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -162,6 +162,30 @@ failed: return success; } +METHOD(charonservice_t, update_imc_state, bool, + private_charonservice_t *this, android_imc_state_t state) +{ + JNIEnv *env; + jmethodID method_id; + bool success = FALSE; + + androidjni_attach_thread(&env); + + method_id = (*env)->GetMethodID(env, android_charonvpnservice_class, + "updateImcState", "(I)V"); + if (!method_id) + { + goto failed; + } + (*env)->CallVoidMethod(env, this->vpn_service, method_id, (jint)state); + success = !androidjni_exception_occurred(env); + +failed: + androidjni_exception_occurred(env); + androidjni_detach_thread(); + return success; +} + /** * Bypass a single socket */ @@ -466,6 +490,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) INIT(this, .public = { .update_status = _update_status, + .update_imc_state = _update_imc_state, .bypass_socket = _bypass_socket, .get_trusted_certificates = _get_trusted_certificates, .get_user_certificate = _get_user_certificate, diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.h b/src/frontends/android/jni/libandroidbridge/charonservice.h index f142f78e5..90f5bc952 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/jni/libandroidbridge/charonservice.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * Hochschule fuer Technik Rapperswil @@ -41,6 +41,7 @@ #include typedef enum android_vpn_state_t android_vpn_state_t; +typedef enum android_imc_state_t android_imc_state_t; typedef struct charonservice_t charonservice_t; /** @@ -56,6 +57,16 @@ enum android_vpn_state_t { CHARONSERVICE_GENERIC_ERROR, }; +/** + * Final IMC state as defined in ImcState.java + */ +enum android_imc_state_t { + ANDROID_IMC_STATE_UNKNOWN = 0, + ANDROID_IMC_STATE_ALLOW = 1, + ANDROID_IMC_STATE_BLOCK = 2, + ANDROID_IMC_STATE_ISOLATE = 3, +}; + /** * Public interface of charonservice. * @@ -71,6 +82,14 @@ struct charonservice_t { */ bool (*update_status)(charonservice_t *this, android_vpn_state_t code); + /** + * Update final IMC state in the Java domain (UI) + * + * @param state IMC state + * @return TRUE on success + */ + bool (*update_imc_state)(charonservice_t *this, android_imc_state_t state); + /** * Install a bypass policy for the given socket using the protect() Method * of the Android VpnService interface. diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index f08a48135..9f920a9ed 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * Hochschule fuer Technik Rapperswil @@ -27,6 +27,7 @@ import org.strongswan.android.data.VpnProfile; import org.strongswan.android.data.VpnProfileDataSource; import org.strongswan.android.logic.VpnStateService.ErrorState; import org.strongswan.android.logic.VpnStateService.State; +import org.strongswan.android.logic.imc.ImcState; import org.strongswan.android.ui.MainActivity; import android.app.PendingIntent; @@ -208,6 +209,7 @@ public class CharonVpnService extends VpnService implements Runnable setProfile(mCurrentProfile); setError(ErrorState.NO_ERROR); setState(State.CONNECTING); + setImcState(ImcState.UNKNOWN); mIsDisconnecting = false; BuilderAdapter builder = new BuilderAdapter(mCurrentProfile.getName()); @@ -296,6 +298,23 @@ public class CharonVpnService extends VpnService implements Runnable } } + /** + * Set the IMC state on the state service. Called by the handler thread and + * any of charon's threads. + * + * @param state IMC state + */ + private void setImcState(ImcState state) + { + synchronized (mServiceLock) + { + if (mService != null) + { + mService.setImcState(state); + } + } + } + /** * Set an error on the state service and disconnect the current connection. * This is not done by calling stopCurrentConnection() above, but instead @@ -355,6 +374,21 @@ public class CharonVpnService extends VpnService implements Runnable } } + /** + * Updates the IMC state of the current connection. + * Called via JNI by different threads (but not concurrently). + * + * @param value new state + */ + public void updateImcState(int value) + { + ImcState state = ImcState.fromValue(value); + if (state != null) + { + setImcState(state); + } + } + /** * Function called via JNI to generate a list of DER encoded CA certificates * as byte array. diff --git a/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java b/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java index 1c14cb601..62ca31f13 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,6 +20,7 @@ import java.util.List; import java.util.concurrent.Callable; import org.strongswan.android.data.VpnProfile; +import org.strongswan.android.logic.imc.ImcState; import android.app.Service; import android.content.Context; @@ -36,6 +37,7 @@ public class VpnStateService extends Service private VpnProfile mProfile; private State mState = State.DISABLED; private ErrorState mError = ErrorState.NO_ERROR; + private ImcState mImcState = ImcState.UNKNOWN; public enum State { @@ -146,6 +148,16 @@ public class VpnStateService extends Service return mError; } + /** + * Get the current IMC state, if any. + * + * @return imc state + */ + public ImcState getImcState() + { /* only updated from the main thread so no synchronization needed */ + return mImcState; + } + /** * Disconnect any existing connection and shutdown the daemon, the * VpnService is not stopped but it is reset so new connections can be @@ -261,4 +273,27 @@ public class VpnStateService extends Service } }); } + + /** + * Set the current IMC state and notify all listeners, if changed. + * + * May be called from threads other than the main thread. + * + * @param error error state + */ + public void setImcState(final ImcState state) + { + notifyListeners(new Callable() { + @Override + public Boolean call() throws Exception + { + if (VpnStateService.this.mImcState != state) + { + VpnStateService.this.mImcState = state; + return true; + } + return false; + } + }); + } } diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/ImcState.java b/src/frontends/android/src/org/strongswan/android/logic/imc/ImcState.java new file mode 100644 index 000000000..4fc3834f9 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/ImcState.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc; + +public enum ImcState +{ + UNKNOWN(0), + ALLOW(1), + BLOCK(2), + ISOLATE(3); + + private final int mValue; + + private ImcState(int value) + { + mValue = value; + } + + /** + * Get the numeric value of the IMC state. + * @return numeric value + */ + public int getValue() + { + return mValue; + } + + /** + * Get the enum entry from a numeric value, if defined + * + * @param value numeric value + * @return the enum entry or null + */ + public static ImcState fromValue(int value) + { + for (ImcState state : ImcState.values()) + { + if (state.mValue == value) + { + return state; + } + } + return null; + } +} From 5e7a4193e57e042658a9f519811740fd2ce21be9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 15 May 2013 18:35:00 +0200 Subject: [PATCH 35/59] android: Clear error only when the user explicitly dismisses the dialog The previous code worked fine on rotation changes as the fragment is destroyed and recreated causing onCreate to be called, which restores the saved error state. But if the user switches to a different application and then back this is not the case. The dialog still gets dismissed (as we have to do so to avoid nasty exceptions on rotation changes) but since that implicitly cleared the error state the UI was never fully restored. --- .../strongswan/android/ui/VpnStateFragment.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java index 738ed111f..6aec7e784 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * Hochschule fuer Technik Rapperswil @@ -305,6 +305,12 @@ public class VpnStateFragment extends Fragment implements VpnStateListener } } + private void clearError() + { + mError = ErrorState.NO_ERROR; + updateView(); + } + private void showConnectDialog(String profile, String gateway) { mProgressDialog = new ProgressDialog(getActivity()); @@ -345,6 +351,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener @Override public void onClick(DialogInterface dialog, int which) { + clearError(); dialog.dismiss(); Intent logIntent = new Intent(getActivity(), LogActivity.class); startActivity(logIntent); @@ -354,16 +361,15 @@ public class VpnStateFragment extends Fragment implements VpnStateListener @Override public void onClick(DialogInterface dialog, int id) { + clearError(); dialog.dismiss(); } }).create(); mErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) - { /* clear the error */ - mError = ErrorState.NO_ERROR; + { mErrorDialog = null; - updateView(); } }); mErrorDialog.show(); From a8dc42b295590fa3abc05a9538662f3e6359ba17 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 16 May 2013 13:32:50 +0200 Subject: [PATCH 36/59] android: Show different error message depending on IMC state --- .../android/res/values-de/strings.xml | 1 + .../android/res/values-pl/strings.xml | 1 + .../android/res/values-ru/strings.xml | 1 + .../android/res/values-ua/strings.xml | 1 + src/frontends/android/res/values/strings.xml | 1 + .../android/ui/VpnStateFragment.java | 24 ++++++++++++++++--- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/frontends/android/res/values-de/strings.xml b/src/frontends/android/res/values-de/strings.xml index 3181e0a54..77bbbe7a2 100644 --- a/src/frontends/android/res/values-de/strings.xml +++ b/src/frontends/android/res/values-de/strings.xml @@ -94,6 +94,7 @@ Gateway ist nicht erreichbar. Authentifizierung des Gateway ist fehlgeschlagen. Benutzerauthentifizierung ist fehlgeschlagen. + Sicherheitsassessment ist fehlgeschlagen. Unbekannter Fehler während des Verbindens. Verbinden: %1$s Verbinde mit \""%1$s\". diff --git a/src/frontends/android/res/values-pl/strings.xml b/src/frontends/android/res/values-pl/strings.xml index 3ba5e1669..9a5471530 100644 --- a/src/frontends/android/res/values-pl/strings.xml +++ b/src/frontends/android/res/values-pl/strings.xml @@ -96,6 +96,7 @@ Bramka jest nieosiągalna Błąd przy weryfikacji bramki Błąd przy autoryzacji użytkownika + Security assessment failed. Nieznany błąd w czasie połączenia Łączenie: %1$s Tworzenie tunelu VPN z \""%1$s\". diff --git a/src/frontends/android/res/values-ru/strings.xml b/src/frontends/android/res/values-ru/strings.xml index afa21361b..9ff1eff5e 100644 --- a/src/frontends/android/res/values-ru/strings.xml +++ b/src/frontends/android/res/values-ru/strings.xml @@ -91,6 +91,7 @@ Шлюз недоступен. Ошибка авторизаци при подключении к шлюзу. Ошибка авторизации пользователя. + Security assessment failed. Неизвестная ошибка. Подключение: %1$s Подключение к VPN с \""%1$s\". diff --git a/src/frontends/android/res/values-ua/strings.xml b/src/frontends/android/res/values-ua/strings.xml index 953ba0a54..e420a35f4 100644 --- a/src/frontends/android/res/values-ua/strings.xml +++ b/src/frontends/android/res/values-ua/strings.xml @@ -92,6 +92,7 @@ Немає зв\'язку зі шлюзом. Помилка перевірки данних аутентифікації шлюза. Помилка аутентифікації користувача. + Security assessment failed. Невідома помилка під час підключення. Підключення: %1$s Підключення VPN з \""%1$s\". diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml index c91bce445..e7b7fb668 100644 --- a/src/frontends/android/res/values/strings.xml +++ b/src/frontends/android/res/values/strings.xml @@ -94,6 +94,7 @@ Gateway is unreachable. Verifying gateway authentication failed. User authentication failed. + Security assessment failed. Unspecified failure while connecting. Connecting: %1$s Establishing VPN with \""%1$s\". diff --git a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java index 6aec7e784..d745d8344 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java @@ -23,6 +23,7 @@ import org.strongswan.android.logic.VpnStateService; import org.strongswan.android.logic.VpnStateService.ErrorState; import org.strongswan.android.logic.VpnStateService.State; import org.strongswan.android.logic.VpnStateService.VpnStateListener; +import org.strongswan.android.logic.imc.ImcState; import android.app.AlertDialog; import android.app.Fragment; @@ -45,6 +46,7 @@ import android.widget.TextView; public class VpnStateFragment extends Fragment implements VpnStateListener { private static final String KEY_ERROR = "error"; + private static final String KEY_IMC_STATE = "imc_state"; private static final String KEY_NAME = "name"; private TextView mProfileNameView; @@ -56,6 +58,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener private State mState; private AlertDialog mErrorDialog; private ErrorState mError; + private ImcState mImcState; private String mErrorProfileName; private VpnStateService mService; private final ServiceConnection mServiceConnection = new ServiceConnection() { @@ -85,9 +88,11 @@ public class VpnStateFragment extends Fragment implements VpnStateListener mServiceConnection, Service.BIND_AUTO_CREATE); mError = ErrorState.NO_ERROR; + mImcState = ImcState.UNKNOWN; if (savedInstanceState != null && savedInstanceState.containsKey(KEY_ERROR)) { mError = (ErrorState)savedInstanceState.getSerializable(KEY_ERROR); + mImcState = (ImcState)savedInstanceState.getSerializable(KEY_IMC_STATE); mErrorProfileName = savedInstanceState.getString(KEY_NAME); } } @@ -98,6 +103,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener super.onSaveInstanceState(outState); outState.putSerializable(KEY_ERROR, mError); + outState.putSerializable(KEY_IMC_STATE, mImcState); outState.putString(KEY_NAME, mErrorProfileName); } @@ -167,6 +173,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener { State state = mService.getState(); ErrorState error = ErrorState.NO_ERROR; + ImcState imcState = ImcState.UNKNOWN; String name = "", gateway = ""; if (state != State.DISABLED) @@ -178,9 +185,10 @@ public class VpnStateFragment extends Fragment implements VpnStateListener gateway = profile.getGateway(); } error = mService.getErrorState(); + imcState = mService.getImcState(); } - if (reportError(name, state, error)) + if (reportError(name, state, error, imcState)) { return; } @@ -223,16 +231,18 @@ public class VpnStateFragment extends Fragment implements VpnStateListener } } - private boolean reportError(String name, State state, ErrorState error) + private boolean reportError(String name, State state, ErrorState error, ImcState imcState) { if (mError != ErrorState.NO_ERROR) { /* we are currently reporting an error which was not yet dismissed */ error = mError; + imcState = mImcState; name = mErrorProfileName; } else if (error != ErrorState.NO_ERROR && (state == State.CONNECTING || state == State.CONNECTED)) { /* while initiating we report errors */ mError = error; + mImcState = imcState; mErrorProfileName = name; } else @@ -257,7 +267,14 @@ public class VpnStateFragment extends Fragment implements VpnStateListener switch (error) { case AUTH_FAILED: - showErrorDialog(R.string.error_auth_failed); + if (imcState == ImcState.BLOCK) + { + showErrorDialog(R.string.error_assessment_failed); + } + else + { + showErrorDialog(R.string.error_auth_failed); + } break; case PEER_AUTH_FAILED: showErrorDialog(R.string.error_peer_auth_failed); @@ -308,6 +325,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener private void clearError() { mError = ErrorState.NO_ERROR; + mImcState = ImcState.UNKNOWN; updateView(); } From 0484989dbda41990dbf269c24425650c4cd39649 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 May 2013 13:08:54 +0200 Subject: [PATCH 37/59] android: Add a parser for XML remediation instructions --- .../logic/imc/RemediationInstruction.java | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/logic/imc/RemediationInstruction.java diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/RemediationInstruction.java b/src/frontends/android/src/org/strongswan/android/logic/imc/RemediationInstruction.java new file mode 100644 index 000000000..8c7f1753c --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/RemediationInstruction.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.imc; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.util.Xml; + +public class RemediationInstruction +{ + private String mTitle; + private String mDescription; + private String mHeader; + private final List mItems = new LinkedList(); + + public String getTitle() + { + return mTitle; + } + + private void setTitle(String title) + { + mTitle = title; + } + + public String getDescription() + { + return mDescription; + } + + private void setDescription(String description) + { + mDescription = description; + } + + public String getHeader() + { + return mHeader; + } + + private void setHeader(String header) + { + mHeader = header; + } + + public List getItems() + { + return Collections.unmodifiableList(mItems); + } + + private void addItem(String item) + { + mItems.add(item); + } + + /** + * Create a list of RemediationInstruction objects from the given XML data. + * + * @param xml XML data + * @return list of RemediationInstruction objects + */ + public static List fromXml(String xml) + { + List instructions = new LinkedList(); + XmlPullParser parser = Xml.newPullParser(); + try + { + parser.setInput(new StringReader(xml)); + parser.nextTag(); + readInstructions(parser, instructions); + } + catch (XmlPullParserException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + return instructions; + } + + /** + * Read a <remediationinstructions> element and store the extracted + * RemediationInstruction objects in the given list. + * + * @param parser + * @param instructions + * @throws XmlPullParserException + * @throws IOException + */ + private static void readInstructions(XmlPullParser parser, List instructions) throws XmlPullParserException, IOException + { + parser.require(XmlPullParser.START_TAG, null, "remediationinstructions"); + while (parser.next() != XmlPullParser.END_TAG) + { + if (parser.getEventType() != XmlPullParser.START_TAG) + { + continue; + } + if (parser.getName().equals("instruction")) + { + RemediationInstruction instruction = new RemediationInstruction(); + readInstruction(parser, instruction); + instructions.add(instruction); + } + else + { + skipTag(parser); + } + } + } + + /** + * Read an <instruction> element and store the information in the + * given RemediationInstruction object. + * + * @param parser + * @param instruction + * @throws XmlPullParserException + * @throws IOException + */ + private static void readInstruction(XmlPullParser parser, RemediationInstruction instruction) throws XmlPullParserException, IOException + { + parser.require(XmlPullParser.START_TAG, null, "instruction"); + while (parser.next() != XmlPullParser.END_TAG) + { + if (parser.getEventType() != XmlPullParser.START_TAG) + { + continue; + } + String name = parser.getName(); + if (name.equals("title")) + { + instruction.setTitle(parser.nextText()); + } + else if (name.equals("description")) + { + instruction.setDescription(parser.nextText()); + } + else if (name.equals("itemsheader")) + { + instruction.setHeader(parser.nextText()); + } + else if (name.equals("items")) + { + readItems(parser, instruction); + } + else + { + skipTag(parser); + } + } + } + + /** + * Read all items of an <items> node and add them to the given + * RemediationInstruction object. + * + * @param parser + * @param instruction + * @throws XmlPullParserException + * @throws IOException + */ + private static void readItems(XmlPullParser parser, RemediationInstruction instruction) throws XmlPullParserException, IOException + { + while (parser.next() != XmlPullParser.END_TAG) + { + if (parser.getEventType() != XmlPullParser.START_TAG) + { + continue; + } + if (parser.getName().equals("item")) + { + instruction.addItem(parser.nextText()); + } + else + { + skipTag(parser); + } + } + } + + /** + * Skip the current tag and all child elements. + * + * @param parser + * @throws XmlPullParserException + * @throws IOException + */ + private static void skipTag(XmlPullParser parser) throws XmlPullParserException, IOException + { + int depth = 1; + + parser.require(XmlPullParser.START_TAG, null, null); + while (depth != 0) + { + switch (parser.next()) + { + case XmlPullParser.END_TAG: + depth--; + break; + case XmlPullParser.START_TAG: + depth++; + break; + } + } + } +} From a05acd76294e4c4e4da7633632732858ae762d2a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 May 2013 13:15:14 +0200 Subject: [PATCH 38/59] android: Handle and store IETF remediation instructions --- .../jni/libandroidbridge/byod/imc_android.c | 19 +++++++++ .../jni/libandroidbridge/charonservice.c | 32 +++++++++++++++ .../jni/libandroidbridge/charonservice.h | 8 ++++ .../android/logic/CharonVpnService.java | 21 ++++++++++ .../android/logic/VpnStateService.java | 41 +++++++++++++++++++ 5 files changed, 121 insertions(+) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 7067e1f89..c60f7ca59 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,24 @@ static void handle_ietf_attribute(pen_type_t attr_type, pa_tnc_attr_t *attr, } enumerator->destroy(enumerator); } + else if (attr_type.type == IETF_ATTR_REMEDIATION_INSTRUCTIONS) + { + ietf_attr_remediation_instr_t *attr_cast; + pen_type_t param; + chunk_t str; + char *instr; + + attr_cast = (ietf_attr_remediation_instr_t*)attr; + param = attr_cast->get_parameters_type(attr_cast); + + if (pen_type_is(param, PEN_IETF, IETF_REMEDIATION_PARAMETERS_STRING)) + { + str = attr_cast->get_string(attr_cast, NULL); + instr = strndup(str.ptr, str.len); + charonservice->add_remediation_instr(charonservice, instr); + free (instr); + } + } } /** diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index 115b53232..03599b717 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -186,6 +186,37 @@ failed: return success; } +METHOD(charonservice_t, add_remediation_instr, bool, + private_charonservice_t *this, char *instr) +{ + JNIEnv *env; + jmethodID method_id; + jstring jinstr; + bool success = FALSE; + + androidjni_attach_thread(&env); + + method_id = (*env)->GetMethodID(env, android_charonvpnservice_class, + "addRemediationInstruction", + "(Ljava/lang/String;)V"); + if (!method_id) + { + goto failed; + } + jinstr = (*env)->NewStringUTF(env, instr); + if (!jinstr) + { + goto failed; + } + (*env)->CallVoidMethod(env, this->vpn_service, method_id, jinstr); + success = !androidjni_exception_occurred(env); + +failed: + androidjni_exception_occurred(env); + androidjni_detach_thread(); + return success; +} + /** * Bypass a single socket */ @@ -491,6 +522,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) .public = { .update_status = _update_status, .update_imc_state = _update_imc_state, + .add_remediation_instr = _add_remediation_instr, .bypass_socket = _bypass_socket, .get_trusted_certificates = _get_trusted_certificates, .get_user_certificate = _get_user_certificate, diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.h b/src/frontends/android/jni/libandroidbridge/charonservice.h index 90f5bc952..0c71d876d 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.h +++ b/src/frontends/android/jni/libandroidbridge/charonservice.h @@ -90,6 +90,14 @@ struct charonservice_t { */ bool (*update_imc_state)(charonservice_t *this, android_imc_state_t state); + /** + * Add a remediation instruction via JNI + * + * @param instr remediation instruction + * @return TRUE on success + */ + bool (*add_remediation_instr)(charonservice_t *this, char *instr); + /** * Install a bypass policy for the given socket using the protect() Method * of the Android VpnService interface. diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 9f920a9ed..bc9038660 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -28,6 +28,7 @@ import org.strongswan.android.data.VpnProfileDataSource; import org.strongswan.android.logic.VpnStateService.ErrorState; import org.strongswan.android.logic.VpnStateService.State; import org.strongswan.android.logic.imc.ImcState; +import org.strongswan.android.logic.imc.RemediationInstruction; import org.strongswan.android.ui.MainActivity; import android.app.PendingIntent; @@ -389,6 +390,26 @@ public class CharonVpnService extends VpnService implements Runnable } } + /** + * Add a remediation instruction to the VPN state service. + * Called via JNI by different threads (but not concurrently). + * + * @param xml XML text + */ + public void addRemediationInstruction(String xml) + { + for (RemediationInstruction instruction : RemediationInstruction.fromXml(xml)) + { + synchronized (mServiceLock) + { + if (mService != null) + { + mService.addRemediationInstruction(instruction); + } + } + } + } + /** * Function called via JNI to generate a list of DER encoded CA certificates * as byte array. diff --git a/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java b/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java index 62ca31f13..2c530bad4 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/VpnStateService.java @@ -16,11 +16,14 @@ package org.strongswan.android.logic; import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; import org.strongswan.android.data.VpnProfile; import org.strongswan.android.logic.imc.ImcState; +import org.strongswan.android.logic.imc.RemediationInstruction; import android.app.Service; import android.content.Context; @@ -38,6 +41,7 @@ public class VpnStateService extends Service private State mState = State.DISABLED; private ErrorState mError = ErrorState.NO_ERROR; private ImcState mImcState = ImcState.UNKNOWN; + private final LinkedList mRemediationInstructions = new LinkedList(); public enum State { @@ -158,6 +162,16 @@ public class VpnStateService extends Service return mImcState; } + /** + * Get the remediation instructions, if any. + * + * @return read-only list of instructions + */ + public List getRemediationInstructions() + { /* only updated from the main thread so no synchronization needed */ + return Collections.unmodifiableList(mRemediationInstructions); + } + /** * Disconnect any existing connection and shutdown the daemon, the * VpnService is not stopped but it is reset so new connections can be @@ -277,6 +291,8 @@ public class VpnStateService extends Service /** * Set the current IMC state and notify all listeners, if changed. * + * Setting the state to UNKNOWN clears all remediation instructions. + * * May be called from threads other than the main thread. * * @param error error state @@ -287,6 +303,10 @@ public class VpnStateService extends Service @Override public Boolean call() throws Exception { + if (state == ImcState.UNKNOWN) + { + VpnStateService.this.mRemediationInstructions.clear(); + } if (VpnStateService.this.mImcState != state) { VpnStateService.this.mImcState = state; @@ -296,4 +316,25 @@ public class VpnStateService extends Service } }); } + + /** + * Add the given remediation instruction to the internal list. Listeners + * are not notified. + * + * Instructions are cleared if the IMC state is set to UNKNOWN. + * + * May be called from threads other than the main thread. + * + * @param instruction remediation instruction + */ + public void addRemediationInstruction(final RemediationInstruction instruction) + { + mHandler.post(new Runnable() { + @Override + public void run() + { + VpnStateService.this.mRemediationInstructions.add(instruction); + } + }); + } } From e5bf6dcddc07877e1422d90851850afcc62969d4 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 May 2013 18:18:07 +0200 Subject: [PATCH 39/59] android: Add fragment that displays the IMC state The fragment hides itself if the state is unknown or the assessment succeeded. --- .../android/res/layout/imc_state_fragment.xml | 54 ++++++++ src/frontends/android/res/layout/main.xml | 8 +- .../android/res/values-de/strings.xml | 7 +- .../android/res/values-pl/strings.xml | 7 +- .../android/res/values-ru/strings.xml | 5 + .../android/res/values-ua/strings.xml | 7 +- src/frontends/android/res/values/colors.xml | 5 +- src/frontends/android/res/values/strings.xml | 7 +- .../android/ui/ImcStateFragment.java | 117 ++++++++++++++++++ 9 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 src/frontends/android/res/layout/imc_state_fragment.xml create mode 100644 src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java diff --git a/src/frontends/android/res/layout/imc_state_fragment.xml b/src/frontends/android/res/layout/imc_state_fragment.xml new file mode 100644 index 000000000..bdb3cd37d --- /dev/null +++ b/src/frontends/android/res/layout/imc_state_fragment.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + diff --git a/src/frontends/android/res/layout/main.xml b/src/frontends/android/res/layout/main.xml index 1c7973e20..ab03e72bc 100644 --- a/src/frontends/android/res/layout/main.xml +++ b/src/frontends/android/res/layout/main.xml @@ -1,6 +1,6 @@ + Assessment: + Eingeschränkt + Fehlgeschlagen + Passwort eingeben um zu verbinden Verbinden diff --git a/src/frontends/android/res/values-pl/strings.xml b/src/frontends/android/res/values-pl/strings.xml index 9a5471530..e3576d5de 100644 --- a/src/frontends/android/res/values-pl/strings.xml +++ b/src/frontends/android/res/values-pl/strings.xml @@ -1,7 +1,5 @@ + Assessment: + Restricted + Failed + Wprowadż hasło Połącz diff --git a/src/frontends/android/res/values-ru/strings.xml b/src/frontends/android/res/values-ru/strings.xml index 9ff1eff5e..f5f696ab4 100644 --- a/src/frontends/android/res/values-ru/strings.xml +++ b/src/frontends/android/res/values-ru/strings.xml @@ -83,6 +83,11 @@ Нет активных VPN Ошибка + + Assessment: + Restricted + Failed + Введите пароль для соединения Соединить diff --git a/src/frontends/android/res/values-ua/strings.xml b/src/frontends/android/res/values-ua/strings.xml index e420a35f4..39d67eaba 100644 --- a/src/frontends/android/res/values-ua/strings.xml +++ b/src/frontends/android/res/values-ua/strings.xml @@ -1,7 +1,7 @@ + Assessment: + Restricted + Failed + Введіть пароль для з\'єднання Підключити diff --git a/src/frontends/android/res/values/colors.xml b/src/frontends/android/res/values/colors.xml index be64d5d5a..ee8d72461 100644 --- a/src/frontends/android/res/values/colors.xml +++ b/src/frontends/android/res/values/colors.xml @@ -1,6 +1,6 @@ + Assessment: + Restricted + Failed + Enter password to connect Connect diff --git a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java new file mode 100644 index 000000000..473611394 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.ui; + +import org.strongswan.android.R; +import org.strongswan.android.logic.VpnStateService; +import org.strongswan.android.logic.VpnStateService.VpnStateListener; + +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class ImcStateFragment extends Fragment implements VpnStateListener +{ + private TextView mStateView; + private VpnStateService mService; + private final ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) + { + mService = null; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) + { + mService = ((VpnStateService.LocalBinder)service).getService(); + mService.registerListener(ImcStateFragment.this); + updateView(); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + /* bind to the service only seems to work from the ApplicationContext */ + Context context = getActivity().getApplicationContext(); + context.bindService(new Intent(context, VpnStateService.class), + mServiceConnection, Service.BIND_AUTO_CREATE); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) + { + View view = inflater.inflate(R.layout.imc_state_fragment, null); + + mStateView = (TextView)view.findViewById(R.id.imc_state); + + return view; + } + + @Override + public void onDestroy() + { + super.onDestroy(); + if (mService != null) + { + mService.unregisterListener(this); + getActivity().getApplicationContext().unbindService(mServiceConnection); + } + } + + @Override + public void stateChanged() + { + updateView(); + } + + public void updateView() + { + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.show(this); + + switch (mService.getImcState()) + { + case UNKNOWN: + case ALLOW: + ft.hide(this); + break; + case ISOLATE: + mStateView.setText(R.string.imc_state_isolate); + mStateView.setTextColor(getResources().getColor(R.color.warning_text)); + break; + case BLOCK: + mStateView.setText(R.string.imc_state_block); + mStateView.setTextColor(getResources().getColor(R.color.error_text)); + break; + } + ft.commit(); + } +} From 2b9108570174f697df0b31cbf62dff0081850223 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 10:50:08 +0200 Subject: [PATCH 40/59] android: Background for state panels provides separator --- ...te_background.xml => state_background.xml} | 21 ++++++++++++++----- .../android/res/layout/imc_state_fragment.xml | 8 ++----- .../android/res/layout/vpn_state_fragment.xml | 11 +++------- src/frontends/android/res/values/colors.xml | 6 ++++++ 4 files changed, 27 insertions(+), 19 deletions(-) rename src/frontends/android/res/drawable/{vpn_state_background.xml => state_background.xml} (60%) diff --git a/src/frontends/android/res/drawable/vpn_state_background.xml b/src/frontends/android/res/drawable/state_background.xml similarity index 60% rename from src/frontends/android/res/drawable/vpn_state_background.xml rename to src/frontends/android/res/drawable/state_background.xml index 24f469add..ee36325cc 100644 --- a/src/frontends/android/res/drawable/vpn_state_background.xml +++ b/src/frontends/android/res/drawable/state_background.xml @@ -1,6 +1,6 @@ - + - + + + + + - \ No newline at end of file + + + + + + + diff --git a/src/frontends/android/res/layout/imc_state_fragment.xml b/src/frontends/android/res/layout/imc_state_fragment.xml index bdb3cd37d..86853889a 100644 --- a/src/frontends/android/res/layout/imc_state_fragment.xml +++ b/src/frontends/android/res/layout/imc_state_fragment.xml @@ -16,7 +16,8 @@ - - diff --git a/src/frontends/android/res/layout/vpn_state_fragment.xml b/src/frontends/android/res/layout/vpn_state_fragment.xml index 6353f3289..e347c4c4b 100644 --- a/src/frontends/android/res/layout/vpn_state_fragment.xml +++ b/src/frontends/android/res/layout/vpn_state_fragment.xml @@ -1,6 +1,6 @@ + + + + + + + + + + + diff --git a/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionFragment.java b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionFragment.java new file mode 100644 index 000000000..04c288bcf --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionFragment.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.ui; + +import org.strongswan.android.R; +import org.strongswan.android.logic.imc.RemediationInstruction; + +import android.app.ListFragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +public class RemediationInstructionFragment extends ListFragment +{ + public static final String ARG_REMEDIATION_INSTRUCTION = "instruction"; + private RemediationInstruction mInstruction = null; + private TextView mTitle; + private TextView mDescription; + private TextView mHeader; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + return inflater.inflate(R.layout.remediation_instruction, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) + { + super.onActivityCreated(savedInstanceState); + + if (savedInstanceState != null) + { + mInstruction = savedInstanceState.getParcelable(ARG_REMEDIATION_INSTRUCTION); + } + /* show dividers only between list items */ + getListView().setHeaderDividersEnabled(false); + getListView().setFooterDividersEnabled(false); + /* don't show loader while adapter is not set */ + setListShown(true); + mTitle = (TextView)getView().findViewById(R.id.title); + mDescription = (TextView)getView().findViewById(R.id.description); + mHeader = (TextView)getView().findViewById(R.id.list_header); + } + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + outState.putParcelable(ARG_REMEDIATION_INSTRUCTION, mInstruction); + } + + @Override + public void onStart() + { + super.onStart(); + + Bundle args = getArguments(); + if (args != null) + { + mInstruction = args.getParcelable(ARG_REMEDIATION_INSTRUCTION); + } + updateView(mInstruction); + } + + public void updateView(RemediationInstruction instruction) + { + mInstruction = instruction; + if (mInstruction != null) + { + mTitle.setText(mInstruction.getTitle()); + mDescription.setText(mInstruction.getDescription()); + if (mInstruction.getHeader() != null) + { + mHeader.setText(mInstruction.getHeader()); + setListAdapter(new ArrayAdapter(getActivity(), + android.R.layout.simple_list_item_1, mInstruction.getItems())); + } + else + { + mHeader.setText(""); + setListAdapter(null); + } + } + else + { + mTitle.setText(""); + mDescription.setText(""); + mHeader.setText(""); + setListAdapter(null); + } + } +} From b6e05f6518c478a65c219aba08df04e8b0b9cb0c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 11:38:05 +0200 Subject: [PATCH 43/59] android: Add adapter for remediation instructions --- .../layout/remediation_instruction_item.xml | 47 ++++++++++++ .../RemediationInstructionAdapter.java | 71 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/frontends/android/res/layout/remediation_instruction_item.xml create mode 100644 src/frontends/android/src/org/strongswan/android/ui/adapter/RemediationInstructionAdapter.java diff --git a/src/frontends/android/res/layout/remediation_instruction_item.xml b/src/frontends/android/res/layout/remediation_instruction_item.xml new file mode 100644 index 000000000..30dfb2219 --- /dev/null +++ b/src/frontends/android/res/layout/remediation_instruction_item.xml @@ -0,0 +1,47 @@ + + + + + + + + + diff --git a/src/frontends/android/src/org/strongswan/android/ui/adapter/RemediationInstructionAdapter.java b/src/frontends/android/src/org/strongswan/android/ui/adapter/RemediationInstructionAdapter.java new file mode 100644 index 000000000..e9ab52287 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/ui/adapter/RemediationInstructionAdapter.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.ui.adapter; + +import java.util.List; + +import org.strongswan.android.R; +import org.strongswan.android.logic.imc.RemediationInstruction; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +public class RemediationInstructionAdapter extends ArrayAdapter +{ + public RemediationInstructionAdapter(Context context) + { + super(context, 0); + } + + /** + * Set new data for this adapter. + * + * @param data the new data (null to clear) + */ + public void setData(List data) + { + clear(); + if (data != null) + { + addAll(data); + } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) + { + View view; + if (convertView != null) + { + view = convertView; + } + else + { + LayoutInflater inflater = LayoutInflater.from(getContext()); + view = inflater.inflate(R.layout.remediation_instruction_item, parent, false); + } + RemediationInstruction item = getItem(position); + TextView text = (TextView)view.findViewById(android.R.id.text1); + text.setText(item.getTitle()); + text = (TextView)view.findViewById(android.R.id.text2); + text.setText(item.getDescription()); + return view; + } +} From 611d35e8e87ed0bbbcd5ab9ff90522f557ee6dd6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 11:47:01 +0200 Subject: [PATCH 44/59] android: Add fragment for a list of remediation instructions This fragment can later be used in one- or two-pane layouts. --- .../ui/RemediationInstructionsFragment.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java diff --git a/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java new file mode 100644 index 000000000..9aa7ea140 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.ui; + +import java.util.ArrayList; + +import org.strongswan.android.logic.imc.RemediationInstruction; +import org.strongswan.android.ui.adapter.RemediationInstructionAdapter; + +import android.app.Activity; +import android.app.ListFragment; +import android.os.Bundle; +import android.view.View; +import android.widget.ListView; + +public class RemediationInstructionsFragment extends ListFragment +{ + public static final String EXTRA_REMEDIATION_INSTRUCTIONS = "instructions"; + private static final String KEY_POSITION = "position"; + private ArrayList mInstructions = null; + private OnRemediationInstructionSelectedListener mListener; + private RemediationInstructionAdapter mAdapter; + private int mCurrentPosition = -1; + + /** + * The activity containing this fragment should implement this interface + */ + public interface OnRemediationInstructionSelectedListener + { + public void onRemediationInstructionSelected(RemediationInstruction instruction); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) + { + super.onActivityCreated(savedInstanceState); + + if (savedInstanceState != null) + { + mInstructions = savedInstanceState.getParcelableArrayList(EXTRA_REMEDIATION_INSTRUCTIONS); + mCurrentPosition = savedInstanceState.getInt(KEY_POSITION); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + outState.putParcelableArrayList(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS, mInstructions); + outState.putInt(KEY_POSITION, mCurrentPosition); + } + + @Override + public void onAttach(Activity activity) + { + super.onAttach(activity); + + if (activity instanceof OnRemediationInstructionSelectedListener) + { + mListener = (OnRemediationInstructionSelectedListener)activity; + } + } + + @Override + public void onStart() + { + super.onStart(); + + boolean two_pane = false; + if (two_pane) + { /* two-pane layout, make list items selectable */ + getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); + } + + Bundle args = getArguments(); + if (mInstructions == null && args != null) + { + mInstructions = args.getParcelableArrayList(EXTRA_REMEDIATION_INSTRUCTIONS); + } + updateView(mInstructions); + + if (two_pane && mCurrentPosition == -1 && mInstructions.size() > 0) + { /* two-pane layout, select first instruction */ + mCurrentPosition = 0; + mListener.onRemediationInstructionSelected(mInstructions.get(0)); + } + getListView().setItemChecked(mCurrentPosition, true); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) + { + mCurrentPosition = position; + mListener.onRemediationInstructionSelected(mInstructions.get(position)); + getListView().setItemChecked(position, true); + } + + public void updateView(ArrayList instructions) + { + if (mAdapter == null) + { + mAdapter = new RemediationInstructionAdapter(getActivity()); + setListAdapter(mAdapter); + } + mInstructions = instructions; + mAdapter.setData(mInstructions); + } +} From 0ef98957a7c5efe8f033ab876ae1969e3f3938c8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 11:55:44 +0200 Subject: [PATCH 45/59] android: Add activity that displays a list of remediation instructions On large displays a two-pane layout is used that displays the list next to the actual instructions. --- src/frontends/android/AndroidManifest.xml | 4 + ...mediation_instruction_background_large.xml | 32 +++++++ .../layout-large/remediation_instructions.xml | 44 +++++++++ .../res/layout/remediation_instructions.xml | 21 +++++ .../android/res/values-de/strings.xml | 3 + .../android/res/values-pl/strings.xml | 3 + .../android/res/values-ru/strings.xml | 3 + .../android/res/values-ua/strings.xml | 3 + src/frontends/android/res/values/strings.xml | 3 + .../ui/RemediationInstructionsActivity.java | 94 +++++++++++++++++++ .../ui/RemediationInstructionsFragment.java | 3 +- 11 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/frontends/android/res/drawable/remediation_instruction_background_large.xml create mode 100644 src/frontends/android/res/layout-large/remediation_instructions.xml create mode 100644 src/frontends/android/res/layout/remediation_instructions.xml create mode 100644 src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsActivity.java diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml index 4d76ac09e..dd03cf2a1 100644 --- a/src/frontends/android/AndroidManifest.xml +++ b/src/frontends/android/AndroidManifest.xml @@ -54,6 +54,10 @@ android:name=".ui.LogActivity" android:label="@string/log_title" > + + diff --git a/src/frontends/android/res/drawable/remediation_instruction_background_large.xml b/src/frontends/android/res/drawable/remediation_instruction_background_large.xml new file mode 100644 index 000000000..470fecb12 --- /dev/null +++ b/src/frontends/android/res/drawable/remediation_instruction_background_large.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + diff --git a/src/frontends/android/res/layout-large/remediation_instructions.xml b/src/frontends/android/res/layout-large/remediation_instructions.xml new file mode 100644 index 000000000..5a28dd654 --- /dev/null +++ b/src/frontends/android/res/layout-large/remediation_instructions.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + diff --git a/src/frontends/android/res/layout/remediation_instructions.xml b/src/frontends/android/res/layout/remediation_instructions.xml new file mode 100644 index 000000000..84143b575 --- /dev/null +++ b/src/frontends/android/res/layout/remediation_instructions.xml @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/src/frontends/android/res/values-de/strings.xml b/src/frontends/android/res/values-de/strings.xml index 97da97ee4..6414f11c0 100644 --- a/src/frontends/android/res/values-de/strings.xml +++ b/src/frontends/android/res/values-de/strings.xml @@ -91,6 +91,9 @@ Eingeschränkt Fehlgeschlagen + + Korrekturanweisungen + Passwort eingeben um zu verbinden Verbinden diff --git a/src/frontends/android/res/values-pl/strings.xml b/src/frontends/android/res/values-pl/strings.xml index e3576d5de..722bc10d3 100644 --- a/src/frontends/android/res/values-pl/strings.xml +++ b/src/frontends/android/res/values-pl/strings.xml @@ -91,6 +91,9 @@ Restricted Failed + + Remediation instructions + Wprowadż hasło Połącz diff --git a/src/frontends/android/res/values-ru/strings.xml b/src/frontends/android/res/values-ru/strings.xml index f5f696ab4..c82350bdf 100644 --- a/src/frontends/android/res/values-ru/strings.xml +++ b/src/frontends/android/res/values-ru/strings.xml @@ -88,6 +88,9 @@ Restricted Failed + + Remediation instructions + Введите пароль для соединения Соединить diff --git a/src/frontends/android/res/values-ua/strings.xml b/src/frontends/android/res/values-ua/strings.xml index 39d67eaba..3d82008c7 100644 --- a/src/frontends/android/res/values-ua/strings.xml +++ b/src/frontends/android/res/values-ua/strings.xml @@ -89,6 +89,9 @@ Restricted Failed + + Remediation instructions + Введіть пароль для з\'єднання Підключити diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml index 78475df6e..b275cd5e7 100644 --- a/src/frontends/android/res/values/strings.xml +++ b/src/frontends/android/res/values/strings.xml @@ -91,6 +91,9 @@ Restricted Failed + + Remediation instructions + Enter password to connect Connect diff --git a/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsActivity.java b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsActivity.java new file mode 100644 index 000000000..66d0de261 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsActivity.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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.ui; + +import java.util.ArrayList; + +import org.strongswan.android.R; +import org.strongswan.android.logic.imc.RemediationInstruction; +import org.strongswan.android.ui.RemediationInstructionsFragment.OnRemediationInstructionSelectedListener; + +import android.app.Activity; +import android.os.Bundle; +import android.view.MenuItem; + +public class RemediationInstructionsActivity extends Activity implements OnRemediationInstructionSelectedListener +{ + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.remediation_instructions); + getActionBar().setDisplayHomeAsUpEnabled(true); + + if (savedInstanceState != null) + { /* only update if we're not restoring */ + return; + } + RemediationInstructionsFragment frag = (RemediationInstructionsFragment)getFragmentManager().findFragmentById(R.id.remediation_instructions_fragment); + if (frag != null) + { /* two-pane layout, update fragment */ + Bundle extras = getIntent().getExtras(); + ArrayList list = extras.getParcelableArrayList(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS); + frag.updateView(list); + } + else + { /* one-pane layout, create fragment */ + frag = new RemediationInstructionsFragment(); + frag.setArguments(getIntent().getExtras()); + getFragmentManager().beginTransaction().add(R.id.fragment_container, frag).commit(); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + switch (item.getItemId()) + { + case android.R.id.home: + /* one-pane layout, pop possible fragment from stack, finish otherwise */ + if (!getFragmentManager().popBackStackImmediate()) + { + finish(); + } + getActionBar().setTitle(getTitle()); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + public void onRemediationInstructionSelected(RemediationInstruction instruction) + { + RemediationInstructionFragment frag = (RemediationInstructionFragment)getFragmentManager().findFragmentById(R.id.remediation_instruction_fragment); + + if (frag != null) + { /* two-pane layout, update directly */ + frag.updateView(instruction); + } + else + { /* one-pane layout, replace fragment */ + frag = new RemediationInstructionFragment(); + Bundle args = new Bundle(); + args.putParcelable(RemediationInstructionFragment.ARG_REMEDIATION_INSTRUCTION, instruction); + frag.setArguments(args); + + getFragmentManager().beginTransaction().replace(R.id.fragment_container, frag).addToBackStack(null).commit(); + getActionBar().setTitle(instruction.getTitle()); + } + } +} diff --git a/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java index 9aa7ea140..86467dc35 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/RemediationInstructionsFragment.java @@ -17,6 +17,7 @@ package org.strongswan.android.ui; import java.util.ArrayList; +import org.strongswan.android.R; import org.strongswan.android.logic.imc.RemediationInstruction; import org.strongswan.android.ui.adapter.RemediationInstructionAdapter; @@ -79,7 +80,7 @@ public class RemediationInstructionsFragment extends ListFragment { super.onStart(); - boolean two_pane = false; + boolean two_pane = getFragmentManager().findFragmentById(R.id.remediation_instruction_fragment) != null; if (two_pane) { /* two-pane layout, make list items selectable */ getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); From 873f389b3760d835d763cc062bf147e4fc0e1265 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 11:57:39 +0200 Subject: [PATCH 46/59] android: Properly hide the IMC state fragment initially --- .../src/org/strongswan/android/ui/ImcStateFragment.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java index 473611394..18893a3b6 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java @@ -62,6 +62,8 @@ public class ImcStateFragment extends Fragment implements VpnStateListener Context context = getActivity().getApplicationContext(); context.bindService(new Intent(context, VpnStateService.class), mServiceConnection, Service.BIND_AUTO_CREATE); + /* hide it initially */ + getFragmentManager().beginTransaction().hide(this).commit(); } @Override @@ -95,7 +97,6 @@ public class ImcStateFragment extends Fragment implements VpnStateListener public void updateView() { FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.show(this); switch (mService.getImcState()) { @@ -106,10 +107,12 @@ public class ImcStateFragment extends Fragment implements VpnStateListener case ISOLATE: mStateView.setText(R.string.imc_state_isolate); mStateView.setTextColor(getResources().getColor(R.color.warning_text)); + ft.show(this); break; case BLOCK: mStateView.setText(R.string.imc_state_block); mStateView.setTextColor(getResources().getColor(R.color.error_text)); + ft.show(this); break; } ft.commit(); From 254d8679c656beda8442122ee31a588c5d6e2eb3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 12:04:59 +0200 Subject: [PATCH 47/59] android: Show remediation instructions instead of log on failure --- .../android/res/values-de/strings.xml | 1 + .../android/res/values-pl/strings.xml | 1 + .../android/res/values-ru/strings.xml | 1 + .../android/res/values-ua/strings.xml | 1 + src/frontends/android/res/values/strings.xml | 1 + .../android/ui/VpnStateFragment.java | 24 ++++++++++++++++--- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/frontends/android/res/values-de/strings.xml b/src/frontends/android/res/values-de/strings.xml index 6414f11c0..7682b3bc7 100644 --- a/src/frontends/android/res/values-de/strings.xml +++ b/src/frontends/android/res/values-de/strings.xml @@ -90,6 +90,7 @@ Assessment: Eingeschränkt Fehlgeschlagen + Korrekturanweisungen anzeigen Korrekturanweisungen diff --git a/src/frontends/android/res/values-pl/strings.xml b/src/frontends/android/res/values-pl/strings.xml index 722bc10d3..18f886f3f 100644 --- a/src/frontends/android/res/values-pl/strings.xml +++ b/src/frontends/android/res/values-pl/strings.xml @@ -90,6 +90,7 @@ Assessment: Restricted Failed + View remediation instructions Remediation instructions diff --git a/src/frontends/android/res/values-ru/strings.xml b/src/frontends/android/res/values-ru/strings.xml index c82350bdf..fdb72b549 100644 --- a/src/frontends/android/res/values-ru/strings.xml +++ b/src/frontends/android/res/values-ru/strings.xml @@ -87,6 +87,7 @@ Assessment: Restricted Failed + View remediation instructions Remediation instructions diff --git a/src/frontends/android/res/values-ua/strings.xml b/src/frontends/android/res/values-ua/strings.xml index 3d82008c7..7c9e124e3 100644 --- a/src/frontends/android/res/values-ua/strings.xml +++ b/src/frontends/android/res/values-ua/strings.xml @@ -88,6 +88,7 @@ Assessment: Restricted Failed + View remediation instructions Remediation instructions diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml index b275cd5e7..94d246416 100644 --- a/src/frontends/android/res/values/strings.xml +++ b/src/frontends/android/res/values/strings.xml @@ -90,6 +90,7 @@ Assessment: Restricted Failed + View remediation instructions Remediation instructions diff --git a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java index d745d8344..3219bba7a 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/VpnStateFragment.java @@ -17,6 +17,9 @@ package org.strongswan.android.ui; +import java.util.ArrayList; +import java.util.List; + import org.strongswan.android.R; import org.strongswan.android.data.VpnProfile; import org.strongswan.android.logic.VpnStateService; @@ -24,6 +27,7 @@ import org.strongswan.android.logic.VpnStateService.ErrorState; import org.strongswan.android.logic.VpnStateService.State; import org.strongswan.android.logic.VpnStateService.VpnStateListener; import org.strongswan.android.logic.imc.ImcState; +import org.strongswan.android.logic.imc.RemediationInstruction; import android.app.AlertDialog; import android.app.Fragment; @@ -362,17 +366,31 @@ public class VpnStateFragment extends Fragment implements VpnStateListener private void showErrorDialog(int textid) { + final List instructions = mService.getRemediationInstructions(); + final boolean show_instructions = mImcState == ImcState.BLOCK && !instructions.isEmpty(); + int text = show_instructions ? R.string.show_remediation_instructions : R.string.show_log; + mErrorDialog = new AlertDialog.Builder(getActivity()) .setMessage(getString(R.string.error_introduction) + " " + getString(textid)) .setCancelable(false) - .setNeutralButton(R.string.show_log, new DialogInterface.OnClickListener() { + .setNeutralButton(text, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { clearError(); dialog.dismiss(); - Intent logIntent = new Intent(getActivity(), LogActivity.class); - startActivity(logIntent); + Intent intent; + if (show_instructions) + { + intent = new Intent(getActivity(), RemediationInstructionsActivity.class); + intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS, + new ArrayList(instructions)); + } + else + { + intent = new Intent(getActivity(), LogActivity.class); + } + startActivity(intent); } }) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { From 6e872fea7a6afb18e0945cf4a2ddb70515838691 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 30 May 2013 12:16:30 +0200 Subject: [PATCH 48/59] android: IMC state fragment is a button that shows remediation instructions or log --- .../android/res/layout/imc_state_fragment.xml | 55 +++++++++++++------ .../android/ui/ImcStateFragment.java | 31 +++++++++++ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/frontends/android/res/layout/imc_state_fragment.xml b/src/frontends/android/res/layout/imc_state_fragment.xml index 86853889a..171c88d2d 100644 --- a/src/frontends/android/res/layout/imc_state_fragment.xml +++ b/src/frontends/android/res/layout/imc_state_fragment.xml @@ -21,29 +21,48 @@ android:orientation="vertical" > + android:background="?android:attr/selectableItemBackground" + android:orientation="vertical" > + + + + + + + + - - + android:layout_marginBottom="10dp" + android:layout_marginLeft="20dp" + android:layout_marginRight="20dp" + android:text="@string/show_remediation_instructions" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" /> diff --git a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java index 18893a3b6..2b6c1466e 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java @@ -15,9 +15,12 @@ package org.strongswan.android.ui; +import java.util.ArrayList; + import org.strongswan.android.R; import org.strongswan.android.logic.VpnStateService; import org.strongswan.android.logic.VpnStateService.VpnStateListener; +import org.strongswan.android.logic.imc.RemediationInstruction; import android.app.Fragment; import android.app.FragmentTransaction; @@ -30,12 +33,16 @@ import android.os.Bundle; import android.os.IBinder; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.TextView; public class ImcStateFragment extends Fragment implements VpnStateListener { private TextView mStateView; + private TextView mAction; + private LinearLayout mButton; private VpnStateService mService; private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override @@ -72,7 +79,28 @@ public class ImcStateFragment extends Fragment implements VpnStateListener { View view = inflater.inflate(R.layout.imc_state_fragment, null); + mButton = (LinearLayout)view.findViewById(R.id.imc_state_button); + mButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) + { + Intent intent; + if (mService != null && !mService.getRemediationInstructions().isEmpty()) + { + intent = new Intent(getActivity(), RemediationInstructionsActivity.class); + intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS, + new ArrayList(mService.getRemediationInstructions())); + } + else + { + intent = new Intent(getActivity(), LogActivity.class); + } + startActivity(intent); + } + }); + mStateView = (TextView)view.findViewById(R.id.imc_state); + mAction = (TextView)view.findViewById(R.id.action); return view; } @@ -116,5 +144,8 @@ public class ImcStateFragment extends Fragment implements VpnStateListener break; } ft.commit(); + + mAction.setText(mService.getRemediationInstructions().isEmpty() ? R.string.show_log + : R.string.show_remediation_instructions); } } From 2ecda3421a263cea708cc94c2a9e5902aa960974 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 19 Jun 2013 12:00:04 +0200 Subject: [PATCH 49/59] android: Use a different set of plugins if BYOD features are enabled --- src/frontends/android/jni/Android.mk | 5 ++-- .../android/jni/libandroidbridge/Android.mk | 6 +++-- .../jni/libandroidbridge/charonservice.c | 23 +++++++++++++++---- .../android/logic/CharonVpnService.java | 5 ++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index 0163e308d..de3403f3d 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -10,10 +10,11 @@ strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ eap-identity eap-mschapv2 eap-md5 eap-gtc ifneq ($(strongswan_USE_BYOD),) -strongswan_CHARON_PLUGINS += eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 +strongswan_BYOD_PLUGINS := eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 endif -strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) +strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) \ + $(strongswan_BYOD_PLUGINS) include $(LOCAL_PATH)/strongswan/Android.common.mk diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk index 29f95e58b..7dd8ad677 100644 --- a/src/frontends/android/jni/libandroidbridge/Android.mk +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -41,6 +41,10 @@ endif LOCAL_CFLAGS := $(strongswan_CFLAGS) \ -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"' +ifneq ($(strongswan_USE_BYOD),) +LOCAL_CFLAGS += -DPLUGINS_BYOD='"$(strongswan_BYOD_PLUGINS)"' +endif + LOCAL_MODULE := libandroidbridge LOCAL_MODULE_TAGS := optional @@ -58,5 +62,3 @@ LOCAL_SHARED_LIBRARIES += libimcv libtncif libtnccs libpts endif include $(BUILD_SHARED_LIBRARY) - - diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index 03599b717..41fc4d617 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -507,7 +507,8 @@ static void set_options(char *logfile) /** * Initialize the charonservice object */ -static void charonservice_init(JNIEnv *env, jobject service, jobject builder) +static void charonservice_init(JNIEnv *env, jobject service, jobject builder, + jboolean byod) { private_charonservice_t *this; static plugin_feature_t features[] = { @@ -543,6 +544,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder) countof(features), TRUE); #ifdef USE_BYOD + if (byod) { plugin_feature_t byod_features[] = { PLUGIN_CALLBACK(imc_android_register, this->vpn_service), @@ -588,11 +590,11 @@ static void segv_handler(int signal) * Initialize charon and the libraries via JNI */ JNI_METHOD(CharonVpnService, initializeCharon, void, - jobject builder, jstring jlogfile) + jobject builder, jstring jlogfile, jboolean byod) { struct sigaction action; struct utsname utsname; - char *logfile; + char *logfile, *plugins; /* logging for library during initialization, as we have no bus yet */ dbg = dbg_android; @@ -635,7 +637,7 @@ JNI_METHOD(CharonVpnService, initializeCharon, void, charon->load_loggers(charon, NULL, FALSE); - charonservice_init(env, this, builder); + charonservice_init(env, this, builder, byod); if (uname(&utsname) != 0) { @@ -644,7 +646,18 @@ JNI_METHOD(CharonVpnService, initializeCharon, void, DBG1(DBG_DMN, "Starting IKE charon daemon (strongSwan "VERSION", %s %s, %s)", utsname.sysname, utsname.release, utsname.machine); - if (!charon->initialize(charon, PLUGINS)) +#ifdef PLUGINS_BYOD + if (byod) + { + plugins = PLUGINS " " PLUGINS_BYOD; + } + else +#endif + { + plugins = PLUGINS; + } + + if (!charon->initialize(charon, plugins)) { libcharon_deinit(); charonservice_deinit(env); diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index bc9038660..9274717b9 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -214,7 +214,7 @@ public class CharonVpnService extends VpnService implements Runnable mIsDisconnecting = false; BuilderAdapter builder = new BuilderAdapter(mCurrentProfile.getName()); - initializeCharon(builder, mLogFile); + initializeCharon(builder, mLogFile, true); Log.i(TAG, "charon started"); initiate(mCurrentProfile.getVpnType().getIdentifier(), @@ -516,8 +516,9 @@ public class CharonVpnService extends VpnService implements Runnable * * @param builder BuilderAdapter for this connection * @param logfile absolute path to the logfile + * @param boyd enable BYOD features */ - public native void initializeCharon(BuilderAdapter builder, String logfile); + public native void initializeCharon(BuilderAdapter builder, String logfile, boolean byod); /** * Deinitialize charon, provided by libandroidbridge.so From 985dcab1c2a0192eada1105cdd1edc665b0fb099 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 19 Jun 2013 12:22:29 +0200 Subject: [PATCH 50/59] utils: Convert string helper macros to static inline functions --- src/libstrongswan/utils/utils.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index 06282de55..081852cd9 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -81,9 +81,12 @@ static inline bool streq(const char *x, const char *y) } /** - * Macro compares two strings for equality, length limited + * Helper function that compares two strings for equality, length limited */ -#define strneq(x,y,len) (strncmp(x, y, len) == 0) +static inline bool strneq(const char *x, const char *y, size_t len) +{ + return strncmp(x, y, len) == 0; +} /** * Helper function that compares two strings for equality ignoring case @@ -94,9 +97,12 @@ static inline bool strcaseeq(const char *x, const char *y) } /** - * Macro compares two strings for equality ignoring case, length limited + * Helper function that compares two strings for equality ignoring case, length limited */ -#define strncaseeq(x,y,len) (strncasecmp(x, y, len) == 0) +static inline bool strncaseeq(const char *x, const char *y, size_t len) +{ + return strncasecmp(x, y, len) == 0; +} /** * NULL-safe strdup variant @@ -107,9 +113,12 @@ static inline char *strdupnull(const char *s) } /** - * Macro compares two binary blobs for equality + * Helper function that compares two binary blobs for equality */ -#define memeq(x,y,len) (memcmp(x, y, len) == 0) +static inline bool memeq(const void *x, const void *y, size_t len) +{ + return memcmp(x, y, len) == 0; +} /** * Macro gives back larger of two values. From f460facdca9995e32d1c69f84945a306c6063a40 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 19 Jun 2013 12:24:40 +0200 Subject: [PATCH 51/59] utils: Add helper function to check a string for a given prefix --- src/libstrongswan/utils/utils.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index 081852cd9..0e103de9c 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -88,6 +88,14 @@ static inline bool strneq(const char *x, const char *y, size_t len) return strncmp(x, y, len) == 0; } +/** + * Helper function that checks if a string starts with a given prefix + */ +static inline bool strpfx(const char *x, const char *prefix) +{ + return strneq(x, prefix, strlen(prefix)); +} + /** * Helper function that compares two strings for equality ignoring case */ From d27f225d9a1064b5883002a293d6adddfbc99a07 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 19 Jun 2013 12:39:12 +0200 Subject: [PATCH 52/59] Use strpfx() helper where appropriate --- src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c | 14 +++++++------- .../plugins/load_tester/load_tester_config.c | 2 +- src/libcharon/plugins/stroke/stroke_config.c | 10 +++++----- src/libcharon/plugins/stroke/stroke_cred.c | 13 ++++++------- .../plugins/kernel_klips/kernel_klips_ipsec.c | 4 ++-- src/libhydra/plugins/resolve/resolve_handler.c | 2 +- src/libimcv/os_info/os_info.c | 4 ++-- src/libstrongswan/plugins/ldap/ldap_fetcher.c | 2 +- src/libstrongswan/plugins/mysql/mysql_database.c | 2 +- src/libstrongswan/plugins/sqlite/sqlite_database.c | 2 +- src/libstrongswan/plugins/sshkey/sshkey_builder.c | 2 +- 11 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c index 96f437583..49e3dd142 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c @@ -782,7 +782,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this, enumerator = enumerator_create_token(message, " ", " "); while (enumerator->enumerate(enumerator, &token)) { - if (strneq(token, "S=", 2)) + if (strpfx(token, "S=")) { chunk_t hex; token += 2; @@ -795,7 +795,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this, hex = chunk_create(token, AUTH_RESPONSE_LEN - 2); auth_string = chunk_from_hex(hex, NULL); } - else if (strneq(token, "M=", 2)) + else if (strpfx(token, "M=")) { token += 2; msg = strdup(token); @@ -864,16 +864,16 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, enumerator = enumerator_create_token(message, " ", " "); while (enumerator->enumerate(enumerator, &token)) { - if (strneq(token, "E=", 2)) + if (strpfx(token, "E=")) { token += 2; error = atoi(token); } - else if (strneq(token, "R=", 2)) + else if (strpfx(token, "R=")) { /* ignore retriable */ } - else if (strneq(token, "C=", 2)) + else if (strpfx(token, "C=")) { chunk_t hex; token += 2; @@ -886,11 +886,11 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, hex = chunk_create(token, 2 * CHALLENGE_LEN); challenge = chunk_from_hex(hex, NULL); } - else if (strneq(token, "V=", 2)) + else if (strpfx(token, "V=")) { /* ignore version */ } - else if (strneq(token, "M=", 2)) + else if (strpfx(token, "M=")) { token += 2; msg = strdup(token); diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index a64affde8..ebadf44ca 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -355,7 +355,7 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str, } } } - else if (strneq(str, "eap", strlen("eap"))) + else if (strpfx(str, "eap")) { /* EAP authentication, use a NAI */ class = AUTH_CLASS_EAP; if (*(str + strlen("eap")) == '-') diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index da8d35c40..079e65f11 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -559,9 +559,9 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } /* authentication metod (class, actually) */ - if (strneq(auth, "pubkey", strlen("pubkey")) || - strneq(auth, "rsa", strlen("rsa")) || - strneq(auth, "ecdsa", strlen("ecdsa"))) + if (strpfx(auth, "pubkey") || + strpfx(auth, "rsa") || + strpfx(auth, "ecdsa")) { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); build_crl_policy(cfg, local, msg->add_conn.crl_policy); @@ -572,7 +572,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); } - else if (strneq(auth, "xauth", 5)) + else if (strpfx(auth, "xauth")) { char *pos; @@ -588,7 +588,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, identification_create_from_string(msg->add_conn.xauth_identity)); } } - else if (strneq(auth, "eap", 3)) + else if (strpfx(auth, "eap")) { eap_vendor_type_t *type; diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 6b37ac787..474417886 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -175,7 +175,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, certificate_t *cert = NULL; char path[PATH_MAX]; - if (strneq(filename, "%smartcard", strlen("%smartcard"))) + if (strpfx(filename, "%smartcard")) { smartcard_format_t format; char module[SC_PART_LEN], keyid[SC_PART_LEN]; @@ -239,7 +239,7 @@ METHOD(stroke_cred_t, load_peer, certificate_t*, certificate_t *cert = NULL; char path[PATH_MAX]; - if (strneq(filename, "%smartcard", strlen("%smartcard"))) + if (strpfx(filename, "%smartcard")) { smartcard_format_t format; char module[SC_PART_LEN], keyid[SC_PART_LEN]; @@ -787,7 +787,7 @@ static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, } chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); - if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7)) + if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) { free(secret.ptr); if (!prompt) @@ -880,7 +880,7 @@ static bool load_from_file(chunk_t line, int line_nr, FILE *prompt, return FALSE; } } - if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7)) + if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) { callback_cred_t *cb; passphrase_cb_data_t pp_data = { @@ -1142,8 +1142,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, { continue; } - if (line.len > strlen("include ") && - strneq(line.ptr, "include ", strlen("include "))) + if (line.len > strlen("include ") && strpfx(line.ptr, "include ")) { char **expanded, *dir, pattern[PATH_MAX]; u_char *pos; @@ -1211,7 +1210,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, continue; } - if (line.len > 2 && strneq(": ", line.ptr, 2)) + if (line.len > 2 && strpfx(line.ptr, ": ")) { /* no ids, skip the ':' */ ids = chunk_empty; diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c index 5ca5879ff..38c92ce71 100644 --- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c +++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c @@ -78,7 +78,7 @@ /** this is the default number of ipsec devices */ #define DEFAULT_IPSEC_DEV_COUNT 4 /** TRUE if the given name matches an ipsec device */ -#define IS_IPSEC_DEV(name) (strneq((name), IPSEC_DEV_PREFIX, sizeof(IPSEC_DEV_PREFIX) - 1)) +#define IS_IPSEC_DEV(name) (strpfx((name), IPSEC_DEV_PREFIX)) /** the following stuff is from ipsec_tunnel.h */ struct ipsectunnelconf @@ -2332,7 +2332,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t, while (fgets(line, sizeof(line), file)) { - if (strneq(line, said, strlen(said))) + if (strpfx(line, said)) { /* fine we found the correct line, now find the idle time */ u_int32_t idle_time; diff --git a/src/libhydra/plugins/resolve/resolve_handler.c b/src/libhydra/plugins/resolve/resolve_handler.c index 6b8d6be7f..6c57fa0bf 100644 --- a/src/libhydra/plugins/resolve/resolve_handler.c +++ b/src/libhydra/plugins/resolve/resolve_handler.c @@ -126,7 +126,7 @@ static void remove_nameserver(private_resolve_handler_t *this, /* copy all, but matching line */ while (fgets(line, sizeof(line), in)) { - if (strneq(line, matcher, strlen(matcher))) + if (strpfx(line, matcher)) { DBG1(DBG_IKE, "removing DNS server %H from %s", addr, this->file); diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 2c49cb01d..17000cd27 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -182,8 +182,8 @@ METHOD(os_info_t, get_setting, chunk_t, size_t i = 0; chunk_t value; - if (!strneq(name, "/etc/", 5) && !strneq(name, "/proc/", 6) && - !strneq(name, "/sys/", 5) && !strneq(name, "/var/", 5)) + if (!strpfx(name, "/etc/") && !strpfx(name, "/proc/") && + !strpfx(name, "/sys/") && !strpfx(name, "/var/")) { /** * In order to guarantee privacy, only settings from the diff --git a/src/libstrongswan/plugins/ldap/ldap_fetcher.c b/src/libstrongswan/plugins/ldap/ldap_fetcher.c index 40b6d1f63..fe4c55545 100644 --- a/src/libstrongswan/plugins/ldap/ldap_fetcher.c +++ b/src/libstrongswan/plugins/ldap/ldap_fetcher.c @@ -112,7 +112,7 @@ METHOD(fetcher_t, fetch, status_t, status_t status = FAILED; chunk_t *result = userdata; - if (!strneq(url, "ldap", 4)) + if (!strpfx(url, "ldap")) { return NOT_SUPPORTED; } diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c index 789f12f20..8bd64692c 100644 --- a/src/libstrongswan/plugins/mysql/mysql_database.c +++ b/src/libstrongswan/plugins/mysql/mysql_database.c @@ -666,7 +666,7 @@ mysql_database_t *mysql_database_create(char *uri) conn_t *conn; private_mysql_database_t *this; - if (!strneq(uri, "mysql://", 8)) + if (!strpfx(uri, "mysql://")) { return NULL; } diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c index 1fb306579..41d45dee7 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_database.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c @@ -319,7 +319,7 @@ sqlite_database_t *sqlite_database_create(char *uri) /** * parse sqlite:///path/to/file.db uri */ - if (!strneq(uri, "sqlite://", 9)) + if (!strpfx(uri, "sqlite://")) { return NULL; } diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c index 986e860d9..d6a7c645a 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -85,7 +85,7 @@ static sshkey_public_key_t *parse_public_key(chunk_t blob) BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } else if (format.len > strlen(ECDSA_PREFIX) && - strneq(format.ptr, ECDSA_PREFIX, strlen(ECDSA_PREFIX))) + strpfx(format.ptr, ECDSA_PREFIX)) { chunk_t ec_blob, identifier, q, oid, encoded; sshkey_public_key_t *key; From 8a5bffb0feea8552036367bf0480172163e5b091 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 19 Jun 2013 12:41:09 +0200 Subject: [PATCH 53/59] android: Add new VpnType to enable BYOD features --- .../backend/android_service.c | 12 ++++++-- .../android/res/values-de/arrays.xml | 1 + .../android/res/values-pl/arrays.xml | 1 + .../android/res/values-ru/arrays.xml | 1 + .../android/res/values-ua/arrays.xml | 1 + src/frontends/android/res/values/arrays.xml | 1 + .../org/strongswan/android/data/VpnType.java | 28 ++++++++++++++++++- .../android/logic/CharonVpnService.java | 2 +- 8 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c index b22186580..c35d348ba 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c @@ -464,13 +464,18 @@ METHOD(listener_t, ike_reestablish, bool, } static void add_auth_cfg_eap(private_android_service_t *this, - peer_cfg_t *peer_cfg) + peer_cfg_t *peer_cfg, bool byod) { identification_t *user; auth_cfg_t *auth; auth = auth_cfg_create(); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); + if (byod) + { /* use EAP-TTLS if BYOD is enabled */ + auth->add(auth, AUTH_RULE_EAP_TYPE, EAP_TTLS); + } + user = identification_create_from_string(this->username); auth->add(auth, AUTH_RULE_IDENTITY, user); @@ -549,9 +554,10 @@ static job_requeue_t initiate(private_android_service_t *this) } } if (streq("ikev2-eap", this->type) || - streq("ikev2-cert-eap", this->type)) + streq("ikev2-cert-eap", this->type) || + streq("ikev2-byod-eap", this->type)) { - add_auth_cfg_eap(this, peer_cfg); + add_auth_cfg_eap(this, peer_cfg, strpfx(this->type, "ikev2-byod")); } /* remote auth config */ diff --git a/src/frontends/android/res/values-de/arrays.xml b/src/frontends/android/res/values-de/arrays.xml index d0117b202..30578c0a8 100644 --- a/src/frontends/android/res/values-de/arrays.xml +++ b/src/frontends/android/res/values-de/arrays.xml @@ -19,5 +19,6 @@ IKEv2 EAP (Benutzername/Passwort) IKEv2 Zertifikat IKEv2 Zertifikat + EAP (Benutzername/Passwort) + IKEv2 EAP-TNC (Benutzername/Passwort) \ No newline at end of file diff --git a/src/frontends/android/res/values-pl/arrays.xml b/src/frontends/android/res/values-pl/arrays.xml index 1b74b2e57..1a04cbf2e 100644 --- a/src/frontends/android/res/values-pl/arrays.xml +++ b/src/frontends/android/res/values-pl/arrays.xml @@ -19,5 +19,6 @@ IKEv2 EAP (użytkownik/hasło) IKEv2 certyfikat IKEv2 certyfikat + EAP (użytkownik/hasło) + IKEv2 EAP-TNC (użytkownik/hasło) \ No newline at end of file diff --git a/src/frontends/android/res/values-ru/arrays.xml b/src/frontends/android/res/values-ru/arrays.xml index 55144f294..713f8e404 100644 --- a/src/frontends/android/res/values-ru/arrays.xml +++ b/src/frontends/android/res/values-ru/arrays.xml @@ -18,5 +18,6 @@ IKEv2 EAP (Логин/Пароль) IKEv2 Сертификат IKEv2 Сертификат + EAP (Логин/Пароль) + IKEv2 EAP-TNC (Логин/Пароль) diff --git a/src/frontends/android/res/values-ua/arrays.xml b/src/frontends/android/res/values-ua/arrays.xml index 490fea5e1..4bd92fe0a 100644 --- a/src/frontends/android/res/values-ua/arrays.xml +++ b/src/frontends/android/res/values-ua/arrays.xml @@ -18,5 +18,6 @@ IKEv2 EAP (Логін/Пароль) IKEv2 Сертифікати IKEv2 Сертифікати + EAP (Логін/Пароль) + IKEv2 EAP-TNC (Логін/Пароль) diff --git a/src/frontends/android/res/values/arrays.xml b/src/frontends/android/res/values/arrays.xml index 1ac4cc21d..29f999d9a 100644 --- a/src/frontends/android/res/values/arrays.xml +++ b/src/frontends/android/res/values/arrays.xml @@ -19,5 +19,6 @@ IKEv2 EAP (Username/Password) IKEv2 Certificate IKEv2 Certificate + EAP (Username/Password) + IKEv2 EAP-TNC (Username/Password) \ No newline at end of file diff --git a/src/frontends/android/src/org/strongswan/android/data/VpnType.java b/src/frontends/android/src/org/strongswan/android/data/VpnType.java index 47cc1cb02..f62c96d76 100644 --- a/src/frontends/android/src/org/strongswan/android/data/VpnType.java +++ b/src/frontends/android/src/org/strongswan/android/data/VpnType.java @@ -20,11 +20,13 @@ public enum VpnType /* the order here must match the items in R.array.vpn_types */ IKEV2_EAP("ikev2-eap", true, false), IKEV2_CERT("ikev2-cert", false, true), - IKEV2_CERT_EAP("ikev2-cert-eap", true, true); + IKEV2_CERT_EAP("ikev2-cert-eap", true, true), + IKEV2_BYOD_EAP("ikev2-byod-eap", true, false, true); private String mIdentifier; private boolean mCertificate; private boolean mUsernamePassword; + private boolean mBYOD; /** * Enum which provides additional information about the supported VPN types. @@ -34,10 +36,24 @@ public enum VpnType * @param certificate true if a client certificate is required */ VpnType(String id, boolean userpass, boolean certificate) + { + this(id, userpass, certificate, false); + } + + /** + * Enum which provides additional information about the supported VPN types. + * + * @param id identifier used to store and transmit this specific type + * @param userpass true if username and password are required + * @param certificate true if a client certificate is required + * @param byod true to enable BYOD features + */ + VpnType(String id, boolean userpass, boolean certificate, boolean byod) { mIdentifier = id; mUsernamePassword = userpass; mCertificate = certificate; + mBYOD = byod; } /** @@ -69,6 +85,16 @@ public enum VpnType return mCertificate; } + /** + * Whether BYOD features should be enabled. + * + * @return true if BYOD features are to be enabled + */ + public boolean getEnableBYOD() + { + return mBYOD; + } + /** * Get the enum entry with the given identifier. * diff --git a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java index 9274717b9..a7b8a8cef 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/logic/CharonVpnService.java @@ -214,7 +214,7 @@ public class CharonVpnService extends VpnService implements Runnable mIsDisconnecting = false; BuilderAdapter builder = new BuilderAdapter(mCurrentProfile.getName()); - initializeCharon(builder, mLogFile, true); + initializeCharon(builder, mLogFile, mCurrentProfile.getVpnType().getEnableBYOD()); Log.i(TAG, "charon started"); initiate(mCurrentProfile.getVpnType().getIdentifier(), From 671614d2291e463d9a2f61e9bcf9a6b59140dc25 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 24 Jun 2013 15:58:34 +0200 Subject: [PATCH 54/59] android: Add device ID in BeginHandshake --- src/frontends/android/jni/libandroidbridge/byod/imc_android.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index c60f7ca59..74cb520e3 100644 --- a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c +++ b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c @@ -488,6 +488,8 @@ static TNC_Result tnc_imc_beginhandshake(TNC_IMCID imc_id, out_msg, NULL); add_measurement((pen_type_t){ PEN_IETF, IETF_ATTR_STRING_VERSION }, out_msg, NULL); + add_measurement((pen_type_t){ PEN_ITA, ITA_ATTR_DEVICE_ID }, + out_msg, NULL); /* send PA-TNC message with the excl flag not set */ result = out_msg->send(out_msg, FALSE); out_msg->destroy(out_msg); From 9390499584dfd94339d03c22067a688dfa2df2e9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 3 Jul 2013 10:58:25 +0200 Subject: [PATCH 55/59] android: Reuse certificate selector as generic two line button --- src/frontends/android/res/layout/profile_detail_view.xml | 4 ++-- .../layout/{certificate_selector.xml => two_line_button.xml} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/frontends/android/res/layout/{certificate_selector.xml => two_line_button.xml} (100%) diff --git a/src/frontends/android/res/layout/profile_detail_view.xml b/src/frontends/android/res/layout/profile_detail_view.xml index 39c94348b..801ced69b 100644 --- a/src/frontends/android/res/layout/profile_detail_view.xml +++ b/src/frontends/android/res/layout/profile_detail_view.xml @@ -114,7 +114,7 @@ + layout="@layout/two_line_button" /> @@ -132,7 +132,7 @@ + layout="@layout/two_line_button" /> diff --git a/src/frontends/android/res/layout/certificate_selector.xml b/src/frontends/android/res/layout/two_line_button.xml similarity index 100% rename from src/frontends/android/res/layout/certificate_selector.xml rename to src/frontends/android/res/layout/two_line_button.xml From e1a98e795689d23f3bb75f4ffc6fc76d00e9c147 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 3 Jul 2013 16:27:36 +0200 Subject: [PATCH 56/59] android: Add information about transmitted data if EAP-TNC is selected --- .../res/layout/profile_detail_view.xml | 5 +++ .../android/res/values-de/strings.xml | 3 ++ .../android/res/values-pl/strings.xml | 3 ++ .../android/res/values-ru/strings.xml | 3 ++ .../android/res/values-ua/strings.xml | 3 ++ src/frontends/android/res/values/strings.xml | 3 ++ .../android/ui/VpnProfileDetailActivity.java | 37 +++++++++++++++++++ 7 files changed, 57 insertions(+) diff --git a/src/frontends/android/res/layout/profile_detail_view.xml b/src/frontends/android/res/layout/profile_detail_view.xml index 801ced69b..91cd345ff 100644 --- a/src/frontends/android/res/layout/profile_detail_view.xml +++ b/src/frontends/android/res/layout/profile_detail_view.xml @@ -65,6 +65,11 @@ android:spinnerMode="dropdown" android:entries="@array/vpn_types" /> + + Bitte geben Sie hier Ihren Benutzernamen ein Kein CA-Zertifikat ausgewählt Bitte wählen Sie eines aus oder aktivieren Sie Automatisch wählen + EAP-TNC kann Ihre Privatsphäre beeinträchtigen + Gerätedaten werden an den Gateway-Betreiber gesendet + <p>Trusted Network Connect (TNC) erlaubt Gateway-Betreibern den Gesundheitszustand von Endgeräten zu prüfen.</p><p>Dazu kann der Betreiber Daten verlangen, wie etwa eine eindeutige Identifikationsnummer, eine Liste der installierten Pakete, Systemeinstellungen oder kryptografische Prüfsummen von Dateien.</p><b>Solche Daten werden nur übermittelt nachdem die Identität des Gateways geprüft wurde.</b> CA-Zertifikate diff --git a/src/frontends/android/res/values-pl/strings.xml b/src/frontends/android/res/values-pl/strings.xml index 18f886f3f..7aa9c51a7 100644 --- a/src/frontends/android/res/values-pl/strings.xml +++ b/src/frontends/android/res/values-pl/strings.xml @@ -69,6 +69,9 @@ Wprowadź swoją nazwę użytkownika Nie wybrano żadnego certyfikatu CA Wybierz lub uaktywnij jeden Wybierz automatycznie + EAP-TNC may affect your privacy + Device data is sent to the gateway operator + <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b> Certyfikaty CA diff --git a/src/frontends/android/res/values-ru/strings.xml b/src/frontends/android/res/values-ru/strings.xml index fdb72b549..3838485af 100644 --- a/src/frontends/android/res/values-ru/strings.xml +++ b/src/frontends/android/res/values-ru/strings.xml @@ -66,6 +66,9 @@ Пожалуйста введите имя пользователя Не выбран сертификат CA Пожалуйста выберите один Выбрать автоматически + EAP-TNC may affect your privacy + Device data is sent to the gateway operator + <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b> Сертификаты CA diff --git a/src/frontends/android/res/values-ua/strings.xml b/src/frontends/android/res/values-ua/strings.xml index 7c9e124e3..df016ff8f 100644 --- a/src/frontends/android/res/values-ua/strings.xml +++ b/src/frontends/android/res/values-ua/strings.xml @@ -67,6 +67,9 @@ Введіть ім\'я користувача тут Не вибрано сертифікат CA Будь ласка виберіть один Вибрати автоматично + EAP-TNC may affect your privacy + Device data is sent to the gateway operator + <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b> Сертифікати CA diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml index 94d246416..180948969 100644 --- a/src/frontends/android/res/values/strings.xml +++ b/src/frontends/android/res/values/strings.xml @@ -69,6 +69,9 @@ Please enter your username here No CA certificate selected Please select one or activate Select automatically + EAP-TNC may affect your privacy + Device data is sent to the gateway operator + <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b> CA certificates diff --git a/src/frontends/android/src/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/src/org/strongswan/android/ui/VpnProfileDetailActivity.java index 91e521cf4..baad9611d 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/src/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -28,6 +28,8 @@ import org.strongswan.android.logic.TrustedCertificateManager; import android.app.Activity; import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -36,6 +38,7 @@ import android.os.Bundle; import android.security.KeyChain; import android.security.KeyChainAliasCallback; import android.security.KeyChainException; +import android.text.Html; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; @@ -73,6 +76,7 @@ public class VpnProfileDetailActivity extends Activity private TwoLineListItem mSelectUserCert; private CheckBox mCheckAuto; private TwoLineListItem mSelectCert; + private TwoLineListItem mTncNotice; @Override public void onCreate(Bundle savedInstanceState) @@ -90,6 +94,7 @@ public class VpnProfileDetailActivity extends Activity mName = (EditText)findViewById(R.id.name); mGateway = (EditText)findViewById(R.id.gateway); mSelectVpnType = (Spinner)findViewById(R.id.vpn_type); + mTncNotice = (TwoLineListItem)findViewById(R.id.tnc_notice); mUsernamePassword = (ViewGroup)findViewById(R.id.username_password_group); mUsername = (EditText)findViewById(R.id.username); @@ -117,6 +122,16 @@ public class VpnProfileDetailActivity extends Activity } }); + mTncNotice.getText1().setText(R.string.tnc_notice_title); + mTncNotice.getText2().setText(R.string.tnc_notice_subtitle); + mTncNotice.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) + { + new TncNoticeDialog().show(VpnProfileDetailActivity.this.getFragmentManager(), "TncNotice"); + } + }); + mSelectUserCert.setOnClickListener(new SelectUserCertOnClickListener()); mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() { @@ -225,6 +240,7 @@ public class VpnProfileDetailActivity extends Activity { mUsernamePassword.setVisibility(mVpnType.getRequiresUsernamePassword() ? View.VISIBLE : View.GONE); mUserCertificate.setVisibility(mVpnType.getRequiresCertificate() ? View.VISIBLE : View.GONE); + mTncNotice.setVisibility(mVpnType.getEnableBYOD() ? View.VISIBLE : View.GONE); if (mVpnType.getRequiresCertificate()) { @@ -536,4 +552,25 @@ public class VpnProfileDetailActivity extends Activity updateCredentialView(); } } + + /** + * Dialog with notification message if EAP-TNC is used. + */ + public static class TncNoticeDialog extends DialogFragment + { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) + { + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.tnc_notice_title) + .setMessage(Html.fromHtml(getString(R.string.tnc_notice_details))) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) + { + dialog.dismiss(); + } + }).create(); + } + } } From a9f94d7efbccb3c0cdd5587127eace05c3085cd6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 3 Jul 2013 16:30:44 +0200 Subject: [PATCH 57/59] android: Use explicit locale when converting settings names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently, these functions use the user's default locale which might not yield the expected result (e.g. lowercase I is not i in the Turkish locale but ı instead). --- .../android/logic/imc/collectors/SettingsCollector.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java index 3f6bcff6f..658c2daea 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/SettingsCollector.java @@ -17,6 +17,8 @@ package org.strongswan.android.logic.imc.collectors; +import java.util.Locale; + import org.strongswan.android.logic.imc.attributes.Attribute; import org.strongswan.android.logic.imc.attributes.SettingsAttribute; @@ -44,10 +46,10 @@ public class SettingsCollector implements Collector SettingsAttribute attribute = new SettingsAttribute(); for (String name : mSettings) { - String value = android.provider.Settings.Secure.getString(mContentResolver, name.toLowerCase()); + String value = android.provider.Settings.Secure.getString(mContentResolver, name.toLowerCase(Locale.US)); if (value == null) { - value = android.provider.Settings.System.getString(mContentResolver, name.toLowerCase()); + value = android.provider.Settings.System.getString(mContentResolver, name.toLowerCase(Locale.US)); } if (value != null) { From 97f1dfb3ec79604880ef1aefe66644bbdbf84dc3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 5 Jul 2013 17:20:21 +0200 Subject: [PATCH 58/59] android: Allow IMC state to be dismissed with a swipe gesture --- .../android/ui/ImcStateFragment.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java index 2b6c1466e..ff58849fc 100644 --- a/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java +++ b/src/frontends/android/src/org/strongswan/android/ui/ImcStateFragment.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import org.strongswan.android.R; import org.strongswan.android.logic.VpnStateService; import org.strongswan.android.logic.VpnStateService.VpnStateListener; +import org.strongswan.android.logic.imc.ImcState; import org.strongswan.android.logic.imc.RemediationInstruction; import android.app.Fragment; @@ -31,9 +32,13 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; +import android.view.GestureDetector; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnTouchListener; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; @@ -98,6 +103,31 @@ public class ImcStateFragment extends Fragment implements VpnStateListener startActivity(intent); } }); + final GestureDetector gestures = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener() { + /* a better value would be getScaledTouchExplorationTapSlop() but that is hidden */ + private final int mMinDistance = ViewConfiguration.get(getActivity()).getScaledTouchSlop() * 4; + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) + { + if (Math.abs(e1.getX() - e2.getX()) >= mMinDistance) + { /* only if the user swiped a minimum horizontal distance */ + if (mService != null) + { + mService.setImcState(ImcState.UNKNOWN); + } + return true; + } + return false; + } + }); + mButton.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) + { + return gestures.onTouchEvent(event); + } + }); mStateView = (TextView)view.findViewById(R.id.imc_state); mAction = (TextView)view.findViewById(R.id.action); From 7ccf02ee933a0fb4faef26f21447588b7241e425 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 8 Jul 2013 15:38:47 +0200 Subject: [PATCH 59/59] android: Properly handle dotted-quad notation of IPv6 addresses For nestat output like ::ffff:127.0.0.1:9876 we shall not treat 127 as port but 9876 instead. --- .../android/logic/imc/collectors/PortFilterCollector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java index b6e740cad..ed86686d8 100644 --- a/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java +++ b/src/frontends/android/src/org/strongswan/android/logic/imc/collectors/PortFilterCollector.java @@ -30,7 +30,7 @@ public class PortFilterCollector implements Collector { private static Pattern LISTEN = Pattern.compile("\\bLISTEN\\b"); private static Pattern PROTOCOL = Pattern.compile("\\b(tcp|udp)6?\\b"); - private static Pattern PORT = Pattern.compile("[:]{1,3}(\\d{1,5})\\b"); + private static Pattern PORT = Pattern.compile("[:]{1,3}(\\d{1,5})\\b(?!\\.)"); @Override public Attribute getMeasurement()