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