1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.anqp.eap; 2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.anqp.Constants; 4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.AuthMatch; 5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.net.ProtocolException; 7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.ByteBuffer; 8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.ByteOrder; 9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collections; 10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.EnumMap; 11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashMap; 12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashSet; 13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map; 14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Set; 15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist/** 17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * An EAP Method, part of the NAI Realm ANQP element, specified in 18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * IEEE802.11-2012 section 8.4.4.10, figure 8-420 19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist */ 20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class EAPMethod { 21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final EAP.EAPMethodID mEAPMethodID; 22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final Map<EAP.AuthInfoID, Set<AuthParam>> mAuthParams; 23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public EAPMethod(ByteBuffer payload) throws ProtocolException { 25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (payload.remaining() < 3) { 26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new ProtocolException("Runt EAP Method: " + payload.remaining()); 27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int length = payload.get() & Constants.BYTE_MASK; 30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int methodID = payload.get() & Constants.BYTE_MASK; 31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int count = payload.get() & Constants.BYTE_MASK; 32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mEAPMethodID = EAP.mapEAPMethod(methodID); 34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAuthParams = new EnumMap<>(EAP.AuthInfoID.class); 35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int realCount = 0; 37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist ByteBuffer paramPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); 39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist paramPayload.limit(paramPayload.position() + length - 2); 40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist payload.position(payload.position() + length - 2); 41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist while (paramPayload.hasRemaining()) { 42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int id = paramPayload.get() & Constants.BYTE_MASK; 43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist EAP.AuthInfoID authInfoID = EAP.mapAuthMethod(id); 45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (authInfoID == null) { 46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new ProtocolException("Unknown auth parameter ID: " + id); 47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int len = paramPayload.get() & Constants.BYTE_MASK; 50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (len == 0 || len > paramPayload.remaining()) { 51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new ProtocolException("Bad auth method length: " + len); 52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist switch (authInfoID) { 55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case ExpandedEAPMethod: 56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload)); 57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case NonEAPInnerAuthType: 59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new NonEAPInnerAuth(len, paramPayload)); 60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case InnerAuthEAPMethodType: 62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new InnerAuthEAP(len, paramPayload)); 63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case ExpandedInnerEAPMethod: 65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload)); 66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case CredentialType: 68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new Credential(authInfoID, len, paramPayload)); 69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case TunneledEAPMethodCredType: 71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new Credential(authInfoID, len, paramPayload)); 72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case VendorSpecific: 74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist addAuthParam(new VendorSpecificAuth(len, paramPayload)); 75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist break; 76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist realCount++; 79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (realCount != count) 81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new ProtocolException("Invalid parameter count: " + realCount + 82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist ", expected " + count); 83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public EAPMethod(EAP.EAPMethodID eapMethodID, AuthParam authParam) { 86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mEAPMethodID = eapMethodID; 87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAuthParams = new HashMap<>(1); 88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (authParam != null) { 89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Set<AuthParam> authParams = new HashSet<>(); 90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist authParams.add(authParam); 91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAuthParams.put(authParam.getAuthInfoID(), authParams); 92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private void addAuthParam(AuthParam param) { 96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Set<AuthParam> authParams = mAuthParams.get(param.getAuthInfoID()); 97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (authParams == null) { 98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist authParams = new HashSet<>(); 99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mAuthParams.put(param.getAuthInfoID(), authParams); 100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist authParams.add(param); 102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public Map<EAP.AuthInfoID, Set<AuthParam>> getAuthParams() { 105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return Collections.unmodifiableMap(mAuthParams); 106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public EAP.EAPMethodID getEAPMethodID() { 109ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mEAPMethodID; 110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public int match(com.android.hotspot2.pps.Credential credential) { 113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist EAPMethod credMethod = credential.getEAPMethod(); 115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mEAPMethodID != credMethod.getEAPMethodID()) { 116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.None; 117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist switch (mEAPMethodID) { 120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case EAP_TTLS: 121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mAuthParams.isEmpty()) { 122ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.Method; 123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int paramCount = 0; 125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (Map.Entry<EAP.AuthInfoID, Set<AuthParam>> entry : 126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist credMethod.getAuthParams().entrySet()) { 127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Set<AuthParam> params = mAuthParams.get(entry.getKey()); 128ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (params == null) { 129ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist continue; 130ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 131ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 132ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (!Collections.disjoint(params, entry.getValue())) { 133ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.MethodParam; 134ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 135ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist paramCount += params.size(); 136ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 137ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return paramCount > 0 ? AuthMatch.None : AuthMatch.Method; 138ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case EAP_TLS: 139ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.MethodParam; 140ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case EAP_SIM: 141ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case EAP_AKA: 142ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist case EAP_AKAPrim: 143ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.Method; 144ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist default: 145ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return AuthMatch.Method; 146ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 147ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 148ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 149ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public AuthParam getAuthParam() { 150ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (mAuthParams.isEmpty()) { 151ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 152ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 153ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Set<AuthParam> params = mAuthParams.values().iterator().next(); 154ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (params.isEmpty()) { 155ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 156ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 157ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return params.iterator().next(); 158ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 159ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 160ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 161ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public boolean equals(Object thatObject) { 162ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (this == thatObject) { 163ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return true; 164ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 165ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist else if (thatObject == null || getClass() != thatObject.getClass()) { 166ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return false; 167ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 168ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 169ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist EAPMethod that = (EAPMethod) thatObject; 170ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mEAPMethodID == that.mEAPMethodID && mAuthParams.equals(that.mAuthParams); 171ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 172ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 173ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 174ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public int hashCode() { 175ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int result = mEAPMethodID.hashCode(); 176ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist result = 31 * result + mAuthParams.hashCode(); 177ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return result; 178ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 179ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 180ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 181ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public String toString() { 182ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist StringBuilder sb = new StringBuilder(); 183ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist sb.append("EAP Method ").append(mEAPMethodID).append('\n'); 184ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (Set<AuthParam> paramSet : mAuthParams.values()) { 185ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (AuthParam param : paramSet) { 186ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist sb.append(" ").append(param.toString()); 187ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 188ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 189ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return sb.toString(); 190ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 191ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist} 192