changeset 1761:a63aa5418847

8186606: Improve LDAP lookup robustness 8190789: sun/security/provider/certpath/LDAPCertStore/TestURICertStoreParameters.java fails after JDK-8186606 Reviewed-by: weijun
author aefimov
date Tue, 14 Nov 2017 13:53:48 +0000
parents fce9d3983439
children 98682486eca1
files src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java
diffstat 1 files changed, 54 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java	Fri Aug 25 20:57:09 2017 -0700
+++ b/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java	Tue Nov 14 13:53:48 2017 +0000
@@ -31,6 +31,8 @@
 import java.net.URI;
 import java.util.*;
 import javax.naming.Context;
+import javax.naming.CompositeName;
+import javax.naming.InvalidNameException;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.NameNotFoundException;
@@ -43,8 +45,10 @@
 import java.security.*;
 import java.security.cert.Certificate;
 import java.security.cert.*;
+import javax.naming.ldap.LdapContext;
 import javax.security.auth.x500.X500Principal;
 
+import com.sun.jndi.ldap.LdapReferralException;
 import sun.misc.HexDumpEncoder;
 import sun.security.provider.certpath.X509CertificatePair;
 import sun.security.util.Cache;
@@ -250,7 +254,7 @@
              */
             Hashtable<?,?> currentEnv = ctx.getEnvironment();
             if (currentEnv.get(Context.REFERRAL) == null) {
-                ctx.addToEnvironment(Context.REFERRAL, "follow-scheme");
+                ctx.addToEnvironment(Context.REFERRAL, "throw");
             }
         } catch (NamingException e) {
             if (debug != null) {
@@ -287,11 +291,25 @@
         private Map<String, byte[][]> valueMap;
         private final List<String> requestedAttributes;
 
-        LDAPRequest(String name) {
-            this.name = name;
+        LDAPRequest(String name) throws CertStoreException {
+            this.name = checkName(name);
             requestedAttributes = new ArrayList<String>(5);
         }
 
+        private String checkName(String name) throws CertStoreException {
+            if (name == null) {
+                throw new CertStoreException("Name absent");
+            }
+            try {
+                if (new CompositeName(name).size() > 1) {
+                    throw new CertStoreException("Invalid name: " + name);
+                }
+            } catch (InvalidNameException ine) {
+                throw new CertStoreException("Invalid name: " + name, ine);
+            }
+            return name;
+        }
+
         String getName() {
             return name;
         }
@@ -306,7 +324,6 @@
         /**
          * Gets one or more binary values from an attribute.
          *
-         * @param name          the location holding the attribute
          * @param attrId                the attribute identifier
          * @return                      an array of binary values (byte arrays)
          * @throws NamingException      if a naming exception occurs
@@ -358,6 +375,39 @@
             Attributes attrs;
             try {
                 attrs = ctx.getAttributes(name, attrIds);
+            } catch (LdapReferralException lre) {
+                // LdapCtx has a hopCount field to avoid infinite loop
+                while (true) {
+                    try {
+                        String newName = (String) lre.getReferralInfo();
+                        URI newUri = new URI(newName);
+                        if (!newUri.getScheme().equalsIgnoreCase("ldap")) {
+                            throw new IllegalArgumentException("Not LDAP");
+                        }
+                        String newDn = newUri.getPath();
+                        if (newDn != null && newDn.charAt(0) == '/') {
+                            newDn = newDn.substring(1);
+                        }
+                        checkName(newDn);
+                    } catch (Exception e) {
+                        throw new NamingException("Cannot follow referral to "
+                                + lre.getReferralInfo());
+                    }
+                    LdapContext refCtx =
+                            (LdapContext)lre.getReferralContext();
+
+                    // repeat the original operation at the new context
+                    try {
+                        attrs = refCtx.getAttributes(name, attrIds);
+                        break;
+                    } catch (LdapReferralException re) {
+                        lre = re;
+                        continue;
+                    } finally {
+                        // Make sure we close referral context
+                        refCtx.close();
+                    }
+                }
             } catch (NameNotFoundException e) {
                 // name does not exist on this LDAP server
                 // treat same as not attributes found