Android Open Source - privacypolice Scan Results Checker






From Project

Back to project page privacypolice.

License

The source code is released under:

GNU General Public License

If you think the Android project privacypolice listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* 
 * Copyright 2014, 2015 Bram Bonn// w w  w.java2 s.c o m
 *
 * This file is part of Wi-Fi PrivacyPolice.
 * 
 * Wi-Fi PrivacyPolice is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * Wi-Fi PrivacyPolice is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Wi-Fi PrivacyPolice.  If not, see <http://www.gnu.org/licenses/>.
*/

package be.uhasselt.privacypolice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.util.Log;

import java.util.List;
import java.util.Set;

/**
 * This class contains the actual logic for deciding whether a network connection is allowed.
 * It receives the broadcast intents for new scan results, in order to decide whether a network is
 * available. It then checks whether we trust the AP's MAC address, based on the user's configuration.
 */

public class ScanResultsChecker extends BroadcastReceiver {

    private enum AccessPointSafety {
        TRUSTED, UNTRUSTED, UNKNOWN
    }

    private static long lastCheck = 0;
    private static PreferencesStorage prefs = null;
    private WifiManager wifiManager = null;
    private NotificationHandler notificationHandler = null;

    /**
     * Called for the following intents:
     *  - SCAN_RESULTS available
     *  - BOOT_COMPLETED
     */
    public void onReceive(Context ctx, Intent i){
        // Older devices might try to scan constantly. Allow them some rest by checking max. once every 0.5 seconds
        if (System.currentTimeMillis() - lastCheck < 500)
            return;
        lastCheck = System.currentTimeMillis();

        // WiFi scan performed
        wifiManager =  (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
        prefs = new PreferencesStorage(ctx);
        notificationHandler = new NotificationHandler(ctx);

        // Keep whether the getNetworkSafety function asked the user for input (to know whether we
        // have to disable any notifications afterwards, and to keep the UX as smooth as possible).
        // Alternatively, we would disable previous notifications here, but that would lead to the
        // notification being jittery (disappearing and re-appearing instantly, instead of just
        // updating).
        boolean notificationShown = false;

        try {
            List<ScanResult> scanResults = wifiManager.getScanResults();
            Log.d("WiFiPolice", "Wi-Fi scan performed, results are: " + scanResults.toString());

            // Collect number of found networks, if allowed by user
            /*Analytics analytics = new Analytics(ctx);
            analytics.scanCompleted(scanResults.size());*/

            List<WifiConfiguration> networkList = wifiManager.getConfiguredNetworks();
            // Check for every network in our network list whether it should be enabled
            for (WifiConfiguration network : networkList) {
                AccessPointSafety networkSafety = getNetworkSafety(network, scanResults);
                if (networkSafety == AccessPointSafety.TRUSTED) {
                    Log.i("WiFiPolice", "Enabling " + network.SSID);
                    // Do not disable other networks, as multiple networks may be available
                    wifiManager.enableNetwork(network.networkId, false);
                    // If we aren't already connected to a network, make sure that Android connects.
                    // This is required for devices running Android Lollipop (5.0) and up, because
                    // they would otherwise never connect.
                    if (!wifiManager.reconnect()) {
                        Log.e("WifiPolice", "Could not reconnect after enabling network");
                    }
                } else if (networkSafety == AccessPointSafety.UNTRUSTED) {
                    // Make sure all other networks are disabled, by disabling them separately
                    // (See previous comment to see why we don't disable all of them at the same
                    // time)
                    wifiManager.disableNetwork(network.networkId);
                } else if (networkSafety == AccessPointSafety.UNKNOWN) {
                    wifiManager.disableNetwork(network.networkId);
                    notificationShown = true;
                }
            }
        } catch (NullPointerException npe) {
            Log.e("WiFiPolice", "Null pointer exception when handling networks. Wi-Fi was probably suddenly disabled after a scan.");
        }

        if (!notificationShown)
            // Disable previous notifications, to make sure that we only request permission for the
            // currently available networks (and not at the wrong location)
            notificationHandler.disableNotifications();
    }

    /**
     * Checks whether we should allow connection to a given network, based on the user's preferences
     * It will also ask the user if it is unknown whether the network should be trusted.
     * @param network The network that should be checked
     * @param scanResults The networks that are currently available
     * @return TRUSTED or UNTRUSTED, based on the user's preferences, or UNKNOWN if the user didn't
     *          specify anything yet
     */
    private AccessPointSafety getNetworkSafety(WifiConfiguration network, List<ScanResult> scanResults) {
        // If all settings are disabled by the user, then allow every network
        // This effectively disables all of the app's functionalities
        if (!(prefs.getEnableOnlyAvailableNetworks() || prefs.getOnlyConnectToKnownAccessPoints()))
            return AccessPointSafety.TRUSTED; // Allow every network

        // Always enable hidden networks, since they *need* to use directed probe requests
        // in order to be discovered. Note that using hidden SSID's does not add any
        // real security , so it's best to avoid them whenever possible.
        if (network.hiddenSSID)
            return AccessPointSafety.TRUSTED;

        // Strip double quotes (") from the SSID string
        String plainSSID = network.SSID.substring(1, network.SSID.length() - 1);

        for (ScanResult scanResult : scanResults) {
            if (scanResult.SSID.equals(plainSSID)) {
                // Check whether the user wants to filter by MAC address
                if (!prefs.getOnlyConnectToKnownAccessPoints()) { // Any MAC address is fair game
                    // Enabling now makes sure that we only want to connect when it is in range
                    return AccessPointSafety.TRUSTED;
                } else { // Check access point's MAC address
                    // Check if the MAC address is in the list of allowed MAC's for this SSID
                    Set<String> allowedBSSIDs = prefs.getAllowedBSSIDs(scanResult.SSID);
                    if (allowedBSSIDs.contains(scanResult.BSSID)) {
                        return AccessPointSafety.TRUSTED;
                    } else {
                        // Not an allowed BSSID
                        if (prefs.getBlockedBSSIDs().contains(scanResult.BSSID)) {
                            // This SSID was explicitly blocked by the user!
                            Log.w("WiFiPolice", "Spoofed network for " + scanResult.SSID + " detected! (BSSID is " + scanResult.BSSID + ")");
                            return AccessPointSafety.UNTRUSTED;
                        } else {
                            // We don't know yet whether the user wants to allow this network
                            // Ask the user what needs to be done
                            notificationHandler.askNetworkPermission(scanResult.SSID, scanResult.BSSID);
                            return AccessPointSafety.UNKNOWN;
                        }
                    }
                }
            }
        }
        return AccessPointSafety.UNTRUSTED; // Network not in range
    }
}




Java Source Code List

be.uhasselt.privacypolice.Analytics.java
be.uhasselt.privacypolice.AskPermissionActivity.java
be.uhasselt.privacypolice.NotificationHandler.java
be.uhasselt.privacypolice.PermissionChangeReceiver.java
be.uhasselt.privacypolice.PreferencesActivity.java
be.uhasselt.privacypolice.PreferencesStorage.java
be.uhasselt.privacypolice.ScanResultsChecker.java