16a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpackage com.android.server.wifi.anqp.eap;
26a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
3866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist
46a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport com.android.server.wifi.anqp.Constants;
571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport com.android.server.wifi.hotspot2.AuthMatch;
66a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
76a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.net.ProtocolException;
86a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.nio.ByteBuffer;
97b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvistimport java.nio.ByteOrder;
106a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.Collections;
116a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.EnumMap;
1271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.util.HashMap;
136a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.HashSet;
146a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.Map;
156a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.Set;
166a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
176a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist/**
186a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist * An EAP Method, part of the NAI Realm ANQP element, specified in
196a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist * IEEE802.11-2012 section 8.4.4.10, figure 8-420
206a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist */
216a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpublic class EAPMethod {
226a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    private final EAP.EAPMethodID mEAPMethodID;
236a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    private final Map<EAP.AuthInfoID, Set<AuthParam>> mAuthParams;
246a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
256a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public EAPMethod(ByteBuffer payload) throws ProtocolException {
266a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        if (payload.remaining() < 3) {
276a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            throw new ProtocolException("Runt EAP Method: " + payload.remaining());
286a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
296a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
306a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int length = payload.get() & Constants.BYTE_MASK;
316a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int methodID = payload.get() & Constants.BYTE_MASK;
326a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int count = payload.get() & Constants.BYTE_MASK;
336a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
346a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        mEAPMethodID = EAP.mapEAPMethod(methodID);
35a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist        mAuthParams = new EnumMap<>(EAP.AuthInfoID.class);
366a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
376a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int realCount = 0;
386a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
397b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        ByteBuffer paramPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
40777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist        paramPayload.limit(paramPayload.position() + length - 2);
41777f4fc037d3ebd555f10041f8acfb41515b2f4bJan Nordqvist        payload.position(payload.position() + length - 2);
426a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        while (paramPayload.hasRemaining()) {
436a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            int id = paramPayload.get() & Constants.BYTE_MASK;
446a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
453be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist            EAP.AuthInfoID authInfoID = EAP.mapAuthMethod(id);
463be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist            if (authInfoID == null) {
476a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                throw new ProtocolException("Unknown auth parameter ID: " + id);
486a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            }
496a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
503be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist            int len = paramPayload.get() & Constants.BYTE_MASK;
513be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist            if (len == 0 || len > paramPayload.remaining()) {
523be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                throw new ProtocolException("Bad auth method length: " + len);
533be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist            }
543be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist
556a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            switch (authInfoID) {
566a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case ExpandedEAPMethod:
573be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload));
586a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
596a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case NonEAPInnerAuthType:
603be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new NonEAPInnerAuth(len, paramPayload));
616a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
626a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case InnerAuthEAPMethodType:
633be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new InnerAuthEAP(len, paramPayload));
646a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
656a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case ExpandedInnerEAPMethod:
663be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload));
676a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
686a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case CredentialType:
693be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new Credential(authInfoID, len, paramPayload));
706a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
716a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case TunneledEAPMethodCredType:
723be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new Credential(authInfoID, len, paramPayload));
736a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
746a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                case VendorSpecific:
753be1b3fc037bef7fb4448dec89aea3f2e1318853Jan Nordqvist                    addAuthParam(new VendorSpecificAuth(len, paramPayload));
766a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    break;
776a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            }
786a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
796a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            realCount++;
806a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
816a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        if (realCount != count)
826a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            throw new ProtocolException("Invalid parameter count: " + realCount +
836a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                    ", expected " + count);
846a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
856a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
8671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public EAPMethod(EAP.EAPMethodID eapMethodID, AuthParam authParam) {
8771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        mEAPMethodID = eapMethodID;
88a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist        mAuthParams = new HashMap<>(1);
8971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (authParam != null) {
90a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist            Set<AuthParam> authParams = new HashSet<>();
9171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            authParams.add(authParam);
9271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            mAuthParams.put(authParam.getAuthInfoID(), authParams);
9371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
9471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
9571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
966a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    private void addAuthParam(AuthParam param) {
976a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        Set<AuthParam> authParams = mAuthParams.get(param.getAuthInfoID());
986a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        if (authParams == null) {
99a7ead3d4be45cb69bb5851f1a6f9673e93607fc2Jan Nordqvist            authParams = new HashSet<>();
1006a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            mAuthParams.put(param.getAuthInfoID(), authParams);
1016a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
1026a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        authParams.add(param);
1036a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1046a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
1056a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public Map<EAP.AuthInfoID, Set<AuthParam>> getAuthParams() {
1066a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        return Collections.unmodifiableMap(mAuthParams);
1076a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1086a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
1096a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public EAP.EAPMethodID getEAPMethodID() {
1106a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        return mEAPMethodID;
1116a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1126a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
113c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist    public int match(com.android.server.wifi.hotspot2.pps.Credential credential) {
1146a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
115866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        EAPMethod credMethod = credential.getEAPMethod();
116866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        if (mEAPMethodID != credMethod.getEAPMethodID()) {
117866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            return AuthMatch.None;
118866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        }
1196a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
120866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        switch (mEAPMethodID) {
121866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            case EAP_TTLS:
122866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                if (mAuthParams.isEmpty()) {
123c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                    return AuthMatch.Method;
124866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                }
125c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                int paramCount = 0;
126866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                for (Map.Entry<EAP.AuthInfoID, Set<AuthParam>> entry :
127866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                        credMethod.getAuthParams().entrySet()) {
128866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                    Set<AuthParam> params = mAuthParams.get(entry.getKey());
129c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                    if (params == null) {
130866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                        continue;
131c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                    }
132866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist
133866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                    if (!Collections.disjoint(params, entry.getValue())) {
134c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                        return AuthMatch.MethodParam;
135866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                    }
136c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                    paramCount += params.size();
137866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                }
138c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                return paramCount > 0 ? AuthMatch.None : AuthMatch.Method;
139866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            case EAP_TLS:
140c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                return AuthMatch.MethodParam;
141866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            case EAP_SIM:
142866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            case EAP_AKA:
143866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            case EAP_AKAPrim:
144c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                return AuthMatch.Method;
145866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            default:
146c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                return AuthMatch.Method;
1476a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
1486a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1496a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
15077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public AuthParam getAuthParam() {
15177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (mAuthParams.isEmpty()) {
15277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return null;
15377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
15477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Set<AuthParam> params = mAuthParams.values().iterator().next();
15577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (params.isEmpty()) {
15677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return null;
15777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
15877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return params.iterator().next();
15977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
16077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1616a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    @Override
162820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    public boolean equals(Object thatObject) {
163820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        if (this == thatObject) {
164820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist            return true;
165820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        }
166820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        else if (thatObject == null || getClass() != thatObject.getClass()) {
167820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist            return false;
168820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        }
169820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist
170820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        EAPMethod that = (EAPMethod) thatObject;
171820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        return mEAPMethodID == that.mEAPMethodID && mAuthParams.equals(that.mAuthParams);
172820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    }
173820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist
174820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    @Override
175820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    public int hashCode() {
176820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        int result = mEAPMethodID.hashCode();
177820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        result = 31 * result + mAuthParams.hashCode();
178820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist        return result;
179820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    }
180820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist
181820d73615f338d6c71f2d75aba0ad8410e9eed3eJan Nordqvist    @Override
1826a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public String toString() {
1837b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        StringBuilder sb = new StringBuilder();
1847b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        sb.append("EAP Method ").append(mEAPMethodID).append('\n');
1857b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        for (Set<AuthParam> paramSet : mAuthParams.values()) {
1867b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist            for (AuthParam param : paramSet) {
1877b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist                sb.append("      ").append(param.toString());
1887b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist            }
1897b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        }
1907b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        return sb.toString();
1916a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1926a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist}
193