changeset 1693:6f21294a714e

8174873: Improved certificate procesing Reviewed-by: jnimeh, ahgross, rhalade
author igerasim
date Tue, 28 Mar 2017 13:33:36 -0700
parents 8de5ec810a96
children 993676823a05
files src/share/classes/sun/security/util/HostnameChecker.java
diffstat 1 files changed, 54 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/util/HostnameChecker.java	Mon May 22 14:40:51 2017 -0700
+++ b/src/share/classes/sun/security/util/HostnameChecker.java	Tue Mar 28 13:33:36 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -26,6 +26,8 @@
 package sun.security.util;
 
 import java.io.IOException;
+import java.net.IDN;
+import java.nio.charset.Charset;
 import java.util.*;
 
 import java.security.Principal;
@@ -173,6 +175,36 @@
                         expectedIP + " found");
     }
 
+    /*
+     * Implements backport of checks from SNIHostName.
+     */
+    private static void checkHostName(String hostname)
+            throws IllegalArgumentException
+    {
+        if (hostname == null) {
+            throw new NullPointerException("Server name value of host_name cannot be null");
+        }
+
+        hostname = IDN.toASCII(hostname, IDN.USE_STD3_ASCII_RULES);
+
+        byte[] encoded = hostname.getBytes(Charset.forName("US-ASCII"));
+        if (encoded == null) {
+            throw new NullPointerException(
+                    "Server name encoded value cannot be null");
+        }
+
+        // check the validity of the string hostname
+        if (hostname.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Server name value of host_name cannot be empty");
+        }
+
+        if (hostname.endsWith(".")) {
+            throw new IllegalArgumentException(
+                    "Server name value of host_name cannot have the trailing dot");
+        }
+    }
+
     /**
      * Check if the certificate allows use of the given DNS name.
      *
@@ -190,6 +222,15 @@
      */
     private void matchDNS(String expectedName, X509Certificate cert)
             throws CertificateException {
+        // Check that the expected name is a valid domain name.
+        try {
+            // Using the checking implemented in checkHostName
+            checkHostName(expectedName);
+        } catch (IllegalArgumentException iae) {
+            throw new CertificateException(
+                "Illegal given domain name: " + expectedName, iae);
+        }
+
         Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
         if (subjAltNames != null) {
             boolean foundDNS = false;
@@ -261,6 +302,18 @@
      * may contain the wildcard character *
      */
     private boolean isMatched(String name, String template) {
+        // check the validity of the domain name template.
+        try {
+            // Replacing wildcard character '*' with 'x' so as to check
+            // the domain name template validity.
+            //
+            // Using the checking implemented in checkHostName
+            checkHostName(template.replace('*', 'x'));
+        } catch (IllegalArgumentException iae) {
+            // It would be nice to add debug log if not matching.
+            return false;
+        }
+
         if (checkType == TYPE_TLS) {
             return matchAllWildcards(name, template);
         } else if (checkType == TYPE_LDAP) {