From: Tobias Brunner Date: Fri, 17 May 2013 11:15:14 +0000 (+0200) Subject: android: Handle and store IETF remediation instructions X-Git-Tag: 5.1.0dr2~2^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a05acd76294e4c4e4da7633632732858ae762d2a;p=thirdparty%2Fstrongswan.git android: Handle and store IETF remediation instructions --- diff --git a/src/frontends/android/jni/libandroidbridge/byod/imc_android.c b/src/frontends/android/jni/libandroidbridge/byod/imc_android.c index 7067e1f898..c60f7ca595 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 115b532324..03599b717d 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 90f5bc9522..0c71d876d9 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 9f920a9edd..bc9038660a 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 62ca31f131..2c530bad47 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); + } + }); + } }