Skip to content

Commit 95ff63c

Browse files
author
petit_baguette
committed
fix(xds): Allow and normalize trailing dot (FQDN) in matchHostName
1 parent e636df5 commit 95ff63c

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

xds/src/main/java/io/grpc/xds/RoutingUtils.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,24 @@ static VirtualHost findVirtualHostForHostName(List<VirtualHost> virtualHosts, St
9292
* </ol>
9393
*/
9494
private static boolean matchHostName(String hostName, String pattern) {
95-
checkArgument(hostName.length() != 0 && !hostName.startsWith(".") && !hostName.endsWith("."),
95+
checkArgument(hostName.length() != 0 && !hostName.startsWith("."),
9696
"Invalid host name");
97-
checkArgument(pattern.length() != 0 && !pattern.startsWith(".") && !pattern.endsWith("."),
97+
checkArgument(pattern.length() != 0 && !pattern.startsWith("."),
9898
"Invalid pattern/domain name");
9999

100100
hostName = hostName.toLowerCase(Locale.US);
101101
pattern = pattern.toLowerCase(Locale.US);
102102
// hostName and pattern are now in lower case -- domain names are case-insensitive.
103103

104+
// Strip trailing dot to normalize FQDN (e.g. "example.com.") to a relative form,
105+
// as per RFC 1034 Section 3.1 the two are semantically equivalent.
106+
if (hostName.endsWith(".")) {
107+
hostName = hostName.substring(0, hostName.length() - 1);
108+
}
109+
if (pattern.endsWith(".")) {
110+
pattern = pattern.substring(0, pattern.length() - 1);
111+
}
112+
104113
if (!pattern.contains("*")) {
105114
// Not a wildcard pattern -- hostName and pattern must match exactly.
106115
return hostName.equals(pattern);

xds/src/main/java/io/grpc/xds/XdsNameResolver.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,15 +354,24 @@ private void updateResolutionResult(XdsConfig xdsConfig) {
354354
*/
355355
@VisibleForTesting
356356
static boolean matchHostName(String hostName, String pattern) {
357-
checkArgument(hostName.length() != 0 && !hostName.startsWith(".") && !hostName.endsWith("."),
357+
checkArgument(hostName.length() != 0 && !hostName.startsWith("."),
358358
"Invalid host name");
359-
checkArgument(pattern.length() != 0 && !pattern.startsWith(".") && !pattern.endsWith("."),
359+
checkArgument(pattern.length() != 0 && !pattern.startsWith("."),
360360
"Invalid pattern/domain name");
361361

362362
hostName = hostName.toLowerCase(Locale.US);
363363
pattern = pattern.toLowerCase(Locale.US);
364364
// hostName and pattern are now in lower case -- domain names are case-insensitive.
365365

366+
// Strip trailing dot to normalize FQDN (e.g. "example.com.") to a relative form,
367+
// as per RFC 1034 Section 3.1 the two are semantically equivalent.
368+
if (hostName.endsWith(".")) {
369+
hostName = hostName.substring(0, hostName.length() - 1);
370+
}
371+
if (pattern.endsWith(".")) {
372+
pattern = pattern.substring(0, pattern.length() - 1);
373+
}
374+
366375
if (!pattern.contains("*")) {
367376
// Not a wildcard pattern -- hostName and pattern must match exactly.
368377
return hostName.equals(pattern);

xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,27 @@ public void matchHostName_postfixWildCard() {
20622062
assertThat(XdsNameResolver.matchHostName("foo-bar", pattern)).isTrue();
20632063
}
20642064

2065+
@Test
2066+
public void matchHostName_trailingDot() {
2067+
// FQDN (trailing dot) is semantically equivalent to the relative form per RFC 1034 Section 3.1.
2068+
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", "foo.googleapis.com")).isTrue();
2069+
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com", "foo.googleapis.com.")).isTrue();
2070+
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", "foo.googleapis.com.")).isTrue();
2071+
assertThat(XdsNameResolver.matchHostName("bar.googleapis.com.", "foo.googleapis.com")).isFalse();
2072+
2073+
// Wildcard + trailing dot combinations.
2074+
String pattern = "*.foo.googleapis.com";
2075+
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com.", pattern)).isTrue();
2076+
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com", pattern + ".")).isTrue();
2077+
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com.", pattern + ".")).isTrue();
2078+
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", pattern)).isFalse();
2079+
2080+
pattern = "foo.*";
2081+
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", pattern)).isTrue();
2082+
assertThat(XdsNameResolver.matchHostName("foo.com.", pattern)).isTrue();
2083+
assertThat(XdsNameResolver.matchHostName("bar.googleapis.com.", pattern)).isFalse();
2084+
}
2085+
20652086
@Test
20662087
public void resolved_faultAbortInLdsUpdate() {
20672088
resolver.start(mockListener);

0 commit comments

Comments
 (0)