• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EAPMethod(ByteBuffer payload)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 
EAPMethod(EAP.EAPMethodID eapMethodID, AuthParam authParam)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 
addAuthParam(AuthParam param)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 
getAuthParams()104     public Map<EAP.AuthInfoID, Set<AuthParam>> getAuthParams() {
105         return Collections.unmodifiableMap(mAuthParams);
106     }
107 
getEAPMethodID()108     public EAP.EAPMethodID getEAPMethodID() {
109         return mEAPMethodID;
110     }
111 
match(com.android.hotspot2.pps.Credential credential)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 
getAuthParam()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
equals(Object thatObject)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
hashCode()174     public int hashCode() {
175         int result = mEAPMethodID.hashCode();
176         result = 31 * result + mAuthParams.hashCode();
177         return result;
178     }
179 
180     @Override
toString()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