16a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpackage com.android.server.wifi.anqp;
26a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
36a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport com.android.server.wifi.anqp.eap.EAPMethod;
471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport com.android.server.wifi.hotspot2.AuthMatch;
5866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvistimport com.android.server.wifi.hotspot2.Utils;
6866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvistimport com.android.server.wifi.hotspot2.pps.Credential;
7866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvistimport com.android.server.wifi.hotspot2.pps.DomainMatcher;
86a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
96a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.net.ProtocolException;
106a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.nio.ByteBuffer;
116a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.nio.charset.StandardCharsets;
126a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.ArrayList;
136a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.Collections;
146a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.List;
156a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
166a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist/**
176a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist * The NAI Realm Data ANQP sub-element, IEEE802.11-2012 section 8.4.4.10 figure 8-418
186a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist */
196a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpublic class NAIRealmData {
206a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    private final List<String> mRealms;
216a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    private final List<EAPMethod> mEAPMethods;
226a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
236a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public NAIRealmData(ByteBuffer payload) throws ProtocolException {
246a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        if (payload.remaining() < 5) {
256a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            throw new ProtocolException("Runt payload: " + payload.remaining());
266a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
276a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
286a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int length = payload.getShort() & Constants.SHORT_MASK;
296a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        if (length > payload.remaining()) {
306a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            throw new ProtocolException("Invalid data length: " + length);
316a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
326a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        boolean utf8 = (payload.get() & 1) == Constants.UTF8_INDICATOR;
336a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
346a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        String realm = Constants.getPrefixedString(payload, 1, utf8 ?
356a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                StandardCharsets.UTF_8 :
366a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                StandardCharsets.US_ASCII);
376a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        String[] realms = realm.split(";");
38866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        mRealms = new ArrayList<>();
396a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        for (String realmElement : realms) {
406a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            if (realmElement.length() > 0) {
416a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist                mRealms.add(realmElement);
426a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            }
436a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
446a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
456a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        int methodCount = payload.get() & Constants.BYTE_MASK;
46866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        mEAPMethods = new ArrayList<>(methodCount);
476a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        while (methodCount > 0) {
486a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            mEAPMethods.add(new EAPMethod(payload));
496a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist            methodCount--;
506a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        }
516a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
526a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
536a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public List<String> getRealms() {
546a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        return Collections.unmodifiableList(mRealms);
556a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
566a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
576a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public List<EAPMethod> getEAPMethods() {
586a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist        return Collections.unmodifiableList(mEAPMethods);
596a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
606a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist
61c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist    public int match(List<String> credLabels, Credential credential) {
62c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist        int realmMatch = AuthMatch.None;
63866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        if (!mRealms.isEmpty()) {
64866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            for (String realm : mRealms) {
65866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                List<String> labels = Utils.splitDomain(realm);
66866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                if (DomainMatcher.arg2SubdomainOfArg1(credLabels, labels)) {
67c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                    realmMatch = AuthMatch.Realm;
68866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                    break;
69866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                }
70866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            }
71c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist            if (realmMatch == AuthMatch.None || mEAPMethods.isEmpty()) {
72c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist                return realmMatch;
73866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            }
74866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            // else there is a realm match and one or more EAP methods - check them.
75866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        }
76866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        else if (mEAPMethods.isEmpty()) {
77866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            return AuthMatch.Indeterminate;
7871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
7971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
80c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist        int best = AuthMatch.None;
81866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist        for (EAPMethod eapMethod : mEAPMethods) {
82c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist            int match = eapMethod.match(credential) | realmMatch;
83c2db1a4ff61fdf72be070e0c1cb739e755760bf3Jan Nordqvist            if (match > best) {
8471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                best = match;
85866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                if (best == AuthMatch.Exact) {
86866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist                    return best;
8771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                }
8871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            }
8971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
9071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        return best;
9171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
9271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
936a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    @Override
946a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    public String toString() {
957b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        StringBuilder sb = new StringBuilder();
967b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist
977b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        sb.append("  NAI Realm(s)");
987b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        for (String realm : mRealms) {
997b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist            sb.append(' ').append(realm);
1007b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        }
1017b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        sb.append('\n');
1027b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist
1037b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        for (EAPMethod eapMethod : mEAPMethods) {
1047b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist            sb.append( "    " ).append(eapMethod.toString());
1057b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        }
1067b2caa25fb57f2d95e0d0421704c49d3af4b8e6fJan Nordqvist        return sb.toString();
1076a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist    }
1086a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist}
109