From: Tobias Brunner Date: Thu, 11 Oct 2012 13:26:19 +0000 (+0200) Subject: android: Added a sample IMC that sends some dummy OS data X-Git-Tag: 5.1.0dr2~2^2~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=96658d7264f9c71cf71a980bb7483f94bb0027ad;p=thirdparty%2Fstrongswan.git android: Added a sample IMC that sends some dummy OS data --- diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk index fbb86126e5..ca154722bc 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 0000000000..f83b6fdeb9 --- /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 0000000000..3bfc6de406 --- /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 0000000000..47eda33cde --- /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 0000000000..3acdea1439 --- /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 25fbf89c65..b7bfdccc65 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 7391ea61d0..f142f78e5d 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 *