# HG changeset patch # User xuelei # Date 1555030698 25200 # Node ID 6cd74f29752c58da6f3fcfaf31e560aef2453dce # Parent 107c8ea4f7c88f11a473c1b96c685bf8dfdfc2f5 8218873: Improve JSSE endpoint checking Reviewed-by: mullan, ahgross, rhalade diff -r 107c8ea4f7c8 -r 6cd74f29752c src/java.base/share/classes/sun/security/util/HostnameChecker.java --- a/src/java.base/share/classes/sun/security/util/HostnameChecker.java Wed Apr 10 14:43:13 2019 -0700 +++ b/src/java.base/share/classes/sun/security/util/HostnameChecker.java Thu Apr 11 17:58:18 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,28 +260,35 @@ * The matching is performed as per RFC 2818 rules for TLS and * RFC 2830 rules for LDAP.

* - * The name parameter should represent a DNS name. - * The template parameter - * may contain the wildcard character * + * The name parameter should represent a DNS name. The + * template parameter may contain the wildcard character '*'. */ private boolean isMatched(String name, String template, boolean chainsToPublicCA) { // Normalize to Unicode, because PSL is in Unicode. - name = IDN.toUnicode(IDN.toASCII(name)); - template = IDN.toUnicode(IDN.toASCII(template)); + try { + name = IDN.toUnicode(IDN.toASCII(name)); + template = IDN.toUnicode(IDN.toASCII(template)); + } catch (RuntimeException re) { + if (SSLLogger.isOn) { + SSLLogger.fine("Failed to normalize to Unicode: " + re); + } - if (hasIllegalWildcard(name, template, chainsToPublicCA)) { + return false; + } + + if (hasIllegalWildcard(template, chainsToPublicCA)) { return false; } // check the validity of the domain name template. try { - // Replacing wildcard character '*' with 'x' so as to check + // Replacing wildcard character '*' with 'z' so as to check // the domain name template validity. // // Using the checking implemented in SNIHostName - new SNIHostName(template.replace('*', 'x')); + new SNIHostName(template.replace('*', 'z')); } catch (IllegalArgumentException iae) { // It would be nice to add debug log if not matching. return false; @@ -299,8 +306,8 @@ /** * Returns true if the template contains an illegal wildcard character. */ - private static boolean hasIllegalWildcard(String domain, String template, - boolean chainsToPublicCA) { + private static boolean hasIllegalWildcard( + String template, boolean chainsToPublicCA) { // not ok if it is a single wildcard character or "*." if (template.equals("*") || template.equals("*.")) { if (SSLLogger.isOn) { @@ -331,25 +338,29 @@ return true; } - // If the wildcarded domain is a top-level domain under which names - // can be registered, then a wildcard is not allowed. - if (!chainsToPublicCA) { return false; // skip check for non-public certificates } - Optional rd = RegisteredDomain.from(domain) - .filter(d -> d.type() == RegisteredDomain.Type.ICANN); - if (rd.isPresent()) { - String wDomain = afterWildcard.substring(firstDotIndex + 1); - if (rd.get().publicSuffix().equalsIgnoreCase(wDomain)) { - if (SSLLogger.isOn) { - SSLLogger.fine( - "Certificate domain name has illegal " + - "wildcard for public suffix: " + template); - } - return true; + // If the wildcarded domain is a top-level domain under which names + // can be registered, then a wildcard is not allowed. + String wildcardedDomain = afterWildcard.substring(firstDotIndex + 1); + String templateDomainSuffix = + RegisteredDomain.from("z." + wildcardedDomain) + .filter(d -> d.type() == RegisteredDomain.Type.ICANN) + .map(RegisteredDomain::publicSuffix).orElse(null); + if (templateDomainSuffix == null) { + return false; // skip check if not known public suffix + } + + // Is it a top-level domain? + if (wildcardedDomain.equalsIgnoreCase(templateDomainSuffix)) { + if (SSLLogger.isOn) { + SSLLogger.fine( + "Certificate domain name has illegal " + + "wildcard for top-level public suffix: " + template); } + return true; } return false;