Browse Source

Merge branch 'feature_jlan_cifs' of https://git.tk.informatik.tu-darmstadt.de/scm-ssi-hostage-v3 into feature_jlan_cifs

Conflicts:
	assets/payload/redirect-ports.sh
	res/raw/jlan_config.xml
Daniel Lazar 9 years ago
parent
commit
01bf5c134d
30 changed files with 362 additions and 248 deletions
  1. 1 5
      AndroidManifest.xml
  2. 2 1
      assets/payload/redirect-ports.sh
  3. BIN
      res/drawable-hdpi/ic_action_discard.png
  4. BIN
      res/drawable-mdpi/ic_action_discard.png
  5. BIN
      res/drawable-xhdpi/ic_action_discard.png
  6. BIN
      res/drawable-xxhdpi/ic_action_discard.png
  7. 1 1
      res/raw/jlan_config.xml
  8. 2 0
      res/values-de/strings.xml
  9. 6 1
      res/values/strings.xml
  10. 6 6
      res/values/strings_preferences.xml
  11. 0 76
      res/xml/preferences.xml
  12. 24 10
      res/xml/settings_preferences.xml
  13. 16 17
      src/de/tudarmstadt/informatik/hostage/ConnectionGuard.java
  14. 1 1
      src/de/tudarmstadt/informatik/hostage/ConnectionRegister.java
  15. 5 2
      src/de/tudarmstadt/informatik/hostage/Handler.java
  16. 4 0
      src/de/tudarmstadt/informatik/hostage/Hostage.java
  17. 30 4
      src/de/tudarmstadt/informatik/hostage/Listener.java
  18. 4 4
      src/de/tudarmstadt/informatik/hostage/commons/HelperUtils.java
  19. 24 7
      src/de/tudarmstadt/informatik/hostage/persistence/HostageDBOpenHelper.java
  20. 1 0
      src/de/tudarmstadt/informatik/hostage/protocol/CIFS.java
  21. 1 1
      src/de/tudarmstadt/informatik/hostage/protocol/SMB.java
  22. 1 1
      src/de/tudarmstadt/informatik/hostage/protocol/TELNET.java
  23. 67 8
      src/de/tudarmstadt/informatik/hostage/protocol/cifs/PseudoCIFSDiskDriver.java
  24. 6 4
      src/de/tudarmstadt/informatik/hostage/sync/android/SyncUtils.java
  25. 11 0
      src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/ui/WiFiP2pSyncActivity.java
  26. 24 1
      src/de/tudarmstadt/informatik/hostage/ui/activity/MainActivity.java
  27. 42 74
      src/de/tudarmstadt/informatik/hostage/ui/adapter/ServicesListAdapter.java
  28. 6 2
      src/de/tudarmstadt/informatik/hostage/ui/fragment/PreferenceHostageFragment.java
  29. 38 0
      src/de/tudarmstadt/informatik/hostage/ui/fragment/RecordOverviewFragment.java
  30. 39 22
      src/de/tudarmstadt/informatik/hostage/ui/fragment/ThreatMapFragment.java

+ 1 - 5
AndroidManifest.xml

@@ -131,11 +131,7 @@
 
         <activity
             android:name=".sync.wifi_direct.ui.WiFiP2pSyncActivity"
-            android:label="@string/title_activity_p2_psync"
-            android:parentActivityName=".ui.activity.MainActivity" >
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value="de.tudarmstadt.informatik.hostage.ui.activity.MainActivity" />
+            android:label="@string/title_activity_p2_psync">
         </activity>
 
         <service android:name=".sync.android.SyncService"

+ 2 - 1
assets/payload/redirect-ports.sh

@@ -10,7 +10,8 @@ destination=( 28144 28169 28217 28580 28274 28275 28274 28276 28159 28160 28582)
 length=${#protocol[@]} # count protocol elements
 
 # for (( i=0; i<$length; i++ ))
-for i in `seq 0 10` # fix for android's annoyingly limited bash
+#for i in `seq 0 9` # fix for android's annoyingly limited bash
+for i in 0 1 2 3 4 5 6 7 8 9 10 # another fix for devices missing the seq command
 do
 	# echo ${protocol[$i]} ${origin[$i]} ${destination[$i]} # debug
 

BIN
res/drawable-hdpi/ic_action_discard.png


BIN
res/drawable-mdpi/ic_action_discard.png


BIN
res/drawable-xhdpi/ic_action_discard.png


BIN
res/drawable-xxhdpi/ic_action_discard.png


+ 1 - 1
res/raw/jlan_config.xml

@@ -39,7 +39,7 @@
         <diskshare name="JLAN" comment="Test share">
             <driver>
                 <class>org.alfresco.jlan.smb.server.disk.JavaFileDiskDriver</class>
-                <LocalPath>.</LocalPath>
+                <LocalPath>/</LocalPath>
             </driver>
         </diskshare>
     </shares>

+ 2 - 0
res/values-de/strings.xml

@@ -58,6 +58,8 @@
     <string name="delete_dialog_title">Delete data sets by:</string>
     <string name="dialog_clear_database_date">Delete all data before:</string>
 
+    <string name="deleteAttacksTitle">Sollen diese Angriffsdaten gel&#246;scht werden?</string>
+
     <string name="threatmap_show_records"><u>Zeige Aufzeichnungen</u></string>
 
 	<string name="RecordAttackType">Typ</string>

+ 6 - 1
res/values/strings.xml

@@ -30,6 +30,7 @@
     <string name="not_rooted">Your device does not have root access. To unlock full functionality of HosTaGe, a rooted device is required.</string>
     <string name="help">Help</string>
     <string name="confirm">Confirm</string>
+	<string name="ok">OK</string>
     <string name="how">How?</string>
     <string name="portbinder">Portbinder</string>
     <string name="portbinder_tutorial">Video Tutorial</string>
@@ -75,6 +76,8 @@
 	<string name="delete_dialog_title">Delete data sets by:</string>	
 	<string name="dialog_clear_database_date">Delete all data before:</string>
 
+    <string name="deleteAttacksTitle">Delete the these attack entries?</string>
+
 	<string name="threatmap_show_records"><u>Show records</u></string>
 
 	<string name="RecordAttackType">Type</string>
@@ -109,7 +112,7 @@
 
     <string name="device_rooted">Device rooted</string>
     <string name="porthack_installed">Portbinder installed</string>
-	<string name="iptables_available">iptables available</string>
+	<string name="iptables_available">Iptables available</string>
 	<string name="install_porthack">Install Portbinder</string>
 	<string name="uninstall_porthack">Uninstall Portbinder</string>
 	<string name="porthack_explanation"><![CDATA[<h1>Portbinder</h1><p>To use protocols with ports below 1024 your device requires root privileges. HosTaGe does not run with root privileges by default. That is why a small program called Portbinder is needed that opens a socket and passes it to the main HosTaGe App.</p><p>Another technique is to redirect those ports to higher port numbers. This is achieved using Android\'s iptables. If iptables is available on your device the Portbinder is not required.</p>]]></string>
@@ -256,4 +259,6 @@
     <string name="pref_sync_countries_desc">Only download attack data of these countries</string>
     <string name="pref_sync_countries">Countries</string>
     <string name="pref_download_server">Download server</string>
+	<string name="google_play_services_unavailable">Error: Google Play Services are unavailable.
+	</string>
 </resources>

+ 6 - 6
res/values/strings_preferences.xml

@@ -17,13 +17,13 @@
 	<string name="pref_upload_server">Server address</string>	
 	<string name="pref_connection_settings">Connection Settings</string>
 	<string name="pref_max_connections">Max Connections</string>	
-	<string name="pref_max_connections_default">5</string>	
+	<integer name="pref_max_connections_default">5</integer>
 	<string name="pref_timeout">Socket Timeout</string>
-	<string name="pref_timeout_summary">Socket timeout in seconds</string>
-	<string name="pref_timeout_default">30</string>	
-	<string name="pref_sleeptime">Stream sleep time</string>
-	<string name="pref_sleeptime_summary">Time in ms for the stream sleep time</string>
-	<string name="pref_sleeptime_default">500</string>
+	<string name="pref_timeout_summary">After this many seconds close socket when no communication occurred</string>
+	<integer name="pref_timeout_default">30</integer>
+	<string name="pref_portscan_timeout">Portscan Timeout</string>
+	<string name="pref_portscan_timeout_summary">Should match the maximum duration of a portscan in seconds</string>
+	<integer name="pref_portscan_timeout_default">60</integer>
 	<string name="pref_location_settings">Location Settings</string>
 	<string name="pref_location_time">Location Data Timeout</string>
 	<string name="pref_location_time_summary">Timeout when requesting location data in ms</string>

+ 0 - 76
res/xml/preferences.xml

@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <PreferenceCategory android:title="@string/pref_storage" >
-        <CheckBoxPreference
-            android:defaultValue="false"
-            android:key="pref_external_storage"
-            android:summary="@string/pref_external_storage_summ"
-            android:title="@string/pref_external_storage_title" />
-        
-        <EditTextPreference
-            android:key="pref_external_location"
-            android:dependency="pref_external_storage"
-            android:defaultValue="/HosTaGe/LogFiles/"
-            android:title="@string/pref_external_location_title"
-            />
-        
-    </PreferenceCategory>
-    <PreferenceCategory android:title="@string/pref_upload" >
-         <CheckBoxPreference
-            android:defaultValue="false"
-            android:key="pref_auto_synchronize"
-            android:summary="@string/pref_auto_synchronize_summ"
-            android:title="@string/pref_auto_synchronize_title" />
-                
-        <EditTextPreference
-            android:key="pref_upload_server"
-            android:defaultValue="https://ssi.cased.de"
-            android:title="@string/pref_upload_server" />
-        
-    </PreferenceCategory>
-    <PreferenceCategory android:title="@string/pref_notification" >
-        <CheckBoxPreference
-            android:defaultValue="true"
-            android:key="pref_vibration"
-            android:summary="@string/pref_vibration_summ"
-            android:title="@string/pref_vibration" />
-
-        <RingtonePreference
-            android:defaultValue="content://settings/system/notification_sound"
-            android:key="pref_notification_sound"
-            android:ringtoneType="notification"
-            android:showDefault="true"
-            android:showSilent="true"
-            android:summary="@string/pref_alarm_summ"
-            android:title="@string/pref_alarm" />
-    </PreferenceCategory>
-    <PreferenceCategory android:title="@string/pref_connection_settings" >
-        <EditTextPreference
-            android:key="pref_max_connections"
-            android:defaultValue="@string/pref_max_connections_default"
-            android:title="@string/pref_max_connections" />
-
-          <EditTextPreference
-            android:key="pref_timeout"
-            android:defaultValue="@string/pref_timeout_default"
-            android:title="@string/pref_timeout" />
-
-          <EditTextPreference
-            android:key="pref_sleeptime"
-            android:defaultValue="@string/pref_sleeptime_default"
-            android:title="@string/pref_sleeptime" />
-    </PreferenceCategory>
-    <PreferenceCategory android:title="@string/pref_location_settings" >
-        <EditTextPreference
-            android:key="pref_location_time"
-            android:defaultValue="@string/pref_location_time_default"
-            android:title="@string/pref_location_time" />
-
-        <EditTextPreference
-            android:key="pref_location_retries"
-            android:defaultValue="@string/pref_location_retries_default"
-            android:title="@string/pref_location_retries" />
-
-    </PreferenceCategory>
-</PreferenceScreen>

+ 24 - 10
res/xml/settings_preferences.xml

@@ -37,10 +37,10 @@
 				android:defaultValue="https://ssi.cased.de"
 				android:title="@string/pref_upload_server" />
 
-        <EditTextPreference
+        <!--<EditTextPreference
             android:key="pref_download_server"
             android:defaultValue="http://ssi.cased.de/api"
-            android:title="@string/pref_download_server" />
+            android:title="@string/pref_download_server" />-->
 	</PreferenceCategory>
 
 	<PreferenceCategory android:title="@string/advanced_settings">
@@ -50,21 +50,35 @@
 				android:persistent="false">
 			<PreferenceCategory android:title="@string/pref_connection_settings" >
 				<EditTextPreference
+						android:inputType="number"
+						android:numeric="decimal"
 						android:key="pref_max_connections"
-						android:defaultValue="@string/pref_max_connections_default"
+						android:defaultValue="@integer/pref_max_connections_default"
 						android:title="@string/pref_max_connections" />
 
 				<EditTextPreference
+						android:inputType="number"
+						android:numeric="decimal"
 						android:key="pref_timeout"
-						android:defaultValue="@string/pref_timeout_default"
-						android:summary="@string/pref_timeout_summary"
-						android:title="@string/pref_timeout" />
+						android:defaultValue="@integer/pref_timeout_default"
+						android:title="@string/pref_timeout"
+						android:summary="@string/pref_timeout_summary" />
 
-				<EditTextPreference
+				<!--<EditTextPreference
+						android:inputType="number"
+						android:numeric="decimal"
 						android:key="pref_sleeptime"
-						android:defaultValue="@string/pref_sleeptime_default"
-						android:summary="@string/pref_sleeptime_summary"
-						android:title="@string/pref_sleeptime" />
+						android:defaultValue="@integer/pref_sleeptime_default"
+						android:title="@string/pref_sleeptime"
+						android:summary="@string/pref_sleeptime_summary" />-->
+
+				<EditTextPreference
+						android:inputType="number"
+						android:numeric="decimal"
+						android:key="pref_portscan_timeout"
+						android:defaultValue="@integer/pref_portscan_timeout_default"
+						android:title="@string/pref_portscan_timeout"
+						android:summary="@string/pref_portscan_timeout_summary" />
 			</PreferenceCategory>
             <PreferenceCategory android:title="@string/pref_location_settings" >
                 <EditTextPreference

+ 16 - 17
src/de/tudarmstadt/informatik/hostage/ConnectionGuard.java

@@ -1,5 +1,7 @@
 package de.tudarmstadt.informatik.hostage;
 
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
 import android.util.Log;
 
 /**
@@ -14,16 +16,23 @@ public class ConnectionGuard {
 	private ConnectionGuard() {
 	}
 
-	/**
-	 * Intervall between 2 connection in wich we assume a port scan
-	 */
-	public final static long TIMESTAMP_THRESHOLD_MS = 1000;
-
 	private static long lastConnectionTimestamp = 0;
 	private static long lastPortscanTimestamp = 0;
 	private static String lastIP = "";
 	private static int lastPort = 0;
 
+	private static long getPortscanTimeout() {
+		// this might be called in a time critical context so maybe
+		// we don't want to do this each time and instead just once
+		SharedPreferences defaultPref = PreferenceManager
+				.getDefaultSharedPreferences(Hostage.getContext());
+		// the pref value is in seconds
+		int portscanTimeoutS = Integer.parseInt(defaultPref.getString("pref_timeout", "60"));
+		long portscanTimeoutMS = 1000 * portscanTimeoutS;
+
+		return portscanTimeoutMS;
+	}
+
 	/**
 	 * Register a connection for port scan detection. Stores information about the last connection.
 	 * @param port The local port used for communication.
@@ -44,17 +53,7 @@ public class ConnectionGuard {
 	}
 
 	public synchronized static boolean portscanInProgress() {
-		return (System.currentTimeMillis() - lastPortscanTimestamp) < TIMESTAMP_THRESHOLD_MS;
-	}
-	
-	/**
-	 * Check if the new connection is part of a port scan attack.
-	 * @param port The local port used for communication.
-	 * @param ip The IP address of the remote device.
-	 * @return True if a port scan has been detected.
-	 */
-	public synchronized static boolean detectedPortscan(int port, String ip){
-		return detectedPortscan(port, ip, System.currentTimeMillis());
+		return (System.currentTimeMillis() - lastPortscanTimestamp) < getPortscanTimeout();
 	}
 	
 	/**
@@ -68,7 +67,7 @@ public class ConnectionGuard {
 		Log.i("Alte Werte:", "LastTime: " + lastConnectionTimestamp + " ,LastIP: " + lastIP + ", lastPort:" + port);
 		Log.i("Alte Werte:", "Time: " + timestamp + " ,IP: " + ip + ", Port:" + port);
 		boolean result = false;
-		boolean belowThreshold = ((timestamp - lastConnectionTimestamp) < TIMESTAMP_THRESHOLD_MS);
+		boolean belowThreshold = ((timestamp - lastConnectionTimestamp) < getPortscanTimeout());
 		boolean sameIP = (lastIP.equals(ip));
 		boolean samePort = (lastPort == port);
 		if (sameIP && belowThreshold && !samePort) {

+ 1 - 1
src/de/tudarmstadt/informatik/hostage/ConnectionRegister.java

@@ -51,7 +51,7 @@ public class ConnectionRegister {
 	public int getMaxConnections() {
 		SharedPreferences defaultPref = PreferenceManager
 				.getDefaultSharedPreferences(context);
-		return defaultPref.getInt("max_connections", 5);
+		return Integer.parseInt(defaultPref.getString("pref_max_connections", "5"));
 	}
 
 	/**

+ 5 - 2
src/de/tudarmstadt/informatik/hostage/Handler.java

@@ -220,7 +220,8 @@ public class Handler implements Runnable {
 		record.setLocalIP(client.getLocalAddress().getHostAddress());
 		record.setLocalPort(client.getLocalPort());
 		int remoteIPAddress = HelperUtils.packInetAddress(client.getInetAddress().getAddress());
-		record.setWasInternalAttack((remoteIPAddress & subnetMask) == (internalIPAddress & subnetMask));
+		record.setWasInternalAttack(
+				(remoteIPAddress & subnetMask) == (internalIPAddress & subnetMask));
 		record.setRemoteIP(client.getInetAddress().getHostAddress());
 		record.setRemotePort(client.getPort());
 		record.setBssid(BSSID);
@@ -256,7 +257,9 @@ public class Handler implements Runnable {
 			Logger.log(Hostage.getContext(), createAttackRecord());
 			logged = true;
 		}
-		Logger.log(Hostage.getContext(), createMessageRecord(type, packet));
+		if (packet != null && packet.length() > 0) { // prevent logging empty packets
+			Logger.log(Hostage.getContext(), createMessageRecord(type, packet));
+		}
 	}
 
 

+ 4 - 0
src/de/tudarmstadt/informatik/hostage/Hostage.java

@@ -467,6 +467,10 @@ public class Hostage extends Service {
 	 * Creates a Notification in the notification bar.
 	 */
 	private void createNotification() {
+		if (MainActivity.getInstance() == null) {
+			return; // prevent NullPointerException
+		}
+
 		HostageDBOpenHelper dbh = new HostageDBOpenHelper(this);
 		boolean activeHandlers = false;
 		boolean bssidSeen = false;

+ 30 - 4
src/de/tudarmstadt/informatik/hostage/Listener.java

@@ -5,6 +5,8 @@ import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.Lock;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocket;
@@ -50,6 +52,8 @@ public class Listener implements Runnable {
 	private ConnectionRegister conReg;
 	private boolean running = false;
 
+	private static Semaphore mutex = new Semaphore(1); // to enable atomic section in portscan detection
+
 	/**
 	 * Constructor for the class. Instantiate class variables.
 	 * 
@@ -193,7 +197,8 @@ public class Listener implements Runnable {
 			try {
 				final Socket client = server.accept();
 				if (ConnectionGuard.portscanInProgress()) {
-					// stop logging attacks
+					// ignore everything for the duration of the port scan
+					client.close();
 					return;
 				}
 				new Thread( new Runnable() {
@@ -201,10 +206,27 @@ public class Listener implements Runnable {
 				    public void run() {
 				    	try {
 				    		String ip = client.getInetAddress().getHostAddress();
-				    		if (ConnectionGuard.registerConnection(port, ip)){ // returns true when a port scan is detected
+
+							// the mutex should prevent multiple logging of a portscan
+							mutex.acquire();
+							if (ConnectionGuard.portscanInProgress()) {
+								mutex.release();
+								client.close();
+								return;
+							}
+				    		if (ConnectionGuard.registerConnection(port, ip)) { // returns true when a port scan is detected
 								logPortscan(client, System.currentTimeMillis());
+								mutex.release();
+								client.close();
 				    			return;
 				    		}
+							mutex.release();
+							Thread.sleep(100); // wait to see if other listeners detected a portscan
+							if (ConnectionGuard.portscanInProgress()) {
+								client.close();
+								return; // prevent starting a handler
+							}
+
 							if (protocol.isSecure()) {
 								startSecureHandler(client);
 							} else {
@@ -266,14 +288,18 @@ public class Listener implements Runnable {
 	}	
 	
 	/**
-	 * Logs a port scan attack
+	 * Logs a port scan attack and notifies ui about the portscan
 	 * @param client The socket on which a port scan has been detected.
 	 * @param timestamp Timestamp when the portscan has been detected.
 	 */
 	private void logPortscan(Socket client, long timestamp){
 		SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(service);
 		SharedPreferences connInfo = service.getSharedPreferences(service.getString(R.string.connection_info), Context.MODE_PRIVATE);
-		
+
+		// only handler informs about attacks so its name is used here
+		service.notifyUI(Handler.class.getName(), new String[] {service.getString(R.string.broadcast_started), "PORTSCAN", Integer.toString(
+				client.getPort())});
+
 		AttackRecord attackRecord = new AttackRecord(true);
 
 		attackRecord.setProtocol("PORTSCAN");

+ 4 - 4
src/de/tudarmstadt/informatik/hostage/commons/HelperUtils.java

@@ -409,10 +409,10 @@ public final class HelperUtils {
 		/*
 		FUCK YOU JAVA!!! WHY DON'T YOU HAVE UNSIGNED TYPES???
 		 */
-		long b0 = bytes[0]; if (b0 < 0) b0 = 255 + b0;
-		long b1 = bytes[1]; if (b1 < 0) b1 = 255 + b1;
-		long b2 = bytes[2]; if (b2 < 0) b2 = 255 + b2;
-		long b3 = bytes[3]; if (b3 < 0) b3 = 255 + b3;
+		long b0 = bytes[0]; if (b0 < 0) b0 = 256 + b0;
+		long b1 = bytes[1]; if (b1 < 0) b1 = 256 + b1;
+		long b2 = bytes[2]; if (b2 < 0) b2 = 256 + b2;
+		long b3 = bytes[3]; if (b3 < 0) b3 = 256 + b3;
 		long packed = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
 		if (packed >= (1l << 31)) {
 			packed -= (1l << 32) - 1l;

+ 24 - 7
src/de/tudarmstadt/informatik/hostage/persistence/HostageDBOpenHelper.java

@@ -469,7 +469,7 @@ public class HostageDBOpenHelper extends SQLiteOpenHelper {
             for (SyncDevice device : allDevices){
                 Long sync_id = deviceIDmap.get(device.getDeviceID());
                 long highestID = device.getHighest_attack_id();
-                if (sync_id != null) highestID = sync_id.longValue();
+                if (sync_id != null && highestID < sync_id) highestID = sync_id.longValue();
                 device.setHighest_attack_id(highestID);
             }
             this.updateSyncDevices(allDevices, db);
@@ -1301,6 +1301,19 @@ public class HostageDBOpenHelper extends SQLiteOpenHelper {
 		db.close();
 	}
 
+    /**
+     * Deletes all attacks for the given filter object.
+     * @param filter
+     */
+    public synchronized void deleteAttacksByFilter(LogFilter filter){
+        String selectQuery = this.selectionQueryFromFilter(filter, ""+ AttackEntry.TABLE_NAME + ", " +PacketEntry.TABLE_NAME);
+        String deleteQuery = selectQuery.replace("SELECT ","DELETE ");
+
+        SQLiteDatabase db = this.getReadableDatabase();
+        db.execSQL(deleteQuery);
+        db.close();
+    }
+
     public ArrayList<MessageRecord> getMessageRecords(AttackRecord attackRecord , SQLiteDatabase db){
         ArrayList<MessageRecord> mr = new ArrayList<MessageRecord>();
 
@@ -1848,9 +1861,11 @@ public class HostageDBOpenHelper extends SQLiteOpenHelper {
 
         String filterQuery = this.selectionQueryFromFilter(filter, AttackEntry.COLUMN_NAME_ATTACK_ID);
 
-        String attackPerESSID_Query = "SELECT " + NetworkEntry.COLUMN_NAME_SSID + " , " + "COUNT( " + AttackEntry.COLUMN_NAME_ATTACK_ID + "  ) " + " "
-                                    + " FROM " + AttackEntry.TABLE_NAME + " a " + " , " + NetworkEntry.TABLE_NAME
-                                    + " WHERE " + " a." + AttackEntry.COLUMN_NAME_ATTACK_ID + " IN " + " ( " + filterQuery + " ) "
+        filterQuery = filterQuery.split("GROUP BY")[0];
+
+        String attackPerESSID_Query = "SELECT " + NetworkEntry.COLUMN_NAME_SSID + " , " + "COUNT( " + " * " + "  ) " + " "
+                                    + " FROM "  +  AttackEntry.TABLE_NAME + " NATURAL JOIN " + NetworkEntry.TABLE_NAME //AttackEntry.TABLE_NAME + " a " + " , " + NetworkEntry.TABLE_NAME
+                                    + " WHERE " + AttackEntry.COLUMN_NAME_ATTACK_ID + " IN " + " ( " + filterQuery + " ) "
                                     + " GROUP BY " + NetworkEntry.TABLE_NAME+"."+NetworkEntry.COLUMN_NAME_SSID;
 
         SQLiteDatabase db = this.getReadableDatabase();
@@ -2093,10 +2108,12 @@ public class HostageDBOpenHelper extends SQLiteOpenHelper {
 
         String filterQuery = this.selectionQueryFromFilter(filter, AttackEntry.COLUMN_NAME_ATTACK_ID);
 
-        String attackPerBSSID_Query = "SELECT " + NetworkEntry.TABLE_NAME + "." + NetworkEntry.COLUMN_NAME_BSSID + " , " + "COUNT( " + AttackEntry.COLUMN_NAME_ATTACK_ID + "  ) " + " "
-                + " FROM " + AttackEntry.TABLE_NAME + " a " + " , " + NetworkEntry.TABLE_NAME
+        filterQuery = filterQuery.split("GROUP BY")[0];
+
+        String attackPerBSSID_Query = "SELECT " + AttackEntry.COLUMN_NAME_BSSID + " , " + "COUNT( " + "*" + "  ) " + " "
+                + " FROM " + AttackEntry.TABLE_NAME + " a "
                 + " WHERE " + " a." + AttackEntry.COLUMN_NAME_ATTACK_ID + " IN " + " ( " + filterQuery + " ) "
-                + " GROUP BY " + NetworkEntry.TABLE_NAME + "." + NetworkEntry.COLUMN_NAME_BSSID;
+                + " GROUP BY " + AttackEntry.COLUMN_NAME_BSSID;
 
         SQLiteDatabase db = this.getReadableDatabase();
         Cursor cursor = db.rawQuery(attackPerBSSID_Query, null);

+ 1 - 0
src/de/tudarmstadt/informatik/hostage/protocol/CIFS.java

@@ -13,6 +13,7 @@ import org.alfresco.jlan.server.SessionListener;
 import org.alfresco.jlan.server.SrvSession;
 import org.alfresco.jlan.server.config.InvalidConfigurationException;
 import org.alfresco.jlan.server.filesys.FileListener;
+import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
 import org.alfresco.jlan.server.filesys.NetworkFile;
 import org.alfresco.jlan.smb.server.CIFSConfigSection;
 import org.alfresco.jlan.smb.server.SMBServer;

+ 1 - 1
src/de/tudarmstadt/informatik/hostage/protocol/SMB.java

@@ -112,7 +112,7 @@ public class SMB implements Protocol {
 	private int initMaxPackets() {
 		int maxPackets;
 		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(Hostage.getContext());
-		maxPackets = prefs.getInt("timeout", 30) / 5;
+		maxPackets = Integer.parseInt(prefs.getString("pref_timeout", "30")) / 5;
 		return maxPackets;
 	}
 

+ 1 - 1
src/de/tudarmstadt/informatik/hostage/protocol/TELNET.java

@@ -82,7 +82,7 @@ public class TELNET implements Protocol {
 	@Override
 	public List<Packet> processMessage(Packet requestPacket) {
 		byte[] request = null;
-		if (requestPacket != null) {
+		if (requestPacket != null && requestPacket.getBytes().length > 0) { // ignore empty packets
 			request = requestPacket.getBytes();
 		}
 		List<Packet> responsePackets = new ArrayList<Packet>();

+ 67 - 8
src/de/tudarmstadt/informatik/hostage/protocol/cifs/PseudoCIFSDiskDriver.java

@@ -4,9 +4,13 @@ package de.tudarmstadt.informatik.hostage.protocol.cifs;
 import org.alfresco.jlan.server.SrvSession;
 import org.alfresco.jlan.server.core.DeviceContext;
 import org.alfresco.jlan.server.core.DeviceContextException;
+import org.alfresco.jlan.server.filesys.DiskDeviceContext;
 import org.alfresco.jlan.server.filesys.DiskInterface;
+import org.alfresco.jlan.server.filesys.FileAttribute;
+import org.alfresco.jlan.server.filesys.FileExistsException;
 import org.alfresco.jlan.server.filesys.FileInfo;
 import org.alfresco.jlan.server.filesys.FileOpenParams;
+import org.alfresco.jlan.server.filesys.FileSystem;
 import org.alfresco.jlan.server.filesys.NetworkFile;
 import org.alfresco.jlan.server.filesys.SearchContext;
 import org.alfresco.jlan.server.filesys.TreeConnection;
@@ -16,19 +20,61 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 
 public class PseudoCIFSDiskDriver implements DiskInterface {
+    private static class PseudoNetworkFile extends NetworkFile {
+        public PseudoNetworkFile(String name){
+            super(name);
+            setFileSize(12);
+            setModifyDate(System.currentTimeMillis());
+            setCreationDate(System.currentTimeMillis());
+        }
+
+        @Override
+        public void openFile(boolean createFlag) throws IOException {
+            setClosed(false);
+        }
+
+        @Override
+        public int readFile(byte[] buf, int len, int pos, long fileOff) throws IOException {
+            return 0;
+        }
+
+        @Override
+        public void writeFile(byte[] buf, int len, int pos, long fileOff) throws IOException {
+
+        }
+
+        @Override
+        public long seekFile(long pos, int typ) throws IOException {
+            return 0;
+        }
+
+        @Override
+        public void flushFile() throws IOException {
+
+        }
+
+        @Override
+        public void truncateFile(long siz) throws IOException {
+
+        }
+
+        @Override
+        public void closeFile() throws IOException {
+            setClosed(true);
+        }
+    }
+
     @Override
     public void closeFile(SrvSession srvSession, TreeConnection treeConnection, NetworkFile networkFile) throws IOException {
-
     }
 
     @Override
     public void createDirectory(SrvSession srvSession, TreeConnection treeConnection, FileOpenParams fileOpenParams) throws IOException {
-
     }
 
     @Override
     public NetworkFile createFile(SrvSession srvSession, TreeConnection treeConnection, FileOpenParams fileOpenParams) throws IOException {
-        return null;
+        throw new FileExistsException();
     }
 
     @Override
@@ -53,17 +99,27 @@ public class PseudoCIFSDiskDriver implements DiskInterface {
 
     @Override
     public FileInfo getFileInformation(SrvSession srvSession, TreeConnection treeConnection, String s) throws IOException {
-        return null;
+        FileInfo finfo = new FileInfo(s, 12, FileAttribute.ReadOnly);
+        long fdate = System.currentTimeMillis();
+        finfo.setModifyDateTime(fdate);
+        finfo.setAllocationSize((12 + 512L) & 0xFFFFFFFFFFFFFE00L);
+        finfo.setFileId(s.hashCode());
+
+        finfo.setCreationDateTime(fdate - 1000);
+        finfo.setChangeDateTime(fdate);
+        return finfo;
     }
 
     @Override
     public boolean isReadOnly(SrvSession srvSession, DeviceContext deviceContext) throws IOException {
-        return false;
+        return true;
     }
 
     @Override
     public NetworkFile openFile(SrvSession srvSession, TreeConnection treeConnection, FileOpenParams fileOpenParams) throws IOException {
-        return null;
+        System.out.println(srvSession + " - " + treeConnection + " - " + fileOpenParams);
+        NetworkFile netFile = new PseudoNetworkFile("Test");
+        return netFile;
     }
 
     @Override
@@ -88,7 +144,7 @@ public class PseudoCIFSDiskDriver implements DiskInterface {
 
     @Override
     public SearchContext startSearch(SrvSession srvSession, TreeConnection treeConnection, String s, int i) throws FileNotFoundException {
-        return null;
+        throw new FileNotFoundException();
     }
 
     @Override
@@ -103,7 +159,10 @@ public class PseudoCIFSDiskDriver implements DiskInterface {
 
     @Override
     public DeviceContext createContext(String s, ConfigElement configElement) throws DeviceContextException {
-        return null;
+        DiskDeviceContext ctx = new DiskDeviceContext("/");
+        ctx.setFilesystemAttributes(FileSystem.CasePreservedNames + FileSystem.UnicodeOnDisk);
+        ctx.setAvailable(true);
+        return ctx;
     }
 
 

+ 6 - 4
src/de/tudarmstadt/informatik/hostage/sync/android/SyncUtils.java

@@ -156,7 +156,7 @@ public class SyncUtils {
                     "\"port\":" + record.getRemotePort() +
                 "}," +
                 "\"dst\":{" +
-                    "\"ip\":\"" + record.getExternalIP() /*record.getLocalIP()*/ + "\"," +
+                    "\"ip\":\"" + record.getLocalIP() + "\"," +
                     "\"port\":" + record.getLocalPort() +
                 "}," +
                 "\"type\":" + (protocolsTypeMap.containsKey(record.getProtocol()) ? protocolsTypeMap.get(record.getProtocol()) : 0) + "," +
@@ -166,7 +166,9 @@ public class SyncUtils {
                 "\"bssid\":\"" + record.getBssid() + "\"," +
                 "\"ssid\":\"" + record.getSsid() + "\"," +
                 "\"device\":\"" + record.getDevice() + "\"," +
-                "\"sync_id\":\"" + record.getSync_id() + "\"" +
+                "\"sync_id\":\"" + record.getSync_id() + "\"," +
+                "\"internal_attack\":\"" + record.getWasInternalAttack() + "\"," +
+                "\"external_ip\":\"" + record.getExternalIP() + "\"" +
              "}\n"
             );
         } catch (IOException e) {
@@ -351,8 +353,8 @@ public class SyncUtils {
                     record.setLocalPort(dst.getInt("port"));
                     record.setRemoteIP(src.getString("ip"));
                     record.setRemotePort(src.getInt("port"));
-                    record.setExternalIP("0.0.0.0");
-                    record.setWasInternalAttack(false);
+                    record.setExternalIP(item.has("external_ip") ? item.getString("external_ip") : "0.0.0.0");
+                    record.setWasInternalAttack(item.has("internal_attack") && item.getBoolean("internal_attack"));
 
                     syncRecords.add(record);
                 } catch(Exception e){

+ 11 - 0
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/ui/WiFiP2pSyncActivity.java

@@ -12,6 +12,7 @@ import android.os.Bundle;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -118,6 +119,7 @@ public class WiFiP2pSyncActivity extends Activity implements AdapterView.OnItemC
 
         assert getActionBar() != null;
         getActionBar().setTitle(ACTIONBAR_TITLE);
+        getActionBar().setDisplayHomeAsUpEnabled(true);
 
         this.extractFromView();
         this.registerListeners();
@@ -139,6 +141,15 @@ public class WiFiP2pSyncActivity extends Activity implements AdapterView.OnItemC
 		}, 1000, seconds * 1000); // search for devices every few seconds
     }
 
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == android.R.id.home) {
+            finish();
+        }
+
+        return super.onOptionsItemSelected(item);
+    }
+
     @Override
     public void onResume() {
         super.onResume();

+ 24 - 1
src/de/tudarmstadt/informatik/hostage/ui/activity/MainActivity.java

@@ -71,6 +71,11 @@ public class MainActivity extends Activity {
 	 */
 	public Fragment mDisplayedFragment;
 
+    /**
+     * The currently displayed fragment index
+     */
+    public int mDisplayedFragmentIndex;
+
 	/**
 	 * Holds the Hostage Service
 	 */
@@ -313,9 +318,26 @@ public class MainActivity extends Activity {
 		if (savedInstanceState == null) {
 			// on first time display view for first nav item
 			displayView(0);
-		}
+		} else {
+            mDisplayedFragmentIndex = savedInstanceState.getInt("mDisplayedFragmentIndex");
+            mDisplayedFragment = getFragmentManager().getFragment(savedInstanceState, "mDisplayedFragment");
+
+            mDrawerList.setItemChecked(mDisplayedFragmentIndex, true);
+            mDrawerList.setSelection(mDisplayedFragmentIndex);
+            setTitle(mDrawerItems.get(mDisplayedFragmentIndex).text);
+
+            injectFragment(mDisplayedFragment);
+        }
 	}
 
+    @Override
+    protected void onSaveInstanceState(Bundle outState){
+        super.onSaveInstanceState(outState);
+
+        outState.putInt("mDisplayedFragmentIndex", mDisplayedFragmentIndex);
+        getFragmentManager().putFragment(outState, "mDisplayedFragment", mDisplayedFragment);
+    }
+
 	/**
 	 * Displays the disclaimer on first run of the application
 	 */
@@ -515,6 +537,7 @@ public class MainActivity extends Activity {
 
 			injectFragment(fragment);
 
+            mDisplayedFragmentIndex = position;
 			mDrawerList.setItemChecked(position, true);
 			mDrawerList.setSelection(position);
 			setTitle(mDrawerItems.get(position).text);

+ 42 - 74
src/de/tudarmstadt/informatik/hostage/ui/adapter/ServicesListAdapter.java

@@ -208,81 +208,49 @@ public class ServicesListAdapter extends ArrayAdapter<ServicesListItem> {
      * @param holder ViewHolder which represents the item in the View
      */
     private void updateStatus(ServicesListItem item, ViewHolder holder) {
-        if(item.protocol.equals("GHOST")){
-            mProfile = ProfileManager.getInstance().getCurrentActivatedProfile();
-            mGhostPorts = mProfile.getGhostPorts();
+		boolean serviceIsActive = false;
+		// determine if service is active
+        if(item.protocol.equals("GHOST")) {
+			mProfile = ProfileManager.getInstance().getCurrentActivatedProfile();
+			mGhostPorts = mProfile.getGhostPorts();
+
+			for (Integer port : mGhostPorts) {
+				if (port != null && MainActivity.getInstance().getHostageService()
+						.isRunning("GHOST", port)) {
+					serviceIsActive = true;
+					break;
+				}
+			}
+		} else if (MainActivity.getInstance().getHostageService().isRunning(item.protocol)) {
+			serviceIsActive = true;
+		}
+
+		if (serviceIsActive){
+			if(!holder.activated.isChecked()) {
+				holder.activated.setChecked(true);
+			}
+
+			if (item.attacks == 0) {
+				setBackground(holder, R.drawable.services_circle_green);
+			} else { // attacks > 0 (will never be negative)
+				if (MainActivity.getInstance().getHostageService().hasProtocolActiveAttacks(item.protocol)) {
+					setBackground(holder, R.drawable.services_circle_red);
+				} else {
+					setBackground(holder, R.drawable.services_circle_yellow);
+				}
+			}
+		} else {
+			if(holder.activated.isChecked()) {
+				holder.activated.setChecked(false);
+			}
+
+			if (item.attacks > 0) {
+				setBackground(holder, R.drawable.services_circle_yellow);
+			} else {
+				setBackground(holder, R.drawable.services_circle);
+			}
+		}
 
-            boolean ghostActive = false;
-            if(mGhostPorts.length != 0) {
-                for (Integer port : mGhostPorts) {
-                    if(port != null){
-                        if (MainActivity.getInstance().getHostageService().isRunning("GHOST", port)) {
-                            ghostActive = true;
-                        }
-                    }
-                }
-            }
-            if(ghostActive){
-                if(!holder.activated.isChecked()) {
-                    holder.activated.setChecked(true);
-                }
-
-                if (!MainActivity.getInstance().getHostageService().hasProtocolActiveAttacks(item.protocol)) {
-                    if (item.attacks > 0) {
-                        setBackground(holder, R.drawable.services_circle_yellow);
-                    } else {
-                        setBackground(holder, R.drawable.services_circle_green);
-                    }
-
-                } else {
-                    if (MainActivity.getInstance().getHostageService().hasProtocolActiveAttacks(item.protocol)) {
-                        setBackground(holder, R.drawable.services_circle_red);
-                    }
-                }
-
-            } else if (item.attacks > 0) {
-                if(holder.activated.isChecked()) {
-                    holder.activated.setChecked(false);
-                }
-                setBackground(holder, R.drawable.services_circle_yellow);
-            } else {
-                if(holder.activated.isChecked()) {
-                    holder.activated.setChecked(false);
-                }
-                setBackground(holder, R.drawable.services_circle);
-            }
-
-
-
-
-        }
-        else if (MainActivity.getInstance().getHostageService().isRunning(item.protocol)) {
-            if(!holder.activated.isChecked()) {
-                holder.activated.setChecked(true);
-            }
-            if (!MainActivity.getInstance().getHostageService().hasProtocolActiveAttacks(item.protocol)) {
-                if (item.attacks > 0) {
-                    setBackground(holder, R.drawable.services_circle_yellow);
-                } else {
-                    setBackground(holder, R.drawable.services_circle_green);
-                }
-
-            } else {
-                if (MainActivity.getInstance().getHostageService().hasProtocolActiveAttacks(item.protocol)) {
-                    setBackground(holder, R.drawable.services_circle_red);
-                }
-            }
-        } else if (item.attacks > 0) {
-            if(holder.activated.isChecked()) {
-                holder.activated.setChecked(false);
-            }
-            setBackground(holder, R.drawable.services_circle_yellow);
-        } else {
-            if(holder.activated.isChecked()) {
-                holder.activated.setChecked(false);
-            }
-            setBackground(holder, R.drawable.services_circle);
-        }
         holder.recordedAttacks
                 .setText(String.format(MainActivity.getContext().getResources().getString(R.string.recorded_attacks) + "  %d", Integer.valueOf(item.attacks)));
     }

+ 6 - 2
src/de/tudarmstadt/informatik/hostage/ui/fragment/PreferenceHostageFragment.java

@@ -43,7 +43,8 @@ public class PreferenceHostageFragment extends PreferenceFragment implements Sha
 				"pref_timeout",
 				"pref_sleeptime",
 				"pref_location_time",
-				"pref_location_retries"
+				"pref_location_retries",
+				"pref_portscan_timeout"
 		};
 
 		// map the text preferences to suffixes
@@ -51,6 +52,7 @@ public class PreferenceHostageFragment extends PreferenceFragment implements Sha
 		this.mSuffixMap.put("pref_timeout", "s");
 		this.mSuffixMap.put("pref_sleeptime", "ms");
 		this.mSuffixMap.put("pref_location_time", "ms");
+		this.mSuffixMap.put("pref_portscan_timeout", "s");
 
 		addPreferencesFromResource(R.xml.settings_preferences);
 
@@ -74,7 +76,9 @@ public class PreferenceHostageFragment extends PreferenceFragment implements Sha
 				suffix = this.mSuffixMap.get(key);
 			}
 
-			p.setSummary(sharedPreferences.getString(key, "") + " " + suffix);
+			if (p.getSummary() == null) {
+				p.setSummary(sharedPreferences.getString(key, "") + " " + suffix);
+			}
 		}
 	}
 

+ 38 - 0
src/de/tudarmstadt/informatik/hostage/ui/fragment/RecordOverviewFragment.java

@@ -426,6 +426,35 @@ public class RecordOverviewFragment extends UpNavigatibleFragment implements Che
 		return false;
 	}
 
+
+    public void openDeleteFilteredAttacksDialog() {
+        // Use the Builder class for convenient dialog construction
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+        String deleteAttacksTitle = MainActivity.getInstance().getString(R.string.deleteAttacksTitle);
+        String cancelTitle = MainActivity.getInstance().getString(R.string.cancel);
+        String deleteTitle = MainActivity.getInstance().getString(R.string.delete);
+
+        builder.setMessage(deleteAttacksTitle)
+                .setPositiveButton(deleteTitle, new DialogInterface.OnClickListener() {
+                    private RecordOverviewFragment recordOverviewFragment = null;
+                    public void onClick(DialogInterface dialog, int id) {
+                        recordOverviewFragment.deleteFilteredAttacks();
+                    }
+                    public DialogInterface.OnClickListener init(RecordOverviewFragment rf){
+                        this.recordOverviewFragment = rf;
+                        return this;
+                    }
+                }.init(this))
+                .setNegativeButton(cancelTitle, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        // User cancelled the dialog
+                    }
+                });
+        AlertDialog dialog = builder.create();
+        dialog.show();
+    }
+
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
@@ -1328,6 +1357,15 @@ public class RecordOverviewFragment extends UpNavigatibleFragment implements Che
         }
     }
 
+    /**
+     * Deletes the current displayed attacks.
+     */
+    public void deleteFilteredAttacks(){
+        LogFilter filter = this.filter;
+        dbh.deleteAttacksByFilter(filter);
+        this.actualiseListViewInBackground();
+    }
+
     /**
      * Will be called if the users clicks the negativ button on a ChechlistDialog.
      * @param  dialog  {@link ChecklistDialog ChecklistDialog }

+ 39 - 22
src/de/tudarmstadt/informatik/hostage/ui/fragment/ThreatMapFragment.java

@@ -9,12 +9,16 @@ import java.util.Map;
 
 import android.app.Activity;
 import android.app.AlertDialog;
-import android.app.Fragment;
 import android.app.FragmentManager;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.Color;
+import android.location.Criteria;
 import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
 import android.os.Bundle;
+import android.text.Html;
 import android.view.InflateException;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -23,9 +27,6 @@ import android.widget.TextView;
 
 import com.google.android.gms.common.ConnectionResult;
 import com.google.android.gms.common.GooglePlayServicesClient;
-import com.google.android.gms.location.LocationClient;
-import com.google.android.gms.location.LocationListener;
-import com.google.android.gms.location.LocationRequest;
 import com.google.android.gms.maps.CameraUpdateFactory;
 import com.google.android.gms.maps.GoogleMap;
 import com.google.android.gms.maps.MapFragment;
@@ -61,13 +62,9 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 
 	private static HashMap<String, String> sMarkerIDToSSID = new HashMap<String, String>();
 
-	private LocationClient mLocationClient;
-
-	private static final LocationRequest REQUEST = LocationRequest.create()
-			.setExpirationDuration(5000) // 5 seconds
-			.setInterval(5000)           // 5 seconds
-			.setFastestInterval(16)      // 16ms = 60fps
-			.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
+	private LocationManager mLocationManager;
+	//private LocationClient mLocationClient;
+	private String mLocationProvider;
 
 	/**
 	 * if google play services aren't available an error notification will be displayed
@@ -117,17 +114,14 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 	 */
 	@Override
 	public void onConnected(Bundle bundle) {
-		mLocationClient.requestLocationUpdates(REQUEST, this);
 	}
 
 	@Override
 	public void onDisconnected() {
-
 	}
 
 	@Override
 	public void onConnectionFailed(ConnectionResult connectionResult) {
-
 	}
 
 	@Override
@@ -136,6 +130,18 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 				new LatLng(location.getLatitude(), location.getLongitude())));
 	}
 
+	@Override
+	public void onStatusChanged(String provider, int status, Bundle extras) {
+	}
+
+	@Override
+	public void onProviderEnabled(String provider) {
+	}
+
+	@Override
+	public void onProviderDisabled(String provider) {
+	}
+
 	/**
 	 * helper class
 	 * easier to use than LatLng
@@ -353,6 +359,17 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 						sMap = mapFragment.getMap();
 					}
 				}
+			} else {
+				AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.getInstance());
+				builder.setMessage(Html.fromHtml(getString(R.string.google_play_services_unavailable)))
+						.setCancelable(false)
+						.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
+							public void onClick(DialogInterface dialog, int id) {
+								// :D-|< :D-/< :D-\<
+							}
+						});
+				AlertDialog alert = builder.create();
+				alert.show();
 			}
 		} catch (InflateException e) {
 			// map already exists
@@ -382,6 +399,12 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 				}
 			});
 
+			mLocationManager = (LocationManager)activity.getSystemService(Context.LOCATION_SERVICE);
+			Criteria criteria = new Criteria();
+			criteria.setAccuracy(Criteria.ACCURACY_FINE);
+			mLocationProvider = mLocationManager.getBestProvider(criteria, false);
+			mLocationManager.requestLocationUpdates(mLocationProvider, (long)0, 1000.0f, (LocationListener)this);
+
 			sMap.setMyLocationEnabled(true);
 
 			LatLng tudarmstadt = new LatLng(49.86923, 8.6632768); // default location
@@ -411,18 +434,12 @@ public class ThreatMapFragment extends TrackerFragment implements GoogleMap.OnIn
 	@Override
 	public void onResume() {
 		super.onResume();
-		if (mLocationClient == null) {
-			mLocationClient = new LocationClient(MainActivity.getInstance().getApplicationContext(),
-					this, this);
-		}
-		mLocationClient.connect();
+		mLocationManager.requestLocationUpdates(mLocationProvider, 0, 1000.0f, this);
 	}
 
 	@Override
 	public void onPause() {
 		super.onPause();
-		if (mLocationClient != null) {
-			mLocationClient.disconnect();
-		}
+		mLocationManager.removeUpdates(this);
 	}
 }