8067694: Improved certification checking
authorxuelei
Wed, 04 Feb 2015 11:13:14 +0000
changeset 31687 d6eb4f028c60
parent 31685 6a6e995cf912
child 31688 42c9b194a469
8067694: Improved certification checking Reviewed-by: mullan, jnimeh, coffeys, robm, asmotrak, ahgross
jdk/src/java.base/share/classes/java/net/InetAddress.java
jdk/src/java.base/share/classes/java/net/URLClassLoader.java
jdk/src/java.base/share/classes/sun/misc/JavaNetAccess.java
jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java	Wed Jul 15 12:10:03 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java	Wed Feb 04 11:13:14 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, 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
@@ -205,16 +205,33 @@
     static transient boolean preferIPv6Address = false;
 
     static class InetAddressHolder {
+        /**
+         * Reserve the original application specified hostname.
+         *
+         * The original hostname is useful for domain-based endpoint
+         * identification (see RFC 2818 and RFC 6125).  If an address
+         * was created with a raw IP address, a reverse name lookup
+         * may introduce endpoint identification security issue via
+         * DNS forging.
+         *
+         * Oracle JSSE provider is using this original hostname, via
+         * sun.misc.JavaNetAccess, for SSL/TLS endpoint identification.
+         *
+         * Note: May define a new public method in the future if necessary.
+         */
+        private String originalHostName;
 
         InetAddressHolder() {}
 
         InetAddressHolder(String hostName, int address, int family) {
+            this.originalHostName = hostName;
             this.hostName = hostName;
             this.address = address;
             this.family = family;
         }
 
         void init(String hostName, int family) {
+            this.originalHostName = hostName;
             this.hostName = hostName;
             if (family != -1) {
                 this.family = family;
@@ -227,6 +244,10 @@
             return hostName;
         }
 
+        String getOriginalHostName() {
+            return originalHostName;
+        }
+
         /**
          * Holds a 32-bit IPv4 address.
          */
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Wed Jul 15 12:10:03 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Wed Feb 04 11:13:14 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -774,6 +774,10 @@
                 public URLClassPath getURLClassPath (URLClassLoader u) {
                     return u.ucp;
                 }
+
+                public String getOriginalHostName(InetAddress ia) {
+                    return ia.holder.getOriginalHostName();
+                }
             }
         );
         ClassLoader.registerAsParallelCapable();
--- a/jdk/src/java.base/share/classes/sun/misc/JavaNetAccess.java	Wed Jul 15 12:10:03 2015 +0800
+++ b/jdk/src/java.base/share/classes/sun/misc/JavaNetAccess.java	Wed Feb 04 11:13:14 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, 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,10 +26,17 @@
 package sun.misc;
 
 import java.net.URLClassLoader;
+import java.net.InetAddress;
 
 public interface JavaNetAccess {
     /**
      * return the URLClassPath belonging to the given loader
      */
     URLClassPath getURLClassPath (URLClassLoader u);
+
+    /**
+     * Return the original application specified hostname of
+     * the given InetAddress object.
+     */
+    String getOriginalHostName(InetAddress ia);
 }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Jul 15 12:10:03 2015 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Feb 04 11:13:14 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -42,6 +42,9 @@
 import javax.net.ssl.*;
 import sun.misc.ManagedLocalsThread;
 
+import sun.misc.JavaNetAccess;
+import sun.misc.SharedSecrets;
+
 /**
  * Implementation of an SSL socket.  This is a normal connection type
  * socket, implementing SSL over some lower level socket, such as TCP.
@@ -377,6 +380,15 @@
      */
     private int maximumPacketSize = 0;
 
+    /*
+     * Is the local name service trustworthy?
+     *
+     * If the local name service is not trustworthy, reverse host name
+     * resolution should not be performed for endpoint identification.
+     */
+    static final boolean trustNameService =
+            Debug.getBooleanProperty("jdk.tls.trustNameService", false);
+
     //
     // CONSTRUCTORS AND INITIALIZATION CODE
     //
@@ -2063,11 +2075,40 @@
     synchronized String getHost() {
         // Note that the host may be null or empty for localhost.
         if (host == null || host.length() == 0) {
-            host = getInetAddress().getHostName();
+            if (!trustNameService) {
+                // If the local name service is not trustworthy, reverse host
+                // name resolution should not be performed for endpoint
+                // identification.  Use the application original specified
+                // hostname or IP address instead.
+                host = getOriginalHostname(getInetAddress());
+            } else {
+                host = getInetAddress().getHostName();
+            }
         }
+
         return host;
     }
 
+    /*
+     * Get the original application specified hostname.
+     */
+    private static String getOriginalHostname(InetAddress inetAddress) {
+        /*
+         * Get the original hostname via sun.misc.SharedSecrets.
+         */
+        JavaNetAccess jna = SharedSecrets.getJavaNetAccess();
+        String originalHostname = jna.getOriginalHostName(inetAddress);
+
+        /*
+         * If no application specified hostname, use the IP address.
+         */
+        if (originalHostname == null || originalHostname.length() == 0) {
+            originalHostname = inetAddress.getHostAddress();
+        }
+
+        return originalHostname;
+    }
+
     // ONLY used by HttpsClient to setup the URI specified hostname
     //
     // Please NOTE that this method MUST be called before calling to