Skip to content

Commit

Permalink
pool: fix lookup for canonical hostname for IPv6 addresses
Browse files Browse the repository at this point in the history
Motivation:

Secure/authenticated HTTP transfers require the server to present an
X.509 certificate, which identifies the server by it's DNS FQDN.
Therefore it is important that the pool returns a URL that uses the DNS
FQDN to identify itself.

An earlier patch attempted to enforce this, but did not fix the problem
for IPv6 addresses.

Modification:

Update code to understand IPv6 addresses as IP addresses.

Include diagnostic messages to record if the DNS canonical name lookup
fails.

Result:

Secure HTTP transfers work over IPv6.  Problems are easier to diagnose.

Target: master
Request: 5.0
Request: 4.2
Requires-notes: yes
Requires-book: no
Ticket: https://rt.dcache.org/Ticket/Display.html?id=9606
Patch: https://rb.dcache.org/r/11524/
Acked-by: Albert Rossi
  • Loading branch information
paulmillar committed Feb 6, 2019
1 parent ed98759 commit 24740b9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
Expand Up @@ -17,6 +17,7 @@
*/
package org.dcache.http;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.net.InetAddresses;

import diskCacheV111.util.CacheException;
Expand All @@ -28,6 +29,8 @@
import eu.emi.security.authn.x509.OCSPCheckingMode;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;

import javax.net.ssl.SSLContext;
Expand All @@ -43,7 +46,9 @@
import java.util.UUID;


public class HttpsTransferService extends HttpTransferService {
public class HttpsTransferService extends HttpTransferService
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpsTransferService.class);

private static final String PROTOCOL_HTTPS = "https";

Expand Down Expand Up @@ -82,20 +87,39 @@ public void setOcspCheckingMode(OCSPCheckingMode ocspCheckingMode)
_ocspCheckingMode = ocspCheckingMode;
}

/**
* Obtain the hostname or IP address from a URL. Unlike URI#getHost, this
* method returns any IPv6 address without the square brackets.
* @param url
* @return
*/
@VisibleForTesting
static String getHost(URI url)
{
String host = url.getHost();
return host != null && !host.isEmpty() && host.charAt(0) == '[' && host.charAt(host.length()-1) == ']'
? host.substring(1, host.length()-1)
: host;
}

@Override
protected URI getUri(HttpProtocolInfo protocolInfo, int port, UUID uuid)
throws SocketException, CacheException, URISyntaxException {

URI plainUrl = super.getUri(protocolInfo, port, uuid);
String host = plainUrl.getHost();
String host = getHost(plainUrl);
try {
if (InetAddresses.isInetAddress(host)) {
// An IP address is unlikely to be in the X.509 host credential.
host = InetAddress.getByName(host).getCanonicalHostName();
}
if (InetAddresses.isInetAddress(host)) {
LOGGER.warn("Unable to resolve IP address {} to a canonical name", host);
}
} catch (UnknownHostException e) {
// This should not happen as getByName should never throw this
// exception for a valid IP address
LOGGER.warn("Unable to resolve IP address {}: {}", host, e.toString());
}
return new URI(PROTOCOL_HTTPS,
plainUrl.getUserInfo(),
Expand Down
@@ -0,0 +1,49 @@
/* dCache - http://www.dcache.org/
*
* Copyright (C) 2019 Deutsches Elektronen-Synchrotron
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dcache.http;

import org.junit.Test;

import java.net.URI;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;

public class HttpsTransferServiceTest
{
@Test
public void shouldReturnIPv4AddressAsIPv4Address()
{
URI url = URI.create("https://192.168.1.1:8443/path/to/file");

String host = HttpsTransferService.getHost(url);

assertThat(host, is(equalTo("192.168.1.1")));
}

@Test
public void shouldReturnIPv6AddressWithoutBrackets()
{
URI url = URI.create("https://[2001:638:700:20d6::1:3a]:8443/path/to/file");

String host = HttpsTransferService.getHost(url);

assertThat(host, is(equalTo("2001:638:700:20d6::1:3a")));
}
}

0 comments on commit 24740b9

Please sign in to comment.