Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6ea41ef authored by Irfan Sheriff's avatar Irfan Sheriff Committed by Gerrit Code Review
Browse files

Merge changes I8c5649c9,I79b43bf7,I83a01690,If5687eac,Ib9fd57c6,I7104250e

* changes:
  Fix broken test.
  Track keys per config and allow cert push from apps
  eix enterprise config storage bugs
  Fix connectivitymanagertest
  Fix build
  Refactor enterprise config
parents 9657ba0e 1c2acdc6
Loading
Loading
Loading
Loading
+27 −17
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
@@ -67,7 +68,6 @@ import java.util.List;
 *      networkprefixlength.
 */
public class AccessPointParserHelper {
    private static final String KEYSTORE_SPACE = "keystore://";
    private static final String TAG = "AccessPointParserHelper";
    static final int NONE = 0;
    static final int WEP = 1;
@@ -212,14 +212,11 @@ public class AccessPointParserHelper {
                        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
                        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
                        // Initialize other fields.
                        config.phase2.setValue("");
                        config.ca_cert.setValue("");
                        config.client_cert.setValue("");
                        config.engine.setValue("");
                        config.engine_id.setValue("");
                        config.key_id.setValue("");
                        config.identity.setValue("");
                        config.anonymous_identity.setValue("");
                        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
                        config.enterpriseConfig.setCaCertificateAlias("");
                        config.enterpriseConfig.setClientCertificateAlias("");
                        config.enterpriseConfig.setIdentity("");
                        config.enterpriseConfig.setAnonymousIdentity("");
                        break;
                    default:
                        throw new SAXException();
@@ -246,7 +243,7 @@ public class AccessPointParserHelper {
                        config.preSharedKey = '"' + passwordStr + '"';
                    }
                } else if (securityType == EAP) {
                    config.password.setValue(passwordStr);
                    config.enterpriseConfig.setPassword(passwordStr);
                } else {
                    throw new SAXException();
                }
@@ -257,33 +254,46 @@ public class AccessPointParserHelper {
                if (!validateEapValue(eapValue)) {
                    throw new SAXException();
                }
                config.eap.setValue(eapValue);
		if (eapValue.equals("TLS")) {
		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
		} else if (eapValue.equals("TTLS")) {
		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
		} else if (eapValue.equals("PEAP")) {
		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
		}
                eap = false;
            }
            if (phase2) {
                String phase2Value = new String(ch, start, length);
                config.phase2.setValue("auth=" + phase2Value);
		if (phase2Value.equals("PAP")) {
                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
		} else if (phase2Value.equals("MSCHAP")) {
                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAP);
		} else if (phase2Value.equals("MSCHAPV2")) {
                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
		} else if (phase2Value.equals("GTC")) {
                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
		}
                phase2 = false;
            }
            if (identity) {
                String identityValue = new String(ch, start, length);
                config.identity.setValue(identityValue);
                config.enterpriseConfig.setIdentity(identityValue);
                identity = false;
            }
            if (anonymousidentity) {
                String anonyId = new String(ch, start, length);
                config.anonymous_identity.setValue(anonyId);
                config.enterpriseConfig.setAnonymousIdentity(anonyId);
                anonymousidentity = false;
            }
            if (cacert) {
                String cacertValue = new String(ch, start, length);
                // need to install the credentail to "keystore://"
                config.ca_cert.setValue(KEYSTORE_SPACE);
                config.enterpriseConfig.setCaCertificateAlias(cacertValue);
                cacert = false;
            }
            if (usercert) {
                String usercertValue = new String(ch, start, length);
                config.client_cert.setValue(KEYSTORE_SPACE);
                config.enterpriseConfig.setClientCertificateAlias(usercertValue);
                usercert = false;
            }
            if (ip) {
+78 −103
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.net.NetworkUtils;
import android.net.NetworkInfo.DetailedState;
import android.net.ProxyProperties;
import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration.EnterpriseField;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
@@ -37,6 +36,7 @@ import android.os.Message;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.Log;

@@ -144,6 +144,7 @@ class WifiConfigStore {
    private static final String EOS = "eos";

    private WifiNative mWifiNative;
    private final KeyStore mKeyStore = KeyStore.getInstance();

    WifiConfigStore(Context c, WifiNative wn) {
        mContext = c;
@@ -295,16 +296,7 @@ class WifiConfigStore {
    boolean forgetNetwork(int netId) {
        if (mWifiNative.removeNetwork(netId)) {
            mWifiNative.saveConfig();
            WifiConfiguration target = null;
            WifiConfiguration config = mConfiguredNetworks.get(netId);
            if (config != null) {
                target = mConfiguredNetworks.remove(netId);
                mNetworkIds.remove(configKey(config));
            }
            if (target != null) {
                writeIpAndProxyConfigurations();
                sendConfiguredNetworksChangedBroadcast(target, WifiManager.CHANGE_REASON_REMOVED);
            }
            removeConfigAndSendBroadcastIfNeeded(netId);
            return true;
        } else {
            loge("Failed to remove network " + netId);
@@ -342,18 +334,25 @@ class WifiConfigStore {
     */
    boolean removeNetwork(int netId) {
        boolean ret = mWifiNative.removeNetwork(netId);
        WifiConfiguration config = null;
        if (ret) {
            config = mConfiguredNetworks.get(netId);
            if (config != null) {
                config = mConfiguredNetworks.remove(netId);
                mNetworkIds.remove(configKey(config));
            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) {
                config.enterpriseConfig.removeKeys(mKeyStore);
            }
            mConfiguredNetworks.remove(netId);
            mNetworkIds.remove(configKey(config));

            writeIpAndProxyConfigurations();
            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
        }
        return ret;
    }

    /**
@@ -1122,34 +1121,57 @@ class WifiConfigStore {
                break setVariables;
            }

            for (WifiConfiguration.EnterpriseField field
                    : config.enterpriseFields) {
                String varName = field.varName();
                String value = field.value();
                if (value != null) {
                    if (field == config.engine) {
                        /*
                         * If the field is declared as an integer, it must not
                         * be null
            if (config.enterpriseConfig != null) {

                WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;

                if (enterpriseConfig.needsKeyStore()) {
                    /**
                     * Keyguard settings may eventually be controlled by device policy.
                     * We check here if keystore is unlocked before installing
                     * credentials.
                     * TODO: Figure a way to store these credentials for wifi alone
                     * 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
                         */
                        if (value.length() == 0) {
                            value = "0";
                        WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
                        String keyId = config.getKeyIdForCredentials(currentConfig);

                        if (!enterpriseConfig.installKeys(mKeyStore, keyId)) {
                            loge(config.SSID + ": failed to install keys");
                            break setVariables;
                        }
                    } catch (IllegalStateException e) {
                        loge(config.SSID + " invalid config for key installation");
                        break setVariables;
                    }
                    } else if (field != config.eap) {
                        value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
                }

                HashMap<String, String> enterpriseFields = enterpriseConfig.getFields();
                for (String key : enterpriseFields.keySet()) {
                        String value = enterpriseFields.get(key);
                        if (!mWifiNative.setNetworkVariable(
                                    netId,
                                varName,
                                    key,
                                    value)) {
                        loge(config.SSID + ": failed to set " + varName +
                            enterpriseConfig.removeKeys(mKeyStore);
                            loge(config.SSID + ": failed to set " + key +
                                    ": " + value);
                            break setVariables;
                        }
                }
            }
            updateFailed = false;
        }
        } //end of setVariables

        if (updateFailed) {
            if (newNetwork) {
@@ -1445,78 +1467,31 @@ class WifiConfigStore {
            }
        }

        for (WifiConfiguration.EnterpriseField field :
                config.enterpriseFields) {
            value = mWifiNative.getNetworkVariable(netId,
                    field.varName());
            if (!TextUtils.isEmpty(value)) {
                if (field != config.eap && field != config.engine) {
                    value = removeDoubleQuotes(value);
                }
                field.setValue(value);
        if (config.enterpriseConfig == null) {
            config.enterpriseConfig = new WifiEnterpriseConfig();
        }
        }

        migrateOldEapTlsIfNecessary(config, netId);
    }

    /**
     * Migration code for old EAP-TLS configurations. This should only be used
     * when restoring an old wpa_supplicant.conf or upgrading from a previous
     * platform version.
     *
     * @param config the configuration to be migrated
     * @param netId the wpa_supplicant's net ID
     * @param value the old private_key value
     */
    private void migrateOldEapTlsIfNecessary(WifiConfiguration config, int netId) {
        String value = mWifiNative.getNetworkVariable(netId,
                WifiConfiguration.OLD_PRIVATE_KEY_NAME);
        /*
         * If the old configuration value is not present, then there is nothing
         * to do.
         */
        if (TextUtils.isEmpty(value)) {
            return;
        } else {
            // Also ignore it if it's empty quotes.
            value = removeDoubleQuotes(value);
            if (TextUtils.isEmpty(value)) {
                return;
            }
        }

        config.engine.setValue(WifiConfiguration.ENGINE_ENABLE);
        config.engine_id.setValue(convertToQuotedString(WifiConfiguration.KEYSTORE_ENGINE_ID));

        /*
         * 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 (value.startsWith(WifiConfiguration.KEYSTORE_URI)) {
            keyName = new String(value.substring(WifiConfiguration.KEYSTORE_URI.length()));
        HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
        for (String key : WifiEnterpriseConfig.getSupplicantKeys()) {
            value = mWifiNative.getNetworkVariable(netId, key);
            if (!TextUtils.isEmpty(value)) {
                enterpriseFields.put(key, removeDoubleQuotes(value));
            } else {
            keyName = value;
                enterpriseFields.put(key, WifiEnterpriseConfig.EMPTY_VALUE);
            }
        config.key_id.setValue(convertToQuotedString(keyName));

        // Now tell the wpa_supplicant the new configuration values.
        final EnterpriseField needsUpdate[] = { config.engine, config.engine_id, config.key_id };
        for (EnterpriseField field : needsUpdate) {
            mWifiNative.setNetworkVariable(netId, field.varName(), field.value());
        }

        // Remove old private_key string so we don't run this again.
        mWifiNative.setNetworkVariable(netId, WifiConfiguration.OLD_PRIVATE_KEY_NAME,
                convertToQuotedString(""));

        if (config.enterpriseConfig.migrateOldEapTlsNative(mWifiNative, netId)) {
            saveConfig();
        }
    }

    private String removeDoubleQuotes(String string) {
        if (string.length() <= 2) return "";
        return string.substring(1, string.length() - 1);
        int length = string.length();
        if ((length > 1) && (string.charAt(0) == '"')
                && (string.charAt(length - 1) == '"')) {
            return string.substring(1, length - 1);
        }
        return string;
    }

    private String convertToQuotedString(String string) {
+73 −108
Original line number Diff line number Diff line
@@ -19,49 +19,16 @@ package android.net.wifi;
import android.net.LinkProperties;
import android.os.Parcelable;
import android.os.Parcel;
import android.text.TextUtils;

import java.util.BitSet;

/**
 * A class representing a configured Wi-Fi network, including the
 * security configuration. Android will not necessarily support
 * all of these security schemes initially.
 * security configuration.
 */
public class WifiConfiguration implements Parcelable {

    /**
     * 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.
     * @hide
     */
    public static final String OLD_PRIVATE_KEY_NAME = "private_key";

    /**
     * String representing the keystore OpenSSL ENGINE's ID.
     * @hide
     */
    public static final String KEYSTORE_ENGINE_ID = "keystore";

    /**
     * String representing the keystore URI used for wpa_supplicant.
     * @hide
     */
    public static final String KEYSTORE_URI = "keystore://";

    /**
     * String to set the engine value to when it should be enabled.
     * @hide
     */
    public static final String ENGINE_ENABLE = "1";

    /**
     * String to set the engine value to when it should be disabled.
     * @hide
     */
    public static final String ENGINE_DISABLE = "0";

    private static final String TAG = "WifiConfiguration";
    /** {@hide} */
    public static final String ssidVarName = "ssid";
    /** {@hide} */
@@ -78,56 +45,6 @@ public class WifiConfiguration implements Parcelable {
    public static final String hiddenSSIDVarName = "scan_ssid";
    /** {@hide} */
    public static final int INVALID_NETWORK_ID = -1;

    /** {@hide} */
    public class EnterpriseField {
        private String varName;
        private String value;

        private EnterpriseField(String varName) {
            this.varName = varName;
            this.value = null;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String varName() {
            return varName;
        }

        public String value() {
            return value;
        }
    }

    /** {@hide} */
    public EnterpriseField eap = new EnterpriseField("eap");
    /** {@hide} */
    public EnterpriseField phase2 = new EnterpriseField("phase2");
    /** {@hide} */
    public EnterpriseField identity = new EnterpriseField("identity");
    /** {@hide} */
    public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
    /** {@hide} */
    public EnterpriseField password = new EnterpriseField("password");
    /** {@hide} */
    public EnterpriseField client_cert = new EnterpriseField("client_cert");
    /** {@hide} */
    public EnterpriseField engine = new EnterpriseField("engine");
    /** {@hide} */
    public EnterpriseField engine_id = new EnterpriseField("engine_id");
    /** {@hide} */
    public EnterpriseField key_id = new EnterpriseField("key_id");
    /** {@hide} */
    public EnterpriseField ca_cert = new EnterpriseField("ca_cert");

    /** {@hide} */
    public EnterpriseField[] enterpriseFields = {
            eap, phase2, identity, anonymous_identity, password, client_cert,
            engine, engine_id, key_id, ca_cert };

    /**
     * Recognized key management schemes.
     */
@@ -357,6 +274,12 @@ public class WifiConfiguration implements Parcelable {
     * Defaults to CCMP TKIP WEP104 WEP40.
     */
    public BitSet allowedGroupCiphers;
    /**
     * The enterprise configuration details specifying the EAP method,
     * certificates and other settings associated with the EAP.
     * @hide
     */
    public WifiEnterpriseConfig enterpriseConfig;

    /**
     * @hide
@@ -412,11 +335,10 @@ public class WifiConfiguration implements Parcelable {
        allowedPairwiseCiphers = new BitSet();
        allowedGroupCiphers = new BitSet();
        wepKeys = new String[4];
        for (int i = 0; i < wepKeys.length; i++)
        for (int i = 0; i < wepKeys.length; i++) {
            wepKeys[i] = null;
        for (EnterpriseField field : enterpriseFields) {
            field.setValue(null);
        }
        enterpriseConfig = new WifiEnterpriseConfig();
        ipAssignment = IpAssignment.UNASSIGNED;
        proxySettings = ProxySettings.UNASSIGNED;
        linkProperties = new LinkProperties();
@@ -496,12 +418,9 @@ public class WifiConfiguration implements Parcelable {
            sbuf.append('*');
        }

        for (EnterpriseField field : enterpriseFields) {
            sbuf.append('\n').append(" " + field.varName() + ": ");
            String value = field.value();
            if (value != null) sbuf.append(value);
        }
        sbuf.append(enterpriseConfig);
        sbuf.append('\n');

        sbuf.append("IP assignment: " + ipAssignment.toString());
        sbuf.append("\n");
        sbuf.append("Proxy settings: " + proxySettings.toString());
@@ -545,12 +464,54 @@ public class WifiConfiguration implements Parcelable {
        return SSID;
    }

    /**
     * Get an identifier for associating credentials with this config
     * @param current configuration contains values for additional fields
     *                that are not part of this configuration. Used
     *                when a config with some fields is passed by an application.
     * @throws IllegalStateException if config is invalid for key id generation
     * @hide
     */
    String getKeyIdForCredentials(WifiConfiguration current) {
        String keyMgmt = null;

        try {
            // Get current config details for fields that are not initialized
            if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
            if (allowedKeyManagement.cardinality() == 0) {
                allowedKeyManagement = current.allowedKeyManagement;
            }
            if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
                keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
            }
            if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
                keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
            }

            if (TextUtils.isEmpty(keyMgmt)) {
                throw new IllegalStateException("Not an EAP network");
            }

            return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
                    trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
                            current.enterpriseConfig : null));
        } catch (NullPointerException e) {
            throw new IllegalStateException("Invalid config details");
        }
    }

    private String trimStringForKeyId(String string) {
        // Remove quotes and spaces
        return string.replace("\"", "").replace(" ", "");
    }

    private static BitSet readBitSet(Parcel src) {
        int cardinality = src.readInt();

        BitSet set = new BitSet();
        for (int i = 0; i < cardinality; i++)
        for (int i = 0; i < cardinality; i++) {
            set.set(src.readInt());
        }

        return set;
    }
@@ -560,12 +521,16 @@ public class WifiConfiguration implements Parcelable {

        dest.writeInt(set.cardinality());

        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1)
        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
            dest.writeInt(nextSetBit);
        }
    }

    /** @hide */
    public int getAuthType() {
        if (allowedKeyManagement.cardinality() > 1) {
            throw new IllegalStateException("More than one auth type set");
        }
        if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
            return KeyMgmt.WPA_PSK;
        } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
@@ -594,8 +559,9 @@ public class WifiConfiguration implements Parcelable {
            preSharedKey = source.preSharedKey;

            wepKeys = new String[4];
            for (int i = 0; i < wepKeys.length; i++)
            for (int i = 0; i < wepKeys.length; i++) {
                wepKeys[i] = source.wepKeys[i];
            }

            wepTxKeyIndex = source.wepTxKeyIndex;
            priority = source.priority;
@@ -606,9 +572,8 @@ public class WifiConfiguration implements Parcelable {
            allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
            allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();

            for (int i = 0; i < source.enterpriseFields.length; i++) {
                enterpriseFields[i].setValue(source.enterpriseFields[i].value());
            }
            enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);

            ipAssignment = source.ipAssignment;
            proxySettings = source.proxySettings;
            linkProperties = new LinkProperties(source.linkProperties);
@@ -623,8 +588,9 @@ public class WifiConfiguration implements Parcelable {
        dest.writeString(SSID);
        dest.writeString(BSSID);
        dest.writeString(preSharedKey);
        for (String wepKey : wepKeys)
        for (String wepKey : wepKeys) {
            dest.writeString(wepKey);
        }
        dest.writeInt(wepTxKeyIndex);
        dest.writeInt(priority);
        dest.writeInt(hiddenSSID ? 1 : 0);
@@ -635,9 +601,8 @@ public class WifiConfiguration implements Parcelable {
        writeBitSet(dest, allowedPairwiseCiphers);
        writeBitSet(dest, allowedGroupCiphers);

        for (EnterpriseField field : enterpriseFields) {
            dest.writeString(field.value());
        }
        dest.writeParcelable(enterpriseConfig, flags);

        dest.writeString(ipAssignment.name());
        dest.writeString(proxySettings.name());
        dest.writeParcelable(linkProperties, flags);
@@ -654,8 +619,9 @@ public class WifiConfiguration implements Parcelable {
                config.SSID = in.readString();
                config.BSSID = in.readString();
                config.preSharedKey = in.readString();
                for (int i = 0; i < config.wepKeys.length; i++)
                for (int i = 0; i < config.wepKeys.length; i++) {
                    config.wepKeys[i] = in.readString();
                }
                config.wepTxKeyIndex = in.readInt();
                config.priority = in.readInt();
                config.hiddenSSID = in.readInt() != 0;
@@ -665,13 +631,12 @@ public class WifiConfiguration implements Parcelable {
                config.allowedPairwiseCiphers = readBitSet(in);
                config.allowedGroupCiphers    = readBitSet(in);

                for (EnterpriseField field : config.enterpriseFields) {
                    field.setValue(in.readString());
                }
                config.enterpriseConfig = in.readParcelable(null);

                config.ipAssignment = IpAssignment.valueOf(in.readString());
                config.proxySettings = ProxySettings.valueOf(in.readString());
                config.linkProperties = in.readParcelable(null);

                return config;
            }

+19 −0

File added.

Preview size limit exceeded, changes collapsed.

+666 −0

File added.

Preview size limit exceeded, changes collapsed.