NAIRealmData.java revision fa04a81daf829e6e5c099c9a249b8dd8dd112102
1package com.android.server.wifi.hotspot2.anqp; 2 3import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; 4import com.android.server.wifi.ByteBufferReader; 5import com.android.server.wifi.hotspot2.AuthMatch; 6import com.android.server.wifi.hotspot2.DomainMatcher; 7import com.android.server.wifi.hotspot2.Utils; 8 9import java.net.ProtocolException; 10import java.nio.ByteBuffer; 11import java.nio.charset.StandardCharsets; 12import java.util.ArrayList; 13import java.util.Collections; 14import java.util.List; 15 16/** 17 * The NAI Realm Data ANQP sub-element, IEEE802.11-2012 section 8.4.4.10 figure 8-418 18 */ 19public class NAIRealmData { 20 private final List<String> mRealms; 21 private final List<EAPMethod> mEAPMethods; 22 23 public NAIRealmData(ByteBuffer payload) throws ProtocolException { 24 if (payload.remaining() < 5) { 25 throw new ProtocolException("Runt payload: " + payload.remaining()); 26 } 27 28 int length = payload.getShort() & Constants.SHORT_MASK; 29 if (length > payload.remaining()) { 30 throw new ProtocolException("Invalid data length: " + length); 31 } 32 boolean utf8 = (payload.get() & 1) == Constants.UTF8_INDICATOR; 33 34 String realm = ByteBufferReader.readStringWithByteLength( 35 payload, utf8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII); 36 String[] realms = realm.split(";"); 37 mRealms = new ArrayList<>(); 38 for (String realmElement : realms) { 39 if (realmElement.length() > 0) { 40 mRealms.add(realmElement); 41 } 42 } 43 44 int methodCount = payload.get() & Constants.BYTE_MASK; 45 mEAPMethods = new ArrayList<>(methodCount); 46 while (methodCount > 0) { 47 mEAPMethods.add(new EAPMethod(payload)); 48 methodCount--; 49 } 50 } 51 52 public List<String> getRealms() { 53 return Collections.unmodifiableList(mRealms); 54 } 55 56 public List<EAPMethod> getEAPMethods() { 57 return Collections.unmodifiableList(mEAPMethods); 58 } 59 60 // TODO(b/32714185): revisit this when integrating the new Passpoint implementation and add 61 // unit tests for this. 62 public int match(String realmToMatch, EAPMethod credMethod) { 63 int realmMatch = AuthMatch.None; 64 if (!mRealms.isEmpty()) { 65 for (String realm : mRealms) { 66 if (DomainMatcher.arg2SubdomainOfArg1(realmToMatch, realm)) { 67 realmMatch = AuthMatch.Realm; 68 break; 69 } 70 } 71 if (realmMatch == AuthMatch.None || mEAPMethods.isEmpty()) { 72 return realmMatch; 73 } 74 // else there is a realm match and one or more EAP methods - check them. 75 } 76 else if (mEAPMethods.isEmpty()) { 77 return AuthMatch.Indeterminate; 78 } 79 80 int best = AuthMatch.None; 81 for (EAPMethod eapMethod : mEAPMethods) { 82 int match = eapMethod.match(credMethod) | realmMatch; 83 if (match > best) { 84 best = match; 85 if (best == AuthMatch.Exact) { 86 return best; 87 } 88 } 89 } 90 return best; 91 } 92 93 @Override 94 public String toString() { 95 StringBuilder sb = new StringBuilder(); 96 97 sb.append(" NAI Realm(s)"); 98 for (String realm : mRealms) { 99 sb.append(' ').append(realm); 100 } 101 sb.append('\n'); 102 103 for (EAPMethod eapMethod : mEAPMethods) { 104 sb.append( " " ).append(eapMethod.toString()); 105 } 106 return sb.toString(); 107 } 108} 109