Skip to content

Commit 9555dca

Browse files
authored
Don't allow loopback IP addresses for hosts (#2920)
I don't know where in the spec these are explicitly disallowed, but it seems like good practice and we'll fail the RST tests if we don't disallow them.
1 parent 49484c0 commit 9555dca

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

core/src/main/java/google/registry/flows/host/HostCreateFlow.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ public EppResponse run() throws EppException {
116116
? new SubordinateHostMustHaveIpException()
117117
: new UnexpectedExternalHostIpException();
118118
}
119+
HostFlowUtils.validateInetAddresses(command.getInetAddresses());
119120
Host newHost =
120121
new Host.Builder()
121122
.setCreationRegistrarId(registrarId)

core/src/main/java/google/registry/flows/host/HostFlowUtils.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import com.google.common.base.Ascii;
2424
import com.google.common.base.CharMatcher;
25+
import com.google.common.collect.ImmutableSet;
2526
import com.google.common.net.InternetDomainName;
2627
import google.registry.flows.EppException;
2728
import google.registry.flows.EppException.AuthorizationErrorException;
@@ -34,6 +35,7 @@
3435
import google.registry.model.domain.Domain;
3536
import google.registry.model.eppcommon.StatusValue;
3637
import google.registry.util.Idn;
38+
import java.net.InetAddress;
3739
import java.util.Optional;
3840
import org.joda.time.DateTime;
3941

@@ -108,6 +110,24 @@ public static Optional<Domain> lookupSuperordinateDomain(
108110
return superordinateDomain;
109111
}
110112

113+
/** Makes sure that no provided IP addresses are local / loopback addresses. */
114+
public static void validateInetAddresses(ImmutableSet<InetAddress> inetAddresses)
115+
throws EppException {
116+
if (inetAddresses == null) {
117+
return;
118+
}
119+
if (inetAddresses.stream().anyMatch(InetAddress::isLoopbackAddress)) {
120+
throw new LoopbackIpNotValidForHostException();
121+
}
122+
}
123+
124+
/** Loopback IPs are not valid for hosts. */
125+
static class LoopbackIpNotValidForHostException extends ParameterValuePolicyErrorException {
126+
public LoopbackIpNotValidForHostException() {
127+
super("Loopback IPs are not valid for hosts");
128+
}
129+
}
130+
111131
/** Superordinate domain for this hostname does not exist. */
112132
static class SuperordinateDomainDoesNotExistException extends ObjectDoesNotExistException {
113133
public SuperordinateDomainDoesNotExistException(String domainName) {

core/src/main/java/google/registry/flows/host/HostUpdateFlow.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public EppResponse run() throws EppException {
161161
AddRemove remove = command.getInnerRemove();
162162
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
163163
checkSameValuesNotAddedAndRemoved(add.getInetAddresses(), remove.getInetAddresses());
164+
HostFlowUtils.validateInetAddresses(add.getInetAddresses());
164165
VKey<Domain> newSuperordinateDomainKey =
165166
newSuperordinateDomain.map(Domain::createVKey).orElse(null);
166167
// If the superordinateDomain field is changing, set the lastSuperordinateChange to now.

core/src/test/java/google/registry/flows/host/HostCreateFlowTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import google.registry.flows.host.HostFlowUtils.HostNameNotPunyCodedException;
4646
import google.registry.flows.host.HostFlowUtils.HostNameTooLongException;
4747
import google.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
48+
import google.registry.flows.host.HostFlowUtils.LoopbackIpNotValidForHostException;
4849
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
4950
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainInPendingDeleteException;
5051
import google.registry.model.ForeignKeyUtils;
@@ -322,6 +323,26 @@ void testFailure_ccTldInBailiwick() {
322323
assertAboutEppExceptions().that(thrown).marshalsToXml();
323324
}
324325

326+
@Test
327+
void testFailure_localhostInetAddress_ipv4() {
328+
createTld("tld");
329+
persistActiveDomain("example.tld");
330+
setEppHostCreateInput("ns1.example.tld", "<host:addr ip=\"v4\">127.0.0.1</host:addr>");
331+
assertAboutEppExceptions()
332+
.that(assertThrows(LoopbackIpNotValidForHostException.class, this::runFlow))
333+
.marshalsToXml();
334+
}
335+
336+
@Test
337+
void testFailure_localhostInetAddress_ipv6() {
338+
createTld("tld");
339+
persistActiveDomain("example.tld");
340+
setEppHostCreateInput("ns1.example.tld", "<host:addr ip=\"v6\">::1</host:addr>");
341+
assertAboutEppExceptions()
342+
.that(assertThrows(LoopbackIpNotValidForHostException.class, this::runFlow))
343+
.marshalsToXml();
344+
}
345+
325346
@Test
326347
void testIcannActivityReportField_getsLogged() throws Exception {
327348
runFlow();

core/src/test/java/google/registry/flows/host/HostUpdateFlowTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import google.registry.flows.host.HostFlowUtils.HostNameNotPunyCodedException;
6262
import google.registry.flows.host.HostFlowUtils.HostNameTooLongException;
6363
import google.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
64+
import google.registry.flows.host.HostFlowUtils.LoopbackIpNotValidForHostException;
6465
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
6566
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainInPendingDeleteException;
6667
import google.registry.flows.host.HostUpdateFlow.CannotAddIpToExternalHostException;
@@ -1306,6 +1307,28 @@ void testFailure_ccTldInBailiwick() throws Exception {
13061307
doFailingHostNameTest("foo.co.uk", HostNameTooShallowException.class);
13071308
}
13081309

1310+
@Test
1311+
void testFailure_localhostInetAddress_ipv4() throws Exception {
1312+
createTld("tld");
1313+
persistActiveSubordinateHost(oldHostName(), persistActiveDomain("example.tld"));
1314+
setEppHostUpdateInput(
1315+
"ns1.example.tld", "ns2.example.tld", "<host:addr ip=\"v4\">127.0.0.1</host:addr>", null);
1316+
assertAboutEppExceptions()
1317+
.that(assertThrows(LoopbackIpNotValidForHostException.class, this::runFlow))
1318+
.marshalsToXml();
1319+
}
1320+
1321+
@Test
1322+
void testFailure_localhostInetAddress_ipv6() throws Exception {
1323+
createTld("tld");
1324+
persistActiveSubordinateHost(oldHostName(), persistActiveDomain("example.tld"));
1325+
setEppHostUpdateInput(
1326+
"ns1.example.tld", "ns2.example.tld", "<host:addr ip=\"v6\">::1</host:addr>", null);
1327+
assertAboutEppExceptions()
1328+
.that(assertThrows(LoopbackIpNotValidForHostException.class, this::runFlow))
1329+
.marshalsToXml();
1330+
}
1331+
13091332
@Test
13101333
void testSuccess_metadata() throws Exception {
13111334
createTld("tld");

0 commit comments

Comments
 (0)