diff options
author | Mitchell Wills <mwills@google.com> | 2016-05-03 15:16:29 -0700 |
---|---|---|
committer | Mitchell Wills <mwills@google.com> | 2016-06-24 17:46:55 -0700 |
commit | 3c8094ab45f3320dbe45e6460c5d62dcc24ce7ae (patch) | |
tree | e0fb45a5375b66434395dea02702634de420dc15 | |
parent | 55b1b58e72df2362888c7a1c60ad76a43523bfcf (diff) |
Clear auth identity if sim removed while the device is off
TEST: Validated that changing a SIM both when the device is on and when
it is off results in the correct identity being used when trying
to authenticate with an EAP-SIM network.
Fixes: 28163651
Change-Id: I3dda95308a527be225a9f70636c727c9826ac939
6 files changed, 164 insertions, 62 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 4c930a667..c1c244de6 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -398,7 +398,7 @@ public class WifiConfigManager { mIpconfigStore = new IpConfigStore(mWriter); mWifiNetworkHistory = new WifiNetworkHistory(context, mLocalLog, mWriter); mWifiConfigStore = - new WifiConfigStore(wifiNative, mKeyStore, mLocalLog, mShowNetworks, true); + new WifiConfigStore(context, wifiNative, mKeyStore, mLocalLog, mShowNetworks, true); } public void trimANQPCache(boolean all) { @@ -3119,15 +3119,6 @@ public class WifiConfigManager { } /** - * 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) { - return mWifiConfigStore.isSimConfig(config); - } - - /** * Resets all sim networks from the network list. */ public void resetSimNetworks() { diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index 25ab4493b..b693e2344 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -16,6 +16,7 @@ package com.android.server.wifi; +import android.content.Context; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.wifi.WifiConfiguration; @@ -36,6 +37,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.server.wifi.hotspot2.Utils; +import com.android.server.wifi.util.TelephonyUtil; import org.json.JSONException; import org.json.JSONObject; @@ -92,6 +94,7 @@ public class WifiConfigStore { private final LocalLog mLocalLog; private final WpaConfigFileObserver mFileObserver; + private final Context mContext; private final WifiNative mWifiNative; private final KeyStore mKeyStore; private final boolean mShowNetworks; @@ -99,8 +102,9 @@ public class WifiConfigStore { private final BackupManagerProxy mBackupManagerProxy; - WifiConfigStore(WifiNative wifiNative, KeyStore keyStore, LocalLog localLog, + WifiConfigStore(Context context, WifiNative wifiNative, KeyStore keyStore, LocalLog localLog, boolean showNetworks, boolean verboseDebug) { + mContext = context; mWifiNative = wifiNative; mKeyStore = keyStore; mShowNetworks = showNetworks; @@ -1079,27 +1083,6 @@ public class WifiConfigStore { } /** - * 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. @@ -1107,10 +1090,26 @@ public class WifiConfigStore { public void resetSimNetworks(Collection<WifiConfiguration> configs) { if (VDBG) 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"); + if (TelephonyUtil.isSimConfig(config)) { + String currentIdentity = TelephonyUtil.getSimIdentity(mContext, + config.enterpriseConfig.getEapMethod()); + String supplicantIdentity = + mWifiNative.getNetworkVariable(config.networkId, "identity"); + if(supplicantIdentity != null) { + supplicantIdentity = removeDoubleQuotes(supplicantIdentity); + } + if (currentIdentity == null || !currentIdentity.equals(supplicantIdentity)) { + // Identity differs so update the identity + mWifiNative.setNetworkVariable(config.networkId, + WifiEnterpriseConfig.IDENTITY_KEY, WifiEnterpriseConfig.EMPTY_VALUE); + // This configuration may have cached Pseudonym IDs; lets remove them + mWifiNative.setNetworkVariable(config.networkId, + WifiEnterpriseConfig.ANON_IDENTITY_KEY, + WifiEnterpriseConfig.EMPTY_VALUE); + } + // Update the loaded config + config.enterpriseConfig.setIdentity(currentIdentity); + config.enterpriseConfig.setAnonymousIdentity(""); } } } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 7193580de..e0e84cb73 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -391,9 +391,12 @@ public class WifiServiceImpl extends IWifiManager.Stub { String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { Log.d(TAG, "resetting networks because SIM was removed"); - mWifiStateMachine.resetSimAuthNetworks(); + mWifiStateMachine.resetSimAuthNetworks(false); Log.d(TAG, "resetting country code because SIM is removed"); mCountryCode.simCardRemoved(); + } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { + Log.d(TAG, "resetting networks because SIM was loaded"); + mWifiStateMachine.resetSimAuthNetworks(true); } } }, diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 7fa739f38..fb3b29326 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -108,6 +108,7 @@ import com.android.server.wifi.hotspot2.IconEvent; import com.android.server.wifi.hotspot2.NetworkDetail; import com.android.server.wifi.hotspot2.Utils; import com.android.server.wifi.p2p.WifiP2pServiceImpl; +import com.android.server.wifi.util.TelephonyUtil; import java.io.BufferedReader; import java.io.FileDescriptor; @@ -2143,8 +2144,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss /** * reset cached SIM credential data */ - public synchronized void resetSimAuthNetworks() { - sendMessage(CMD_RESET_SIM_NETWORKS); + public synchronized void resetSimAuthNetworks(boolean simPresent) { + sendMessage(CMD_RESET_SIM_NETWORKS, simPresent ? 1 : 0); } /** @@ -4507,7 +4508,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss replyToMessage(message, message.what, stats); break; case CMD_RESET_SIM_NETWORKS: - log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed"); + log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); mWifiConfigManager.resetSimNetworks(); break; default: @@ -5610,24 +5611,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss && targetWificonfiguration.networkId == networkId && targetWificonfiguration.allowedKeyManagement .get(WifiConfiguration.KeyMgmt.IEEE8021X) - && (eapMethod == WifiEnterpriseConfig.Eap.SIM - || eapMethod == WifiEnterpriseConfig.Eap.AKA - || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME)) { - TelephonyManager tm = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - if (tm != null) { - String imsi = tm.getSubscriberId(); - String mccMnc = ""; - - if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) - mccMnc = tm.getSimOperator(); - - String identity = buildIdentity(eapMethod, imsi, mccMnc); - - if (!identity.isEmpty()) { - mWifiNative.simIdentityResponse(networkId, identity); - identitySent = true; - } + && TelephonyUtil.isSimEapMethod(eapMethod)) { + String identity = TelephonyUtil.getSimIdentity(mContext, eapMethod); + if (identity != null) { + mWifiNative.simIdentityResponse(networkId, identity); + identitySent = true; } } if (!identitySent) { @@ -6686,10 +6674,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss stopRssiMonitoringOffload(); break; case CMD_RESET_SIM_NETWORKS: - if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { + if (message.arg1 == 0 // sim was removed + && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(mLastNetworkId); - if (mWifiConfigManager.isSimConfig(config)) { + if (TelephonyUtil.isSimConfig(config)) { mWifiNative.disconnect(); transitionTo(mDisconnectingState); } @@ -7881,6 +7870,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss return result; } + // TODO move to TelephonyUtil, same with utilities above String getGsmSimAuthResponse(String[] requestData, TelephonyManager tm) { StringBuilder sb = new StringBuilder(); for (String challenge : requestData) { @@ -7942,6 +7932,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss return sb.toString(); } + // TODO move to TelephonyUtil void handleGsmAuthRequest(SimAuthRequestData requestData) { if (targetWificonfiguration == null || targetWificonfiguration.networkId == requestData.networkId) { @@ -7969,6 +7960,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss } } + // TODO move to TelephonyUtil void handle3GAuthRequest(SimAuthRequestData requestData) { StringBuilder sb = new StringBuilder(); byte[] rand = null; diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java new file mode 100644 index 000000000..3d7ce455c --- /dev/null +++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java @@ -0,0 +1,115 @@ +/* + * 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.util; + +import android.content.Context; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiEnterpriseConfig; +import android.telephony.TelephonyManager; + +/** + * Utilities for the Wifi Service to interact with telephony. + */ +public class TelephonyUtil { + + /** + * Get the identity for the current SIM or null if the sim is not available + */ + public static String getSimIdentity(Context context, int eapMethod) { + TelephonyManager tm = TelephonyManager.from(context); + if (tm != null) { + String imsi = tm.getSubscriberId(); + String mccMnc = ""; + + if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) { + mccMnc = tm.getSimOperator(); + } + + return buildIdentity(eapMethod, imsi, mccMnc); + } else { + return null; + } + } + + /** + * create Permanent Identity base on IMSI, + * + * rfc4186 & rfc4187: + * identity = usernam@realm + * with username = prefix | IMSI + * and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) + */ + private static String buildIdentity(int eapMethod, String imsi, String mccMnc) { + if (imsi == null || imsi.isEmpty()) { + return null; + } + + String prefix; + if (eapMethod == WifiEnterpriseConfig.Eap.SIM) { + prefix = "1"; + } else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) { + prefix = "0"; + } else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) { + prefix = "6"; + } else { // not a valide EapMethod + return null; + } + + /* extract mcc & mnc from mccMnc */ + String mcc; + String mnc; + if (mccMnc != null && !mccMnc.isEmpty()) { + mcc = mccMnc.substring(0, 3); + mnc = mccMnc.substring(3); + if (mnc.length() == 2) { + mnc = "0" + mnc; + } + } else { + // extract mcc & mnc from IMSI, assume mnc size is 3 + mcc = imsi.substring(0, 3); + mnc = imsi.substring(3, 6); + } + + return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; + } + + /** + * 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 static boolean isSimConfig(WifiConfiguration config) { + if (config == null || config.enterpriseConfig == null) { + return false; + } + + return isSimEapMethod(config.enterpriseConfig.getEapMethod()); + } + + /** + * Checks if the network is a sim config. + * + * @param method + * @return true if it is a sim config, false otherwise. + */ + public static boolean isSimEapMethod(int eapMethod) { + return eapMethod == WifiEnterpriseConfig.Eap.SIM + || eapMethod == WifiEnterpriseConfig.Eap.AKA + || eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME; + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java index 145c84026..3993fe565 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java @@ -19,6 +19,7 @@ package com.android.server.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import android.content.Context; import android.test.suitebuilder.annotation.SmallTest; import org.junit.Before; @@ -155,6 +156,7 @@ public class WifiConfigStoreTest { + "}\n"; @Mock private WifiNative mWifiNative; + @Mock private Context mContext; private MockKeyStore mMockKeyStore; private WifiConfigStore mWifiConfigStore; @@ -163,8 +165,8 @@ public class WifiConfigStoreTest { MockitoAnnotations.initMocks(this); mMockKeyStore = new MockKeyStore(); - mWifiConfigStore = new WifiConfigStore(mWifiNative, mMockKeyStore.createMock(), null, - false, true); + mWifiConfigStore = new WifiConfigStore(mContext, mWifiNative, mMockKeyStore.createMock(), + null, false, true); } /** |