summaryrefslogtreecommitdiffstats
path: root/service/java/com/android/server/wifi/WifiConfigStore.java
diff options
context:
space:
mode:
Diffstat (limited to 'service/java/com/android/server/wifi/WifiConfigStore.java')
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java2001
1 files changed, 0 insertions, 2001 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
deleted file mode 100644
index 6ce473288..000000000
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ /dev/null
@@ -1,2001 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.NetworkUtils;
-import android.net.NetworkInfo.DetailedState;
-import android.net.ProxyProperties;
-import android.net.RouteInfo;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.IpAssignment;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
-import android.net.wifi.WifiConfiguration.Status;
-import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
-
-import android.net.wifi.WifiEnterpriseConfig;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiSsid;
-import android.net.wifi.WpsInfo;
-import android.net.wifi.WpsResult;
-import android.os.Environment;
-import android.os.FileObserver;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.os.UserHandle;
-import android.security.Credentials;
-import android.security.KeyChain;
-import android.security.KeyStore;
-import android.text.TextUtils;
-import android.util.LocalLog;
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This class provides the API to manage configured
- * wifi networks. The API is not thread safe is being
- * used only from WifiStateMachine.
- *
- * It deals with the following
- * - Add/update/remove a WifiConfiguration
- * The configuration contains two types of information.
- * = IP and proxy configuration that is handled by WifiConfigStore and
- * is saved to disk on any change.
- *
- * The format of configuration file is as follows:
- * <version>
- * <netA_key1><netA_value1><netA_key2><netA_value2>...<EOS>
- * <netB_key1><netB_value1><netB_key2><netB_value2>...<EOS>
- * ..
- *
- * (key, value) pairs for a given network are grouped together and can
- * be in any order. A EOS at the end of a set of (key, value) pairs
- * indicates that the next set of (key, value) pairs are for a new
- * network. A network is identified by a unique ID_KEY. If there is no
- * ID_KEY in the (key, value) pairs, the data is discarded.
- *
- * An invalid version on read would result in discarding the contents of
- * the file. On the next write, the latest version is written to file.
- *
- * Any failures during read or write to the configuration file are ignored
- * without reporting to the user since the likelihood of these errors are
- * low and the impact on connectivity is low.
- *
- * = SSID & security details that is pushed to the supplicant.
- * supplicant saves these details to the disk on calling
- * saveConfigCommand().
- *
- * We have two kinds of APIs exposed:
- * > public API calls that provide fine grained control
- * - enableNetwork, disableNetwork, addOrUpdateNetwork(),
- * removeNetwork(). For these calls, the config is not persisted
- * to the disk. (TODO: deprecate these calls in WifiManager)
- * > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork().
- * These calls persist the supplicant config to disk.
- *
- * - Maintain a list of configured networks for quick access
- *
- */
-public class WifiConfigStore {
-
- private Context mContext;
- private static final String TAG = "WifiConfigStore";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- private static final String SUPPLICANT_CONFIG_FILE = "/data/misc/wifi/wpa_supplicant.conf";
-
- /* configured networks with network id as the key */
- private HashMap<Integer, WifiConfiguration> mConfiguredNetworks =
- new HashMap<Integer, WifiConfiguration>();
-
- /* A network id is a unique identifier for a network configured in the
- * supplicant. Network ids are generated when the supplicant reads
- * the configuration file at start and can thus change for networks.
- * We store the IP configuration for networks along with a unique id
- * that is generated from SSID and security type of the network. A mapping
- * from the generated unique id to network id of the network is needed to
- * map supplicant config to IP configuration. */
- private HashMap<Integer, Integer> mNetworkIds =
- new HashMap<Integer, Integer>();
-
- /* Tracks the highest priority of configured networks */
- private int mLastPriority = -1;
-
- private static final String ipConfigFile = Environment.getDataDirectory() +
- "/misc/wifi/ipconfig.txt";
-
- private static final int IPCONFIG_FILE_VERSION = 2;
-
- /* IP and proxy configuration keys */
- private static final String ID_KEY = "id";
- private static final String IP_ASSIGNMENT_KEY = "ipAssignment";
- private static final String LINK_ADDRESS_KEY = "linkAddress";
- private static final String GATEWAY_KEY = "gateway";
- private static final String DNS_KEY = "dns";
- private static final String PROXY_SETTINGS_KEY = "proxySettings";
- private static final String PROXY_HOST_KEY = "proxyHost";
- private static final String PROXY_PORT_KEY = "proxyPort";
- private static final String PROXY_PAC_FILE = "proxyPac";
- private static final String EXCLUSION_LIST_KEY = "exclusionList";
- private static final String EOS = "eos";
-
-
- /* Enterprise configuration keys */
- /**
- * In old configurations, the "private_key" field was used. However, newer
- * configurations use the key_id field with the engine_id set to "keystore".
- * If this field is found in the configuration, the migration code is
- * triggered.
- */
- public static final String OLD_PRIVATE_KEY_NAME = "private_key";
-
- /** This represents an empty value of an enterprise field.
- * NULL is used at wpa_supplicant to indicate an empty value
- */
- static final String EMPTY_VALUE = "NULL";
-
- /** Internal use only */
- private static final String[] ENTERPRISE_CONFIG_SUPPLICANT_KEYS = new String[] {
- WifiEnterpriseConfig.EAP_KEY, WifiEnterpriseConfig.PHASE2_KEY,
- WifiEnterpriseConfig.IDENTITY_KEY, WifiEnterpriseConfig.ANON_IDENTITY_KEY,
- WifiEnterpriseConfig.PASSWORD_KEY, WifiEnterpriseConfig.CLIENT_CERT_KEY,
- WifiEnterpriseConfig.CA_CERT_KEY, WifiEnterpriseConfig.SUBJECT_MATCH_KEY,
- WifiEnterpriseConfig.ENGINE_KEY, WifiEnterpriseConfig.ENGINE_ID_KEY,
- WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY };
-
- private final LocalLog mLocalLog;
- private final WpaConfigFileObserver mFileObserver;
-
- private WifiNative mWifiNative;
- private final KeyStore mKeyStore = KeyStore.getInstance();
-
- WifiConfigStore(Context c, WifiNative wn) {
- mContext = c;
- mWifiNative = wn;
-
- if (VDBG) {
- mLocalLog = mWifiNative.getLocalLog();
- mFileObserver = new WpaConfigFileObserver();
- mFileObserver.startWatching();
- } else {
- mLocalLog = null;
- mFileObserver = null;
- }
- }
-
- class WpaConfigFileObserver extends FileObserver {
-
- public WpaConfigFileObserver() {
- super(SUPPLICANT_CONFIG_FILE, CLOSE_WRITE);
- }
-
- @Override
- public void onEvent(int event, String path) {
- if (event == CLOSE_WRITE) {
- File file = new File(SUPPLICANT_CONFIG_FILE);
- if (VDBG) localLog("wpa_supplicant.conf changed; new size = " + file.length());
- }
- }
- }
-
-
- /**
- * Fetch the list of configured networks
- * and enable all stored networks in supplicant.
- */
- void loadAndEnableAllNetworks() {
- if (DBG) log("Loading config and enabling all networks");
- loadConfiguredNetworks();
- enableAllNetworks();
- }
-
- /**
- * Fetch the list of currently configured networks
- * @return List of networks
- */
- List<WifiConfiguration> getConfiguredNetworks() {
- List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- networks.add(new WifiConfiguration(config));
- }
- return networks;
- }
-
- /**
- * enable all networks and save config. This will be a no-op if the list
- * of configured networks indicates all networks as being enabled
- */
- void enableAllNetworks() {
- boolean networkEnabledStateChanged = false;
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.status == Status.DISABLED) {
- if(mWifiNative.enableNetwork(config.networkId, false)) {
- networkEnabledStateChanged = true;
- config.status = Status.ENABLED;
- } else {
- loge("Enable network failed on " + config.networkId);
- }
- }
- }
-
- if (networkEnabledStateChanged) {
- mWifiNative.saveConfig();
- sendConfiguredNetworksChangedBroadcast();
- }
- }
-
-
- /**
- * Selects the specified network for connection. This involves
- * updating the priority of all the networks and enabling the given
- * network while disabling others.
- *
- * Selecting a network will leave the other networks disabled and
- * a call to enableAllNetworks() needs to be issued upon a connection
- * or a failure event from supplicant
- *
- * @param netId network to select for connection
- * @return false if the network id is invalid
- */
- boolean selectNetwork(int netId) {
- if (VDBG) localLog("selectNetwork", netId);
- if (netId == INVALID_NETWORK_ID) return false;
-
- // Reset the priority of each network at start or if it goes too high.
- if (mLastPriority == -1 || mLastPriority > 1000000) {
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if (config.networkId != INVALID_NETWORK_ID) {
- config.priority = 0;
- addOrUpdateNetworkNative(config);
- }
- }
- mLastPriority = 0;
- }
-
- // Set to the highest priority and save the configuration.
- WifiConfiguration config = new WifiConfiguration();
- config.networkId = netId;
- config.priority = ++mLastPriority;
-
- addOrUpdateNetworkNative(config);
- mWifiNative.saveConfig();
-
- /* Enable the given network while disabling all other networks */
- enableNetworkWithoutBroadcast(netId, true);
-
- /* Avoid saving the config & sending a broadcast to prevent settings
- * from displaying a disabled list of networks */
- return true;
- }
-
- /**
- * Add/update the specified configuration and save config
- *
- * @param config WifiConfiguration to be saved
- * @return network update result
- */
- NetworkUpdateResult saveNetwork(WifiConfiguration config) {
- if (VDBG) localLog("saveNetwork", config.networkId);
- // A new network cannot have null SSID
- if (config == null || (config.networkId == INVALID_NETWORK_ID &&
- config.SSID == null)) {
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
-
- boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
- NetworkUpdateResult result = addOrUpdateNetworkNative(config);
- int netId = result.getNetworkId();
- /* enable a new network */
- if (newNetwork && netId != INVALID_NETWORK_ID) {
- mWifiNative.enableNetwork(netId, false);
- mConfiguredNetworks.get(netId).status = Status.ENABLED;
- }
- mWifiNative.saveConfig();
- sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
- WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- return result;
- }
-
- void updateStatus(int netId, DetailedState state) {
- if (netId != INVALID_NETWORK_ID) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config == null) return;
- switch (state) {
- case CONNECTED:
- config.status = Status.CURRENT;
- break;
- case DISCONNECTED:
- //If network is already disabled, keep the status
- if (config.status == Status.CURRENT) {
- config.status = Status.ENABLED;
- }
- break;
- default:
- //do nothing, retain the existing state
- break;
- }
- }
- }
-
- /**
- * Forget the specified network and save config
- *
- * @param netId network to forget
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean forgetNetwork(int netId) {
- if (VDBG) localLog("forgetNetwork", netId);
- if (mWifiNative.removeNetwork(netId)) {
- mWifiNative.saveConfig();
- removeConfigAndSendBroadcastIfNeeded(netId);
- return true;
- } else {
- loge("Failed to remove network " + netId);
- return false;
- }
- }
-
- /**
- * Add/update a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful saveNetwork() is used by the
- * state machine
- *
- * @param config wifi configuration to add/update
- * @return network Id
- */
- int addOrUpdateNetwork(WifiConfiguration config) {
- if (VDBG) localLog("addOrUpdateNetwork", config.networkId);
- NetworkUpdateResult result = addOrUpdateNetworkNative(config);
- if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
- sendConfiguredNetworksChangedBroadcast(mConfiguredNetworks.get(result.getNetworkId()),
- result.isNewNetwork ? WifiManager.CHANGE_REASON_ADDED :
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return result.getNetworkId();
- }
-
- /**
- * Remove a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful forgetNetwork() is used by the
- * state machine for network removal
- *
- * @param netId network to be removed
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean removeNetwork(int netId) {
- if (VDBG) localLog("removeNetwork", netId);
- boolean ret = mWifiNative.removeNetwork(netId);
- if (ret) {
- removeConfigAndSendBroadcastIfNeeded(netId);
- }
- return ret;
- }
-
- private void removeConfigAndSendBroadcastIfNeeded(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) {
- // Remove any associated keys
- if (config.enterpriseConfig != null) {
- removeKeys(config.enterpriseConfig);
- }
- mConfiguredNetworks.remove(netId);
- mNetworkIds.remove(configKey(config));
-
- writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
- }
- }
-
- /**
- * Enable a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful selectNetwork()/saveNetwork() is used by the
- * state machine for connecting to a network
- *
- * @param netId network to be enabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean enableNetwork(int netId, boolean disableOthers) {
- boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers);
- if (disableOthers) {
- if (VDBG) localLog("enableNetwork(disableOthers=true) ", netId);
- sendConfiguredNetworksChangedBroadcast();
- } else {
- if (VDBG) localLog("enableNetwork(disableOthers=false) ", netId);
- WifiConfiguration enabledNetwork = null;
- synchronized(mConfiguredNetworks) {
- enabledNetwork = mConfiguredNetworks.get(netId);
- }
- // check just in case the network was removed by someone else.
- if (enabledNetwork != null) {
- sendConfiguredNetworksChangedBroadcast(enabledNetwork,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- }
- return ret;
- }
-
- boolean enableNetworkWithoutBroadcast(int netId, boolean disableOthers) {
- boolean ret = mWifiNative.enableNetwork(netId, disableOthers);
-
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) config.status = Status.ENABLED;
-
- if (disableOthers) {
- markAllNetworksDisabledExcept(netId);
- }
- return ret;
- }
-
- void disableAllNetworks() {
- if (VDBG) localLog("disableAllNetworks");
- boolean networkDisabled = false;
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.status != Status.DISABLED) {
- if(mWifiNative.disableNetwork(config.networkId)) {
- networkDisabled = true;
- config.status = Status.DISABLED;
- } else {
- loge("Disable network failed on " + config.networkId);
- }
- }
- }
-
- if (networkDisabled) {
- sendConfiguredNetworksChangedBroadcast();
- }
- }
- /**
- * Disable a network. Note that there is no saveConfig operation.
- * @param netId network to be disabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean disableNetwork(int netId) {
- return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON);
- }
-
- /**
- * Disable a network. Note that there is no saveConfig operation.
- * @param netId network to be disabled
- * @param reason reason code network was disabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean disableNetwork(int netId, int reason) {
- if (VDBG) localLog("disableNetwork", netId);
- boolean ret = mWifiNative.disableNetwork(netId);
- WifiConfiguration network = null;
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- /* Only change the reason if the network was not previously disabled */
- if (config != null && config.status != Status.DISABLED) {
- config.status = Status.DISABLED;
- config.disableReason = reason;
- network = config;
- }
- if (network != null) {
- sendConfiguredNetworksChangedBroadcast(network,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return ret;
- }
-
- /**
- * Save the configured networks in supplicant to disk
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean saveConfig() {
- return mWifiNative.saveConfig();
- }
-
- /**
- * Start WPS pin method configuration with pin obtained
- * from the access point
- * @param config WPS configuration
- * @return Wps result containing status and pin
- */
- WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) {
- WpsResult result = new WpsResult();
- if (mWifiNative.startWpsRegistrar(config.BSSID, config.pin)) {
- /* WPS leaves all networks disabled */
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS pin method configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Start WPS pin method configuration with pin obtained
- * from the device
- * @return WpsResult indicating status and pin
- */
- WpsResult startWpsWithPinFromDevice(WpsInfo config) {
- WpsResult result = new WpsResult();
- result.pin = mWifiNative.startWpsPinDisplay(config.BSSID);
- /* WPS leaves all networks disabled */
- if (!TextUtils.isEmpty(result.pin)) {
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS pin method configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Start WPS push button configuration
- * @param config WPS configuration
- * @return WpsResult indicating status and pin
- */
- WpsResult startWpsPbc(WpsInfo config) {
- WpsResult result = new WpsResult();
- if (mWifiNative.startWpsPbc(config.BSSID)) {
- /* WPS leaves all networks disabled */
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS push button configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Fetch the link properties for a given network id
- * @return LinkProperties for the given network id
- */
- LinkProperties getLinkProperties(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) return new LinkProperties(config.linkProperties);
- return null;
- }
-
- /**
- * set IP configuration for a given network id
- */
- void setLinkProperties(int netId, LinkProperties linkProperties) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) {
- // add old proxy details - TODO - is this still needed?
- if(config.linkProperties != null) {
- linkProperties.setHttpProxy(config.linkProperties.getHttpProxy());
- }
- config.linkProperties = linkProperties;
- }
- }
-
- /**
- * clear IP configuration for a given network id
- * @param network id
- */
- void clearLinkProperties(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null && config.linkProperties != null) {
- // Clear everything except proxy
- ProxyProperties proxy = config.linkProperties.getHttpProxy();
- config.linkProperties.clear();
- config.linkProperties.setHttpProxy(proxy);
- }
- }
-
-
- /**
- * Fetch the proxy properties for a given network id
- * @param network id
- * @return ProxyProperties for the network id
- */
- ProxyProperties getProxyProperties(int netId) {
- LinkProperties linkProperties = getLinkProperties(netId);
- if (linkProperties != null) {
- return new ProxyProperties(linkProperties.getHttpProxy());
- }
- return null;
- }
-
- /**
- * Return if the specified network is using static IP
- * @param network id
- * @return {@code true} if using static ip for netId
- */
- boolean isUsingStaticIp(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null && config.ipAssignment == IpAssignment.STATIC) {
- return true;
- }
- return false;
- }
-
- /**
- * Should be called when a single network configuration is made.
- * @param network The network configuration that changed.
- * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
- * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
- */
- private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
- int reason) {
- Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
- intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
- intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- /**
- * Should be called when multiple network configuration changes are made.
- */
- private void sendConfiguredNetworksChangedBroadcast() {
- Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- void loadConfiguredNetworks() {
- String listStr = mWifiNative.listNetworks();
- mLastPriority = 0;
-
- mConfiguredNetworks.clear();
- mNetworkIds.clear();
-
- if (listStr == null)
- return;
-
- String[] lines = listStr.split("\n");
- // Skip the first line, which is a header
- for (int i = 1; i < lines.length; i++) {
- String[] result = lines[i].split("\t");
- // network-id | ssid | bssid | flags
- WifiConfiguration config = new WifiConfiguration();
- try {
- config.networkId = Integer.parseInt(result[0]);
- } catch(NumberFormatException e) {
- loge("Failed to read network-id '" + result[0] + "'");
- continue;
- }
- if (result.length > 3) {
- if (result[3].indexOf("[CURRENT]") != -1)
- config.status = WifiConfiguration.Status.CURRENT;
- else if (result[3].indexOf("[DISABLED]") != -1)
- config.status = WifiConfiguration.Status.DISABLED;
- else
- config.status = WifiConfiguration.Status.ENABLED;
- } else {
- config.status = WifiConfiguration.Status.ENABLED;
- }
- readNetworkVariables(config);
- if (config.priority > mLastPriority) {
- mLastPriority = config.priority;
- }
- config.ipAssignment = IpAssignment.DHCP;
- config.proxySettings = ProxySettings.NONE;
-
- if (mNetworkIds.containsKey(configKey(config))) {
- // That SSID is already known, just ignore this duplicate entry
- if (VDBG) localLog("discarded duplicate network", config.networkId);
- } else {
- mConfiguredNetworks.put(config.networkId, config);
- mNetworkIds.put(configKey(config), config.networkId);
- if (VDBG) localLog("loaded configured network", config.networkId);
- }
- }
-
- readIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast();
-
- if (VDBG) localLog("loadConfiguredNetworks loaded " + mNetworkIds.size() + " networks");
-
- if (mNetworkIds.size() == 0) {
- // no networks? Lets log if the wpa_supplicant.conf file contents
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(SUPPLICANT_CONFIG_FILE));
- if (VDBG) localLog("--- Begin wpa_supplicant.conf Contents ---");
- for (String line = reader.readLine(); line != null; line = reader.readLine()) {
- if (VDBG) localLog(line);
- }
- if (VDBG) localLog("--- End wpa_supplicant.conf Contents ---");
- } catch (FileNotFoundException e) {
- if (VDBG) localLog("Could not open " + SUPPLICANT_CONFIG_FILE + ", " + e);
- } catch (IOException e) {
- if (VDBG) localLog("Could not read " + SUPPLICANT_CONFIG_FILE + ", " + e);
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- // Just ignore the fact that we couldn't close
- }
- }
- }
- }
-
- /* Mark all networks except specified netId as disabled */
- private void markAllNetworksDisabledExcept(int netId) {
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.networkId != netId) {
- if (config.status != Status.DISABLED) {
- config.status = Status.DISABLED;
- config.disableReason = WifiConfiguration.DISABLED_UNKNOWN_REASON;
- }
- }
- }
- }
-
- private void markAllNetworksDisabled() {
- markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
- }
-
- boolean needsUnlockedKeyStore() {
-
- // Any network using certificates to authenticate access requires
- // unlocked key store; unless the certificates can be stored with
- // hardware encryption
-
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
-
- if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
- && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
-
- if (needsSoftwareBackedKeyStore(config.enterpriseConfig)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- private void writeIpAndProxyConfigurations() {
-
- /* Make a copy */
- List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- networks.add(new WifiConfiguration(config));
- }
-
- DelayedDiskWrite.write(networks);
- }
-
- private static class DelayedDiskWrite {
-
- private static HandlerThread sDiskWriteHandlerThread;
- private static Handler sDiskWriteHandler;
- /* Tracks multiple writes on the same thread */
- private static int sWriteSequence = 0;
- private static final String TAG = "DelayedDiskWrite";
-
- static void write (final List<WifiConfiguration> networks) {
-
- /* Do a delayed write to disk on a seperate handler thread */
- synchronized (DelayedDiskWrite.class) {
- if (++sWriteSequence == 1) {
- sDiskWriteHandlerThread = new HandlerThread("WifiConfigThread");
- sDiskWriteHandlerThread.start();
- sDiskWriteHandler = new Handler(sDiskWriteHandlerThread.getLooper());
- }
- }
-
- sDiskWriteHandler.post(new Runnable() {
- @Override
- public void run() {
- onWriteCalled(networks);
- }
- });
- }
-
- private static void onWriteCalled(List<WifiConfiguration> networks) {
-
- DataOutputStream out = null;
- try {
- out = new DataOutputStream(new BufferedOutputStream(
- new FileOutputStream(ipConfigFile)));
-
- out.writeInt(IPCONFIG_FILE_VERSION);
-
- for(WifiConfiguration config : networks) {
- boolean writeToFile = false;
-
- try {
- LinkProperties linkProperties = config.linkProperties;
- switch (config.ipAssignment) {
- case STATIC:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.ipAssignment.toString());
- for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
- out.writeUTF(LINK_ADDRESS_KEY);
- out.writeUTF(linkAddr.getAddress().getHostAddress());
- out.writeInt(linkAddr.getNetworkPrefixLength());
- }
- for (RouteInfo route : linkProperties.getRoutes()) {
- out.writeUTF(GATEWAY_KEY);
- LinkAddress dest = route.getDestination();
- if (dest != null) {
- out.writeInt(1);
- out.writeUTF(dest.getAddress().getHostAddress());
- out.writeInt(dest.getNetworkPrefixLength());
- } else {
- out.writeInt(0);
- }
- if (route.getGateway() != null) {
- out.writeInt(1);
- out.writeUTF(route.getGateway().getHostAddress());
- } else {
- out.writeInt(0);
- }
- }
- for (InetAddress inetAddr : linkProperties.getDnses()) {
- out.writeUTF(DNS_KEY);
- out.writeUTF(inetAddr.getHostAddress());
- }
- writeToFile = true;
- break;
- case DHCP:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.ipAssignment.toString());
- writeToFile = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid ip assignment while writing");
- break;
- }
-
- switch (config.proxySettings) {
- case STATIC:
- ProxyProperties proxyProperties = linkProperties.getHttpProxy();
- String exclusionList = proxyProperties.getExclusionList();
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- out.writeUTF(PROXY_HOST_KEY);
- out.writeUTF(proxyProperties.getHost());
- out.writeUTF(PROXY_PORT_KEY);
- out.writeInt(proxyProperties.getPort());
- out.writeUTF(EXCLUSION_LIST_KEY);
- out.writeUTF(exclusionList);
- writeToFile = true;
- break;
- case PAC:
- ProxyProperties proxyPacProperties = linkProperties.getHttpProxy();
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- out.writeUTF(PROXY_PAC_FILE);
- out.writeUTF(proxyPacProperties.getPacFileUrl());
- writeToFile = true;
- break;
- case NONE:
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- writeToFile = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignthisore invalid proxy settings while writing");
- break;
- }
- if (writeToFile) {
- out.writeUTF(ID_KEY);
- out.writeInt(configKey(config));
- }
- } catch (NullPointerException e) {
- loge("Failure in writing " + config.linkProperties + e);
- }
- out.writeUTF(EOS);
- }
-
- } catch (IOException e) {
- loge("Error writing data file");
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception e) {}
- }
-
- //Quit if no more writes sent
- synchronized (DelayedDiskWrite.class) {
- if (--sWriteSequence == 0) {
- sDiskWriteHandler.getLooper().quit();
- sDiskWriteHandler = null;
- sDiskWriteHandlerThread = null;
- }
- }
- }
- }
-
- private static void loge(String s) {
- Log.e(TAG, s);
- }
- }
-
- private void readIpAndProxyConfigurations() {
-
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(new FileInputStream(
- ipConfigFile)));
-
- int version = in.readInt();
- if (version != 2 && version != 1) {
- loge("Bad version on IP configuration file, ignore read");
- return;
- }
-
- while (true) {
- int id = -1;
- // Default is DHCP with no proxy
- IpAssignment ipAssignment = IpAssignment.DHCP;
- ProxySettings proxySettings = ProxySettings.NONE;
- LinkProperties linkProperties = new LinkProperties();
- String proxyHost = null;
- String pacFileUrl = null;
- int proxyPort = -1;
- String exclusionList = null;
- String key;
-
- do {
- key = in.readUTF();
- try {
- if (key.equals(ID_KEY)) {
- id = in.readInt();
- } else if (key.equals(IP_ASSIGNMENT_KEY)) {
- ipAssignment = IpAssignment.valueOf(in.readUTF());
- } else if (key.equals(LINK_ADDRESS_KEY)) {
- LinkAddress linkAddr = new LinkAddress(
- NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
- linkProperties.addLinkAddress(linkAddr);
- } else if (key.equals(GATEWAY_KEY)) {
- LinkAddress dest = null;
- InetAddress gateway = null;
- if (version == 1) {
- // only supported default gateways - leave the dest/prefix empty
- gateway = NetworkUtils.numericToInetAddress(in.readUTF());
- } else {
- if (in.readInt() == 1) {
- dest = new LinkAddress(
- NetworkUtils.numericToInetAddress(in.readUTF()),
- in.readInt());
- }
- if (in.readInt() == 1) {
- gateway = NetworkUtils.numericToInetAddress(in.readUTF());
- }
- }
- linkProperties.addRoute(new RouteInfo(dest, gateway));
- } else if (key.equals(DNS_KEY)) {
- linkProperties.addDns(
- NetworkUtils.numericToInetAddress(in.readUTF()));
- } else if (key.equals(PROXY_SETTINGS_KEY)) {
- proxySettings = ProxySettings.valueOf(in.readUTF());
- } else if (key.equals(PROXY_HOST_KEY)) {
- proxyHost = in.readUTF();
- } else if (key.equals(PROXY_PORT_KEY)) {
- proxyPort = in.readInt();
- } else if (key.equals(PROXY_PAC_FILE)) {
- pacFileUrl = in.readUTF();
- } else if (key.equals(EXCLUSION_LIST_KEY)) {
- exclusionList = in.readUTF();
- } else if (key.equals(EOS)) {
- break;
- } else {
- loge("Ignore unknown key " + key + "while reading");
- }
- } catch (IllegalArgumentException e) {
- loge("Ignore invalid address while reading" + e);
- }
- } while (true);
-
- if (id != -1) {
- WifiConfiguration config = mConfiguredNetworks.get(
- mNetworkIds.get(id));
-
- if (config == null) {
- loge("configuration found for missing network, ignored");
- } else {
- config.linkProperties = linkProperties;
- switch (ipAssignment) {
- case STATIC:
- case DHCP:
- config.ipAssignment = ipAssignment;
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED IP on file, use DHCP");
- config.ipAssignment = IpAssignment.DHCP;
- break;
- default:
- loge("Ignore invalid ip assignment while reading");
- break;
- }
-
- switch (proxySettings) {
- case STATIC:
- config.proxySettings = proxySettings;
- ProxyProperties proxyProperties =
- new ProxyProperties(proxyHost, proxyPort, exclusionList);
- linkProperties.setHttpProxy(proxyProperties);
- break;
- case PAC:
- config.proxySettings = proxySettings;
- ProxyProperties proxyPacProperties =
- new ProxyProperties(pacFileUrl);
- linkProperties.setHttpProxy(proxyPacProperties);
- break;
- case NONE:
- config.proxySettings = proxySettings;
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED proxy on file, use NONE");
- config.proxySettings = ProxySettings.NONE;
- break;
- default:
- loge("Ignore invalid proxy settings while reading");
- break;
- }
- }
- } else {
- if (DBG) log("Missing id while parsing configuration");
- }
- }
- } catch (EOFException ignore) {
- } catch (IOException e) {
- loge("Error parsing configuration" + e);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (Exception e) {}
- }
- }
- }
-
- private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
- /*
- * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
- * network configuration. Otherwise, the networkId should
- * refer to an existing configuration.
- */
-
- if (VDBG) localLog("addOrUpdateNetworkNative " + config.getPrintableSsid());
-
- int netId = config.networkId;
- boolean newNetwork = false;
- // networkId of INVALID_NETWORK_ID means we want to create a new network
- if (netId == INVALID_NETWORK_ID) {
- Integer savedNetId = mNetworkIds.get(configKey(config));
- if (savedNetId != null) {
- netId = savedNetId;
- } else {
- newNetwork = true;
- netId = mWifiNative.addNetwork();
- if (netId < 0) {
- loge("Failed to add a network!");
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
- }
- }
-
- boolean updateFailed = true;
-
- setVariables: {
-
- if (config.SSID != null &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.ssidVarName,
- config.SSID)) {
- loge("failed to set SSID: "+config.SSID);
- break setVariables;
- }
-
- if (config.BSSID != null &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.bssidVarName,
- config.BSSID)) {
- loge("failed to set BSSID: "+config.BSSID);
- break setVariables;
- }
-
- String allowedKeyManagementString =
- makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
- if (config.allowedKeyManagement.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.KeyMgmt.varName,
- allowedKeyManagementString)) {
- loge("failed to set key_mgmt: "+
- allowedKeyManagementString);
- break setVariables;
- }
-
- String allowedProtocolsString =
- makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings);
- if (config.allowedProtocols.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.Protocol.varName,
- allowedProtocolsString)) {
- loge("failed to set proto: "+
- allowedProtocolsString);
- break setVariables;
- }
-
- String allowedAuthAlgorithmsString =
- makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings);
- if (config.allowedAuthAlgorithms.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.AuthAlgorithm.varName,
- allowedAuthAlgorithmsString)) {
- loge("failed to set auth_alg: "+
- allowedAuthAlgorithmsString);
- break setVariables;
- }
-
- String allowedPairwiseCiphersString =
- makeString(config.allowedPairwiseCiphers,
- WifiConfiguration.PairwiseCipher.strings);
- if (config.allowedPairwiseCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.PairwiseCipher.varName,
- allowedPairwiseCiphersString)) {
- loge("failed to set pairwise: "+
- allowedPairwiseCiphersString);
- break setVariables;
- }
-
- String allowedGroupCiphersString =
- makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings);
- if (config.allowedGroupCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.GroupCipher.varName,
- allowedGroupCiphersString)) {
- loge("failed to set group: "+
- allowedGroupCiphersString);
- break setVariables;
- }
-
- // Prevent client screw-up by passing in a WifiConfiguration we gave it
- // by preventing "*" as a key.
- if (config.preSharedKey != null && !config.preSharedKey.equals("*") &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.pskVarName,
- config.preSharedKey)) {
- loge("failed to set psk");
- break setVariables;
- }
-
- boolean hasSetKey = false;
- if (config.wepKeys != null) {
- for (int i = 0; i < config.wepKeys.length; i++) {
- // Prevent client screw-up by passing in a WifiConfiguration we gave it
- // by preventing "*" as a key.
- if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) {
- if (!mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.wepKeyVarNames[i],
- config.wepKeys[i])) {
- loge("failed to set wep_key" + i + ": " + config.wepKeys[i]);
- break setVariables;
- }
- hasSetKey = true;
- }
- }
- }
-
- if (hasSetKey) {
- if (!mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.wepTxKeyIdxVarName,
- Integer.toString(config.wepTxKeyIndex))) {
- loge("failed to set wep_tx_keyidx: " + config.wepTxKeyIndex);
- break setVariables;
- }
- }
-
- if (!mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.priorityVarName,
- Integer.toString(config.priority))) {
- loge(config.SSID + ": failed to set priority: "
- +config.priority);
- break setVariables;
- }
-
- if (config.hiddenSSID && !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.hiddenSSIDVarName,
- Integer.toString(config.hiddenSSID ? 1 : 0))) {
- loge(config.SSID + ": failed to set hiddenSSID: "+
- config.hiddenSSID);
- break setVariables;
- }
-
- if (config.enterpriseConfig != null &&
- config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
-
- WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
-
- if (needsKeyStore(enterpriseConfig)) {
- /**
- * Keyguard settings may eventually be controlled by device policy.
- * We check here if keystore is unlocked before installing
- * credentials.
- * TODO: Do we need a dialog here ?
- */
- if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
- loge(config.SSID + ": key store is locked");
- break setVariables;
- }
-
- try {
- /* config passed may include only fields being updated.
- * In order to generate the key id, fetch uninitialized
- * fields from the currently tracked configuration
- */
- WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
- String keyId = config.getKeyIdForCredentials(currentConfig);
-
- if (!installKeys(enterpriseConfig, keyId)) {
- loge(config.SSID + ": failed to install keys");
- break setVariables;
- }
- } catch (IllegalStateException e) {
- loge(config.SSID + " invalid config for key installation");
- break setVariables;
- }
- }
-
- HashMap<String, String> enterpriseFields = enterpriseConfig.getFields();
- for (String key : enterpriseFields.keySet()) {
- String value = enterpriseFields.get(key);
- if (!mWifiNative.setNetworkVariable(
- netId,
- key,
- value)) {
- removeKeys(enterpriseConfig);
- loge(config.SSID + ": failed to set " + key +
- ": " + value);
- break setVariables;
- }
- }
- }
- updateFailed = false;
- } //end of setVariables
-
- if (updateFailed) {
- if (newNetwork) {
- mWifiNative.removeNetwork(netId);
- loge("Failed to set a network variable, removed network: " + netId);
- }
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
-
- /* An update of the network variables requires reading them
- * back from the supplicant to update mConfiguredNetworks.
- * This is because some of the variables (SSID, wep keys &
- * passphrases) reflect different values when read back than
- * when written. For example, wep key is stored as * irrespective
- * of the value sent to the supplicant
- */
- WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
- if (currentConfig == null) {
- currentConfig = new WifiConfiguration();
- currentConfig.ipAssignment = IpAssignment.DHCP;
- currentConfig.proxySettings = ProxySettings.NONE;
- currentConfig.networkId = netId;
- }
-
- readNetworkVariables(currentConfig);
-
- mConfiguredNetworks.put(netId, currentConfig);
- mNetworkIds.put(configKey(currentConfig), netId);
-
- NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
- result.setIsNewNetwork(newNetwork);
- result.setNetworkId(netId);
- return result;
- }
-
- /* Compare current and new configuration and write to file on change */
- private NetworkUpdateResult writeIpAndProxyConfigurationsOnChange(
- WifiConfiguration currentConfig,
- WifiConfiguration newConfig) {
- boolean ipChanged = false;
- boolean proxyChanged = false;
- LinkProperties linkProperties = null;
-
- switch (newConfig.ipAssignment) {
- case STATIC:
- Collection<LinkAddress> currentLinkAddresses = currentConfig.linkProperties
- .getLinkAddresses();
- Collection<LinkAddress> newLinkAddresses = newConfig.linkProperties
- .getLinkAddresses();
- Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
- Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
- Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes();
- Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes();
-
- boolean linkAddressesDiffer =
- (currentLinkAddresses.size() != newLinkAddresses.size()) ||
- !currentLinkAddresses.containsAll(newLinkAddresses);
- boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
- !currentDnses.containsAll(newDnses);
- boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) ||
- !currentRoutes.containsAll(newRoutes);
-
- if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
- linkAddressesDiffer ||
- dnsesDiffer ||
- routesDiffer) {
- ipChanged = true;
- }
- break;
- case DHCP:
- if (currentConfig.ipAssignment != newConfig.ipAssignment) {
- ipChanged = true;
- }
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid ip assignment during write");
- break;
- }
-
- switch (newConfig.proxySettings) {
- case STATIC:
- case PAC:
- ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy();
- ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy();
-
- if (newHttpProxy != null) {
- proxyChanged = !newHttpProxy.equals(currentHttpProxy);
- } else {
- proxyChanged = (currentHttpProxy != null);
- }
- break;
- case NONE:
- if (currentConfig.proxySettings != newConfig.proxySettings) {
- proxyChanged = true;
- }
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid proxy configuration during write");
- break;
- }
-
- if (!ipChanged) {
- linkProperties = copyIpSettingsFromConfig(currentConfig);
- } else {
- currentConfig.ipAssignment = newConfig.ipAssignment;
- linkProperties = copyIpSettingsFromConfig(newConfig);
- log("IP config changed SSID = " + currentConfig.SSID + " linkProperties: " +
- linkProperties.toString());
- }
-
-
- if (!proxyChanged) {
- linkProperties.setHttpProxy(currentConfig.linkProperties.getHttpProxy());
- } else {
- currentConfig.proxySettings = newConfig.proxySettings;
- linkProperties.setHttpProxy(newConfig.linkProperties.getHttpProxy());
- log("proxy changed SSID = " + currentConfig.SSID);
- if (linkProperties.getHttpProxy() != null) {
- log(" proxyProperties: " + linkProperties.getHttpProxy().toString());
- }
- }
-
- if (ipChanged || proxyChanged) {
- currentConfig.linkProperties = linkProperties;
- writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast(currentConfig,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return new NetworkUpdateResult(ipChanged, proxyChanged);
- }
-
- private LinkProperties copyIpSettingsFromConfig(WifiConfiguration config) {
- LinkProperties linkProperties = new LinkProperties();
- linkProperties.setInterfaceName(config.linkProperties.getInterfaceName());
- for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
- linkProperties.addLinkAddress(linkAddr);
- }
- for (RouteInfo route : config.linkProperties.getRoutes()) {
- linkProperties.addRoute(route);
- }
- for (InetAddress dns : config.linkProperties.getDnses()) {
- linkProperties.addDns(dns);
- }
- return linkProperties;
- }
-
- /**
- * Read the variables from the supplicant daemon that are needed to
- * fill in the WifiConfiguration object.
- *
- * @param config the {@link WifiConfiguration} object to be filled in.
- */
- private void readNetworkVariables(WifiConfiguration config) {
-
- int netId = config.networkId;
- if (netId < 0)
- return;
-
- /*
- * TODO: maybe should have a native method that takes an array of
- * variable names and returns an array of values. But we'd still
- * be doing a round trip to the supplicant daemon for each variable.
- */
- String value;
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.ssidVarName);
- if (!TextUtils.isEmpty(value)) {
- if (value.charAt(0) != '"') {
- config.SSID = "\"" + WifiSsid.createFromHex(value).toString() + "\"";
- //TODO: convert a hex string that is not UTF-8 decodable to a P-formatted
- //supplicant string
- } else {
- config.SSID = value;
- }
- } else {
- config.SSID = null;
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.bssidVarName);
- if (!TextUtils.isEmpty(value)) {
- config.BSSID = value;
- } else {
- config.BSSID = null;
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.priorityVarName);
- config.priority = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.priority = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.hiddenSSIDVarName);
- config.hiddenSSID = false;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.hiddenSSID = Integer.parseInt(value) != 0;
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.wepTxKeyIdxVarName);
- config.wepTxKeyIndex = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.wepTxKeyIndex = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- for (int i = 0; i < 4; i++) {
- value = mWifiNative.getNetworkVariable(netId,
- WifiConfiguration.wepKeyVarNames[i]);
- if (!TextUtils.isEmpty(value)) {
- config.wepKeys[i] = value;
- } else {
- config.wepKeys[i] = null;
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.pskVarName);
- if (!TextUtils.isEmpty(value)) {
- config.preSharedKey = value;
- } else {
- config.preSharedKey = null;
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.Protocol.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.Protocol.strings);
- if (0 <= index) {
- config.allowedProtocols.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.KeyMgmt.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.KeyMgmt.strings);
- if (0 <= index) {
- config.allowedKeyManagement.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.AuthAlgorithm.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.AuthAlgorithm.strings);
- if (0 <= index) {
- config.allowedAuthAlgorithms.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.PairwiseCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.PairwiseCipher.strings);
- if (0 <= index) {
- config.allowedPairwiseCiphers.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.GroupCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.GroupCipher.strings);
- if (0 <= index) {
- config.allowedGroupCiphers.set(index);
- }
- }
- }
-
- if (config.enterpriseConfig == null) {
- config.enterpriseConfig = new WifiEnterpriseConfig();
- }
- HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
- for (String key : ENTERPRISE_CONFIG_SUPPLICANT_KEYS) {
- value = mWifiNative.getNetworkVariable(netId, key);
- if (!TextUtils.isEmpty(value)) {
- enterpriseFields.put(key, removeDoubleQuotes(value));
- } else {
- enterpriseFields.put(key, EMPTY_VALUE);
- }
- }
-
- if (migrateOldEapTlsNative(config.enterpriseConfig, netId)) {
- saveConfig();
- }
-
- migrateCerts(config.enterpriseConfig);
- // initializeSoftwareKeystoreFlag(config.enterpriseConfig, mKeyStore);
- }
-
- private static String removeDoubleQuotes(String string) {
- int length = string.length();
- if ((length > 1) && (string.charAt(0) == '"')
- && (string.charAt(length - 1) == '"')) {
- return string.substring(1, length - 1);
- }
- return string;
- }
-
- private static String convertToQuotedString(String string) {
- return "\"" + string + "\"";
- }
-
- private static String makeString(BitSet set, String[] strings) {
- StringBuffer buf = new StringBuffer();
- int nextSetBit = -1;
-
- /* Make sure all set bits are in [0, strings.length) to avoid
- * going out of bounds on strings. (Shouldn't happen, but...) */
- set = set.get(0, strings.length);
-
- while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
- buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
- }
-
- // remove trailing space
- if (set.cardinality() > 0) {
- buf.setLength(buf.length() - 1);
- }
-
- return buf.toString();
- }
-
- private int lookupString(String string, String[] strings) {
- int size = strings.length;
-
- string = string.replace('-', '_');
-
- for (int i = 0; i < size; i++)
- if (string.equals(strings[i]))
- return i;
-
- // if we ever get here, we should probably add the
- // value to WifiConfiguration to reflect that it's
- // supported by the WPA supplicant
- loge("Failed to look-up a string: " + string);
-
- return -1;
- }
-
- /* Returns a unique for a given configuration */
- private static int configKey(WifiConfiguration config) {
- String key;
-
- if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
- } else if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
- config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
- } else if (config.wepKeys[0] != null) {
- key = config.SSID + "WEP";
- } else {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.NONE];
- }
-
- return key.hashCode();
- }
-
- void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("WifiConfigStore");
- pw.println("mLastPriority " + mLastPriority);
- pw.println("Configured networks");
- for (WifiConfiguration conf : getConfiguredNetworks()) {
- pw.println(conf);
- }
- pw.println();
-
- if (mLocalLog != null) {
- pw.println("WifiConfigStore - Log Begin ----");
- mLocalLog.dump(fd, pw, args);
- pw.println("WifiConfigStore - Log End ----");
- }
- }
-
- public String getConfigFile() {
- return ipConfigFile;
- }
-
- private void loge(String s) {
- Log.e(TAG, s);
- }
-
- private void log(String s) {
- Log.d(TAG, s);
- }
-
- private void localLog(String s) {
- if (mLocalLog != null) {
- mLocalLog.log(s);
- }
- }
-
- private void localLog(String s, int netId) {
- if (mLocalLog == null) {
- return;
- }
-
- WifiConfiguration config;
- synchronized(mConfiguredNetworks) {
- config = mConfiguredNetworks.get(netId);
- }
-
- if (config != null) {
- mLocalLog.log(s + " " + config.getPrintableSsid());
- } else {
- mLocalLog.log(s + " " + netId);
- }
- }
-
- // Certificate and private key management for EnterpriseConfig
- static boolean needsKeyStore(WifiEnterpriseConfig config) {
- // Has no keys to be installed
- if (config.getClientCertificate() == null && config.getCaCertificate() == null)
- return false;
- return true;
- }
-
- static boolean isHardwareBackedKey(PrivateKey key) {
- return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm());
- }
-
- static boolean hasHardwareBackedKey(Certificate certificate) {
- return KeyChain.isBoundKeyAlgorithm(certificate.getPublicKey().getAlgorithm());
- }
-
- static boolean needsSoftwareBackedKeyStore(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- if (!TextUtils.isEmpty(client)) {
- // a valid client certificate is configured
-
- // BUGBUG: keyStore.get() never returns certBytes; because it is not
- // taking WIFI_UID as a parameter. It always looks for certificate
- // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
- // all certificates need software keystore until we get the get() API
- // fixed.
-
- return true;
- }
-
- /*
- try {
-
- if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
- .USER_CERTIFICATE + client);
-
- CertificateFactory factory = CertificateFactory.getInstance("X.509");
- if (factory == null) {
- Slog.e(TAG, "Error getting certificate factory");
- return;
- }
-
- byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
- if (certBytes != null) {
- Certificate cert = (X509Certificate) factory.generateCertificate(
- new ByteArrayInputStream(certBytes));
-
- if (cert != null) {
- mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);
-
- if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
- .USER_CERTIFICATE + client);
- if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
- "does not need" ) + " software key store");
- } else {
- Slog.d(TAG, "could not generate certificate");
- }
- } else {
- Slog.e(TAG, "Could not load client certificate " + Credentials
- .USER_CERTIFICATE + client);
- mNeedsSoftwareKeystore = true;
- }
-
- } catch(CertificateException e) {
- Slog.e(TAG, "Could not read certificates");
- mCaCert = null;
- mClientCertificate = null;
- }
- */
-
- return false;
- }
-
- boolean installKeys(WifiEnterpriseConfig config, String name) {
- boolean ret = true;
- String privKeyName = Credentials.USER_PRIVATE_KEY + name;
- String userCertName = Credentials.USER_CERTIFICATE + name;
- String caCertName = Credentials.CA_CERTIFICATE + name;
- if (config.getClientCertificate() != null) {
- byte[] privKeyData = config.getClientPrivateKey().getEncoded();
- if (isHardwareBackedKey(config.getClientPrivateKey())) {
- // Hardware backed key store is secure enough to store keys un-encrypted, this
- // removes the need for user to punch a PIN to get access to these keys
- if (DBG) Log.d(TAG, "importing keys " + name + " in hardware backed store");
- ret = mKeyStore.importKey(privKeyName, privKeyData, android.os.Process.WIFI_UID,
- KeyStore.FLAG_NONE);
- } else {
- // Software backed key store is NOT secure enough to store keys un-encrypted.
- // Save keys encrypted so they are protected with user's PIN. User will
- // have to unlock phone before being able to use these keys and connect to
- // networks.
- if (DBG) Log.d(TAG, "importing keys " + name + " in software backed store");
- ret = mKeyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
- KeyStore.FLAG_ENCRYPTED);
- }
- if (ret == false) {
- return ret;
- }
-
- ret = putCertInKeyStore(userCertName, config.getClientCertificate());
- if (ret == false) {
- // Remove private key installed
- mKeyStore.delKey(privKeyName, Process.WIFI_UID);
- return ret;
- }
- }
-
- if (config.getCaCertificate() != null) {
- ret = putCertInKeyStore(caCertName, config.getCaCertificate());
- if (ret == false) {
- if (config.getClientCertificate() != null) {
- // Remove client key+cert
- mKeyStore.delKey(privKeyName, Process.WIFI_UID);
- mKeyStore.delete(userCertName, Process.WIFI_UID);
- }
- return ret;
- }
- }
-
- // Set alias names
- if (config.getClientCertificate() != null) {
- config.setClientCertificateAlias(name);
- config.resetClientKeyEntry();
- }
-
- if (config.getCaCertificate() != null) {
- config.setCaCertificateAlias(name);
- config.resetCaCertificate();
- }
-
- return ret;
- }
-
- private boolean putCertInKeyStore(String name, Certificate cert) {
- try {
- byte[] certData = Credentials.convertToPem(cert);
- if (DBG) Log.d(TAG, "putting certificate " + name + " in keystore");
- return mKeyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_NONE);
-
- } catch (IOException e1) {
- return false;
- } catch (CertificateException e2) {
- return false;
- }
- }
-
- void removeKeys(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- // a valid client certificate is configured
- if (!TextUtils.isEmpty(client)) {
- if (DBG) Log.d(TAG, "removing client private key and user cert");
- mKeyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
- mKeyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
- }
-
- String ca = config.getCaCertificateAlias();
- // a valid ca certificate is configured
- if (!TextUtils.isEmpty(ca)) {
- if (DBG) Log.d(TAG, "removing CA cert");
- mKeyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
- }
- }
-
-
- /** Migrates the old style TLS config to the new config style. This should only be used
- * when restoring an old wpa_supplicant.conf or upgrading from a previous
- * platform version.
- * @return true if the config was updated
- * @hide
- */
- boolean migrateOldEapTlsNative(WifiEnterpriseConfig config, int netId) {
- String oldPrivateKey = mWifiNative.getNetworkVariable(netId, OLD_PRIVATE_KEY_NAME);
- /*
- * If the old configuration value is not present, then there is nothing
- * to do.
- */
- if (TextUtils.isEmpty(oldPrivateKey)) {
- return false;
- } else {
- // Also ignore it if it's empty quotes.
- oldPrivateKey = removeDoubleQuotes(oldPrivateKey);
- if (TextUtils.isEmpty(oldPrivateKey)) {
- return false;
- }
- }
-
- config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, WifiEnterpriseConfig.ENGINE_ENABLE);
- config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY,
- WifiEnterpriseConfig.ENGINE_ID_KEYSTORE);
-
- /*
- * The old key started with the keystore:// URI prefix, but we don't
- * need that anymore. Trim it off if it exists.
- */
- final String keyName;
- if (oldPrivateKey.startsWith(WifiEnterpriseConfig.KEYSTORE_URI)) {
- keyName = new String(
- oldPrivateKey.substring(WifiEnterpriseConfig.KEYSTORE_URI.length()));
- } else {
- keyName = oldPrivateKey;
- }
- config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, keyName);
-
- mWifiNative.setNetworkVariable(netId, WifiEnterpriseConfig.ENGINE_KEY,
- config.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY, ""));
-
- mWifiNative.setNetworkVariable(netId, WifiEnterpriseConfig.ENGINE_ID_KEY,
- config.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, ""));
-
- mWifiNative.setNetworkVariable(netId, WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY,
- config.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, ""));
-
- // Remove old private_key string so we don't run this again.
- mWifiNative.setNetworkVariable(netId, OLD_PRIVATE_KEY_NAME, EMPTY_VALUE);
-
- return true;
- }
-
- /** Migrate certs from global pool to wifi UID if not already done */
- void migrateCerts(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- // a valid client certificate is configured
- if (!TextUtils.isEmpty(client)) {
- if (!mKeyStore.contains(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID)) {
- mKeyStore.duplicate(Credentials.USER_PRIVATE_KEY + client, -1,
- Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
- mKeyStore.duplicate(Credentials.USER_CERTIFICATE + client, -1,
- Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
- }
- }
-
- String ca = config.getCaCertificateAlias();
- // a valid ca certificate is configured
- if (!TextUtils.isEmpty(ca)) {
- if (!mKeyStore.contains(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID)) {
- mKeyStore.duplicate(Credentials.CA_CERTIFICATE + ca, -1,
- Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
- }
- }
- }
-
-}
-