8245472: Backport JDK-8038893 to JDK8

Tue, 25 Aug 2020 09:23:47 +0300

author
abakhtin
date
Tue, 25 Aug 2020 09:23:47 +0300
changeset 14190
b58fdaa80b5a
parent 14189
90d302484147
child 14191
896bbc5499ff

8245472: Backport JDK-8038893 to JDK8
Reviewed-by: mbalao

src/share/classes/java/net/SocketPermission.java file | annotate | diff | comparison | revisions
src/share/classes/sun/net/RegisteredDomain.java file | annotate | diff | comparison | revisions
src/share/classes/sun/security/util/HostnameChecker.java file | annotate | diff | comparison | revisions
src/share/classes/sun/security/util/RegisteredDomain.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/java/net/SocketPermission.java	Tue Aug 25 08:41:48 2020 +0300
     1.2 +++ b/src/share/classes/java/net/SocketPermission.java	Tue Aug 25 09:23:47 2020 +0300
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -43,8 +43,8 @@
    1.11  import java.io.ObjectInputStream;
    1.12  import java.io.IOException;
    1.13  import sun.net.util.IPAddressUtil;
    1.14 -import sun.net.RegisteredDomain;
    1.15  import sun.net.PortConfig;
    1.16 +import sun.security.util.RegisteredDomain;
    1.17  import sun.security.util.SecurityConstants;
    1.18  import sun.security.util.Debug;
    1.19  
    1.20 @@ -677,13 +677,18 @@
    1.21          String a = cname.toLowerCase();
    1.22          String b = hname.toLowerCase();
    1.23          if (a.startsWith(b)  &&
    1.24 -            ((a.length() == b.length()) || (a.charAt(b.length()) == '.')))
    1.25 +            ((a.length() == b.length()) || (a.charAt(b.length()) == '.'))) {
    1.26              return true;
    1.27 +        }
    1.28          if (cdomain == null) {
    1.29 -            cdomain = RegisteredDomain.getRegisteredDomain(a);
    1.30 +            cdomain = RegisteredDomain.from(a)
    1.31 +                                      .map(RegisteredDomain::name)
    1.32 +                                      .orElse(a);
    1.33          }
    1.34          if (hdomain == null) {
    1.35 -            hdomain = RegisteredDomain.getRegisteredDomain(b);
    1.36 +            hdomain = RegisteredDomain.from(b)
    1.37 +                                      .map(RegisteredDomain::name)
    1.38 +                                      .orElse(b);
    1.39          }
    1.40  
    1.41          return cdomain.length() != 0 && hdomain.length() != 0
     2.1 --- a/src/share/classes/sun/net/RegisteredDomain.java	Tue Aug 25 08:41:48 2020 +0300
     2.2 +++ b/src/share/classes/sun/net/RegisteredDomain.java	Tue Aug 25 09:23:47 2020 +0300
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -32,6 +32,10 @@
    2.11  import java.util.Set;
    2.12  
    2.13  /*
    2.14 + * WARNING: This class may contain out-of-date information. It should be
    2.15 + * updated or replaced with an appropriate implementation. See
    2.16 + * sun.security.util.RegisteredDomain for more information.
    2.17 + *
    2.18   * The naming tables listed below were gathered from publicly available data such as
    2.19   * the subdomain registration websites listed for each top-level domain by the Internet
    2.20   * Assigned Numbers Authority and the website of the Internet Corporation for Assigned Names
    2.21 @@ -696,6 +700,36 @@
    2.22      top3Map.put("tr", new HashSet<String>(Arrays.asList("gov.nc.tr")));
    2.23  }
    2.24  
    2.25 +    /**
    2.26 +     * Returns a {@code sun.security.util.RegisteredDomain} representing the
    2.27 +     * registered part of the specified domain.
    2.28 +     *
    2.29 +     * @param domain the domain name
    2.30 +     * @return a {@code sun.security.util.RegisteredDomain} or null
    2.31 +     *    if the domain is unknown or not registerable
    2.32 +     * @throws NullPointerException if domain is null
    2.33 +     */
    2.34 +    public static sun.security.util.RegisteredDomain registeredDomain(String domain) {
    2.35 +        String name = getRegisteredDomain(domain);
    2.36 +        if (name.equals(domain)) {
    2.37 +            return null;
    2.38 +        }
    2.39 +        return new sun.security.util.RegisteredDomain() {
    2.40 +            private String rname = name;
    2.41 +            @Override
    2.42 +            public String name() {
    2.43 +                return rname;
    2.44 +            }
    2.45 +            @Override
    2.46 +            public sun.security.util.RegisteredDomain.Type type() {
    2.47 +                return sun.security.util.RegisteredDomain.Type.ICANN;
    2.48 +            }
    2.49 +            @Override
    2.50 +            public String publicSuffix() {
    2.51 +                return rname.substring(rname.indexOf(".") + 1);
    2.52 +            }
    2.53 +        };
    2.54 +    }
    2.55  
    2.56      /*
    2.57       * Return the registered part of a qualified domain
     3.1 --- a/src/share/classes/sun/security/util/HostnameChecker.java	Tue Aug 25 08:41:48 2020 +0300
     3.2 +++ b/src/share/classes/sun/security/util/HostnameChecker.java	Tue Aug 25 09:23:47 2020 +0300
     3.3 @@ -41,6 +41,7 @@
     3.4  import sun.security.x509.X500Name;
     3.5  
     3.6  import sun.net.util.IPAddressUtil;
     3.7 +import sun.security.ssl.SSLLogger;
     3.8  
     3.9  /**
    3.10   * Class to check hostnames against the names specified in a certificate as
    3.11 @@ -86,18 +87,27 @@
    3.12      /**
    3.13       * Perform the check.
    3.14       *
    3.15 -     * @exception CertificateException if the name does not match any of
    3.16 -     * the names specified in the certificate
    3.17 +     * @param expectedName the expected host name or ip address
    3.18 +     * @param cert the certificate to check against
    3.19 +     * @param chainsToPublicCA true if the certificate chains to a public
    3.20 +     *     root CA (as pre-installed in the cacerts file)
    3.21 +     * @throws CertificateException if the name does not match any of
    3.22 +     *     the names specified in the certificate
    3.23       */
    3.24 -    public void match(String expectedName, X509Certificate cert)
    3.25 -            throws CertificateException {
    3.26 +    public void match(String expectedName, X509Certificate cert,
    3.27 +                      boolean chainsToPublicCA) throws CertificateException {
    3.28          if (isIpAddress(expectedName)) {
    3.29             matchIP(expectedName, cert);
    3.30          } else {
    3.31 -           matchDNS(expectedName, cert);
    3.32 +           matchDNS(expectedName, cert, chainsToPublicCA);
    3.33          }
    3.34      }
    3.35  
    3.36 +    public void match(String expectedName, X509Certificate cert)
    3.37 +            throws CertificateException {
    3.38 +        match(expectedName, cert, false);
    3.39 +    }
    3.40 +
    3.41      /**
    3.42       * Perform the check for Kerberos.
    3.43       */
    3.44 @@ -182,11 +192,12 @@
    3.45       * Certification Authorities are encouraged to use the dNSName instead.
    3.46       *
    3.47       * Matching is performed using the matching rules specified by
    3.48 -     * [RFC2459].  If more than one identity of a given type is present in
    3.49 +     * [RFC5280].  If more than one identity of a given type is present in
    3.50       * the certificate (e.g., more than one dNSName name, a match in any one
    3.51       * of the set is considered acceptable.)
    3.52       */
    3.53 -    private void matchDNS(String expectedName, X509Certificate cert)
    3.54 +    private void matchDNS(String expectedName, X509Certificate cert,
    3.55 +                          boolean chainsToPublicCA)
    3.56              throws CertificateException {
    3.57          // Check that the expected name is a valid domain name.
    3.58          try {
    3.59 @@ -204,7 +215,7 @@
    3.60                  if (((Integer)next.get(0)).intValue() == ALTNAME_DNS) {
    3.61                      foundDNS = true;
    3.62                      String dnsName = (String)next.get(1);
    3.63 -                    if (isMatched(expectedName, dnsName)) {
    3.64 +                    if (isMatched(expectedName, dnsName, chainsToPublicCA)) {
    3.65                          return;
    3.66                      }
    3.67                  }
    3.68 @@ -226,7 +237,8 @@
    3.69                      throw new CertificateException("Not a formal name "
    3.70                              + cname);
    3.71                  }
    3.72 -                if (isMatched(expectedName, cname)) {
    3.73 +                if (isMatched(expectedName, cname,
    3.74 +                              chainsToPublicCA)) {
    3.75                      return;
    3.76                  }
    3.77              } catch (IOException e) {
    3.78 @@ -271,7 +283,11 @@
    3.79       * The <code>name</code> parameter should represent a DNS name.  The
    3.80       * <code>template</code> parameter may contain the wildcard character '*'.
    3.81       */
    3.82 -    private boolean isMatched(String name, String template) {
    3.83 +    private boolean isMatched(String name, String template,
    3.84 +                              boolean chainsToPublicCA) {
    3.85 +        if (hasIllegalWildcard(name, template, chainsToPublicCA)) {
    3.86 +            return false;
    3.87 +        }
    3.88          // check the validity of the domain name template.
    3.89          try {
    3.90              // Replacing wildcard character '*' with 'z' so as to check
    3.91 @@ -293,6 +309,64 @@
    3.92          }
    3.93      }
    3.94  
    3.95 +    /**
    3.96 +     * Returns true if the template contains an illegal wildcard character.
    3.97 +     */
    3.98 +    private static boolean hasIllegalWildcard(String domain, String template,
    3.99 +                                              boolean chainsToPublicCA) {
   3.100 +        // not ok if it is a single wildcard character or "*."
   3.101 +        if (template.equals("*") || template.equals("*.")) {
   3.102 +            if (SSLLogger.isOn) {
   3.103 +                SSLLogger.fine(
   3.104 +                    "Certificate domain name has illegal single " +
   3.105 +                      "wildcard character: " + template);
   3.106 +            }
   3.107 +            return true;
   3.108 +        }
   3.109 +
   3.110 +        int lastWildcardIndex = template.lastIndexOf("*");
   3.111 +
   3.112 +        // ok if it has no wildcard character
   3.113 +        if (lastWildcardIndex == -1) {
   3.114 +            return false;
   3.115 +        }
   3.116 +
   3.117 +        String afterWildcard = template.substring(lastWildcardIndex);
   3.118 +        int firstDotIndex = afterWildcard.indexOf(".");
   3.119 +
   3.120 +        // not ok if there is no dot after wildcard (ex: "*com")
   3.121 +        if (firstDotIndex == -1) {
   3.122 +            if (SSLLogger.isOn) {
   3.123 +                SSLLogger.fine(
   3.124 +                    "Certificate domain name has illegal wildcard, " +
   3.125 +                    "no dot after wildcard character: " + template);
   3.126 +            }
   3.127 +            return true;
   3.128 +        }
   3.129 +
   3.130 +        // If the wildcarded domain is a top-level domain under which names
   3.131 +        // can be registered, then a wildcard is not allowed.
   3.132 +
   3.133 +        if (!chainsToPublicCA) {
   3.134 +            return false; // skip check for non-public certificates
   3.135 +        }
   3.136 +        Optional<RegisteredDomain> rd = RegisteredDomain.from(domain)
   3.137 +                .filter(d -> d.type() == RegisteredDomain.Type.ICANN);
   3.138 +
   3.139 +        if (rd.isPresent()) {
   3.140 +            String wDomain = afterWildcard.substring(firstDotIndex + 1);
   3.141 +            if (rd.get().publicSuffix().equalsIgnoreCase(wDomain)) {
   3.142 +            if (SSLLogger.isOn) {
   3.143 +                SSLLogger.fine(
   3.144 +                    "Certificate domain name has illegal " +
   3.145 +                    "wildcard for public suffix: " + template);
   3.146 +                }
   3.147 +                return true;
   3.148 +            }
   3.149 +        }
   3.150 +
   3.151 +        return false;
   3.152 +    }
   3.153  
   3.154      /**
   3.155       * Returns true if name matches against template.<p>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/sun/security/util/RegisteredDomain.java	Tue Aug 25 09:23:47 2020 +0300
     4.3 @@ -0,0 +1,93 @@
     4.4 +/*
     4.5 + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package sun.security.util;
    4.30 +
    4.31 +import java.util.Optional;
    4.32 +
    4.33 +/**
    4.34 + * A domain that is registered under a "public suffix". The public suffix is
    4.35 + * a top-level domain under which names can be registered. For example,
    4.36 + * "com" and "co.uk" are public suffixes, and "example.com" and "example.co.uk"
    4.37 + * are registered domains.
    4.38 + * <p>
    4.39 + * The primary purpose of this class is to determine if domains are safe to
    4.40 + * use in various use-cases.
    4.41 + */
    4.42 +public interface RegisteredDomain {
    4.43 +
    4.44 +    public enum Type {
    4.45 +        /**
    4.46 +         * An ICANN registered domain.
    4.47 +         */
    4.48 +        ICANN,
    4.49 +        /**
    4.50 +         * A private registered domain.
    4.51 +         */
    4.52 +        PRIVATE
    4.53 +    }
    4.54 +
    4.55 +    /**
    4.56 +     * Returns the name of the registered domain.
    4.57 +     *
    4.58 +     * @return the name of the registered domain
    4.59 +     */
    4.60 +    String name();
    4.61 +
    4.62 +    /**
    4.63 +     * Returns the type of the registered domain.
    4.64 +     *
    4.65 +     * @return the type of the registered domain
    4.66 +     */
    4.67 +    Type type();
    4.68 +
    4.69 +    /**
    4.70 +     * Returns the public suffix of the registered domain.
    4.71 +     *
    4.72 +     * @return the public suffix of the registered domain
    4.73 +     */
    4.74 +    String publicSuffix();
    4.75 +
    4.76 +    /**
    4.77 +     * Returns an {@code Optional<RegisteredDomain>} representing the
    4.78 +     * registered part of the specified domain.
    4.79 +     *
    4.80 +     * {@implNote}
    4.81 +     * The default implementation is based on the legacy
    4.82 +     * {@code sun.net.RegisteredDomain} class which is no longer maintained.
    4.83 +     * It should be updated or replaced with an appropriate implementation.
    4.84 +     *
    4.85 +     * @param domain the domain name
    4.86 +     * @return an {@code Optional<RegisteredDomain>}; the {@code Optional} is
    4.87 +     *    empty if the domain is unknown or not registerable
    4.88 +     * @throws NullPointerException if domain is null
    4.89 +     */
    4.90 +    public static Optional<RegisteredDomain> from(String domain) {
    4.91 +        if (domain == null) {
    4.92 +            throw new NullPointerException();
    4.93 +        }
    4.94 +        return Optional.ofNullable(sun.net.RegisteredDomain.registeredDomain(domain));
    4.95 +    }
    4.96 +}

mercurial