package de.ecspride.javaclasses;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
public class InstrumentationHelper {
public static EventPEP eventPep = null;
public static RemoteServiceConnection connection = null;
private final static String keyBaseName = "taintinfo";
private static String pdpPackage = "de.tum.in.i22.uc.pdp.android";
private static String pdpClassFull = "de.tum.in.i22.uc.pdp.android.pdpService";
private static String applicationPackageName = "";
public static Map<Integer, Set<String>> sourceSinkConnection = new HashMap<Integer, Set<String>>();
public static void initializeEventPEP(Context context){
Log.i("PEP", "in InstrumentationHelper.initializeEventPEP");
if(eventPep == null){
eventPep = new EventPEP();
eventPep.init();
}
if(connection == null)
connection = new RemoteServiceConnection(eventPep);
setupBindService(context);
}
private static void setupBindService(Context context){
Log.i("PEP", "in InstrumentationHelper.setupBindService");
Intent intent=new Intent();
intent.setClassName(pdpPackage, pdpClassFull);
intent.setAction("de.tum.in.i22.uc.pdp.android.pdpService");
context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
public static boolean isStmtExecutionAllowed(String eventName, int dataFlowAvailable, Object[] parameter){
Log.i("PEP", "in InstrumentationHelper.isStmtExecutionAllowed");
if (eventName == null) {
Log.e("DroidForce", "eventName is null!");
throw new RuntimeException("error: eventName is null");
}
if (parameter == null) {
Log.e("DroidForce", "parameter is null!");
throw new RuntimeException("error: parameter is null");
}
Bundle event = new Bundle();
event.putString("eventname", eventName);
if(parameter.length%2 != 0)
throw new RuntimeException("Ooops problem in isStmtExecutionAllowed");
for(int i = 0; i < parameter.length; i++){
String paramName = parameter[i].toString();
String paramValue = parameter[++i].toString();
event.putString(paramName, paramValue);
}
// for (Object paramName: categories.keySet()) {
// String category = categories.get(paramName).toString();
// if (category == "") {
// // do nothing since there is no dataflow information
// } else {
// event.putString(paramName +"|DATA_" + category, "true");
// }
// }
if(dataFlowAvailable != -1){
Log.i("PEP", "dataFlowAvailable="+dataFlowAvailable);
Log.i("PEP", sourceSinkConnection.toString());
// if(!sourceSinkConnection.containsKey(dataFlowAvailable))
// throw new RuntimeException("Oops, there should be a correct ID");
Log.i("PEP", "sourceSinkConnection:");
for (Integer k: sourceSinkConnection.keySet()) {
Log.i("PEP", " key: "+ k);
}
if(sourceSinkConnection.containsKey(dataFlowAvailable)) {
for(String cat : sourceSinkConnection.get(dataFlowAvailable))
event.putString("DATA_" + cat, "true");
}
}
// add information about
event.putString("APP_PACKAGE_NAME", applicationPackageName);
Log.i("PEP", "event: "+ event.toString());
return InstrumentationHelper.eventPep.isStmtExecutionAllowed(event);
}
public static void killBinder(Context context){
if(eventPep.isBound){
context.unbindService(connection);
eventPep.isBound = false;
}
}
public static void addTaintInformationToIntent(Intent i, HashSet<String> taintCategories){
boolean intentHasNoExtras= i.getExtras() == null ? true : false;
Log.i("PEP", "in addTaintInformationToIntent(Intent i, HashSet<String> taintCategories)");
//A bit of limitation here, because we do only care about the extras
if(!intentHasNoExtras){
Bundle extras = i.getExtras();
String taintKeyName = generateKeyNameForTaintInfo(extras.keySet());
String taintInformation = null;
if(taintCategories.size() > 1)
taintInformation = taintCategories.toString().substring(1,taintCategories.toString().length()-1);
else
taintInformation = taintCategories.iterator().next();
i.putExtra(taintKeyName, taintInformation);
}
}
private static String generateKeyNameForTaintInfo(Set<String> allIntentKeys){
String keyName = keyBaseName;
int counter = 0;
for(String intentKey : allIntentKeys){
if(intentKey.startsWith(keyBaseName)){
String possibleNumber = intentKey.substring(keyBaseName.length());
if(possibleNumber.length() > 0 && TextUtils.isDigitsOnly(possibleNumber)){
int currentCounter = Integer.parseInt(possibleNumber);
counter = currentCounter + 1;
}
}
}
if(counter != 0)
keyName += counter;
return keyName;
}
public static void registerNewSourceSinkConnection(int counter, String taintInfoOfSource){
Log.i("PEP", "in registerNewSourceSinkConnection(int counter, String taintInfoOfSource)"
+ counter + " "
+ taintInfoOfSource);
Set<String> taintInfos = new HashSet<String>();
taintInfos.add(taintInfoOfSource);
sourceSinkConnection.put(counter, taintInfos);
}
public static void registerNewSourceSinkConnection(int counter, Bundle bundle){
Log.i("PEP", "in registerNewSourceSinkConnection(int counter, Bundle bundle)"
+ counter +" "
+ bundle.toString());
int taintInfoKeyCounter = 0;
if(bundle != null){
for(String intentKey : bundle.keySet()){
if(intentKey.startsWith(keyBaseName)){
String possibleNumber = intentKey.substring(keyBaseName.length());
if(possibleNumber.length() > 0 && TextUtils.isDigitsOnly(possibleNumber)){
int currentCounter = Integer.parseInt(possibleNumber);
if(taintInfoKeyCounter < currentCounter)
taintInfoKeyCounter = currentCounter;
}
}
}
if(taintInfoKeyCounter == 0){
Log.i("PEP", "bundle:" + bundle.toString());
if(bundle.containsKey(keyBaseName)){
String taintSourceCats = bundle.getString(keyBaseName);
String[] allCats = taintSourceCats.split(",");
sourceSinkConnection.put(counter, new HashSet<String>(Arrays.asList(allCats)));
}
}
else{
if(bundle.containsKey(keyBaseName+taintInfoKeyCounter)){
String taintSourceCats = bundle.getString(keyBaseName+taintInfoKeyCounter);
String[] allCats = taintSourceCats.split(",");
sourceSinkConnection.put(counter, new HashSet<String>(Arrays.asList(allCats)));
}
}
}
}
}