summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/hotspot2/DomainMatcher.java199
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java5
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java3
3 files changed, 136 insertions, 71 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java b/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java
index 3f93101ba..ce60c55b0 100644
--- a/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java
+++ b/service/java/com/android/server/wifi/hotspot2/DomainMatcher.java
@@ -1,45 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.server.wifi.hotspot2;
+import android.text.TextUtils;
+
import com.android.server.wifi.hotspot2.Utils;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+/**
+ * Utility class for matching domain names.
+ */
public class DomainMatcher {
+ public static final int MATCH_NONE = 0;
+ public static final int MATCH_PRIMARY = 1;
+ public static final int MATCH_SECONDARY = 2;
- public enum Match {None, Primary, Secondary}
-
+ /**
+ * The root of the Label tree.
+ */
private final Label mRoot;
+ /**
+ * Label tree representation for the domain name. Labels are delimited by "." in the domain
+ * name.
+ *
+ * For example, the tree representation of "android.google.com" as a primary domain:
+ * [com, None] -> [google, None] -> [android, Primary]
+ *
+ */
private static class Label {
private final Map<String, Label> mSubDomains;
- private final Match mMatch;
+ private int mMatch;
- private Label(Match match) {
+ Label(int match) {
mMatch = match;
- mSubDomains = match == Match.None ? new HashMap<String, Label>() : null;
+ mSubDomains = new HashMap<String, Label>();
}
- private void addDomain(Iterator<String> labels, Match match) {
+ /**
+ * Add sub-domains to this label.
+ *
+ * @param labels The iterator of domain label strings
+ * @param match The match status of the domain
+ */
+ public void addDomain(Iterator<String> labels, int match) {
String labelName = labels.next();
- if (labels.hasNext()) {
- Label subLabel = new Label(Match.None);
+ // Create the Label object if it doesn't exist yet.
+ Label subLabel = mSubDomains.get(labelName);
+ if (subLabel == null) {
+ subLabel = new Label(MATCH_NONE);
mSubDomains.put(labelName, subLabel);
+ }
+
+ if (labels.hasNext()) {
+ // Adding sub-domain.
subLabel.addDomain(labels, match);
} else {
- mSubDomains.put(labelName, new Label(match));
+ // End of the domain, update the match status.
+ subLabel.mMatch = match;
}
}
- private Label getSubLabel(String labelString) {
+ /**
+ * Return the Label for the give label string.
+ * @param labelString The label string to look for
+ * @return {@link Label}
+ */
+ public Label getSubLabel(String labelString) {
return mSubDomains.get(labelString);
}
- public Match getMatch() {
+ /**
+ * Return the match status
+ *
+ * @return The match status
+ */
+ public int getMatch() {
return mMatch;
}
@@ -64,46 +118,90 @@ public class DomainMatcher {
}
}
- public DomainMatcher(List<String> primary, List<List<String>> secondary) {
- mRoot = new Label(Match.None);
- for (List<String> secondaryLabel : secondary) {
- mRoot.addDomain(secondaryLabel.iterator(), Match.Secondary);
+ public DomainMatcher(String primaryDomain, List<String> secondaryDomains) {
+ // Create the root label.
+ mRoot = new Label(MATCH_NONE);
+
+ // Add secondary domains.
+ if (secondaryDomains != null) {
+ for (String domain : secondaryDomains) {
+ if (!TextUtils.isEmpty(domain)) {
+ List<String> secondaryLabel = Utils.splitDomain(domain);
+ mRoot.addDomain(secondaryLabel.iterator(), MATCH_SECONDARY);
+ }
+ }
+ }
+
+ // Add primary domain, primary overwrites secondary.
+ if (!TextUtils.isEmpty(primaryDomain)) {
+ List<String> primaryLabel = Utils.splitDomain(primaryDomain);
+ mRoot.addDomain(primaryLabel.iterator(), MATCH_PRIMARY);
}
- // Primary overwrites secondary.
- mRoot.addDomain(primary.iterator(), Match.Primary);
}
/**
- * Check if domain is either a the same or a sub-domain of any of the domains in the domain tree
- * in this matcher, i.e. all or or a sub-set of the labels in domain matches a path in the tree.
- * @param domain Domain to be checked.
- * @return None if domain is not a sub-domain, Primary if it matched one of the primary domains
- * or Secondary if it matched on of the secondary domains.
+ * Check if domain is either the same or a sub-domain of any of the domains in the
+ * domain tree in this matcher, i.e. all or a sub-set of the labels in domain matches
+ * a path in the tree.
+ *
+ * This will have precedence for matching primary domain over secondary domain if both
+ * are found.
+ *
+ * For example, with primary domain set to "test.google.com" and secondary domain set to
+ * "google.com":
+ * "test2.test.google.com" -> Match.Primary
+ * "test1.google.com" -> Match.Secondary
+ *
+ * @param domainName Domain name to be checked.
+ * @return The match status
*/
- public Match isSubDomain(List<String> domain) {
+ public int isSubDomain(String domainName) {
+ if (TextUtils.isEmpty(domainName)) {
+ return MATCH_NONE;
+ }
+ List<String> domainLabels = Utils.splitDomain(domainName);
Label label = mRoot;
- for (String labelString : domain) {
+ int match = MATCH_NONE;
+ for (String labelString : domainLabels) {
label = label.getSubLabel(labelString);
if (label == null) {
- return Match.None;
- } else if (label.getMatch() != Match.None) {
- return label.getMatch();
+ break;
+ } else if (label.getMatch() != MATCH_NONE) {
+ match = label.getMatch();
+ if (match == MATCH_PRIMARY) {
+ break;
+ }
}
}
- return Match.None; // Domain is a super domain
+ return match;
}
- public static boolean arg2SubdomainOfArg1(List<String> arg1, List<String> arg2) {
- if (arg2.size() < arg1.size()) {
+ /**
+ * Check if domain2 is a sub-domain of domain1.
+ *
+ * @param domain1 The string of the first domain
+ * @param domain2 The string of the second domain
+ * @return true if the second domain is the sub-domain of the first
+ */
+ public static boolean arg2SubdomainOfArg1(String domain1, String domain2) {
+ if (TextUtils.isEmpty(domain1) || TextUtils.isEmpty(domain2)) {
+ return false;
+ }
+
+ List<String> labels1 = Utils.splitDomain(domain1);
+ List<String> labels2 = Utils.splitDomain(domain2);
+
+ // domain2 must be the same or longer than domain1 in order to be a sub-domain.
+ if (labels2.size() < labels1.size()) {
return false;
}
- Iterator<String> l1 = arg1.iterator();
- Iterator<String> l2 = arg2.iterator();
+ Iterator<String> l1 = labels1.iterator();
+ Iterator<String> l2 = labels2.iterator();
while(l1.hasNext()) {
- if (!l1.next().equals(l2.next())) {
+ if (!TextUtils.equals(l1.next(), l2.next())) {
return false;
}
}
@@ -114,35 +212,4 @@ public class DomainMatcher {
public String toString() {
return "Domain matcher " + mRoot;
}
-
- private static final String[] TestDomains = {
- "garbage.apple.com",
- "apple.com",
- "com",
- "jan.android.google.com.",
- "jan.android.google.com",
- "android.google.com",
- "google.com",
- "jan.android.google.net.",
- "jan.android.google.net",
- "android.google.net",
- "google.net",
- "net.",
- "."
- };
-
- public static void main(String[] args) {
- DomainMatcher dm1 = new DomainMatcher(Utils.splitDomain("android.google.com"),
- Collections.<List<String>>emptyList());
- for (String domain : TestDomains) {
- System.out.println(domain + ": " + dm1.isSubDomain(Utils.splitDomain(domain)));
- }
- List<List<String>> secondaries = new ArrayList<List<String>>();
- secondaries.add(Utils.splitDomain("apple.com"));
- secondaries.add(Utils.splitDomain("net"));
- DomainMatcher dm2 = new DomainMatcher(Utils.splitDomain("android.google.com"), secondaries);
- for (String domain : TestDomains) {
- System.out.println(domain + ": " + dm2.isSubDomain(Utils.splitDomain(domain)));
- }
- }
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
index 58c4913e5..95fbc893c 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
@@ -59,12 +59,11 @@ public class NAIRealmData {
// TODO(b/32714185): revisit this when integrating the new Passpoint implementation and add
// unit tests for this.
- public int match(List<String> credLabels, EAPMethod credMethod) {
+ public int match(String realmToMatch, EAPMethod credMethod) {
int realmMatch = AuthMatch.None;
if (!mRealms.isEmpty()) {
for (String realm : mRealms) {
- List<String> labels = Utils.splitDomain(realm);
- if (DomainMatcher.arg2SubdomainOfArg1(credLabels, labels)) {
+ if (DomainMatcher.arg2SubdomainOfArg1(realmToMatch, realm)) {
realmMatch = AuthMatch.Realm;
break;
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java
index de80f585a..e1bafa85f 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmElement.java
@@ -51,10 +51,9 @@ public class NAIRealmElement extends ANQPElement {
if (mRealmData.isEmpty())
return AuthMatch.Indeterminate;
- List<String> credLabels = Utils.splitDomain(realm);
int best = AuthMatch.None;
for (NAIRealmData realmData : mRealmData) {
- int match = realmData.match(credLabels, credMethod);
+ int match = realmData.match(realm, credMethod);
if (match > best) {
best = match;
if (best == AuthMatch.Exact) {