Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize ipv6 addresses for HostNameVerification in OkHostNameVerifier #5885

Closed
magwan opened this issue Mar 21, 2020 · 4 comments · Fixed by #5889
Closed

Normalize ipv6 addresses for HostNameVerification in OkHostNameVerifier #5885

magwan opened this issue Mar 21, 2020 · 4 comments · Fixed by #5889
Labels
enhancement Feature not a bug
Milestone

Comments

@magwan
Copy link

magwan commented Mar 21, 2020

In our k8 environment,
KUBERNETES_SERVICE_HOST is set to ipv6 address in compact form. Ex: FD::0001
In certificate subject alternative name, the same ip is set in normalized form. Ex FD00:0:0:0:0:0:0:1
Due to above different formats, hostname verification is failed even though both are same address.

It will be good, if OkHostNameVerifier normalize the hostname and sans before comparing them.

Reference Implementation from https://github.com/apache/cxf/blob/master/rt/transports/http/src/main/java/org/apache/cxf/transport/https/httpclient/DefaultHostnameVerifier.java

static void matchIPv6Address(final String host, final List<SubjectName> subjectAlts) throws SSLException {
        final String normalisedHost = normaliseAddress(host);
        for (int i = 0; i < subjectAlts.size(); i++) {
            final SubjectName subjectAlt = subjectAlts.get(i);
            if (subjectAlt.getType() == SubjectName.IP) {
                final String normalizedSubjectAlt = normaliseAddress(subjectAlt.getValue());
                if (normalisedHost.equals(normalizedSubjectAlt)) {
                    return;
                }
            }
        }
        throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any "
                + "of the subject alternative names: " + subjectAlts);
    }
@magwan magwan added the enhancement Feature not a bug label Mar 21, 2020
@yschimke
Copy link
Collaborator

yschimke commented Mar 21, 2020

Agree 100%. Looks like the correct thing to do

https://tools.ietf.org/html/rfc2818#section-3.1

In some cases, the URI is specified as an IP address rather than a
hostname. In this case, the iPAddress subjectAltName must be present
in the certificate and must exactly match the IP in the URI.

https://tools.ietf.org/html/rfc2459#section-4.2.1.7

When the subjectAltName extension contains a iPAddress, the address
MUST be stored in the octet string in "network byte order," as
specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
each octet is the LSB of the corresponding byte in the network
address. For IP Version 4, as specified in RFC 791, the octet string
MUST contain exactly four octets. For IP Version 6, as specified in
RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
1883].

@yschimke
Copy link
Collaborator

private fun verifyIpAddress(ipAddress: String, certificate: X509Certificate): Boolean {

@magwan
Copy link
Author

magwan commented Mar 21, 2020

@yschimke Thanks for the comment. Certificate contains ip in 16 octets as per spec. There is no issue with the certificate.

The issue is whether to consider "FD::001" is exact match to "FD00:0:0:0:0:0:0:1" for the purpose of hostname verification.
If we consider them as strings, then they are not. But if we consider them as Ipv6 Addresses then they are exact match.

Ipv6 address spec allows both representation, though 16 octet form is preferred.

Refer section 2.2.2 from https://tools.ietf.org/html/rfc4291

  1. Due to some methods of allocating certain styles of IPv6
    addresses, it will be common for addresses to contain long strings
    of zero bits. In order to make writing addresses containing zero
    bits easier, a special syntax is available to compress the zeros.
    The use of "::" indicates one or more groups of 16 bits of zeros.
    The "::" can only appear once in an address. The "::" can also be
    used to compress leading or trailing zeros in an address.

    For example, the following addresses

    2001:DB8:0:0:8:800:200C:417A a unicast address
    FF01:0:0:0:0:0:0:101 a multicast address
    0:0:0:0:0:0:0:1 the loopback address
    0:0:0:0:0:0:0:0 the unspecified address

    may be represented as

    2001:DB8::8:800:200C:417A a unicast address
    FF01::101 a multicast address
    ::1 the loopback address
    :: the unspecified address

@yschimke
Copy link
Collaborator

yschimke commented Mar 22, 2020

HttpUrl canonicalises the host automatically (::1), so I've gone the other direction and am doing the same to the certificate (0:0:0:0:0:1 -> ::1) since it's a more controlled change.

I can't assume it's always the case since javax.net.ssl.HostnameVerifier is a public API taking a String hostname

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature not a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants