android: Handle and store IETF remediation instructions

This commit is contained in:
Tobias Brunner
2013-07-08 18:49:28 +02:00
parent 0484989dbd
commit a05acd7629
5 changed files with 121 additions and 0 deletions
@@ -31,6 +31,7 @@
#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>
@@ -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);
}
}
}
/**
@@ -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,
@@ -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.
@@ -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.
@@ -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<RemediationInstruction> mRemediationInstructions = new LinkedList<RemediationInstruction>();
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<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
@@ -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);
}
});
}
}