#include <ietf/ietf_attr_installed_packages.h>
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <ietf/ietf_attr_product_info.h>
+#include <ietf/ietf_attr_remediation_instr.h>
#include <ietf/ietf_attr_string_version.h>
#include <ita/ita_attr.h>
#include <ita/ita_attr_get_settings.h>
}
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);
+ }
+ }
}
/**
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
*/
.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,
*/
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.
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;
}
}
+ /**
+ * 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.
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;
private State mState = State.DISABLED;
private ErrorState mError = ErrorState.NO_ERROR;
private ImcState mImcState = ImcState.UNKNOWN;
+ private final LinkedList<RemediationInstruction> mRemediationInstructions = new LinkedList<RemediationInstruction>();
public enum State
{
return mImcState;
}
+ /**
+ * Get the remediation instructions, if any.
+ *
+ * @return read-only list of instructions
+ */
+ public List<RemediationInstruction> 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
/**
* 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
@Override
public Boolean call() throws Exception
{
+ if (state == ImcState.UNKNOWN)
+ {
+ VpnStateService.this.mRemediationInstructions.clear();
+ }
if (VpnStateService.this.mImcState != state)
{
VpnStateService.this.mImcState = state;
}
});
}
+
+ /**
+ * 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);
+ }
+ });
+ }
}