diff options
author | Roshan Pius <rpius@google.com> | 2016-06-16 09:45:44 -0700 |
---|---|---|
committer | Roshan Pius <rpius@google.com> | 2016-06-22 14:00:18 -0700 |
commit | 1a731d9b8078e156b99dd281b814d93ab025e363 (patch) | |
tree | 37961b9449de03aaee2c66005890b04286036703 /service/java/com/android/server/wifi/WifiConfigStore.java | |
parent | f5837a2ccff3a9e3bf86c9f80bf2154e26ddfb9b (diff) | |
download | android_frameworks_opt_net_wifi-1a731d9b8078e156b99dd281b814d93ab025e363.tar.gz android_frameworks_opt_net_wifi-1a731d9b8078e156b99dd281b814d93ab025e363.tar.bz2 android_frameworks_opt_net_wifi-1a731d9b8078e156b99dd281b814d93ab025e363.zip |
WifiConfigStore: Remove class
Remove the existing WifiConfigStore class. Move all the existing
functionality to two separate classes:
1. WifiSupplicantControl: For any wpa_supplicant operations.
2. WifiKeyStore: For any key management operations.
This CL doesn't change any functionality, it's only a refactor.
BUG: 29394274
BUG: 29396499
Change-Id: Ic3d3f9eb3c241f34f2fddcfa67374c9a98277e0a
TEST: Unit tests
TEST: Successfully associated the device with GoogleGuest.
Diffstat (limited to 'service/java/com/android/server/wifi/WifiConfigStore.java')
-rw-r--r-- | service/java/com/android/server/wifi/WifiConfigStore.java | 1306 |
1 files changed, 0 insertions, 1306 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 fed8d684f..000000000 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Copyright (C) 2016 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.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiSsid; -import android.net.wifi.WpsInfo; -import android.net.wifi.WpsResult; -import android.os.FileObserver; -import android.os.Process; -import android.security.Credentials; -import android.security.KeyChain; -import android.security.KeyStore; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; -import android.util.SparseArray; - -import com.android.server.wifi.hotspot2.Utils; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This class provides the API's to save/load/modify network configurations from a persistent - * config database. - * We use wpa_supplicant as our config database currently, but will be migrating to a different - * one sometime in the future. - * We use keystore for certificate/key management operations. - * - * NOTE: This class should only be used from WifiConfigManager!!! - */ -public class WifiConfigStore { - - public static final String TAG = "WifiConfigStore"; - // This is the only variable whose contents will not be interpreted by wpa_supplicant. We use it - // to store metadata that allows us to correlate a wpa_supplicant.conf entry with additional - // information about the same network stored in other files. The metadata is stored as a - // serialized JSON dictionary. - public static final String ID_STRING_VAR_NAME = "id_str"; - public static final String ID_STRING_KEY_FQDN = "fqdn"; - public static final String ID_STRING_KEY_CREATOR_UID = "creatorUid"; - public static final String ID_STRING_KEY_CONFIG_KEY = "configKey"; - public static final String SUPPLICANT_CONFIG_FILE = "/data/misc/wifi/wpa_supplicant.conf"; - public static final String SUPPLICANT_CONFIG_FILE_BACKUP = SUPPLICANT_CONFIG_FILE + ".tmp"; - - // Value stored by supplicant to requirePMF - public static final int STORED_VALUE_FOR_REQUIRE_PMF = 2; - private static final boolean DBG = true; - - private final LocalLog mLocalLog; - private final WpaConfigFileObserver mFileObserver; - private final WifiNative mWifiNative; - private final KeyStore mKeyStore; - private final BackupManagerProxy mBackupManagerProxy; - - private boolean mVerboseLoggingEnabled = false; - - WifiConfigStore(WifiNative wifiNative, KeyStore keyStore, LocalLog localLog) { - mWifiNative = wifiNative; - mKeyStore = keyStore; - mBackupManagerProxy = new BackupManagerProxy(); - - mLocalLog = localLog; - mFileObserver = new WpaConfigFileObserver(); - mFileObserver.startWatching(); - } - - 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; - } - - /** - * Generate a string to be used as a key value by wpa_supplicant from - * 'set', within the set of strings from 'strings' for the variable concatenated. - * Also transform the internal string format that uses _ (for bewildering - * reasons) into a wpa_supplicant adjusted value, that uses - as a separator - * (most of the time at least...). - * @param set a bit set with a one for each corresponding string to be included from strings. - * @param strings the set of string literals to concatenate strinfs from. - * @return A wpa_supplicant formatted value. - */ - private static String makeString(BitSet set, String[] strings) { - return makeStringWithException(set, strings, null); - } - - /** - * Same as makeString with an exclusion parameter. - * @param set a bit set with a one for each corresponding string to be included from strings. - * @param strings the set of string literals to concatenate strinfs from. - * @param exception literal string to be excluded from the _ to - transformation. - * @return A wpa_supplicant formatted value. - */ - private static String makeStringWithException(BitSet set, String[] strings, String exception) { - StringBuilder result = new StringBuilder(); - - /* Make sure all set bits are in [0, strings.length) to avoid - * going out of bounds on strings. (Shouldn't happen, but...) */ - BitSet trimmedSet = set.get(0, strings.length); - - List<String> valueSet = new ArrayList<>(); - for (int bit = trimmedSet.nextSetBit(0); - bit >= 0; - bit = trimmedSet.nextSetBit(bit+1)) { - String currentName = strings[bit]; - if (exception != null && currentName.equals(exception)) { - valueSet.add(currentName); - } else { - // Most wpa_supplicant strings use a dash whereas (for some bizarre - // reason) the strings are defined with underscore in the code... - valueSet.add(currentName.replace('_', '-')); - } - } - return TextUtils.join(" ", valueSet); - } - - /* - * Convert string to Hexadecimal before passing to wifi native layer - * In native function "doCommand()" have trouble in converting Unicode character string to UTF8 - * conversion to hex is required because SSIDs can have space characters in them; - * and that can confuses the supplicant because it uses space charaters as delimiters - */ - private static String encodeSSID(String str) { - return Utils.toHex(removeDoubleQuotes(str).getBytes(StandardCharsets.UTF_8)); - } - - // Certificate and private key management for EnterpriseConfig - private static boolean needsKeyStore(WifiEnterpriseConfig config) { - return (!(config.getClientCertificate() == null && config.getCaCertificate() == null)); - } - - private static boolean isHardwareBackedKey(PrivateKey key) { - return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm()); - } - - private static boolean hasHardwareBackedKey(Certificate certificate) { - return KeyChain.isBoundKeyAlgorithm(certificate.getPublicKey().getAlgorithm()); - } - - private static boolean needsSoftwareBackedKeyStore(WifiEnterpriseConfig config) { - java.lang.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; - } - return false; - } - - 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; - } - } - loge("Failed to look-up a string: " + string); - return -1; - } - - private void readNetworkBitsetVariable(int netId, BitSet variable, String varName, - String[] strings) { - String value = mWifiNative.getNetworkVariable(netId, varName); - if (!TextUtils.isEmpty(value)) { - variable.clear(); - String[] vals = value.split(" "); - for (String val : vals) { - int index = lookupString(val, strings); - if (0 <= index) { - variable.set(index); - } - } - } - } - - /** - * 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. - */ - public void readNetworkVariables(WifiConfiguration config) { - if (config == null) { - return; - } - if (mVerboseLoggingEnabled) localLog("readNetworkVariables: " + config.networkId); - 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.getNetworkSelectionStatus().setNetworkSelectionBSSID(value); - } else { - config.getNetworkSelectionStatus().setNetworkSelectionBSSID(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.pmfVarName); - config.requirePMF = false; - if (!TextUtils.isEmpty(value)) { - try { - config.requirePMF = Integer.parseInt(value) == STORED_VALUE_FOR_REQUIRE_PMF; - } 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; - } - - readNetworkBitsetVariable(config.networkId, config.allowedProtocols, - WifiConfiguration.Protocol.varName, WifiConfiguration.Protocol.strings); - - readNetworkBitsetVariable(config.networkId, config.allowedKeyManagement, - WifiConfiguration.KeyMgmt.varName, WifiConfiguration.KeyMgmt.strings); - - readNetworkBitsetVariable(config.networkId, config.allowedAuthAlgorithms, - WifiConfiguration.AuthAlgorithm.varName, WifiConfiguration.AuthAlgorithm.strings); - - readNetworkBitsetVariable(config.networkId, config.allowedPairwiseCiphers, - WifiConfiguration.PairwiseCipher.varName, WifiConfiguration.PairwiseCipher.strings); - - readNetworkBitsetVariable(config.networkId, config.allowedGroupCiphers, - WifiConfiguration.GroupCipher.varName, WifiConfiguration.GroupCipher.strings); - - if (config.enterpriseConfig == null) { - config.enterpriseConfig = new WifiEnterpriseConfig(); - } - config.enterpriseConfig.loadFromSupplicant(new SupplicantLoader(netId)); - } - - /** - * Load all the configured networks from wpa_supplicant. - * - * @param configs Map of configuration key to configuration objects corresponding to all - * the networks. - * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf - * @return Max priority of all the configs. - */ - public int loadNetworks(Map<String, WifiConfiguration> configs, - SparseArray<Map<String, String>> networkExtras) { - int lastPriority = 0; - int last_id = -1; - boolean done = false; - while (!done) { - String listStr = mWifiNative.listNetworks(last_id); - if (listStr == null) { - return lastPriority; - } - String[] lines = listStr.split("\n"); - if (mVerboseLoggingEnabled) { - localLog("loadNetworks: "); - for (String net : lines) { - localLog(net); - } - } - // 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]); - last_id = config.networkId; - } catch (NumberFormatException e) { - loge("Failed to read network-id '" + result[0] + "'"); - continue; - } - // Ignore the supplicant status, start all networks disabled. - config.status = WifiConfiguration.Status.DISABLED; - readNetworkVariables(config); - // Parse the serialized JSON dictionary in ID_STRING_VAR_NAME once and cache the - // result for efficiency. - Map<String, String> extras = mWifiNative.getNetworkExtra(config.networkId, - ID_STRING_VAR_NAME); - if (extras == null) { - extras = new HashMap<String, String>(); - // If ID_STRING_VAR_NAME did not contain a dictionary, assume that it contains - // just a quoted FQDN. This is the legacy format that was used in Marshmallow. - final String fqdn = Utils.unquote(mWifiNative.getNetworkVariable( - config.networkId, ID_STRING_VAR_NAME)); - if (fqdn != null) { - extras.put(ID_STRING_KEY_FQDN, fqdn); - config.FQDN = fqdn; - // Mark the configuration as a Hotspot 2.0 network. - config.providerFriendlyName = ""; - } - } - networkExtras.put(config.networkId, extras); - - if (config.priority > lastPriority) { - lastPriority = config.priority; - } - config.setIpAssignment(IpAssignment.DHCP); - config.setProxySettings(ProxySettings.NONE); - if (!WifiServiceImpl.isValid(config)) { - if (mVerboseLoggingEnabled) { - localLog("Ignoring network " + config.networkId + " because configuration " - + "loaded from wpa_supplicant.conf is not valid."); - } - continue; - } - // The configKey is explicitly stored in wpa_supplicant.conf, because config does - // not contain sufficient information to compute it at this point. - String configKey = extras.get(ID_STRING_KEY_CONFIG_KEY); - if (configKey == null) { - // Handle the legacy case where the configKey is not stored in - // wpa_supplicant.conf but can be computed straight away. - // Force an update of this legacy network configuration by writing - // the configKey for this network into wpa_supplicant.conf. - configKey = config.configKey(); - saveNetworkMetadata(config); - } - final WifiConfiguration duplicateConfig = configs.put(configKey, config); - if (duplicateConfig != null) { - // The network is already known. Overwrite the duplicate entry. - if (mVerboseLoggingEnabled) { - localLog("Replacing duplicate network " + duplicateConfig.networkId - + " with " + config.networkId + "."); - } - // This can happen after the user manually connected to an AP and tried to use - // WPS to connect the AP later. In this case, the supplicant will create a new - // network for the AP although there is an existing network already. - mWifiNative.removeNetwork(duplicateConfig.networkId); - } - } - done = (lines.length == 1); - } - return lastPriority; - } - - /** - * Install keys for given enterprise network. - * - * @param existingConfig Existing config corresponding to the network already stored in our - * database. This maybe null if it's a new network. - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - private boolean installKeys(WifiEnterpriseConfig existingConfig, WifiEnterpriseConfig config, - String name) { - boolean ret = true; - String privKeyName = Credentials.USER_PRIVATE_KEY + name; - String userCertName = Credentials.USER_CERTIFICATE + name; - if (config.getClientCertificate() != null) { - byte[] privKeyData = config.getClientPrivateKey().getEncoded(); - if (DBG) { - if (isHardwareBackedKey(config.getClientPrivateKey())) { - Log.d(TAG, "importing keys " + name + " in hardware backed store"); - } else { - Log.d(TAG, "importing keys " + name + " in software backed store"); - } - } - ret = mKeyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID, - KeyStore.FLAG_NONE); - - if (!ret) { - return ret; - } - - ret = putCertInKeyStore(userCertName, config.getClientCertificate()); - if (!ret) { - // Remove private key installed - mKeyStore.delete(privKeyName, Process.WIFI_UID); - return ret; - } - } - - X509Certificate[] caCertificates = config.getCaCertificates(); - Set<String> oldCaCertificatesToRemove = new ArraySet<String>(); - if (existingConfig != null && existingConfig.getCaCertificateAliases() != null) { - oldCaCertificatesToRemove.addAll( - Arrays.asList(existingConfig.getCaCertificateAliases())); - } - List<String> caCertificateAliases = null; - if (caCertificates != null) { - caCertificateAliases = new ArrayList<String>(); - for (int i = 0; i < caCertificates.length; i++) { - String alias = caCertificates.length == 1 ? name - : String.format("%s_%d", name, i); - - oldCaCertificatesToRemove.remove(alias); - ret = putCertInKeyStore(Credentials.CA_CERTIFICATE + alias, caCertificates[i]); - if (!ret) { - // Remove client key+cert - if (config.getClientCertificate() != null) { - mKeyStore.delete(privKeyName, Process.WIFI_UID); - mKeyStore.delete(userCertName, Process.WIFI_UID); - } - // Remove added CA certs. - for (String addedAlias : caCertificateAliases) { - mKeyStore.delete(Credentials.CA_CERTIFICATE + addedAlias, Process.WIFI_UID); - } - return ret; - } else { - caCertificateAliases.add(alias); - } - } - } - // Remove old CA certs. - for (String oldAlias : oldCaCertificatesToRemove) { - mKeyStore.delete(Credentials.CA_CERTIFICATE + oldAlias, Process.WIFI_UID); - } - // Set alias names - if (config.getClientCertificate() != null) { - config.setClientCertificateAlias(name); - config.resetClientKeyEntry(); - } - - if (caCertificates != null) { - config.setCaCertificateAliases( - caCertificateAliases.toArray(new String[caCertificateAliases.size()])); - 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; - } - } - - /** - * Remove enterprise keys from the network config. - * - * @param config Config corresponding to the network. - */ - private 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.delete(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID); - mKeyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID); - } - - String[] aliases = config.getCaCertificateAliases(); - // a valid ca certificate is configured - if (aliases != null) { - for (String ca : aliases) { - if (!TextUtils.isEmpty(ca)) { - if (DBG) Log.d(TAG, "removing CA cert: " + ca); - mKeyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID); - } - } - } - } - - /** - * Update the network metadata info stored in wpa_supplicant network extra field. - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - public boolean saveNetworkMetadata(WifiConfiguration config) { - final Map<String, String> metadata = new HashMap<String, String>(); - if (config.isPasspoint()) { - metadata.put(ID_STRING_KEY_FQDN, config.FQDN); - } - metadata.put(ID_STRING_KEY_CONFIG_KEY, config.configKey()); - metadata.put(ID_STRING_KEY_CREATOR_UID, Integer.toString(config.creatorUid)); - if (!mWifiNative.setNetworkExtra(config.networkId, ID_STRING_VAR_NAME, metadata)) { - loge("failed to set id_str: " + metadata.toString()); - return false; - } - return true; - } - - /** - * Save an entire network configuration to wpa_supplicant. - * - * @param config Config corresponding to the network. - * @param netId Net Id of the network. - * @return true if successful, false otherwise. - */ - private boolean saveNetwork(WifiConfiguration config, int netId) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("saveNetwork: " + netId); - if (config.SSID != null && !mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.ssidVarName, - encodeSSID(config.SSID))) { - loge("failed to set SSID: " + config.SSID); - return false; - } - if (!saveNetworkMetadata(config)) { - return false; - } - //set selected BSSID to supplicant - if (config.getNetworkSelectionStatus().getNetworkSelectionBSSID() != null) { - String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); - if (!mWifiNative.setNetworkVariable(netId, WifiConfiguration.bssidVarName, bssid)) { - loge("failed to set BSSID: " + bssid); - return false; - } - } - 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); - return false; - } - 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); - return false; - } - 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); - return false; - } - 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); - return false; - } - // Make sure that the string "GTK_NOT_USED" is /not/ transformed - wpa_supplicant - // uses this literal value and not the 'dashed' version. - String allowedGroupCiphersString = - makeStringWithException(config.allowedGroupCiphers, - WifiConfiguration.GroupCipher.strings, - WifiConfiguration.GroupCipher - .strings[WifiConfiguration.GroupCipher.GTK_NOT_USED]); - if (config.allowedGroupCiphers.cardinality() != 0 && !mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.GroupCipher.varName, - allowedGroupCiphersString)) { - loge("failed to set group: " + allowedGroupCiphersString); - return false; - } - // 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"); - return false; - } - 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]); - return false; - } - hasSetKey = true; - } - } - } - if (hasSetKey) { - if (!mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.wepTxKeyIdxVarName, - Integer.toString(config.wepTxKeyIndex))) { - loge("failed to set wep_tx_keyidx: " + config.wepTxKeyIndex); - return false; - } - } - if (!mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.priorityVarName, - Integer.toString(config.priority))) { - loge(config.SSID + ": failed to set priority: " + config.priority); - return false; - } - if (config.hiddenSSID && !mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.hiddenSSIDVarName, - Integer.toString(config.hiddenSSID ? 1 : 0))) { - loge(config.SSID + ": failed to set hiddenSSID: " + config.hiddenSSID); - return false; - } - if (config.requirePMF && !mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.pmfVarName, - Integer.toString(STORED_VALUE_FOR_REQUIRE_PMF))) { - loge(config.SSID + ": failed to set requirePMF: " + config.requirePMF); - return false; - } - if (config.updateIdentifier != null && !mWifiNative.setNetworkVariable( - netId, - WifiConfiguration.updateIdentiferVarName, - config.updateIdentifier)) { - loge(config.SSID + ": failed to set updateIdentifier: " + config.updateIdentifier); - return false; - } - return true; - } - - /** - * Update/Install keys for given enterprise network. - * - * @param config Config corresponding to the network. - * @param existingConfig Existing config corresponding to the network already stored in our - * database. This maybe null if it's a new network. - * @return true if successful, false otherwise. - */ - private boolean updateNetworkKeys(WifiConfiguration config, WifiConfiguration existingConfig) { - WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; - if (needsKeyStore(enterpriseConfig)) { - try { - /* config passed may include only fields being updated. - * In order to generate the key id, fetch uninitialized - * fields from the currently tracked configuration - */ - String keyId = config.getKeyIdForCredentials(existingConfig); - - if (!installKeys(existingConfig != null - ? existingConfig.enterpriseConfig : null, enterpriseConfig, keyId)) { - loge(config.SSID + ": failed to install keys"); - return false; - } - } catch (IllegalStateException e) { - loge(config.SSID + " invalid config for key installation: " + e.getMessage()); - return false; - } - } - if (!enterpriseConfig.saveToSupplicant( - new SupplicantSaver(config.networkId, config.SSID))) { - removeKeys(enterpriseConfig); - return false; - } - return true; - } - - /** - * Add or update a network configuration to wpa_supplicant. - * - * @param config Config corresponding to the network. - * @param existingConfig Existing config corresponding to the network saved in our database. - * @return true if successful, false otherwise. - */ - public boolean addOrUpdateNetwork(WifiConfiguration config, WifiConfiguration existingConfig) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("addOrUpdateNetwork: " + config.networkId); - int netId = config.networkId; - boolean newNetwork = false; - /* - * 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 (netId == WifiConfiguration.INVALID_NETWORK_ID) { - newNetwork = true; - netId = mWifiNative.addNetwork(); - if (netId < 0) { - loge("Failed to add a network!"); - return false; - } else { - logi("addOrUpdateNetwork created netId=" + netId); - } - // Save the new network ID to the config - config.networkId = netId; - } - if (!saveNetwork(config, netId)) { - if (newNetwork) { - mWifiNative.removeNetwork(netId); - loge("Failed to set a network variable, removed network: " + netId); - } - return false; - } - if (config.enterpriseConfig != null - && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { - return updateNetworkKeys(config, existingConfig); - } - // Stage the backup of the SettingsProvider package which backs this up - mBackupManagerProxy.notifyDataChanged(); - return true; - } - - /** - * Remove the specified network and save config - * - * @param config Config corresponding to the network. - * @return {@code true} if it succeeds, {@code false} otherwise - */ - public boolean removeNetwork(WifiConfiguration config) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("removeNetwork: " + config.networkId); - if (!mWifiNative.removeNetwork(config.networkId)) { - loge("Remove network in wpa_supplicant failed on " + config.networkId); - return false; - } - // Remove any associated keys - if (config.enterpriseConfig != null) { - removeKeys(config.enterpriseConfig); - } - // Stage the backup of the SettingsProvider package which backs this up - mBackupManagerProxy.notifyDataChanged(); - return true; - } - - /** - * Select a network in wpa_supplicant. - * - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - public boolean selectNetwork(WifiConfiguration config) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("selectNetwork: " + config.networkId); - if (!mWifiNative.selectNetwork(config.networkId)) { - loge("Select network in wpa_supplicant failed on " + config.networkId); - return false; - } - return true; - } - - /** - * Disable a network in wpa_supplicant. - * - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - boolean disableNetwork(WifiConfiguration config) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("disableNetwork: " + config.networkId); - if (!mWifiNative.disableNetwork(config.networkId)) { - loge("Disable network in wpa_supplicant failed on " + config.networkId); - return false; - } - return true; - } - - /** - * Set priority for a network in wpa_supplicant. - * - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - public boolean setNetworkPriority(WifiConfiguration config, int priority) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("setNetworkPriority: " + config.networkId); - if (!mWifiNative.setNetworkVariable(config.networkId, - WifiConfiguration.priorityVarName, Integer.toString(priority))) { - loge("Set priority of network in wpa_supplicant failed on " + config.networkId); - return false; - } - config.priority = priority; - return true; - } - - /** - * Set SSID for a network in wpa_supplicant. - * - * @param config Config corresponding to the network. - * @return true if successful, false otherwise. - */ - public boolean setNetworkSSID(WifiConfiguration config, String ssid) { - if (config == null) { - return false; - } - if (mVerboseLoggingEnabled) localLog("setNetworkSSID: " + config.networkId); - if (!mWifiNative.setNetworkVariable(config.networkId, WifiConfiguration.ssidVarName, - encodeSSID(ssid))) { - loge("Set SSID of network in wpa_supplicant failed on " + config.networkId); - return false; - } - config.SSID = ssid; - return true; - } - - /** - * Set BSSID for a network in wpa_supplicant from network selection. - * - * @param config Config corresponding to the network. - * @param bssid BSSID to be set. - * @return true if successful, false otherwise. - */ - public boolean setNetworkBSSID(WifiConfiguration config, String bssid) { - // Sanity check the config is valid - if (config == null - || (config.networkId == WifiConfiguration.INVALID_NETWORK_ID - && config.SSID == null)) { - return false; - } - if (mVerboseLoggingEnabled) localLog("setNetworkBSSID: " + config.networkId); - if (!mWifiNative.setNetworkVariable(config.networkId, WifiConfiguration.bssidVarName, - bssid)) { - loge("Set BSSID of network in wpa_supplicant failed on " + config.networkId); - return false; - } - config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid); - return true; - } - - /** - * Enable/Disable HS20 parameter in wpa_supplicant. - * - * @param enable Enable/Disable the parameter. - */ - public void enableHS20(boolean enable) { - mWifiNative.setHs20(enable); - } - - /** - * Disables all the networks in the provided list in wpa_supplicant. - * - * @param configs Collection of configs which needs to be enabled. - * @return true if successful, false otherwise. - */ - public boolean disableAllNetworks(Collection<WifiConfiguration> configs) { - if (mVerboseLoggingEnabled) localLog("disableAllNetworks"); - boolean networkDisabled = false; - for (WifiConfiguration enabled : configs) { - if (disableNetwork(enabled)) { - networkDisabled = true; - } - } - saveConfig(); - return networkDisabled; - } - - /** - * Save the current configuration to wpa_supplicant.conf. - */ - public boolean saveConfig() { - return mWifiNative.saveConfig(); - } - - /** - * Read network variables from wpa_supplicant.conf. - * - * @param key The parameter to be parsed. - * @return Map of corresponding configKey to the value of the param requested. - */ - public Map<String, String> readNetworkVariablesFromSupplicantFile(String key) { - Map<String, String> result = new HashMap<>(); - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(SUPPLICANT_CONFIG_FILE)); - result = readNetworkVariablesFromReader(reader, key); - } catch (FileNotFoundException e) { - if (mVerboseLoggingEnabled) loge("Could not open " + SUPPLICANT_CONFIG_FILE + ", " + e); - } catch (IOException e) { - if (mVerboseLoggingEnabled) loge("Could not read " + SUPPLICANT_CONFIG_FILE + ", " + e); - } finally { - try { - if (reader != null) { - reader.close(); - } - } catch (IOException e) { - if (mVerboseLoggingEnabled) { - loge("Could not close reader for " + SUPPLICANT_CONFIG_FILE + ", " + e); - } - } - } - return result; - } - - /** - * Read network variables from a given reader. This method is separate from - * readNetworkVariablesFromSupplicantFile() for testing. - * - * @param reader The reader to read the network variables from. - * @param key The parameter to be parsed. - * @return Map of corresponding configKey to the value of the param requested. - */ - public Map<String, String> readNetworkVariablesFromReader(BufferedReader reader, String key) - throws IOException { - Map<String, String> result = new HashMap<>(); - if (mVerboseLoggingEnabled) localLog("readNetworkVariablesFromReader key=" + key); - boolean found = false; - String configKey = null; - String value = null; - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - if (line.matches("[ \\t]*network=\\{")) { - found = true; - configKey = null; - value = null; - } else if (line.matches("[ \\t]*\\}")) { - found = false; - configKey = null; - value = null; - } - if (found) { - String trimmedLine = line.trim(); - if (trimmedLine.startsWith(ID_STRING_VAR_NAME + "=")) { - try { - // Trim the quotes wrapping the id_str value. - final String encodedExtras = trimmedLine.substring( - 8, trimmedLine.length() -1); - final JSONObject json = - new JSONObject(URLDecoder.decode(encodedExtras, "UTF-8")); - if (json.has(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY)) { - final Object configKeyFromJson = - json.get(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY); - if (configKeyFromJson instanceof String) { - configKey = (String) configKeyFromJson; - } - } - } catch (JSONException e) { - if (mVerboseLoggingEnabled) { - loge("Could not get "+ WifiConfigStore.ID_STRING_KEY_CONFIG_KEY - + ", " + e); - } - } - } - if (trimmedLine.startsWith(key + "=")) { - value = trimmedLine.substring(key.length() + 1); - } - if (configKey != null && value != null) { - result.put(configKey, value); - } - } - } - return result; - } - - /** - * Checks if the network is a sim config. - * - * @param config Config corresponding to the network. - * @return true if it is a sim config, false otherwise. - */ - public boolean isSimConfig(WifiConfiguration config) { - if (config == null) { - return false; - } - - if (config.enterpriseConfig == null) { - return false; - } - - int method = config.enterpriseConfig.getEapMethod(); - return (method == WifiEnterpriseConfig.Eap.SIM - || method == WifiEnterpriseConfig.Eap.AKA - || method == WifiEnterpriseConfig.Eap.AKA_PRIME); - } - - /** - * Resets all sim networks from the provided network list. - * - * @param configs List of all the networks. - */ - public void resetSimNetworks(Collection<WifiConfiguration> configs) { - if (mVerboseLoggingEnabled) localLog("resetSimNetworks"); - for (WifiConfiguration config : configs) { - if (isSimConfig(config)) { - /* This configuration may have cached Pseudonym IDs; lets remove them */ - mWifiNative.setNetworkVariable(config.networkId, "identity", "NULL"); - mWifiNative.setNetworkVariable(config.networkId, "anonymous_identity", "NULL"); - } - } - } - - /** - * Clear BSSID blacklist in wpa_supplicant & HAL. - */ - public void clearBssidBlacklist() { - if (mVerboseLoggingEnabled) localLog("clearBlacklist"); - mWifiNative.clearBlacklist(); - mWifiNative.setBssidBlacklist(null); - } - - /** - * Add a BSSID to the blacklist. - * - * @param bssid to be added. - * @param bssidList entire BSSID list. - */ - public void blackListBssid(String bssid, String[] bssidList) { - if (mVerboseLoggingEnabled) localLog("blackListBssid: " + bssid); - // Blacklist at wpa_supplicant - mWifiNative.addToBlacklist(bssid); - // Blacklist at firmware - mWifiNative.setBssidBlacklist(bssidList); - } - - /** - * Start WPS pin method configuration with pin obtained - * from the access point - * - * @param config WPS configuration - * @return Wps result containing status and pin - */ - public WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) { - WpsResult result = new WpsResult(); - if (mWifiNative.startWpsRegistrar(config.BSSID, config.pin)) { - 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 obtained - * from the device - * - * @return WpsResult indicating status and pin - */ - public WpsResult startWpsWithPinFromDevice(WpsInfo config) { - WpsResult result = new WpsResult(); - result.pin = mWifiNative.startWpsPinDisplay(config.BSSID); - if (!TextUtils.isEmpty(result.pin)) { - 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 - */ - public WpsResult startWpsPbc(WpsInfo config) { - WpsResult result = new WpsResult(); - if (mWifiNative.startWpsPbc(config.BSSID)) { - result.status = WpsResult.Status.SUCCESS; - } else { - loge("Failed to start WPS push button configuration"); - result.status = WpsResult.Status.FAILURE; - } - return result; - } - - protected void logd(String s) { - Log.d(TAG, s); - } - - protected void logi(String s) { - Log.i(TAG, s); - } - - protected void loge(String s) { - loge(s, false); - } - - protected void loge(String s, boolean stack) { - if (stack) { - Log.e(TAG, s + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() - + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); - } else { - Log.e(TAG, s); - } - } - - protected void log(String s) { - Log.d(TAG, s); - } - - private void localLog(String s) { - if (mLocalLog != null) { - mLocalLog.log(TAG + ": " + s); - } - } - - private void localLogAndLogcat(String s) { - localLog(s); - Log.d(TAG, s); - } - - void enableVerboseLogging(boolean verbose) { - mVerboseLoggingEnabled = verbose; - } - - private class SupplicantSaver implements WifiEnterpriseConfig.SupplicantSaver { - private final int mNetId; - private final String mSetterSSID; - - SupplicantSaver(int netId, String setterSSID) { - mNetId = netId; - mSetterSSID = setterSSID; - } - - @Override - public boolean saveValue(String key, String value) { - if (key.equals(WifiEnterpriseConfig.PASSWORD_KEY) - && value != null && value.equals("*")) { - // No need to try to set an obfuscated password, which will fail - return true; - } - if (key.equals(WifiEnterpriseConfig.REALM_KEY) - || key.equals(WifiEnterpriseConfig.PLMN_KEY)) { - // No need to save realm or PLMN in supplicant - return true; - } - // TODO: We need a way to clear values in wpa_supplicant as opposed to - // mapping unset values to empty strings. - if (value == null) { - value = "\"\""; - } - if (!mWifiNative.setNetworkVariable(mNetId, key, value)) { - loge(mSetterSSID + ": failed to set " + key + ": " + value); - return false; - } - return true; - } - } - - private class SupplicantLoader implements WifiEnterpriseConfig.SupplicantLoader { - private final int mNetId; - - SupplicantLoader(int netId) { - mNetId = netId; - } - - @Override - public String loadValue(String key) { - String value = mWifiNative.getNetworkVariable(mNetId, key); - if (!TextUtils.isEmpty(value)) { - if (!enterpriseConfigKeyShouldBeQuoted(key)) { - value = removeDoubleQuotes(value); - } - return value; - } else { - return null; - } - } - - /** - * Returns true if a particular config key needs to be quoted when passed to the supplicant. - */ - private boolean enterpriseConfigKeyShouldBeQuoted(String key) { - switch (key) { - case WifiEnterpriseConfig.EAP_KEY: - case WifiEnterpriseConfig.ENGINE_KEY: - return false; - default: - return true; - } - } - } - - // TODO(rpius): Remove this (see b/27377614). - private class WpaConfigFileObserver extends FileObserver { - - 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 (mVerboseLoggingEnabled) { - localLog("wpa_supplicant.conf changed; new size = " + file.length()); - } - } - } - } -} |