diff options
author | Masashi Honma <masashi.honma@gmail.com> | 2018-04-02 17:09:51 +0900 |
---|---|---|
committer | Ecco Park <eccopark@google.com> | 2018-04-10 14:29:11 -0700 |
commit | 2e889dc0b3f348f45cc5f5006d8784bed30583a9 (patch) | |
tree | a6029d1c0b94173e389246a686b22a5085369588 | |
parent | a6bf3d5d91be6913e45408262638d60bbc4cdb5b (diff) |
Wifi: Allow Hotspot 2.0 connection without Roaming Consortium ANQP-element
Currently, the Android could not connect to APs which has Roaming
Consortium OIs less than 3.
To send Roaming Consortium OIs from an AP to some STAs, an AP can use
"Roaming Consortium information element". As defined in [1] "9.4.2.96
Roaming Consortium element", the maximum number of the OIs the
information element can carry is 3. If an AP has more OIs, the AP can
use "Roaming Consortium ANQP-element" also.
The Android uses only "Roaming Consortium ANQP-element". So the
Android could not connect to the APs which does not send "Roaming
Consortium ANQP-element". There could be an AP which sends "Roaming
Consortium ANQP-element" even if it has only one OI. At least hostapd
does not send "Roaming Consortium ANQP-element" when it has only one
OI.
This patch supports to connect to such APs.
Bug: 77624036
Test: Connect with roaming consortium OI on Nexus 5X with hostapd
commit 64624f31cf81dc6164462fa153ee7a5909e21183 "OWE: Fix CONFIG_OWE=y
build without CONFIG_IEEE80211R=y". I tested with android-8.1.0_r18
branch and port the patch to master branch because my Nexus 5X does
not boot with master branch.
Test: All the tests are passed
./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: Ia48b242382836f7ee3a6f97888d2a3dcc4f2b189
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
7 files changed, 137 insertions, 27 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java index 0c7716286..edee2da1a 100644 --- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java +++ b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java @@ -253,7 +253,7 @@ public class NetworkDetail { mHSRelease = vsa.hsRelease; mAnqpDomainID = vsa.anqpDomainID; mAnqpOICount = roamingConsortium.anqpOICount; - mRoamingConsortiums = roamingConsortium.roamingConsortiums; + mRoamingConsortiums = roamingConsortium.getRoamingConsortiums(); mExtendedCapabilities = extendedCapabilities; mANQPElements = null; //set up channel info diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index 9423edea9..a0915fa52 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -411,7 +411,7 @@ public class PasspointManager { for (Map.Entry<String, PasspointProvider> entry : mProviders.entrySet()) { PasspointProvider provider = entry.getValue(); - PasspointMatch matchStatus = provider.match(anqpEntry.getElements()); + PasspointMatch matchStatus = provider.match(anqpEntry.getElements(), roamingConsortium); if (matchStatus == PasspointMatch.HomeProvider || matchStatus == PasspointMatch.RoamingProvider) { allMatches.add(Pair.create(provider, matchStatus)); diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java index 23ab57ff4..f86a938d7 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java @@ -40,6 +40,7 @@ import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; +import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -253,10 +254,12 @@ public class PasspointProvider { * Return the matching status with the given AP, based on the ANQP elements from the AP. * * @param anqpElements ANQP elements from the AP + * @param roamingConsortium Roaming Consortium information element from the AP * @return {@link PasspointMatch} */ - public PasspointMatch match(Map<ANQPElementType, ANQPElement> anqpElements) { - PasspointMatch providerMatch = matchProvider(anqpElements); + public PasspointMatch match(Map<ANQPElementType, ANQPElement> anqpElements, + RoamingConsortium roamingConsortium) { + PasspointMatch providerMatch = matchProvider(anqpElements, roamingConsortium); // Perform authentication match against the NAI Realm. int authMatch = ANQPMatcher.matchNAIRealm( @@ -454,9 +457,11 @@ public class PasspointProvider { * Perform a provider match based on the given ANQP elements. * * @param anqpElements List of ANQP elements + * @param roamingConsortium Roaming Consortium information element from the AP * @return {@link PasspointMatch} */ - private PasspointMatch matchProvider(Map<ANQPElementType, ANQPElement> anqpElements) { + private PasspointMatch matchProvider(Map<ANQPElementType, ANQPElement> anqpElements, + RoamingConsortium roamingConsortium) { // Domain name matching. if (ANQPMatcher.matchDomainName( (DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName), @@ -464,13 +469,26 @@ public class PasspointProvider { return PasspointMatch.HomeProvider; } - // Roaming Consortium OI matching. + // ANQP Roaming Consortium OI matching. + long[] providerOIs = mConfig.getHomeSp().getRoamingConsortiumOis(); if (ANQPMatcher.matchRoamingConsortium( (RoamingConsortiumElement) anqpElements.get(ANQPElementType.ANQPRoamingConsortium), - mConfig.getHomeSp().getRoamingConsortiumOis())) { + providerOIs)) { return PasspointMatch.RoamingProvider; } + long[] roamingConsortiums = roamingConsortium.getRoamingConsortiums(); + // Roaming Consortium OI information element matching. + if (roamingConsortiums != null && providerOIs != null) { + for (long sta_oi: roamingConsortiums) { + for (long ap_oi: providerOIs) { + if (sta_oi == ap_oi) { + return PasspointMatch.RoamingProvider; + } + } + } + } + // 3GPP Network matching. if (ANQPMatcher.matchThreeGPPNetwork( (ThreeGPPNetworkElement) anqpElements.get(ANQPElementType.ANQP3GPPNetwork), diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java index 14912b5f5..2128a410d 100644 --- a/service/java/com/android/server/wifi/util/InformationElementUtil.java +++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java @@ -259,7 +259,12 @@ public class InformationElementUtil { public static class RoamingConsortium { public int anqpOICount = 0; - public long[] roamingConsortiums = null; + + private long[] roamingConsortiums = null; + + public long[] getRoamingConsortiums() { + return roamingConsortiums; + } public void from(InformationElement ie) { if (ie.id != InformationElement.EID_ROAMING_CONSORTIUM) { diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java index 0e04a05a7..2a76d6a32 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java @@ -82,6 +82,7 @@ import com.android.server.wifi.hotspot2.anqp.DomainNameElement; import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; import com.android.server.wifi.hotspot2.anqp.I18Name; import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; +import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; import com.android.server.wifi.util.ScanResultUtil; import org.junit.Before; @@ -698,7 +699,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.HomeProvider); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.HomeProvider); Pair<PasspointProvider, PasspointMatch> result = mManager.matchProvider(createTestScanResult()); assertEquals(PasspointMatch.HomeProvider, result.second); @@ -716,7 +718,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.RoamingProvider); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.RoamingProvider); Pair<PasspointProvider, PasspointMatch> result = mManager.matchProvider(createTestScanResult()); assertEquals(PasspointMatch.RoamingProvider, result.second); @@ -734,7 +737,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.None); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.None); assertNull(mManager.matchProvider(createTestScanResult())); } @@ -789,7 +793,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.HomeProvider); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.HomeProvider); when(provider.getWifiConfig()).thenReturn(new WifiConfiguration()); WifiConfiguration config = mManager.getMatchingWifiConfig(createTestScanResult()); assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID), config.SSID); @@ -808,7 +813,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.RoamingProvider); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.RoamingProvider); when(provider.getWifiConfig()).thenReturn(new WifiConfiguration()); WifiConfiguration config = mManager.getMatchingWifiConfig(createTestScanResult()); assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID), config.SSID); @@ -827,7 +833,8 @@ public class PasspointManagerTest { ANQPData entry = new ANQPData(mClock, null); when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(provider.match(anyMap())).thenReturn(PasspointMatch.None); + when(provider.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.None); assertNull(mManager.getMatchingWifiConfig(createTestScanResult())); verify(provider, never()).getWifiConfig(); } @@ -897,9 +904,12 @@ public class PasspointManagerTest { when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); - when(providerHome.match(anyMap())).thenReturn(PasspointMatch.HomeProvider); - when(providerRoaming.match(anyMap())).thenReturn(PasspointMatch.RoamingProvider); - when(providerNone.match(anyMap())).thenReturn(PasspointMatch.None); + when(providerHome.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.HomeProvider); + when(providerRoaming.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.RoamingProvider); + when(providerNone.match(anyMap(), any(RoamingConsortium.class))) + .thenReturn(PasspointMatch.None); when(providerHome.getWifiConfig()).thenReturn(new WifiConfiguration()); when(providerRoaming.getWifiConfig()).thenReturn(new WifiConfiguration()); diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java index 53feae67a..0055fbaaa 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java @@ -48,6 +48,7 @@ import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; +import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -77,12 +78,14 @@ public class PasspointProviderTest { @Mock WifiKeyStore mKeyStore; @Mock SIMAccessor mSimAccessor; + @Mock RoamingConsortium mRoamingConsortium; PasspointProvider mProvider; /** Sets up test. */ @Before public void setUp() throws Exception { initMocks(this); + when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(null); } /** @@ -362,7 +365,8 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQPDomName, createDomainNameElement(new String[] {testDomain})); - assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.HomeProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -397,7 +401,8 @@ public class PasspointProviderTest { createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS, new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.HomeProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -432,7 +437,7 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQPNAIRealm, createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null)); - assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -462,7 +467,8 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQPDomName, createDomainNameElement(new String[] {"wlan.mnc456.mcc123.3gppnetwork.org"})); - assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.HomeProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -493,7 +499,75 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, createRoamingConsortiumElement(anqpRCOIs)); - assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.RoamingProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); + } + + /** + * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI + * in the roaming consortium information element. + * + * @throws Exception + */ + @Test + public void matchRoamingConsortiumIe() throws Exception { + long[] providerRCOIs = new long[] {0x1234L, 0x2345L}; + long[] ieRCOIs = new long[] {0x1234L, 0x2133L}; + + // Setup test provider. + PasspointConfiguration config = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setRoamingConsortiumOis(providerRCOIs); + config.setHomeSp(homeSp); + Credential credential = new Credential(); + Credential.UserCredential userCredential = new Credential.UserCredential(); + userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); + credential.setUserCredential(userCredential); + config.setCredential(credential); + mProvider = createProvider(config); + + // Setup Roaming Consortium ANQP element. + Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); + + // Setup Roaming Consortium Information element. + when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(ieRCOIs); + + assertEquals(PasspointMatch.RoamingProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); + } + + /** + * Verify that none of matched providers are not found when a roaming consortium OI doesn't + * matches an OI in the roaming consortium information element and + * none of NAI realms match each other. + * + * @throws Exception + */ + @Test + public void misMatchForRoamingConsortiumIeAndNAIRealm() throws Exception { + long[] providerRCOIs = new long[] {0x1234L, 0x2345L}; + long[] ieRCOIs = new long[] {0x2255L, 0x2133L}; + + // Setup test provider. + PasspointConfiguration config = new PasspointConfiguration(); + HomeSp homeSp = new HomeSp(); + homeSp.setRoamingConsortiumOis(providerRCOIs); + config.setHomeSp(homeSp); + Credential credential = new Credential(); + Credential.UserCredential userCredential = new Credential.UserCredential(); + userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); + credential.setUserCredential(userCredential); + config.setCredential(credential); + mProvider = createProvider(config); + + // Setup Roaming Consortium ANQP element. + Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); + + // Setup Roaming Consortium Information element. + when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(ieRCOIs); + + assertEquals(PasspointMatch.None, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -523,7 +597,8 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, createThreeGPPNetworkElement(new String[] {"123456"})); - assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.RoamingProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -553,7 +628,8 @@ public class PasspointProviderTest { createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS, new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); - assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.RoamingProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** @@ -595,7 +671,8 @@ public class PasspointProviderTest { anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, createThreeGPPNetworkElement(new String[] {"123456"})); - assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); + assertEquals(PasspointMatch.HomeProvider, + mProvider.match(anqpElementMap, mRoamingConsortium)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java index 8c4b2ff58..a1b37ff7b 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java @@ -692,8 +692,8 @@ public class InformationElementUtilTest { InformationElementUtil.RoamingConsortium roamingConsortium = InformationElementUtil.getRoamingConsortiumIE(new InformationElement[] {ie}); assertEquals(1, roamingConsortium.anqpOICount); - assertEquals(1, roamingConsortium.roamingConsortiums.length); - assertEquals(0x112233, roamingConsortium.roamingConsortiums[0]); + assertEquals(1, roamingConsortium.getRoamingConsortiums().length); + assertEquals(0x112233, roamingConsortium.getRoamingConsortiums()[0]); } /** |