mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Check the host is under registry suffix instead of public suffix
Guava now has support to distinguish a registry suffix from a public suffix. Since we are only interested in registrable domains, registry suffix is the proper thing to check.
See:
692446a303/guava/src/com/google/common/net/InternetDomainName.java
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=176126916
This commit is contained in:
parent
9ab68613a0
commit
0796a0ff1c
4 changed files with 50 additions and 59 deletions
|
@ -1032,7 +1032,7 @@ allows creating a host name, and if necessary enqueues tasks to update DNS.
|
|||
* 2304
|
||||
* Superordinate domain for this hostname is in pending delete.
|
||||
* 2306
|
||||
* Host names must be at least two levels below the public suffix.
|
||||
* Host names must be at least two levels below the registry suffix.
|
||||
|
||||
## HostDeleteFlow
|
||||
|
||||
|
@ -1131,7 +1131,7 @@ are enqueued to update DNS accordingly.
|
|||
* Cannot rename an external host.
|
||||
* 2306
|
||||
* Cannot add and remove the same value.
|
||||
* Host names must be at least two levels below the public suffix.
|
||||
* Host names must be at least two levels below the registry suffix.
|
||||
|
||||
## LoginFlow
|
||||
|
||||
|
|
|
@ -57,32 +57,21 @@ public class HostFlowUtils {
|
|||
if (!name.equals(hostName.toString())) {
|
||||
throw new HostNameNotNormalizedException(hostName.toString());
|
||||
}
|
||||
// Checks whether a hostname is deep enough. Technically a host can be just one under a
|
||||
// public suffix (e.g. example.com) but we require by policy that it has to be at least one
|
||||
// part beyond that (e.g. ns1.example.com). The public suffix list includes all current
|
||||
// ccTlds, so this check requires 4+ parts if it's a ccTld that doesn't delegate second
|
||||
// level domains, such as .co.uk. But the list does not include new tlds, so in that case
|
||||
// we just ensure 3+ parts. In the particular case where our own tld has a '.' in it, we know
|
||||
// that there need to be 4 parts as well.
|
||||
// TODO(b/63128999): Use better method (once implemented) that determines if it's a public
|
||||
// suffix that domain names can be registered under.
|
||||
if (hostName.isUnderPublicSuffix()) {
|
||||
if (hostName.parent().isUnderPublicSuffix()) {
|
||||
return hostName;
|
||||
}
|
||||
} else {
|
||||
// We need to know how many parts the hostname has beyond the public suffix, but we don't
|
||||
// know what the public suffix is. If the host is in bailiwick and we are hosting a
|
||||
// multipart "tld" like .co.uk the public suffix might be 2 parts. Otherwise it's an
|
||||
// unrecognized tld that's not on the public suffix list, so assume the tld alone is the
|
||||
// public suffix.
|
||||
Optional<InternetDomainName> tldParsed = findTldForName(hostName);
|
||||
int suffixSize = tldParsed.isPresent() ? tldParsed.get().parts().size() : 1;
|
||||
if (hostName.parts().size() >= suffixSize + 2) {
|
||||
return hostName;
|
||||
}
|
||||
}
|
||||
// The effective TLD is, in order of preference, the registry suffix, if the TLD is a real TLD
|
||||
// published in the public suffix list (https://publicsuffix.org/, note that a registry suffix
|
||||
// is in the "ICANN DOMAINS" in that list); or a TLD managed by Nomulus (in-bailiwick), found
|
||||
// by #findTldForName; or just the last part of a domain name.
|
||||
InternetDomainName effectiveTld =
|
||||
hostName.isUnderRegistrySuffix()
|
||||
? hostName.registrySuffix()
|
||||
: findTldForName(hostName).orElse(InternetDomainName.from("invalid"));
|
||||
// Checks whether a hostname is deep enough. Technically a host can be just one level beneath
|
||||
// the effective TLD (e.g. example.com) but we require by policy that it has to be at least
|
||||
// one part beyond that (e.g. ns1.example.com).
|
||||
if (hostName.parts().size() < effectiveTld.parts().size() + 2) {
|
||||
throw new HostNameTooShallowException();
|
||||
}
|
||||
return hostName;
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InvalidHostNameException();
|
||||
}
|
||||
|
@ -119,8 +108,7 @@ public class HostFlowUtils {
|
|||
|
||||
/** Ensure that the superordinate domain is sponsored by the provided clientId. */
|
||||
static void verifySuperordinateDomainOwnership(
|
||||
String clientId,
|
||||
DomainResource superordinateDomain) throws EppException {
|
||||
String clientId, DomainResource superordinateDomain) throws EppException {
|
||||
if (superordinateDomain != null
|
||||
&& !clientId.equals(superordinateDomain.getCurrentSponsorClientId())) {
|
||||
throw new HostDomainNotOwnedException();
|
||||
|
@ -135,8 +123,8 @@ public class HostFlowUtils {
|
|||
}
|
||||
|
||||
/** Ensure that the superordinate domain is not in pending delete. */
|
||||
static void verifySuperordinateDomainNotInPendingDelete(
|
||||
DomainResource superordinateDomain) throws EppException {
|
||||
static void verifySuperordinateDomainNotInPendingDelete(DomainResource superordinateDomain)
|
||||
throws EppException {
|
||||
if ((superordinateDomain != null)
|
||||
&& superordinateDomain.getStatusValues().contains(StatusValue.PENDING_DELETE)) {
|
||||
throw new SuperordinateDomainInPendingDeleteException();
|
||||
|
@ -158,10 +146,10 @@ public class HostFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/** Host names must be at least two levels below the public suffix. */
|
||||
/** Host names must be at least two levels below the registry suffix. */
|
||||
static class HostNameTooShallowException extends ParameterValuePolicyErrorException {
|
||||
public HostNameTooShallowException() {
|
||||
super("Host names must be at least two levels below the public suffix");
|
||||
super("Host names must be at least two levels below the registry suffix");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1006,10 +1006,10 @@ def com_google_gdata_core():
|
|||
def com_google_guava():
|
||||
java_import_external(
|
||||
name = "com_google_guava",
|
||||
jar_sha256 = "7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596",
|
||||
jar_sha256 = "4a87d5b1ca996e5e46a99594cf3566ae16885d0cf00b381b5e9f816a0e0125b3",
|
||||
jar_urls = [
|
||||
"http://repo1.maven.org/maven2/com/google/guava/guava/23.0/guava-23.0.jar",
|
||||
"http://domain-registry-maven.storage.googleapis.com/repo1.maven.org/maven2/com/google/guava/guava/23.0/guava-23.0.jar",
|
||||
"http://repo1.maven.org/maven2/com/google/guava/guava/23.3-jre/guava-23.3-jre.jar",
|
||||
"http://maven.ibiblio.org/maven2/com/google/guava/guava/23.3-jre/guava-23.3-jre.jar",
|
||||
],
|
||||
licenses = ["notice"], # The Apache Software License, Version 2.0
|
||||
exports = [
|
||||
|
@ -1021,10 +1021,10 @@ def com_google_guava():
|
|||
def com_google_guava_testlib():
|
||||
java_import_external(
|
||||
name = "com_google_guava_testlib",
|
||||
jar_sha256 = "7e328d0f89a5ea103de4f9b689130eb555ff277e83bf86294bc14c2c40a59a80",
|
||||
jar_sha256 = "377c60720828a655ffd0f64d8b64643962b2957635323ddc9c5223827f6e5482",
|
||||
jar_urls = [
|
||||
"http://repo1.maven.org/maven2/com/google/guava/guava-testlib/23.0/guava-testlib-23.0.jar",
|
||||
"http://domain-registry-maven.storage.googleapis.com/repo1.maven.org/maven2/com/google/guava/guava-testlib/23.0/guava-testlib-23.0.jar",
|
||||
"http://maven.ibiblio.org/maven2/com/google/guava/guava-testlib/23.3-jre/guava-testlib-23.3-jre.jar",
|
||||
"http://repo1.maven.org/maven2/com/google/guava/guava-testlib/23.3-jre/guava-testlib-23.3-jre.jar",
|
||||
],
|
||||
licenses = ["notice"], # The Apache Software License, Version 2.0
|
||||
testonly_ = True,
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.flows.host;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import google.registry.flows.host.HostFlowUtils.HostNameNotLowerCaseException;
|
||||
|
@ -25,8 +26,6 @@ import google.registry.flows.host.HostFlowUtils.HostNameTooLongException;
|
|||
import google.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
|
||||
import google.registry.flows.host.HostFlowUtils.InvalidHostNameException;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.ExceptionRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -36,8 +35,6 @@ import org.junit.runners.JUnit4;
|
|||
@RunWith(JUnit4.class)
|
||||
public class HostFlowUtilsTest {
|
||||
|
||||
@Rule public final ExceptionRule thrown = new ExceptionRule();
|
||||
|
||||
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||
|
||||
@Test
|
||||
|
@ -46,47 +43,53 @@ public class HostFlowUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
// TODO(b/63128999): Fix handling of public suffix lists so that hostnames that aren't on
|
||||
// effective TLDs validate.
|
||||
public void test_validExternalHostNameOnPublicSuffixList_validates() throws Exception {
|
||||
public void test_validExternalHostNameOnRegistrySuffixList_validates() throws Exception {
|
||||
assertThat(validateHostName("host.blogspot.com").toString()).isEqualTo("host.blogspot.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validExternalHostNameOnRegistrySuffixList_multipartTLD_validates()
|
||||
throws Exception {
|
||||
assertThat(validateHostName("ns1.host.co.uk").toString()).isEqualTo("ns1.host.co.uk");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validExternalHostNameOnRegistrySuffixList_multipartTLD_tooShallow()
|
||||
throws Exception {
|
||||
assertThrows(
|
||||
HostNameTooShallowException.class, () -> validateHostName("host.co.uk").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameTooLong() throws Exception {
|
||||
thrown.expect(HostNameTooLongException.class);
|
||||
validateHostName(Strings.repeat("na", 200) + ".wat.man");
|
||||
assertThrows(
|
||||
HostNameTooLongException.class,
|
||||
() -> validateHostName(Strings.repeat("na", 200) + ".wat.man"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameNotLowerCase() throws Exception {
|
||||
thrown.expect(HostNameNotLowerCaseException.class);
|
||||
validateHostName("NA.CAPS.TLD");
|
||||
assertThrows(HostNameNotLowerCaseException.class, () -> validateHostName("NA.CAPS.TLD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameNotPunyCoded() throws Exception {
|
||||
thrown.expect(HostNameNotPunyCodedException.class);
|
||||
validateHostName("motörhead.death.metal");
|
||||
assertThrows(
|
||||
HostNameNotPunyCodedException.class, () -> validateHostName("motörhead.death.metal"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameNotNormalized() throws Exception {
|
||||
thrown.expect(HostNameNotNormalizedException.class);
|
||||
validateHostName("root.node.yeah.");
|
||||
assertThrows(HostNameNotNormalizedException.class, () -> validateHostName("root.node.yeah."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameHasLeadingHyphen() throws Exception {
|
||||
thrown.expect(InvalidHostNameException.class);
|
||||
validateHostName("-giga.mega.tld");
|
||||
assertThrows(InvalidHostNameException.class, () -> validateHostName("-giga.mega.tld"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_validateHostName_hostNameTooShallow() throws Exception {
|
||||
thrown.expect(HostNameTooShallowException.class);
|
||||
validateHostName("domain.tld");
|
||||
assertThrows(HostNameTooShallowException.class, () -> validateHostName("domain.tld"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue