diff options
author | Peter Qiu <zqiu@google.com> | 2016-12-09 12:10:04 -0800 |
---|---|---|
committer | Peter Qiu <zqiu@google.com> | 2016-12-21 16:19:05 -0800 |
commit | d8dddd9671750e6bfbcfa218db16ad096b9904ee (patch) | |
tree | ad267f8dc665dbd96b8d41482fecefad2a257aba /service | |
parent | 54481f724e41249c4e036a9f59e8cb3e6fb821d8 (diff) |
hotspot2: ANQP elements cleanup Part 4
Cleaned up the implementation and added unit tests for NAIRealmElement
and the classes used by it.
While there, remove the match() function from NAIRealmElement for now.
So that all ANQP elements class are purely data storages for the element.
The match() function will be added to PasspointProvider for matching
a NAI Realm Element against the provider's configuration.
Other changes included:
- removed the now unused EAP.java
- removed the uses of enum for EAP Method ID and Authentication
Parameter type constants.
- renamed Credential to CredentialType
Bug: 33000864
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: I940f6d7cecb9bec405f0786845af768caf527990
Diffstat (limited to 'service')
12 files changed, 616 insertions, 633 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java index bc724ceaf..9ae89f219 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java @@ -94,7 +94,7 @@ public class ANQPFactory { case ANQPIPAddrAvailability: return IPAddressTypeAvailabilityElement.parse(payload); case ANQPNAIRealm: - return new NAIRealmElement(infoID, payload); + return NAIRealmElement.parse(payload); case ANQP3GPPNetwork: return ThreeGPPNetworkElement.parse(payload); case ANQPDomName: diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java index 6acdbc535..7b3144969 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java @@ -1,52 +1,93 @@ +/* + * 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.hotspot2.anqp; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.ByteBufferReader; -import com.android.server.wifi.hotspot2.AuthMatch; -import com.android.server.wifi.hotspot2.DomainMatcher; -import com.android.server.wifi.hotspot2.Utils; +import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; /** - * The NAI Realm Data ANQP sub-element, IEEE802.11-2012 section 8.4.4.10 figure 8-418 + * The NAI Realm Data ANQP sub-element, IEEE802.11-2012 section 8.4.4.10 figure 8-418. + * + * Format: + * | Length | Encoding | NAIRealm Length | NAIRealm | EAPMethod Count | EAPMethod #1 (optional) | + * 2 1 1 variable 1 variable */ public class NAIRealmData { + /** + * Mask for determining NAI Realm String encoding type. + */ + @VisibleForTesting + public static final int NAI_ENCODING_UTF8_MASK = 0x1; + + @VisibleForTesting + public static final String NAI_REALM_STRING_SEPARATOR = ";"; + private final List<String> mRealms; private final List<EAPMethod> mEAPMethods; - public NAIRealmData(ByteBuffer payload) throws ProtocolException { - if (payload.remaining() < 5) { - throw new ProtocolException("Runt payload: " + payload.remaining()); - } + @VisibleForTesting + public NAIRealmData(List<String> realms, List<EAPMethod> eapMethods) { + mRealms = realms; + mEAPMethods = eapMethods; + } - int length = payload.getShort() & Constants.SHORT_MASK; + /** + * Parse a NAIRealmData from the given buffer. + * + * @param payload The byte buffer to read from + * @return {@link NAIRealmElement} + * @throws BufferUnderflowException + * @throws ProtocolException + */ + public static NAIRealmData parse(ByteBuffer payload) throws ProtocolException { + // Read and verify the length field. + int length = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) + & 0xFFFF; if (length > payload.remaining()) { throw new ProtocolException("Invalid data length: " + length); } - boolean utf8 = (payload.get() & 1) == Constants.UTF8_INDICATOR; + // Read the encoding field. + boolean utf8 = (payload.get() & NAI_ENCODING_UTF8_MASK) != 0; + + // Read the realm string. String realm = ByteBufferReader.readStringWithByteLength( payload, utf8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII); - String[] realms = realm.split(";"); - mRealms = new ArrayList<>(); - for (String realmElement : realms) { - if (realmElement.length() > 0) { - mRealms.add(realmElement); - } - } + List<String> realmList = Arrays.asList(realm.split(NAI_REALM_STRING_SEPARATOR)); - int methodCount = payload.get() & Constants.BYTE_MASK; - mEAPMethods = new ArrayList<>(methodCount); + // Read the EAP methods. + int methodCount = payload.get() & 0xFF; + List<EAPMethod> eapMethodList = new ArrayList<>(); while (methodCount > 0) { - mEAPMethods.add(new EAPMethod(payload)); + eapMethodList.add(EAPMethod.parse(payload)); methodCount--; } + return new NAIRealmData(realmList, eapMethodList); } public List<String> getRealms() { @@ -57,52 +98,25 @@ public class NAIRealmData { return Collections.unmodifiableList(mEAPMethods); } - // TODO(b/32714185): revisit this when integrating the new Passpoint implementation and add - // unit tests for this. - public int match(String realmToMatch, EAPMethod credMethod) { - int realmMatch = AuthMatch.None; - if (!mRealms.isEmpty()) { - for (String realm : mRealms) { - if (DomainMatcher.arg2SubdomainOfArg1(realmToMatch, realm)) { - realmMatch = AuthMatch.Realm; - break; - } - } - if (realmMatch == AuthMatch.None || mEAPMethods.isEmpty()) { - return realmMatch; - } - // else there is a realm match and one or more EAP methods - check them. + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; } - else if (mEAPMethods.isEmpty()) { - return AuthMatch.Indeterminate; + if (!(thatObject instanceof NAIRealmData)) { + return false; } + NAIRealmData that = (NAIRealmData) thatObject; + return mRealms.equals(that.mRealms) && mEAPMethods.equals(that.mEAPMethods); + } - int best = AuthMatch.None; - for (EAPMethod eapMethod : mEAPMethods) { - int match = eapMethod.match(credMethod) | realmMatch; - if (match > best) { - best = match; - if (best == AuthMatch.Exact) { - return best; - } - } - } - return best; + @Override + public int hashCode() { + return mRealms.hashCode() * 31 + mEAPMethods.hashCode(); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append(" NAI Realm(s)"); - for (String realm : mRealms) { - sb.append(' ').append(realm); - } - sb.append('\n'); - - for (EAPMethod eapMethod : mEAPMethods) { - sb.append( " " ).append(eapMethod.toString()); - } - return sb.toString(); + return "NAIRealmElement{mRealms=" + mRealms + " mEAPMethods=" + mEAPMethods + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java index e1bafa85f..6f18bad7a 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java @@ -1,76 +1,93 @@ +/* + * 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.hotspot2.anqp; -import com.android.server.wifi.SIMAccessor; -import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; -import com.android.server.wifi.hotspot2.AuthMatch; -import com.android.server.wifi.hotspot2.Utils; +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.ByteBufferReader; import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTES_IN_SHORT; -import static com.android.server.wifi.hotspot2.anqp.Constants.SHORT_MASK; /** - * The NAI Realm ANQP Element, IEEE802.11-2012 section 8.4.4.10 + * The NAI (Network Access Identifier) Realm ANQP Element, IEEE802.11-2012 section 8.4.4.10. + * + * Format: + * | NAI Realm Count (optional) | NAI Realm Data #1 (optional) | .... + * 2 variable */ public class NAIRealmElement extends ANQPElement { - private final List<NAIRealmData> mRealmData; + private final List<NAIRealmData> mRealmDataList; - public NAIRealmElement(Constants.ANQPElementType infoID, ByteBuffer payload) - throws ProtocolException { - super(infoID); - - if (!payload.hasRemaining()) { - mRealmData = Collections.emptyList(); - return; - } - - if (payload.remaining() < BYTES_IN_SHORT) { - throw new ProtocolException("Runt NAI Realm: " + payload.remaining()); - } + @VisibleForTesting + public NAIRealmElement(List<NAIRealmData> realmDataList) { + super(Constants.ANQPElementType.ANQPNAIRealm); + mRealmDataList = realmDataList; + } - int count = payload.getShort() & SHORT_MASK; - mRealmData = new ArrayList<>(count); - while (count > 0) { - mRealmData.add(new NAIRealmData(payload)); - count--; + /** + * Parse a NAIRealmElement from the given buffer. + * + * @param payload The byte buffer to read from + * @return {@link NAIRealmElement} + * @throws BufferUnderflowException + */ + public static NAIRealmElement parse(ByteBuffer payload) + throws ProtocolException { + List<NAIRealmData> realmDataList = new ArrayList<>(); + if (payload.hasRemaining()) { + int count = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) + & 0xFFFF; + while (count > 0) { + realmDataList.add(NAIRealmData.parse(payload)); + count--; + } } + return new NAIRealmElement(realmDataList); } - public List<NAIRealmData> getRealmData() { - return Collections.unmodifiableList(mRealmData); + public List<NAIRealmData> getRealmDataList() { + return Collections.unmodifiableList(mRealmDataList); } - // TODO(b/32714185): revisit this when integrating the new Passpoint implementation and add - // unit tests for this. - public int match(String realm, EAPMethod credMethod) { - if (mRealmData.isEmpty()) - return AuthMatch.Indeterminate; - - int best = AuthMatch.None; - for (NAIRealmData realmData : mRealmData) { - int match = realmData.match(realm, credMethod); - if (match > best) { - best = match; - if (best == AuthMatch.Exact) { - return best; - } - } + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; + } + if (!(thatObject instanceof NAIRealmElement)) { + return false; } - return best; + NAIRealmElement that = (NAIRealmElement) thatObject; + return mRealmDataList.equals(that.mRealmDataList); + } + + @Override + public int hashCode() { + return mRealmDataList.hashCode(); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("NAI Realm:\n"); - for (NAIRealmData data : mRealmData) { - sb.append(data); - } - return sb.toString(); + return "NAIRealmElement{mRealmDataList=" + mRealmDataList + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java index 10c765920..ce4edb216 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/AuthParam.java @@ -1,9 +1,41 @@ +/* + * 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.hotspot2.anqp.eap; /** * An Authentication parameter, part of the NAI Realm ANQP element, specified in * IEEE802.11-2012 section 8.4.4.10, table 8-188 */ -public interface AuthParam { - public EAP.AuthInfoID getAuthInfoID(); +public abstract class AuthParam { + public static final int PARAM_TYPE_EXPANDED_EAP_METHOD = 1; + public static final int PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE = 2; + public static final int PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE = 3; + public static final int PARAM_TYPE_EXPANDED_INNER_EAP_METHOD = 4; + public static final int PARAM_TYPE_CREDENTIAL_TYPE = 5; + public static final int PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE = 6; + public static final int PARAM_TYPE_VENDOR_SPECIFIC = 221; + + private final int mAuthTypeID; + + protected AuthParam(int authTypeID) { + mAuthTypeID = authTypeID; + } + + public int getAuthTypeID() { + return mAuthTypeID; + } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/Credential.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/Credential.java deleted file mode 100644 index bc2bec862..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/Credential.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp.eap; - -import java.net.ProtocolException; -import java.nio.ByteBuffer; - -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; - -/** - * An EAP authentication parameter, IEEE802.11-2012, table 8-188 - */ -public class Credential implements AuthParam { - - public enum CredType { - Reserved, - SIM, - USIM, - NFC, - HWToken, - Softoken, - Certificate, - Username, - None, - Anonymous, - VendorSpecific} - - private final EAP.AuthInfoID mAuthInfoID; - private final CredType mCredType; - - public Credential(EAP.AuthInfoID infoID, int length, ByteBuffer payload) - throws ProtocolException { - if (length != 1) { - throw new ProtocolException("Bad length: " + length); - } - - mAuthInfoID = infoID; - int typeID = payload.get() & BYTE_MASK; - - mCredType = typeID < CredType.values().length ? - CredType.values()[typeID] : - CredType.Reserved; - } - - @Override - public EAP.AuthInfoID getAuthInfoID() { - return mAuthInfoID; - } - - @Override - public int hashCode() { - return mAuthInfoID.hashCode() * 31 + mCredType.hashCode(); - } - - @Override - public boolean equals(Object thatObject) { - if (thatObject == this) { - return true; - } else if (thatObject == null || thatObject.getClass() != Credential.class) { - return false; - } else { - return ((Credential) thatObject).getCredType() == getCredType(); - } - } - - public CredType getCredType() { - return mCredType; - } - - @Override - public String toString() { - return "Auth method " + mAuthInfoID + " = " + mCredType + "\n"; - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java new file mode 100644 index 000000000..1efc00bc5 --- /dev/null +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/CredentialType.java @@ -0,0 +1,103 @@ +/* + * 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.hotspot2.anqp.eap; + +import com.android.internal.annotations.VisibleForTesting; + +import java.net.ProtocolException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +/** + * The Credential Type authentication parameter, IEEE802.11-2012, table 8-188. + * Used by both Credential Type and Tunneled EAP Method Credential Type authentication + * parameter. + * + * Format: + * | Type | + * 1 + */ +public class CredentialType extends AuthParam { + public static final int CREDENTIAL_TYPE_SIM = 1; + public static final int CREDENTIAL_TYPE_USIM = 2; + public static final int CREDENTIAL_TYPE_NFC = 3; + public static final int CREDENTIAL_TYPE_HARDWARE_TOKEN = 4; + public static final int CREDENTIAL_TYPE_SOFTWARE_TOKEN = 5; + public static final int CREDENTIAL_TYPE_CERTIFICATE = 6; + public static final int CREDENTIAL_TYPE_USERNAME_PASSWORD = 7; + public static final int CREDENTIAL_TYPE_NONE = 8; + public static final int CREDENTIAL_TYPE_ANONYMOUS = 9; + public static final int CREDENTIAL_TYPE_VENDOR_SPECIFIC = 10; + + @VisibleForTesting + public static final int EXPECTED_LENGTH_VALUE = 1; + + private final int mType; + + @VisibleForTesting + public CredentialType(int authType, int credType) { + super(authType); + mType = credType; + } + + /** + * Parse a CredentialType from the given buffer. + * + * @param payload The byte buffer to read from + * @param length The length of the data + * @param tunneled Flag indicating if this is for a Tunneled EAP Method + * @return {@link CredentialType} + * @throws ProtocolException + * @throws BufferUnderflowException + */ + public static CredentialType parse(ByteBuffer payload, int length, boolean tunneled) + throws ProtocolException { + if (length != EXPECTED_LENGTH_VALUE) { + throw new ProtocolException("Invalid length: " + length); + } + int credType = payload.get() & 0xFF; + int authType = tunneled ? AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE + : AuthParam.PARAM_TYPE_CREDENTIAL_TYPE; + return new CredentialType(authType, credType); + } + + public int getType() { + return mType; + } + + @Override + public boolean equals(Object thatObject) { + if (thatObject == this) { + return true; + } + if (!(thatObject instanceof CredentialType)) { + return false; + } + CredentialType that = (CredentialType) thatObject; + return mType == that.mType; + } + + @Override + public int hashCode() { + return mType; + } + + @Override + public String toString() { + return "CredentialType{mType=" + mType + "}"; + } +} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAP.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAP.java deleted file mode 100644 index 9e6c058e3..000000000 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAP.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.android.server.wifi.hotspot2.anqp.eap; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * EAP Related constants for the ANQP NAIRealm element, IEEE802.11-2012 section 8.4.4.10 - */ -public abstract class EAP { - - private static final Map<Integer, EAPMethodID> sEapIds = new HashMap<>(); - private static final Map<EAPMethodID, Integer> sRevEapIds = new HashMap<>(); - private static final Map<Integer, AuthInfoID> sAuthIds = new HashMap<>(); - - public static final int EAP_MD5 = 4; - public static final int EAP_OTP = 5; - public static final int EAP_RSA = 9; - public static final int EAP_KEA = 11; - public static final int EAP_KEA_VALIDATE = 12; - public static final int EAP_TLS = 13; - public static final int EAP_LEAP = 17; - public static final int EAP_SIM = 18; - public static final int EAP_TTLS = 21; - public static final int EAP_AKA = 23; - public static final int EAP_3Com = 24; - public static final int EAP_MSCHAPv2 = 26; - public static final int EAP_PEAP = 29; - public static final int EAP_POTP = 32; - public static final int EAP_ActiontecWireless = 35; - public static final int EAP_HTTPDigest = 38; - public static final int EAP_SPEKE = 41; - public static final int EAP_MOBAC = 42; - public static final int EAP_FAST = 43; - public static final int EAP_ZLXEAP = 44; - public static final int EAP_Link = 45; - public static final int EAP_PAX = 46; - public static final int EAP_PSK = 47; - public static final int EAP_SAKE = 48; - public static final int EAP_IKEv2 = 49; - public static final int EAP_AKAPrim = 50; - public static final int EAP_GPSK = 51; - public static final int EAP_PWD = 52; - public static final int EAP_EKE = 53; - public static final int EAP_TEAP = 55; - - public enum EAPMethodID { - EAP_MD5, - EAP_OTP, - EAP_RSA, - EAP_KEA, - EAP_KEA_VALIDATE, - EAP_TLS, - EAP_LEAP, - EAP_SIM, - EAP_TTLS, - EAP_AKA, - EAP_3Com, - EAP_MSCHAPv2, - EAP_PEAP, - EAP_POTP, - EAP_ActiontecWireless, - EAP_HTTPDigest, - EAP_SPEKE, - EAP_MOBAC, - EAP_FAST, - EAP_ZLXEAP, - EAP_Link, - EAP_PAX, - EAP_PSK, - EAP_SAKE, - EAP_IKEv2, - EAP_AKAPrim, - EAP_GPSK, - EAP_PWD, - EAP_EKE, - EAP_TEAP - } - - public static final int ExpandedEAPMethod = 1; - public static final int NonEAPInnerAuthType = 2; - public static final int InnerAuthEAPMethodType = 3; - public static final int ExpandedInnerEAPMethod = 4; - public static final int CredentialType = 5; - public static final int TunneledEAPMethodCredType = 6; - public static final int VendorSpecific = 221; - - public enum AuthInfoID { - Undefined, - ExpandedEAPMethod, - NonEAPInnerAuthType, - InnerAuthEAPMethodType, - ExpandedInnerEAPMethod, - CredentialType, - TunneledEAPMethodCredType, - VendorSpecific - } - - static { - sEapIds.put(EAP_MD5, EAPMethodID.EAP_MD5); - sEapIds.put(EAP_OTP, EAPMethodID.EAP_OTP); - sEapIds.put(EAP_RSA, EAPMethodID.EAP_RSA); - sEapIds.put(EAP_KEA, EAPMethodID.EAP_KEA); - sEapIds.put(EAP_KEA_VALIDATE, EAPMethodID.EAP_KEA_VALIDATE); - sEapIds.put(EAP_TLS, EAPMethodID.EAP_TLS); - sEapIds.put(EAP_LEAP, EAPMethodID.EAP_LEAP); - sEapIds.put(EAP_SIM, EAPMethodID.EAP_SIM); - sEapIds.put(EAP_TTLS, EAPMethodID.EAP_TTLS); - sEapIds.put(EAP_AKA, EAPMethodID.EAP_AKA); - sEapIds.put(EAP_3Com, EAPMethodID.EAP_3Com); - sEapIds.put(EAP_MSCHAPv2, EAPMethodID.EAP_MSCHAPv2); - sEapIds.put(EAP_PEAP, EAPMethodID.EAP_PEAP); - sEapIds.put(EAP_POTP, EAPMethodID.EAP_POTP); - sEapIds.put(EAP_ActiontecWireless, EAPMethodID.EAP_ActiontecWireless); - sEapIds.put(EAP_HTTPDigest, EAPMethodID.EAP_HTTPDigest); - sEapIds.put(EAP_SPEKE, EAPMethodID.EAP_SPEKE); - sEapIds.put(EAP_MOBAC, EAPMethodID.EAP_MOBAC); - sEapIds.put(EAP_FAST, EAPMethodID.EAP_FAST); - sEapIds.put(EAP_ZLXEAP, EAPMethodID.EAP_ZLXEAP); - sEapIds.put(EAP_Link, EAPMethodID.EAP_Link); - sEapIds.put(EAP_PAX, EAPMethodID.EAP_PAX); - sEapIds.put(EAP_PSK, EAPMethodID.EAP_PSK); - sEapIds.put(EAP_SAKE, EAPMethodID.EAP_SAKE); - sEapIds.put(EAP_IKEv2, EAPMethodID.EAP_IKEv2); - sEapIds.put(EAP_AKAPrim, EAPMethodID.EAP_AKAPrim); - sEapIds.put(EAP_GPSK, EAPMethodID.EAP_GPSK); - sEapIds.put(EAP_PWD, EAPMethodID.EAP_PWD); - sEapIds.put(EAP_EKE, EAPMethodID.EAP_EKE); - sEapIds.put(EAP_TEAP, EAPMethodID.EAP_TEAP); - - for (Map.Entry<Integer, EAPMethodID> entry : sEapIds.entrySet()) { - sRevEapIds.put(entry.getValue(), entry.getKey()); - } - - sAuthIds.put(ExpandedEAPMethod, AuthInfoID.ExpandedEAPMethod); - sAuthIds.put(NonEAPInnerAuthType, AuthInfoID.NonEAPInnerAuthType); - sAuthIds.put(InnerAuthEAPMethodType, AuthInfoID.InnerAuthEAPMethodType); - sAuthIds.put(ExpandedInnerEAPMethod, AuthInfoID.ExpandedInnerEAPMethod); - sAuthIds.put(CredentialType, AuthInfoID.CredentialType); - sAuthIds.put(TunneledEAPMethodCredType, AuthInfoID.TunneledEAPMethodCredType); - sAuthIds.put(VendorSpecific, AuthInfoID.VendorSpecific); - } - - public static EAPMethodID mapEAPMethod(int methodID) { - return sEapIds.get(methodID); - } - - public static Integer mapEAPMethod(EAPMethodID methodID) { - return sRevEapIds.get(methodID); - } - - public static AuthInfoID mapAuthMethod(int methodID) { - return sAuthIds.get(methodID); - } -} diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java index 26d02dfe4..6879d4135 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/EAPMethod.java @@ -1,192 +1,154 @@ -package com.android.server.wifi.hotspot2.anqp.eap; +/* + * 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.hotspot2.anqp.eap; -import com.android.server.wifi.hotspot2.anqp.Constants; -import com.android.server.wifi.hotspot2.AuthMatch; +import com.android.internal.annotations.VisibleForTesting; import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.Collections; -import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** - * An EAP Method, part of the NAI Realm ANQP element, specified in + * An EAP Method part of the NAI Realm ANQP element, specified in * IEEE802.11-2012 section 8.4.4.10, figure 8-420 + * + * Format: + * | Length | EAP Method | Auth Param Count | Auth Param #1 (optional) | .... + * 1 1 1 variable */ public class EAPMethod { - private final EAP.EAPMethodID mEAPMethodID; - private final Map<EAP.AuthInfoID, Set<AuthParam>> mAuthParams; - - public EAPMethod(ByteBuffer payload) throws ProtocolException { - if (payload.remaining() < 3) { - throw new ProtocolException("Runt EAP Method: " + payload.remaining()); - } - - int length = payload.get() & Constants.BYTE_MASK; - int methodID = payload.get() & Constants.BYTE_MASK; - int count = payload.get() & Constants.BYTE_MASK; - - mEAPMethodID = EAP.mapEAPMethod(methodID); - mAuthParams = new EnumMap<>(EAP.AuthInfoID.class); + private final int mEAPMethodID; + private final Map<Integer, Set<AuthParam>> mAuthParams; - int realCount = 0; - - ByteBuffer paramPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); - paramPayload.limit(paramPayload.position() + length - 2); - payload.position(payload.position() + length - 2); - while (paramPayload.hasRemaining()) { - int id = paramPayload.get() & Constants.BYTE_MASK; - - EAP.AuthInfoID authInfoID = EAP.mapAuthMethod(id); - if (authInfoID == null) { - throw new ProtocolException("Unknown auth parameter ID: " + id); - } - - int len = paramPayload.get() & Constants.BYTE_MASK; - if (len == 0 || len > paramPayload.remaining()) { - throw new ProtocolException("Bad auth method length: " + len); - } + @VisibleForTesting + public EAPMethod(int methodID, Map<Integer, Set<AuthParam>> authParams) { + mEAPMethodID = methodID; + mAuthParams = authParams; + } - switch (authInfoID) { - case ExpandedEAPMethod: - addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload)); - break; - case NonEAPInnerAuthType: - addAuthParam(new NonEAPInnerAuth(len, paramPayload)); - break; - case InnerAuthEAPMethodType: - addAuthParam(new InnerAuthEAP(len, paramPayload)); - break; - case ExpandedInnerEAPMethod: - addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload)); - break; - case CredentialType: - addAuthParam(new Credential(authInfoID, len, paramPayload)); - break; - case TunneledEAPMethodCredType: - addAuthParam(new Credential(authInfoID, len, paramPayload)); - break; - case VendorSpecific: - addAuthParam(new VendorSpecificAuth(len, paramPayload)); - break; - } + /** + * Parse a EAPMethod from the given buffer. + * + * @param payload The byte buffer to read from + * @return {@link EAPMethod} + * @throws ProtocolException + * @throws BufferUnderflowException + */ + public static EAPMethod parse(ByteBuffer payload) throws ProtocolException { + // Read and verify the length field. + int length = payload.get() & 0xFF; + if (length > payload.remaining()) { + throw new ProtocolException("Invalid data length: " + length); + } - realCount++; + int methodID = payload.get() & 0xFF; + int authCount = payload.get() & 0xFF; + Map<Integer, Set<AuthParam>> authParams = new HashMap<>(); + while (authCount > 0) { + addAuthParam(authParams, parseAuthParam(payload)); + authCount--; } - if (realCount != count) - throw new ProtocolException("Invalid parameter count: " + realCount + - ", expected " + count); + return new EAPMethod(methodID, authParams); } - public EAPMethod(EAP.EAPMethodID eapMethodID, AuthParam authParam) { - mEAPMethodID = eapMethodID; - mAuthParams = new HashMap<>(1); - if (authParam != null) { - Set<AuthParam> authParams = new HashSet<>(); - authParams.add(authParam); - mAuthParams.put(authParam.getAuthInfoID(), authParams); + /** + * Parse a AuthParam from the given buffer. + * + * Format: + * | Auth ID | Length | Value | + * 1 1 variable + * + * @param payload The byte buffer to read from + * @return {@link AuthParam} + * @throws BufferUnderflowException + * @throws ProtocolException + */ + private static AuthParam parseAuthParam(ByteBuffer payload) throws ProtocolException { + int authID = payload.get() & 0xFF; + int length = payload.get() & 0xFF; + switch (authID) { + case AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD: + return ExpandedEAPMethod.parse(payload, length, false); + case AuthParam.PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE: + return NonEAPInnerAuth.parse(payload, length); + case AuthParam.PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE: + return InnerAuthEAP.parse(payload, length); + case AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD: + return ExpandedEAPMethod.parse(payload, length, true); + case AuthParam.PARAM_TYPE_CREDENTIAL_TYPE: + return CredentialType.parse(payload, length, false); + case AuthParam.PARAM_TYPE_TUNNELED_EAP_METHOD_CREDENTIAL_TYPE: + return CredentialType.parse(payload, length, true); + case AuthParam.PARAM_TYPE_VENDOR_SPECIFIC: + return VendorSpecificAuth.parse(payload, length); + default: + throw new ProtocolException("Unknow Auth Type ID: " + authID); } } - private void addAuthParam(AuthParam param) { - Set<AuthParam> authParams = mAuthParams.get(param.getAuthInfoID()); + /** + * Add an AuthParam to a map of authentication parameters. It is possible to have + * multiple authentication parameters for the same type. + * + * @param paramsMap The authentication parameter map to add the new parameter to + * @param authParam The authentication parameter to add + */ + private static void addAuthParam(Map<Integer, Set<AuthParam>> paramsMap, + AuthParam authParam) { + Set<AuthParam> authParams = paramsMap.get(authParam.getAuthTypeID()); if (authParams == null) { authParams = new HashSet<>(); - mAuthParams.put(param.getAuthInfoID(), authParams); + paramsMap.put(authParam.getAuthTypeID(), authParams); } - authParams.add(param); + authParams.add(authParam); } - public Map<EAP.AuthInfoID, Set<AuthParam>> getAuthParams() { + public Map<Integer, Set<AuthParam>> getAuthParams() { return Collections.unmodifiableMap(mAuthParams); } - public EAP.EAPMethodID getEAPMethodID() { + public int getEAPMethodID() { return mEAPMethodID; } - // TODO(b/32714185): revisit this when integrating the new Passpoint implementation and add - // unit tests for this. - public int match(EAPMethod credMethod) { - if (mEAPMethodID != credMethod.getEAPMethodID()) { - return AuthMatch.None; - } - - switch (mEAPMethodID) { - case EAP_TTLS: - if (mAuthParams.isEmpty()) { - return AuthMatch.Method; - } - int paramCount = 0; - for (Map.Entry<EAP.AuthInfoID, Set<AuthParam>> entry : - credMethod.getAuthParams().entrySet()) { - Set<AuthParam> params = mAuthParams.get(entry.getKey()); - if (params == null) { - continue; - } - - if (!Collections.disjoint(params, entry.getValue())) { - return AuthMatch.MethodParam; - } - paramCount += params.size(); - } - return paramCount > 0 ? AuthMatch.None : AuthMatch.Method; - case EAP_TLS: - return AuthMatch.MethodParam; - case EAP_SIM: - case EAP_AKA: - case EAP_AKAPrim: - return AuthMatch.Method; - default: - return AuthMatch.Method; - } - } - - public AuthParam getAuthParam() { - if (mAuthParams.isEmpty()) { - return null; - } - Set<AuthParam> params = mAuthParams.values().iterator().next(); - if (params.isEmpty()) { - return null; - } - return params.iterator().next(); - } - @Override public boolean equals(Object thatObject) { - if (this == thatObject) { + if (thatObject == this) { return true; } - else if (thatObject == null || getClass() != thatObject.getClass()) { + if (!(thatObject instanceof EAPMethod)) { return false; } - EAPMethod that = (EAPMethod) thatObject; return mEAPMethodID == that.mEAPMethodID && mAuthParams.equals(that.mAuthParams); } @Override public int hashCode() { - int result = mEAPMethodID.hashCode(); - result = 31 * result + mAuthParams.hashCode(); - return result; + return mEAPMethodID * 31 + mAuthParams.hashCode(); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("EAP Method ").append(mEAPMethodID).append('\n'); - for (Set<AuthParam> paramSet : mAuthParams.values()) { - for (AuthParam param : paramSet) { - sb.append(" ").append(param.toString()); - } - } - return sb.toString(); + return "EAPMethod{mEAPMethodID=" + mEAPMethodID + " mAuthParams=" + mAuthParams + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java index c5ed3ca9b..a2a303f5e 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/ExpandedEAPMethod.java @@ -1,78 +1,105 @@ +/* + * 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.hotspot2.anqp.eap; +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.ByteBufferReader; + import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; -import static com.android.server.wifi.hotspot2.anqp.Constants.INT_MASK; -import static com.android.server.wifi.hotspot2.anqp.Constants.SHORT_MASK; - /** - * An EAP authentication parameter, IEEE802.11-2012, table 8-188 + * The Expanded EAP Method authentication parameter, IEEE802.11-2012, table 8-189. + * Used by both Expanded EAP Method and Expanded Inner EAP Method. + * + * Format: + * | Vendor ID | Vendor Type | + * 3 4 */ -public class ExpandedEAPMethod implements AuthParam { +public class ExpandedEAPMethod extends AuthParam { + public static final int EXPECTED_LENGTH_VALUE = 7; - private final EAP.AuthInfoID mAuthInfoID; private final int mVendorID; private final long mVendorType; - public ExpandedEAPMethod(EAP.AuthInfoID authInfoID, int length, ByteBuffer payload) + @VisibleForTesting + public ExpandedEAPMethod(int authType, int vendorID, long vendorType) { + super(authType); + mVendorID = vendorID; + mVendorType = vendorType; + } + + /** + * Parse a ExpandedEAPMethod from the given buffer. + * + * @param payload The byte buffer to read from + * @param length The length of the data + * @param inner Flag indicating if this is for an Inner EAP method + * @return {@link ExpandedEAPMethod} + * @throws ProtocolException + * @throws BufferUnderflowException + */ + public static ExpandedEAPMethod parse(ByteBuffer payload, int length, boolean inner) throws ProtocolException { - if (length != 7) { - throw new ProtocolException("Bad length: " + payload.remaining()); + if (length != EXPECTED_LENGTH_VALUE) { + throw new ProtocolException("Invalid length value: " + length); } - mAuthInfoID = authInfoID; + // Vendor ID and Vendor Type are expressed in big-endian byte order according to + // the spec. + int vendorID = (int) ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, 3) + & 0xFFFFFF; + long vendorType = ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, 4) + & 0xFFFFFFFF; - ByteBuffer vndBuffer = payload.duplicate().order(ByteOrder.BIG_ENDIAN); - - int id = vndBuffer.getShort() & SHORT_MASK; - id = (id << Byte.SIZE) | (vndBuffer.get() & BYTE_MASK); - mVendorID = id; - mVendorType = vndBuffer.getInt() & INT_MASK; - - payload.position(payload.position()+7); + int authType = inner ? AuthParam.PARAM_TYPE_EXPANDED_INNER_EAP_METHOD + : AuthParam.PARAM_TYPE_EXPANDED_EAP_METHOD; + return new ExpandedEAPMethod(authType, vendorID, vendorType); } - public ExpandedEAPMethod(EAP.AuthInfoID authInfoID, int vendorID, long vendorType) { - mAuthInfoID = authInfoID; - mVendorID = vendorID; - mVendorType = vendorType; - } - - @Override - public EAP.AuthInfoID getAuthInfoID() { - return mAuthInfoID; + public int getVendorID() { + return mVendorID; } - @Override - public int hashCode() { - return (mAuthInfoID.hashCode() * 31 + mVendorID) * 31 + (int) mVendorType; + public long getVendorType() { + return mVendorType; } @Override public boolean equals(Object thatObject) { if (thatObject == this) { return true; - } else if (thatObject == null || thatObject.getClass() != ExpandedEAPMethod.class) { + } + if (!(thatObject instanceof ExpandedEAPMethod)) { return false; - } else { - ExpandedEAPMethod that = (ExpandedEAPMethod) thatObject; - return that.getVendorID() == getVendorID() && that.getVendorType() == getVendorType(); } + ExpandedEAPMethod that = (ExpandedEAPMethod) thatObject; + return mVendorID == that.mVendorID && mVendorType == that.mVendorType; } - public int getVendorID() { - return mVendorID; - } - - public long getVendorType() { - return mVendorType; + @Override + public int hashCode() { + return (mVendorID) * 31 + (int) mVendorType; } @Override public String toString() { - return "Auth method " + mAuthInfoID + ", id " + mVendorID + ", type " + mVendorType + "\n"; + return "ExpandedEAPMethod{mVendorID=" + mVendorID + " mVendorType=" + mVendorType + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java index 6c17bd403..a7dbdac37 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/InnerAuthEAP.java @@ -1,56 +1,86 @@ +/* + * 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.hotspot2.anqp.eap; +import com.android.internal.annotations.VisibleForTesting; + import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; - /** - * An EAP authentication parameter, IEEE802.11-2012, table 8-188 + * The Inner Authentication EAP Method Type authentication parameter, IEEE802.11-2012, table 8-188. + * + * Format: + * | EAP Method ID | + * 1 */ -public class InnerAuthEAP implements AuthParam { - - private final EAP.EAPMethodID mEapMethodID; +public class InnerAuthEAP extends AuthParam { + @VisibleForTesting + public static final int EXPECTED_LENGTH_VALUE = 1; - public InnerAuthEAP(int length, ByteBuffer payload) throws ProtocolException { - if (length != 1) { - throw new ProtocolException("Bad length: " + length); - } - int typeID = payload.get() & BYTE_MASK; - mEapMethodID = EAP.mapEAPMethod(typeID); - } - - public InnerAuthEAP(EAP.EAPMethodID eapMethodID) { - mEapMethodID = eapMethodID; - } + private final int mEAPMethodID; - @Override - public EAP.AuthInfoID getAuthInfoID() { - return EAP.AuthInfoID.InnerAuthEAPMethodType; + @VisibleForTesting + public InnerAuthEAP(int eapMethodID) { + super(AuthParam.PARAM_TYPE_INNER_AUTH_EAP_METHOD_TYPE); + mEAPMethodID = eapMethodID; } - public EAP.EAPMethodID getEAPMethodID() { - return mEapMethodID; + /** + * Parse a InnerAuthEAP from the given buffer. + * + * @param payload The byte buffer to read from + * @param length The length of the data + * @return {@link InnerAuthEAP} + * @throws ProtocolException + * @throws BufferUnderflowException + */ + public static InnerAuthEAP parse(ByteBuffer payload, int length) throws ProtocolException { + if (length != EXPECTED_LENGTH_VALUE) { + throw new ProtocolException("Invalid length: " + length); + } + int eapMethodID = payload.get() & 0xFF; + return new InnerAuthEAP(eapMethodID); } - @Override - public int hashCode() { - return mEapMethodID != null ? mEapMethodID.hashCode() : 0; + public int getEAPMethodID() { + return mEAPMethodID; } @Override public boolean equals(Object thatObject) { if (thatObject == this) { return true; - } else if (thatObject == null || thatObject.getClass() != InnerAuthEAP.class) { + } + if (!(thatObject instanceof InnerAuthEAP)) { return false; - } else { - return ((InnerAuthEAP) thatObject).getEAPMethodID() == getEAPMethodID(); } + InnerAuthEAP that = (InnerAuthEAP) thatObject; + return mEAPMethodID == that.mEAPMethodID; + } + + @Override + public int hashCode() { + return mEAPMethodID; } @Override public String toString() { - return "Auth method InnerAuthEAP, inner = " + mEapMethodID + '\n'; + return "InnerAuthEAP{mEAPMethodID=" + mEAPMethodID + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java index 1e32b30e8..1afe0d099 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/NonEAPInnerAuth.java @@ -1,93 +1,85 @@ +/* + * 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.hotspot2.anqp.eap; +import com.android.internal.annotations.VisibleForTesting; + import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; /** - * An EAP authentication parameter, IEEE802.11-2012, table 8-188 + * The Non-EAP Inner Authentication Type authentication parameter, IEEE802.11-2012, table 8-188. + * + * Format: + * | Type | + * 1 */ -public class NonEAPInnerAuth implements AuthParam { - - public enum NonEAPType {Reserved, PAP, CHAP, MSCHAP, MSCHAPv2} - private static final Map<NonEAPType, String> sOmaMap = new EnumMap<>(NonEAPType.class); - private static final Map<String, NonEAPType> sRevOmaMap = new HashMap<>(); - - private final NonEAPType mType; - - static { - sOmaMap.put(NonEAPType.PAP, "PAP"); - sOmaMap.put(NonEAPType.CHAP, "CHAP"); - sOmaMap.put(NonEAPType.MSCHAP, "MS-CHAP"); - sOmaMap.put(NonEAPType.MSCHAPv2, "MS-CHAP-V2"); - - for (Map.Entry<NonEAPType, String> entry : sOmaMap.entrySet()) { - sRevOmaMap.put(entry.getValue(), entry.getKey()); - } - } +public class NonEAPInnerAuth extends AuthParam { + public static final int AUTH_TYPE_PAP = 1; + public static final int AUTH_TYPE_CHAP = 2; + public static final int AUTH_TYPE_MSCHAP = 3; + public static final int AUTH_TYPE_MSCHAPV2 = 4; - public NonEAPInnerAuth(int length, ByteBuffer payload) throws ProtocolException { - if (length != 1) { - throw new ProtocolException("Bad length: " + payload.remaining()); - } + @VisibleForTesting + public static final int EXPECTED_LENGTH_VALUE = 1; - int typeID = payload.get() & BYTE_MASK; - mType = typeID < NonEAPType.values().length ? - NonEAPType.values()[typeID] : - NonEAPType.Reserved; - } + private final int mAuthType; - public NonEAPInnerAuth(NonEAPType type) { - mType = type; + public NonEAPInnerAuth(int authType) { + super(AuthParam.PARAM_TYPE_NON_EAP_INNER_AUTH_TYPE); + mAuthType = authType; } /** - * Construct from the OMA-DM PPS data - * @param eapType as defined in the HS2.0 spec. + * Parse a NonEAPInnerAuth from the given buffer. + * + * @param payload The byte buffer to read from + * @param length The length of the data + * @return {@link NonEAPInnerAuth} + * @throws BufferUnderflowException */ - public NonEAPInnerAuth(String eapType) { - mType = sRevOmaMap.get(eapType); - } - - @Override - public EAP.AuthInfoID getAuthInfoID() { - return EAP.AuthInfoID.NonEAPInnerAuthType; - } - - public NonEAPType getType() { - return mType; - } - - public String getOMAtype() { - return sOmaMap.get(mType); - } - - public static String mapInnerType(NonEAPType type) { - return sOmaMap.get(type); - } - - @Override - public int hashCode() { - return mType.hashCode(); + public static NonEAPInnerAuth parse(ByteBuffer payload, int length) throws ProtocolException { + if (length != EXPECTED_LENGTH_VALUE) { + throw new ProtocolException("Invalid length: " + length); + } + int authType = payload.get() & 0xFF; + return new NonEAPInnerAuth(authType); } @Override public boolean equals(Object thatObject) { if (thatObject == this) { return true; - } else if (thatObject == null || thatObject.getClass() != NonEAPInnerAuth.class) { + } + if (!(thatObject instanceof NonEAPInnerAuth)) { return false; - } else { - return ((NonEAPInnerAuth) thatObject).getType() == getType(); } + NonEAPInnerAuth that = (NonEAPInnerAuth) thatObject; + return mAuthType == that.mAuthType; + } + + @Override + public int hashCode() { + return mAuthType; } @Override public String toString() { - return "Auth method NonEAPInnerAuthEAP, inner = " + mType + '\n'; + return "NonEAPInnerAuth{mAuthType=" + mAuthType + "}"; } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java b/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java index 60a14c2c9..048f0d637 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/eap/VendorSpecificAuth.java @@ -1,47 +1,80 @@ +/* + * 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.hotspot2.anqp.eap; -import java.net.ProtocolException; +import com.android.internal.annotations.VisibleForTesting; + +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.Arrays; /** - * An EAP authentication parameter, IEEE802.11-2012, table 8-188 + * The Vendor Specific authentication parameter, IEEE802.11-2012, table 8-188. + * + * Format: + * | Data | + * variable */ -public class VendorSpecificAuth implements AuthParam { - +public class VendorSpecificAuth extends AuthParam { private final byte[] mData; - public VendorSpecificAuth(int length, ByteBuffer payload) throws ProtocolException { - mData = new byte[length]; - payload.get(mData); + @VisibleForTesting + public VendorSpecificAuth(byte[] data) { + super(AuthParam.PARAM_TYPE_VENDOR_SPECIFIC); + mData = data; } - @Override - public EAP.AuthInfoID getAuthInfoID() { - return EAP.AuthInfoID.VendorSpecific; + /** + * Parse a VendorSpecificAuth from the given buffer. + * + * @param payload The byte buffer to read from + * @param length The length of the data + * @return {@link VendorSpecificAuth} + * @throws BufferUnderflowException + */ + public static VendorSpecificAuth parse(ByteBuffer payload, int length) { + byte[] data = new byte[length]; + payload.get(data); + return new VendorSpecificAuth(data); } - public int hashCode() { - return Arrays.hashCode(mData); + public byte[] getData() { + return mData; } @Override public boolean equals(Object thatObject) { if (thatObject == this) { return true; - } else if (thatObject == null || thatObject.getClass() != VendorSpecificAuth.class) { + } + if (!(thatObject instanceof VendorSpecificAuth)) { return false; - } else { - return Arrays.equals(((VendorSpecificAuth) thatObject).getData(), getData()); } + VendorSpecificAuth that = (VendorSpecificAuth) thatObject; + return Arrays.equals(mData, that.mData); } - public byte[] getData() { - return mData; + @Override + public int hashCode() { + return Arrays.hashCode(mData); } @Override public String toString() { - return "Auth method VendorSpecificAuth, data = " + Arrays.toString(mData) + '\n'; + return "VendorSpecificAuth{mData=" + Arrays.toString(mData) + "}"; } } |