package de.tudarmstadt.informatik.hostage.ui; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.net.ConnectivityManager; import android.os.Bundle; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.ToggleButton; import android.widget.ViewAnimator; import de.tudarmstadt.informatik.hostage.HoneyService; import de.tudarmstadt.informatik.hostage.HoneyService.LocalBinder; import de.tudarmstadt.informatik.hostage.R; import de.tudarmstadt.informatik.hostage.commons.HelperUtils; import de.tudarmstadt.informatik.hostage.logging.DatabaseHandler; import de.tudarmstadt.informatik.hostage.logging.Logger; import de.tudarmstadt.informatik.hostage.logging.SQLLogger; /** * MainActivity is the central activity for the GUI of the application. * MainActivity is launched when the application is first started. * It shows the user:
* - information about the network
* - light indicators for recorded attacks on each protocol
* - amount of attacks on each protocols
* The user can start and stop services. * @author Mihai Plasoianu * @author Lars Pandikow * */ public class MainActivity extends Activity { // String constants for whole application /** * Used for Broadcast between service and GUI. String: "de.tudarmstadt.informatik.hostage.BROADCAST" */ public static final String BROADCAST = "de.tudarmstadt.informatik.hostage.BROADCAST"; /** * Used to store session related data in a SharedPrefereces. String: "de.tudarmstadt.informatik.hostage.SESSION_DATA" */ public static final String SESSION_DATA = "de.tudarmstadt.informatik.hostage.SESSION_DATA"; public static final String LISTENER = "_LISTENER"; public static final String HANDLER_COUNT = "_HANDLER_COUNT"; public static final String SSID = "SSID"; public static final String BSSID = "BSSID"; public static final String INTERNAL_IP = "INTERNAL_IP"; public static final String EXTERNAL_IP = "EXTERNAL_IP"; /** * Integer representing a grey light. */ public static final int LIGHT_GREY = 0x01; /** * Integer representing a green light. */ public static final int LIGHT_GREEN = 0x02; /** * Integer representing a red light. */ public static final int LIGHT_RED = 0x03; /** * Integer representing a yellow light. */ public static final int LIGHT_YELLOW = 0x04; private HoneyService mService; private boolean serviceBound; private SharedPreferences pref; private Editor editor; private Logger logger; // variables for the swipe animation private ViewAnimator viewAnimator; private GestureDetector gestureDetector; private Animation animFlipInLR; private Animation animFlipOutLR; private Animation animFlipInRL; private Animation animFlipOutRL; private ListView listView; private ListViewAdapter adapter; private String protocolClicked; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create dynamic view elements initViewAnimator(); initListView(); // Initialize Class variables pref = getSharedPreferences(MainActivity.SESSION_DATA, Context.MODE_PRIVATE); logger = new SQLLogger(this); editor = pref.edit(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.action_settings: startActivity(new Intent(this, SettingsActivity.class)); break; case R.id.action_about: startActivity(new Intent(this, AboutActivity.class)); break; default: } return super.onOptionsItemSelected(item); } @Override protected void onStart() { super.onStart(); //Register Broadcast Receiver registerReceiver(); registerNetReceiver(); // Bind service if running, else check for connection change and delete sessionData if (isServiceRunning()) { bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE); } else { String bssid_old = pref.getString(MainActivity.BSSID, ""); String bssid_new = HelperUtils.getBSSID(this); if(bssid_new == null || !bssid_new.equals(bssid_old)){ deleteSessionData(); } } // Update UI updateUI(); updateConnectionInfo(); } @Override protected void onStop() { //Unbind running service if (isServiceRunning()) { unbindService(mConnection); } // Unregister Broadcast Receiver unregisterNetReceiver(); unregisterReceiver(); super.onStop(); } @Override protected void onDestroy(){ super.onDestroy(); // If service not running delete session data if(!isServiceRunning()){ deleteSessionData(); } } /** * Called when User presses on/off button * @param view */ public void buttonOnOffClick(View view) { if (((ToggleButton) view).isChecked()) { if (isParanoid()) { protocolClicked = "PANIC"; } else { protocolClicked = "SMB"; } startAndBind(); } else { mService.stopListeners(); stopAndUnbind(); } } /** * Starts the ViewLog activity, when the Button is pressed * @see ViewLog * @param view View elements which triggers the method call. */ public void showLog(View view){ startActivity(new Intent(this, ViewLog.class)); } /** * If mobile phone is connected to a wireless network starts the background service ands binds itself to it. * Else notifies the user that service could not be started. */ private void startAndBind() { if(HelperUtils.getBSSID(this) != null){ startService(getServiceIntent()); bindService(); } else{ ToggleButton button = (ToggleButton) findViewById(R.id.toggleButtonOnOff); button.setChecked(false); Toast.makeText(getApplicationContext(), "To start a service, first connect to a wireless network.", Toast.LENGTH_SHORT).show(); } } /** * Binds service to Activity * @see HoneyService */ private void bindService(){ bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE); serviceBound = true; } /** * Stops service and unbinds it. * @see HoneyService */ private void stopAndUnbind() { unbindService(); stopService(getServiceIntent()); } /** * Unbinds service. * @see HoneyService */ private void unbindService(){ unbindService(mConnection); serviceBound = false; } /** * Connection to bind the background service * @see HoneyService */ private ServiceConnection mConnection = new ServiceConnection() { /** * After the service is bound, check which has been clicked and start it. * @see android.content.ServiceConnection#onServiceConnected(android.content.ComponentName) */ @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = ((LocalBinder) service).getService(); if(protocolClicked != null && protocolClicked.equals("PANIC")){ mService.startListeners(); }else if (protocolClicked != null){ mService.toggleListener(protocolClicked); } protocolClicked = null; } /** * After the service is unbound, delete reference. * @see android.content.ServiceConnection#onServiceDisconnected(android.content.ComponentName) */ @Override public void onServiceDisconnected(ComponentName name) { mService = null; } }; /** * Returns an intent to start HoneyService. * @return An Intent to start HoneyService */ private Intent getServiceIntent() { return new Intent(this, HoneyService.class); } /** * Checks if user selected paranoid mode. * @return True when paranoid mode is selected, else returns false. */ private boolean isParanoid() { return ((CheckBox) findViewById(R.id.checkBoxParanoid)).isChecked(); } /** * Initializes the ListView. Creating its contents dynamic from protocol protocols.xml * @see /res/values/protocols.xml */ private void initListView() { ArrayList> data = new ArrayList>(); for (String protocol : getResources().getStringArray(R.array.protocols)) { HashMap d = new HashMap(); d.put("light", String.valueOf(R.drawable.light_grey)); d.put("protocol", protocol); d.put("connections", "-"); data.add(d); } listView = (ListView) findViewById(R.id.listViewProtocols); adapter = new ListViewAdapter(getLayoutInflater(), data); listView.setAdapter(adapter); listView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { String protocolName = (String) ((HashMap) adapter .getItem(position)).get("protocol"); if (isServiceRunning()) { mService.toggleListener(protocolName); if(!mService.hasRunningListeners()){ stopAndUnbind(); } }else{ protocolClicked = protocolName; startAndBind(); } } }); } /** * Checks if a HoneService instance is running. * @return True if HonerService is running, else false. * @see HonerService */ private boolean isServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (service.service.getClassName().equals(HoneyService.class.getName())) { return true; } } return false; } /** * Deletes all session related Data. */ private void deleteSessionData(){ editor.clear(); editor.commit(); } /** * Register broadcast receiver for custom broadcast. * @see MainActivity#BROADCAST */ private void registerReceiver() { LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(BROADCAST)); } /** * Unregisters broadcast receiver for custom broadcast. * @see MainActivity#BROADCAST */ private void unregisterReceiver() { LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); } /** * Receiver for custom broadcast. * @see MainActivity#BROADCAST */ private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Update user interface. updateUI(); } }; /** * Register broadcast receiver for network state changes. * @see ConnectivityManager#CONNECTIVITY_ACTION */ private void registerNetReceiver() { IntentFilter intent = new IntentFilter(); intent.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //"android.net.conn.CONNECTIVITY_CHANGE" registerReceiver(netReceiver, intent); } /** * Unregister broadcast receiver for network state changes. */ private void unregisterNetReceiver() { unregisterReceiver(netReceiver); } /** * Receiver for network state change events. */ private BroadcastReceiver netReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String bssid_old = pref.getString(BSSID, ""); String bssid_new = HelperUtils.getBSSID(context); if ((bssid_new == null || !bssid_new.equals(bssid_old)) && serviceBound) { Toast.makeText(getApplicationContext(),"Connection changed! Services stopped!", Toast.LENGTH_LONG).show(); unbindService(); } updateConnectionInfo(); } }; /** * Updates Information shown by the GUI. */ private void updateUI() { boolean activeListeners = false; boolean activeHandlers = false; boolean yellowLight = false; //Check for all protocols if listeners are active and attacks have been recorded //Update protocol lights and connection information. for(String protocol : getResources().getStringArray(R.array.protocols)){ //Check if protocol is active if(pref.getBoolean(protocol + LISTENER, false)){ activeListeners = true; int handlerCount = pref.getInt(protocol + HANDLER_COUNT, 0); //Check if attacks have been recorded in this session. if(handlerCount > 0){ activeHandlers = true; updateProtocolLight(LIGHT_RED, protocol); updateProtocolConnections(handlerCount, protocol); } else{ //Check if the bssid of the wireless network has already been recorded as infected. if(logger.bssidSeen(protocol, HelperUtils.getBSSID(getApplicationContext()))){ updateProtocolLight(LIGHT_YELLOW, protocol); yellowLight = true; } else{ updateProtocolLight(LIGHT_GREEN, protocol); } updateProtocolConnections(0, protocol); } }else{ updateProtocolLight(LIGHT_GREY, protocol); } } //Update the big attack indicator. if (activeListeners) { if (activeHandlers) { updateStatusLight(LIGHT_RED); } else { if(yellowLight){ updateStatusLight(LIGHT_YELLOW); } else { updateStatusLight(LIGHT_GREEN); } } ((ToggleButton) findViewById(R.id.toggleButtonOnOff)) .setChecked(true); findViewById(R.id.checkBoxParanoid).setEnabled(false); } else { updateStatusLight(LIGHT_GREY); ((ToggleButton) findViewById(R.id.toggleButtonOnOff)) .setChecked(false); findViewById(R.id.checkBoxParanoid).setEnabled(true); } } /** * Sets the big light indicator. * @param light Integer code to set the light color. * @see MainActivity#LIGHT_GREY * @see MainActivity#LIGHT_GREEN * @see MainActivity#LIGHT_RED * @see MainActivity#LIGHT_YELLOW */ private void updateStatusLight(int light) { switch (light) { case LIGHT_GREY: ((ImageView) findViewById(R.id.imageViewLight)) .setImageResource(R.drawable.light_grey_large); break; case LIGHT_GREEN: ((ImageView) findViewById(R.id.imageViewLight)) .setImageResource(R.drawable.light_green_large); break; case LIGHT_RED: ((ImageView) findViewById(R.id.imageViewLight)) .setImageResource(R.drawable.light_red_large); break; case LIGHT_YELLOW: ((ImageView) findViewById(R.id.imageViewLight)) .setImageResource(R.drawable.light_yellow_large); break; } } /** * Sets the light indicator for a given protocol. * @param light Integer code to set the light color. * @param protocolName Name of the protocol which should be updated. */ private void updateProtocolLight(int light, String protocolName) { for (int i = 0; i < adapter.getCount(); ++i) { HashMap d = (HashMap) adapter .getItem(i); if (d.get("protocol").equals(protocolName)) { switch (light) { case LIGHT_GREY: d.put("light", String.valueOf(R.drawable.light_grey)); d.put("connections", "-"); break; case LIGHT_GREEN: d.put("light", String.valueOf(R.drawable.light_green)); break; case LIGHT_RED: d.put("light", String.valueOf(R.drawable.light_red)); break; case LIGHT_YELLOW: d.put("light", String.valueOf(R.drawable.light_yellow)); break; } } } adapter.notifyDataSetChanged(); } /** * Sets the connections count for a given protocol * @param connections New value for recorded connections. * @param protocolName Name of the protocol which should be updated. */ private void updateProtocolConnections(int connections, String protocolName) { for (int i = 0; i < adapter.getCount(); ++i) { HashMap d = ((HashMap) adapter .getItem(i)); if (d.get("protocol").equals(protocolName)) { d.put("connections", String.valueOf(connections)); } } adapter.notifyDataSetChanged(); } /** * Gets Information about connection state and updates the GUI. */ private void updateConnectionInfo() { //Get text fields TextView ssidView = (TextView) findViewById(R.id.textViewSSIDValue); TextView bssidView = (TextView) findViewById(R.id.textViewBSSIDValue); TextView internalIPView = (TextView) findViewById(R.id.textViewInternalIPValue); TextView externalIPView = (TextView) findViewById(R.id.textViewExternalIPValue); //Update the connection information HelperUtils.updateConnectionInfo(this); //Get connection information String ssid = pref.getString(SSID, "-"); String bssid = pref.getString(BSSID, "-"); String internalIP = pref.getString(INTERNAL_IP, "-"); String externalIP = pref.getString(EXTERNAL_IP, "-"); //Set text fields if (ssid != null) ssidView.setText(ssid); else ssidView.setText("-"); if (bssid != null) bssidView.setText(bssid); else bssidView.setText("-"); if (internalIP != null) internalIPView.setText(internalIP); else internalIPView.setText("-"); if (externalIP != null) externalIPView.setText(externalIP); else externalIPView.setText("-"); } /*############# Help functions for animation ##################*/ @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } /** * Initializes variables for screen animation */ private void initViewAnimator() { viewAnimator = (ViewAnimator) findViewById(R.id.viewAnimator); gestureDetector = new GestureDetector(this, simpleOnGestureListener); animFlipInLR = AnimationUtils.loadAnimation(this, R.anim.in_left_to_right); animFlipOutLR = AnimationUtils.loadAnimation(this, R.anim.out_left_to_right); animFlipInRL = AnimationUtils.loadAnimation(this, R.anim.in_right_to_left); animFlipOutRL = AnimationUtils.loadAnimation(this, R.anim.out_right_to_left); } /** * Called when a swipe to the Left is registered. */ private void swipeRightToLeft() { if (viewAnimator.getDisplayedChild() == 0) { viewAnimator.setInAnimation(animFlipInRL); viewAnimator.setOutAnimation(animFlipOutRL); viewAnimator.setDisplayedChild(1); } } /** * Called when a swipe to the Right is registered. */ private void swipeLeftToRight() { if (viewAnimator.getDisplayedChild() == 1) { viewAnimator.setInAnimation(animFlipInLR); viewAnimator.setOutAnimation(animFlipOutLR); viewAnimator.setDisplayedChild(0); } } SimpleOnGestureListener simpleOnGestureListener = new SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { float sensitvity = 50; if ((e1.getX() - e2.getX()) > sensitvity) { swipeRightToLeft(); } else if ((e2.getX() - e1.getX()) > sensitvity) { swipeLeftToRight(); } return true; } }; }